/*
Theme Name:   Broadsheet
Theme URI:    https://example.com/broadsheet
Description:  A light editorial theme for writing-led sites. Serif for reading, sans for interface, one accent colour. Ships eight templates, five patterns and three palettes. Retheme the whole site by changing two hex values in theme.json.
Author:       You
Version:      1.9.9
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 7.4
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  broadsheet
Tags:         blog, news, editorial, one-column, block-patterns, full-site-editing, custom-colors, custom-logo, accessibility-ready
*/

/* ============================================================
   Shorthands over the theme.json presets
   ============================================================ */
:root {
	--primary:      var(--wp--preset--color--primary);
	--primary-dark: var(--wp--preset--color--primary-dark);
	--primary-light: var(--wp--preset--color--primary-light);
	--accent:      var(--wp--preset--color--accent);
	--accent-hi:   var(--wp--preset--color--accent-light);
	--accent-text: var(--wp--preset--color--accent-text);
	--paper:     var(--wp--preset--color--paper);
	--wash:      var(--wp--preset--color--wash);
	--wash-alt:  var(--wp--preset--color--wash-alt);
	--rule:      var(--wp--preset--color--rule);
	--ink:       var(--wp--preset--color--ink);
	--body:      var(--wp--preset--color--body);
	--muted:     var(--wp--preset--color--muted);
	--sans:      var(--wp--preset--font-family--sans);
	--serif:     var(--wp--preset--font-family--serif);
}

/* ------------------------------------------------------------
   BOX SIZING

   Without this, width:100% on anything carrying padding or a
   border resolves wider than its container — which is why a
   full-width input overflows the screen edge on mobile.

   WordPress sets this on some blocks but not globally, and form
   controls are among the elements it misses.
   ------------------------------------------------------------ */
*,
*::before,
*::after { box-sizing: border-box; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ------------------------------------------------------------
   MEDIA RESET
   Nothing may exceed its container. Without this any image wider
   than its column spills out of the layout — which is easy to
   miss in the editor, where the canvas is narrower than the
   front end and the overflow is hidden by the frame.
   ------------------------------------------------------------ */
img,
svg,
video,
canvas,
iframe,
embed,
object {
	max-width: 100%;
	height: auto;
}
figure { margin-inline: 0; }

/* ============================================================
   HEADER — hairline treatment
   The logo sits at 44px inline with the nav. The single 1px
   rule is the entire separation device: no band, no shadow.
   ============================================================ */
/* Sticky lives on the template-part wrapper, not the inner group.
   WordPress renders <header class="wp-block-template-part"> around this
   part, and a sticky element only travels within its parent's box — on
   the inner div that box is exactly the header's own height, so it
   sticks across zero pixels and looks broken. */
header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--paper);
}

.site-header {
	border-bottom: 1px solid var(--rule);
	background: var(--paper);
	padding-block: 1.15rem;
}
/* max-width, not width — the Site Logo block writes an inline width when
   you drag its size slider, and a fixed width here would silently win. */
.site-header .wp-block-site-logo img { max-width: 100%; height: auto; }
.site-header .wp-block-site-logo:not([style*="width"]) img { width: 48px; }
.site-header .wp-block-site-title a {
	font-family: var(--sans);
	font-weight: 700;
	font-size: 1.0625rem;
	letter-spacing: -0.01em;
	color: var(--ink);
	text-decoration: none;
}
.site-header .wp-block-navigation { gap: 1.75rem; }
.site-header .wp-block-navigation a {
	color: var(--body);
	text-decoration: none;
	padding-block: 0.25rem;
	border-bottom: 2px solid transparent;
	transition: color .15s ease, border-color .15s ease;
}
.site-header .wp-block-navigation a:hover {
	color: var(--ink);
	border-bottom-color: var(--accent);
}
.site-header .wp-block-navigation .current-menu-item a { border-bottom-color: var(--accent); }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
	background: var(--wash);
	border-top: 1px solid var(--rule);
	padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
	margin-top: clamp(4rem, 8vw, 7rem);
}
.site-footer .wp-block-site-title a {
	font-family: var(--sans);
	font-weight: 700;
	font-size: 1.25rem;
	color: var(--ink);
	text-decoration: none;
}
.site-footer h4,
.footer-head {
	font-family: var(--sans);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--muted);
	margin-block: 0 1.15rem;
}
.site-footer .wp-block-navigation { display: block; }
.site-footer .wp-block-navigation ul { display: grid; gap: 0.6rem; }
.site-footer .wp-block-navigation a { color: var(--body); text-decoration: none; }
.site-footer .wp-block-navigation a:hover { color: var(--primary); }
.site-footer .legal {
	border-top: 1px solid var(--rule);
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	font-family: var(--sans);
	font-size: 0.8125rem;
	color: var(--muted);
	margin-bottom: 0;
}

/* ============================================================
   TYPE UTILITIES
   .kicker — the accent eyebrow above section headings. Its job is
   to tell you what kind of thing follows, so keep it to 1-3 words.
   ============================================================ */
.kicker {
	font-family: var(--sans);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--accent-text);
	margin-block: 0 0.85rem;
}
.kicker-primary { color: var(--primary-light); }

.lede {
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.55;
	color: var(--body);
	max-width: 46ch;
}
/* WordPress stamps `margin-left/right: auto !important` on every direct child
   of a constrained group, so anything with a narrower max-width gets centred
   away from its siblings' left edge. These are meant to sit flush left.

   Note this pins to the PARENT's left edge — which is only correct when the
   parent's box matches the column its siblings occupy. Where it does not,
   wrap the group in a default-layout group (see .archive-head) rather than
   widening this rule. */
.hero h1,
.lede {
	margin-inline: 0 auto !important;
}

.archive-head { margin-bottom: 0; }
.archive-head > *:first-child { margin-top: 0; }
.meta {
	font-family: var(--sans);
	font-size: 0.8125rem;
	letter-spacing: 0.04em;
	color: var(--muted);
	margin-block: 0 0.65rem;
}

/* ============================================================
   BANDS — vertical rhythm
   ============================================================ */
.band       { padding-block: var(--wp--preset--spacing--70); }
.band-tight { padding-block: var(--wp--preset--spacing--60); }
.band-flush { padding-top: 0; }
.band-rule  { border-top: 1px solid var(--rule); }

/* ------------------------------------------------------------
   FULL-BLEED BANDS

   Any band carrying a background is always meant to reach the
   viewport edges, so this is unconditional rather than something
   you set per-block in the editor.

   WordPress's own `alignfull` escape only fires when the block is
   a direct child of the element holding the root padding. On the
   front page these sit two levels deep, inside both `main` and
   `post-content`, so that selector never matches and the band
   collapses back to content width. The viewport-margin technique
   below works from any nesting depth.
   ------------------------------------------------------------ */
.band-wash,
.band-primary {
	width: 100vw;
	max-width: 100vw;
	margin-inline: calc(50% - 50vw);
	padding-inline: clamp(1.25rem, 5vw, 2.5rem);
}

/* 100vw counts the scrollbar, which introduces a few pixels of
   horizontal overflow. `clip` rather than `hidden`: hidden would
   create a scroll container and break the sticky header. */
html { overflow-x: clip; }

.band-wash  { background: var(--wash); }
.band-primary  { background: var(--primary); color: #fff; }
.band-primary :is(h1,h2,h3,h4) { color: #fff; }
.band-primary p { color: rgba(255,255,255,.82); }

/* ============================================================
   HERO
   ============================================================ */
/* Top padding is deliberately lighter than the bottom. The header already
   contributes generous space above, so a full measure here pushes the first
   words a long way down the page before anyone has read anything. */
.hero { padding-block: clamp(2.25rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem); }
.hero h1 {
	font-size: var(--wp--preset--font-size--display);
	line-height: 1.02;
	letter-spacing: -0.028em;
	margin-block: 0 1.5rem;
	max-width: 16ch;
}
.hero .lede { margin-block: 0 2.25rem; }

/* Trust strip under the hero */
.trust-strip {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem 2.5rem;
	border-top: 1px solid var(--rule);
	padding-top: 1.5rem;
	margin-top: 3rem;
	font-family: var(--sans);
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--muted);
}

/* ============================================================
   PROCESS STEPS
   Numbered because the content genuinely is a sequence — the
   rules run in this order. Do not reuse for unordered lists.
   ============================================================ */
.process { display: grid; gap: 0; counter-reset: step; }
.process > * {
	counter-increment: step;
	border-top: 1px solid var(--rule);
	padding-block: 2rem;
	display: grid;
	grid-template-columns: 3.5rem 1fr;
	gap: 0 1.5rem;
	align-items: start;
	margin: 0;
}
.process > *:last-child { border-bottom: 1px solid var(--rule); }
.process > *::before {
	content: counter(step, decimal-leading-zero);
	font-family: var(--sans);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	color: var(--accent);
	padding-top: 0.4rem;
}
/* Every real child belongs in column two.
   Without this the ::before counter takes cell 1/1 and the h3 takes 1/2,
   which leaves the paragraph to wrap into 2/1 — a 3.5rem column. That is
   what produces one word per line. */
.process > * > * { grid-column: 2; }
.process h3 { margin-block: 0 0.5rem; }
.process p { margin: 0; color: var(--body); }

/* ============================================================
   STAT ROW
   ============================================================ */
.stat-row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: 1px;
	background: var(--rule);
	border: 1px solid var(--rule);
}
.stat-row > * { background: var(--paper); padding: 1.75rem 1.5rem; margin: 0; }
.stat-value {
	font-family: var(--sans);
	font-size: 2.25rem;
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--primary);
	font-variant-numeric: tabular-nums;
	margin-block: 0 0.4rem;
}
.stat-label {
	font-family: var(--sans);
	font-size: 0.75rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--muted);
	margin: 0;
}

/* ============================================================
   ARTICLE GRID — used by home, archive, search and the
   featured-articles pattern
   ============================================================ */
.article-grid.wp-block-post-template,
ul.article-grid {
	list-style: none;
	padding-left: 0;
	margin-block: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: 2.5rem 2rem;
}
.article-grid > li { margin: 0; padding-bottom: 2rem; border-bottom: 1px solid var(--rule); }
.article-grid > li > *:first-child { margin-top: 0; }
.article-grid .wp-block-post-title {
	font-size: 1.3125rem;
	line-height: 1.25;
	margin-block: 0 0.6rem;
}
.article-grid .wp-block-post-title a { color: var(--ink); text-decoration: none; }
.article-grid .wp-block-post-title a:hover { color: var(--primary); }
.article-grid .wp-block-post-date {
	font-family: var(--sans);
	font-size: 0.75rem;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--muted);
	margin-block: 0 0.7rem;
}
.article-grid .wp-block-post-excerpt__excerpt { font-size: 1rem; line-height: 1.6; color: var(--body); }
.article-grid .wp-block-post-excerpt__more-text a { font-family: var(--sans); font-size: 0.8125rem; font-weight: 600; }

/* ============================================================
   PROSE — long-form reading column
   ============================================================ */
.prose > * { margin-block: 1.6rem; }
.prose > :first-child { margin-top: 0; }
.prose h2 { margin-top: 3rem; }
.prose h3 { margin-top: 2.25rem; }
.prose a { color: var(--primary); text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
.prose a:hover { text-decoration-color: var(--primary); }
.prose blockquote {
	border-left: 3px solid var(--accent);
	padding-left: 1.5rem;
	margin-inline: 0;
	font-style: italic;
	color: var(--ink);
}
.prose ul, .prose ol { padding-left: 1.35rem; }
.prose li { margin-block: 0.5rem; }
.prose img { border: 1px solid var(--rule); }
.prose hr { border: 0; border-top: 1px solid var(--rule); margin-block: 3rem; }

/* ============================================================
   BUTTONS — outline variant
   ============================================================ */
.is-style-outline .wp-block-button__link,
.btn-outline .wp-block-button__link {
	background: transparent;
	color: var(--primary);
	border: 1px solid var(--primary);
}
.is-style-outline .wp-block-button__link:hover,
.btn-outline .wp-block-button__link:hover { background: var(--primary); color: #fff; }

/* ============================================================
   PAGINATION / SEARCH / 404
   ============================================================ */
.wp-block-query-pagination {
	font-family: var(--sans);
	font-size: 0.875rem;
	margin-top: 3.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--rule);
}
.wp-block-query-pagination a { text-decoration: none; color: var(--primary); }
.wp-block-query-pagination .current { font-weight: 700; color: var(--ink); }

.wp-block-search__input {
	border: 1px solid var(--rule);
	border-radius: 2px;
	padding: 0.85rem 1rem;
	font-family: var(--sans);
	font-size: 1rem;
	background: var(--paper);
	color: var(--ink);
}
.wp-block-search__input:focus { border-color: var(--primary); outline: none; }
.wp-block-search__button { border-radius: 2px; }

.error-code {
	font-family: var(--sans);
	font-size: clamp(4rem, 12vw, 8rem);
	font-weight: 700;
	line-height: 1;
	color: var(--wash-alt);
	letter-spacing: -0.04em;
	margin-block: 0 1rem;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 700px) {
	header.wp-block-template-part { position: static; }
	.process > * { grid-template-columns: 1fr; gap: 0.5rem; }
	.process > *::before { padding-top: 0; }
}
@media (prefers-reduced-motion: reduce) {
	* { transition: none !important; animation: none !important; }
}

/* ============================================================
   POST FOOTER — conversion surfaces after the article
   Search traffic lands on posts, so this is where subscribing
   has to be possible. Order is deliberate: offer, then identity,
   then somewhere else to go.
   ============================================================ */
.post-cta {
	border: 1px solid var(--rule);
	border-left: 3px solid var(--accent);
	background: var(--wash);
	padding: 2rem 2rem 2.25rem;
	margin-top: 3.5rem;
}
.post-cta h2 { font-size: 1.5rem; margin-block: 0 0.5rem; }
.post-cta p  { margin-block: 0 1.5rem; font-size: 1.0625rem; }

.post-author {
	border-top: 1px solid var(--rule);
	margin-top: 3rem;
	padding-top: 2rem;
}
/* The label reuses .kicker so it matches "Related" directly below it —
   the post footer reads as one sequence rather than three loose blocks. */
.post-author .kicker { margin-block: 0 1.25rem; }
.post-author .wp-block-post-author { display: flex; gap: 1.25rem; align-items: flex-start; }
.post-author .wp-block-post-author__avatar { flex: none; line-height: 0; }
.post-author .wp-block-post-author__avatar img {
	width: 64px;
	height: 64px;
	border-radius: 50%;
	display: block;
}
.post-author .wp-block-post-author__name {
	font-family: var(--sans);
	font-weight: 700;
	font-size: 1rem;
	color: var(--ink);
}
.post-author .wp-block-post-author__bio {
	font-size: 1rem;
	line-height: 1.6;
	color: var(--body);
	margin-top: 0.35rem;
}

.related-wrap { border-top: 1px solid var(--rule); margin-top: 3.5rem; padding-top: 2.5rem; }
.related-wrap h2 { font-size: 1.75rem; margin-block: 0 2rem; }
.related.article-grid { gap: 2rem; }
.related h3 { font-size: 1.125rem; line-height: 1.3; margin-block: 0 0.5rem; }
.related h3 a { color: var(--ink); text-decoration: none; }
.related h3 a:hover { color: var(--primary); }
.related p:last-child { font-size: 0.9375rem; color: var(--body); margin: 0; }

/* Reading time sits in the meta row and needs separating from the terms */
.meta .wp-block-shortcode { margin: 0; }

/* Jump links land below the sticky header rather than behind it. */
:target { scroll-margin-top: 6rem; }

/* The admin bar is fixed at the top for logged-in users; offset so the
   sticky header tucks under it instead of behind it. */
.admin-bar header.wp-block-template-part { top: 32px; }
@media screen and (max-width: 782px) {
	.admin-bar header.wp-block-template-part { top: 46px; }
}

/* ============================================================
   READING PROGRESS
   Fixed to the very top, above the sticky header.
   ============================================================ */
.reading-progress {
	position: fixed;
	inset: 0 0 auto 0;
	height: 3px;
	z-index: 100;
	pointer-events: none;
	background: transparent;
}
.reading-progress span {
	display: block;
	height: 100%;
	width: 0;
	background: var(--accent);
	transition: width .08s linear;
}
.admin-bar .reading-progress { top: 32px; }

/* ============================================================
   TABLE OF CONTENTS
   Ordered list because the sections have a reading order.
   ============================================================ */
.toc {
	border: 1px solid var(--rule);
	border-left: 3px solid var(--accent);
	background: var(--wash);
	padding: 1.5rem 1.75rem;
	margin-block: 2.5rem;
}
.toc-title {
	font-family: var(--sans);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--muted);
	margin-block: 0 1rem;
}
.toc ol { margin: 0; padding-left: 1.15rem; }
.toc li { margin-block: 0.45rem; font-size: 1rem; }
.toc li.toc-l3 { margin-left: 1rem; font-size: 0.9375rem; }
.toc a { color: var(--body); text-decoration: none; border-bottom: 1px solid transparent; }
.toc a:hover { color: var(--primary); border-bottom-color: var(--accent); }

/* ============================================================
   KEY TAKEAWAYS
   ============================================================ */
.takeaways {
	border: 1px solid var(--rule);
	border-left: 3px solid var(--accent);
	background: var(--wash);
	padding: 1.75rem 2rem;
	margin-block: 2.5rem;
}
.takeaways ul { margin: 0; padding-left: 1.15rem; }
.takeaways li { margin-block: 0.6rem; }
.takeaways li::marker { color: var(--accent-text); }

/* ============================================================
   CALLOUTS — block styles on core/group
   ============================================================ */
.wp-block-group.is-style-note,
.wp-block-group.is-style-warning,
.wp-block-group.is-style-changed {
	padding: 1.4rem 1.6rem;
	margin-block: 2rem;
	border-left: 3px solid;
	background: var(--wash);
}
.wp-block-group.is-style-note    { border-left-color: var(--primary-light); }
.wp-block-group.is-style-warning { border-left-color: #B4432F; background: #FDF6F4; }
.wp-block-group.is-style-changed { border-left-color: var(--accent); }

.callout-label {
	font-family: var(--sans);
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--muted);
	margin-block: 0 0.5rem;
}
.is-style-warning .callout-label { color: #B4432F; }
.is-style-changed .callout-label { color: var(--accent-text); }
.wp-block-group[class*="is-style-"] > p:last-child { margin-bottom: 0; }

/* ============================================================
   SIGNUP + CONTENT UPGRADE
   ============================================================ */
.optin-inline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem 1.5rem;
	border-block: 1px solid var(--rule);
	padding-block: 1.5rem;
	margin-block: 2.5rem;
}
.optin-text { margin: 0; flex: 1 1 18rem; font-size: 1.0625rem; }
.optin-inline .wp-block-buttons { margin: 0; }

.upgrade {
	border: 1px solid var(--primary);
	padding: 1.75rem 2rem 2rem;
	margin-block: 2.5rem;
}
.upgrade h3 { margin-block: 0 0.6rem; font-size: 1.25rem; }
.upgrade p { margin-block: 0 1.4rem; }

/* ============================================================
   FIGURES + DEFINITIONS
   ============================================================ */
.figure-block { margin-block: 2.5rem; }
.figure-block figure { margin: 0; }
.figure-block img { border: 1px solid var(--rule); }
.figure-block figcaption {
	font-family: var(--sans);
	font-size: 0.875rem;
	color: var(--body);
	margin-top: 0.75rem;
}
.figure-source {
	font-family: var(--sans);
	font-size: 0.75rem;
	letter-spacing: 0.04em;
	color: var(--muted);
	margin-block: 0.35rem 0;
}

.definition {
	border-top: 1px solid var(--rule);
	border-bottom: 1px solid var(--rule);
	padding-block: 1.25rem;
	margin-block: 2.25rem;
}
.definition-term {
	font-family: var(--sans);
	font-size: 0.9375rem;
	font-weight: 700;
	color: var(--ink);
	margin-block: 0 0.4rem;
}
.definition p:last-child { margin-bottom: 0; font-size: 1rem; }

/* ============================================================
   PREVIOUS / NEXT POST
   ============================================================ */
.post-nav {
	border-top: 1px solid var(--rule);
	margin-top: 3rem;
	padding-top: 1.75rem;
	gap: 1.5rem;
}
.post-nav .wp-block-post-navigation-link {
	font-family: var(--sans);
	font-size: 0.9375rem;
	max-width: 22rem;
}
.post-nav .wp-block-post-navigation-link a { color: var(--primary); text-decoration: none; }
.post-nav .wp-block-post-navigation-link a:hover { color: var(--accent); }
.post-nav .post-navigation-link-next { text-align: right; }

@media (max-width: 700px) {
	.post-nav { flex-direction: column; }
	.post-nav .post-navigation-link-next { text-align: left; }
}

/* ============================================================
   CONTACT
   ============================================================ */
.contact-split {
	border: 1px solid var(--rule);
	padding: clamp(1.75rem, 4vw, 3rem);
	margin-block: 2rem;
}
.contact-info { background: var(--wash); padding: clamp(1.5rem, 3vw, 2.25rem); }
.contact-info h2 { margin-block: 0 0.75rem; }
.contact-details { list-style: none; margin: 2rem 0 0; padding: 0; }
.contact-details li {
	font-family: var(--sans);
	font-size: 0.9375rem;
	line-height: 1.5;
	padding-block: 0.85rem;
	border-top: 1px solid var(--rule);
}
.contact-details strong {
	display: block;
	font-size: 0.6875rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--muted);
	margin-bottom: 0.25rem;
}
.contact-form .form-slot {
	border: 1px dashed var(--rule);
	padding: 1.5rem;
	font-family: var(--sans);
	font-size: 0.875rem;
	color: var(--muted);
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form input[type="tel"],
.contact-form textarea {
	width: 100%;
	border: 1px solid var(--rule);
	border-radius: 2px;
	padding: 0.75rem 0.9rem;
	font-family: var(--sans);
	font-size: 1rem;
	background: var(--paper);
	color: var(--ink);
}
.contact-form input:focus,
.contact-form textarea:focus { border-color: var(--primary); outline: none; }
.contact-form label {
	font-family: var(--sans);
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--ink);
}

/* ============================================================
   SINGLE POST — head and two column body

   Content column first in the markup, rail second, so the rail
   sits right. Content-first reads better and degrades correctly
   when the columns stack on mobile.
   ============================================================ */
.post-head { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.post-head .wp-block-post-title { margin-block: 0.75rem; }
.post-head .wp-block-post-featured-image { width: 100%; margin: 0; }
.post-head .wp-block-post-featured-image img {
	width: 100%;
	max-width: 100%;
	display: block;
	border: 1px solid var(--rule);
}

/* align-items matters more than it looks: columns are flex, and the default
   align-self of stretch makes each column full height, which silently
   disables position:sticky on everything inside the rail. */
.post-layout { gap: clamp(2rem, 5vw, 4.5rem); align-items: flex-start; }

.post-rail {
	position: sticky;
	top: 6rem;
	align-self: flex-start;
	font-family: var(--sans);
	font-size: 0.9375rem;
}
.admin-bar .post-rail { top: 8rem; }

.rail-block { border-top: 1px solid var(--rule); padding-top: 1rem; margin-bottom: 1.75rem; }

.rail-optin p { font-size: 0.875rem; color: var(--body); margin-block: 0 1rem; }
.rail-optin .wp-block-button__link { font-size: 0.75rem; padding: 0.7rem 1.1rem; }

/* In the rail the contents list drops its own box — it is already inside one */
.post-rail .toc {
	border: 0;
	border-top: 1px solid var(--rule);
	background: transparent;
	padding: 1rem 0 0;
	margin-block: 0 1.75rem;
}
.post-rail .toc ol { padding-left: 1rem; }
.post-rail .toc li { font-size: 0.875rem; margin-block: 0.4rem; }

/* Everything after the article returns to the reading column so the closing
   blocks line up with the prose rather than the full 1180px shell. */
.post-foot { margin-top: clamp(3rem, 6vw, 5rem); }

@media (max-width: 900px) {
	.post-layout { display: block; }
	.post-rail { position: static; margin-top: 3rem; }
	.post-rail .toc {
		border: 1px solid var(--rule);
		border-left: 3px solid var(--accent);
		background: var(--wash);
		padding: 1.5rem 1.75rem;
	}
}

/* ------------------------------------------------------------
   ONE LEFT EDGE

   Constrained layout centres every child that has a narrower
   max-width. In the two-column body that pushes the prose away
   from the column's left edge, and the closing blocks away from
   both — three different left edges down one page.

   Pinning them left lines the masthead, the article and the
   footer blocks up on a single axis. WordPress writes its own
   auto margins with !important, so matching it is the only way
   to win. Wide and full alignments are excluded so images can
   still break out of the measure.
   ------------------------------------------------------------ */
.post-layout .wp-block-post-content > *:not(.alignwide):not(.alignfull):not(.alignleft):not(.alignright),
.post-foot > *:not(.alignwide):not(.alignfull) {
	margin-inline: 0 auto !important;
}

/* ------------------------------------------------------------
   MASTHEAD RULE
   One hairline under the title block, spanning wider than the
   prose, so the header reads as a masthead rather than a
   paragraph break. Applied to posts and pages alike so the two
   feel like the same site.
   ------------------------------------------------------------ */
.post-head {
	border-bottom: 1px solid var(--rule);
	padding-bottom: clamp(2rem, 4vw, 3.5rem);
}
.page-head {
	border-bottom: 1px solid var(--rule);
	padding-bottom: clamp(1.25rem, 3vw, 2rem);
	margin-bottom: clamp(2rem, 4vw, 3rem) !important;
}

/* ------------------------------------------------------------
   MOBILE ORDER

   Stacked, the rail moves above the article as a single unit —
   byline, contents list, then signup. The byline before the
   piece is normal editorial practice, and it matters more on
   analysis than on general writing.

   The rail keeps its own box here rather than being dissolved
   with display:contents, because ordering it as one element is
   simpler and its internal order already matches the desktop
   column.
   ------------------------------------------------------------ */
@media (max-width: 900px) {
	.post-layout {
		display: flex;
		flex-direction: column;
		gap: 0;
	}

	.post-rail {
		position: static;
		order: -1;
		margin-bottom: clamp(2.5rem, 6vw, 3.5rem);
	}

	.post-rail .rail-block { margin-bottom: 1.5rem; }

	/* The rail signup earns its place on desktop by being sticky —
	   visible for the whole scroll, catching readers who never reach
	   the end. Stacked it loses that, and becomes the same ask the
	   end-of-post CTA already makes a moment later. Byline and
	   contents stay: those help someone decide whether to read. */
	.post-rail .rail-optin { display: none; }

	/* Boxed again once it is in the flow — in the desktop rail it
	   sits inside an existing column, so it drops its own frame. */
	.post-rail .toc {
		border: 1px solid var(--rule);
		border-left: 3px solid var(--accent);
		background: var(--wash);
		padding: 1.5rem 1.75rem;
		margin-block: 0 1.5rem;
	}
	.post-rail .toc li { font-size: 0.9375rem; }
}

/* ============================================================
   FEATURED IMAGE FALLBACK

   The post masthead puts the image beside the title. Without
   one, the right column renders empty and the title sits in a
   half-width box for no reason. Collapse to full width instead.
   ============================================================ */
.post-head:not(:has(.wp-block-post-featured-image img)) .wp-block-column {
	flex-basis: 100% !important;
}
.post-head:not(:has(.wp-block-post-featured-image img)) .wp-block-post-title {
	max-width: 20ch;
}

/* ============================================================
   CORE BLOCK LIBRARY

   Anything a writer can reach for from the inserter needs to
   look deliberate, not just the blocks the templates happen to
   use. This is most of what separates a finished theme from a
   set of templates.
   ============================================================ */

/* Tables — tabular figures, hairline rules, no zebra striping */
.wp-block-table { margin-block: 2.5rem; }
.wp-block-table table {
	border-collapse: collapse;
	width: 100%;
	font-family: var(--sans);
	font-size: 0.9375rem;
	font-variant-numeric: tabular-nums;
}
.wp-block-table th,
.wp-block-table td {
	border-bottom: 1px solid var(--rule);
	padding: 0.75rem 1rem 0.75rem 0;
	text-align: left;
	vertical-align: top;
}
.wp-block-table th {
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--muted);
	border-bottom-color: var(--ink);
}
.wp-block-table tbody tr:last-child td { border-bottom-color: var(--ink); }
.wp-block-table figcaption {
	font-family: var(--sans);
	font-size: 0.8125rem;
	color: var(--muted);
	margin-top: 0.75rem;
}
.wp-block-table.is-style-stripes tbody tr:nth-child(odd) { background: var(--wash); }

/* Pull quote — the one place type gets to be large and quiet */
.wp-block-pullquote {
	border-block: 1px solid var(--rule);
	padding-block: 2.25rem;
	margin-block: 3rem;
	text-align: left;
}
.wp-block-pullquote blockquote { margin: 0; border: 0; padding: 0; font-style: normal; }
.wp-block-pullquote p {
	font-family: var(--serif);
	font-size: clamp(1.25rem, 1rem + 1.2vw, 1.75rem);
	line-height: 1.35;
	letter-spacing: -0.015em;
	color: var(--ink);
	margin: 0;
}
.wp-block-pullquote cite {
	display: block;
	margin-top: 1rem;
	font-family: var(--sans);
	font-size: 0.8125rem;
	font-style: normal;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--muted);
}

/* Details — the accordion behind FAQ sections */
.wp-block-details {
	border-top: 1px solid var(--rule);
	padding-block: 1.25rem;
	margin-block: 0;
}
.wp-block-details:last-of-type { border-bottom: 1px solid var(--rule); }
.wp-block-details summary {
	font-family: var(--sans);
	font-weight: 600;
	font-size: 1.0625rem;
	color: var(--ink);
	cursor: pointer;
	list-style: none;
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	align-items: baseline;
}
.wp-block-details summary::-webkit-details-marker { display: none; }
.wp-block-details summary::after {
	content: '+';
	font-family: var(--sans);
	font-weight: 400;
	font-size: 1.25rem;
	color: var(--accent);
	line-height: 1;
}
.wp-block-details[open] summary::after { content: '–'; }
.wp-block-details > *:not(summary) { margin-top: 1rem; font-size: 1rem; }

/* Cover, gallery, media-text, file */
.wp-block-cover { margin-block: 2.5rem; }
.wp-block-cover .wp-block-cover__inner-container :is(h1,h2,h3,p) { color: #fff; }
.wp-block-gallery { margin-block: 2.5rem; }
.wp-block-gallery figcaption {
	font-family: var(--sans);
	font-size: 0.8125rem;
	color: var(--muted);
}
.wp-block-media-text { margin-block: 2.5rem; }
.wp-block-file {
	border: 1px solid var(--rule);
	border-left: 3px solid var(--accent);
	padding: 1rem 1.25rem;
	font-family: var(--sans);
	font-size: 0.9375rem;
	margin-block: 2rem;
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	align-items: center;
	justify-content: space-between;
}

/* Code and preformatted */
.wp-block-code,
.wp-block-preformatted {
	background: var(--wash);
	border: 1px solid var(--rule);
	padding: 1.25rem 1.5rem;
	font-size: 0.875rem;
	line-height: 1.6;
	overflow-x: auto;
	margin-block: 2rem;
}
.prose :not(pre) > code {
	background: var(--wash-alt);
	padding: 0.1em 0.4em;
	font-size: 0.9em;
	border-radius: 2px;
}

/* Embeds stay inside the measure and keep their aspect ratio */
.wp-block-embed { margin-block: 2.5rem; }
.wp-block-embed figcaption {
	font-family: var(--sans);
	font-size: 0.8125rem;
	color: var(--muted);
	margin-top: 0.75rem;
}

/* Captions everywhere */
.wp-element-caption,
figcaption {
	font-family: var(--sans);
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--muted);
}

/* ============================================================
   COMMENTS
   Rendered only when discussion is open on a post, but a theme
   that shows nothing when a user enables them is broken.
   ============================================================ */
.wp-block-comments { border-top: 1px solid var(--rule); margin-top: 3.5rem; padding-top: 2.5rem; }
.wp-block-comments-title { font-size: 1.5rem; margin-block: 0 2rem; }
.wp-block-comment-template li { border-bottom: 1px solid var(--rule); padding-block: 1.5rem; }
.wp-block-comment-author-name { font-family: var(--sans); font-weight: 600; color: var(--ink); }
.wp-block-comment-date { font-family: var(--sans); font-size: 0.8125rem; color: var(--muted); }
.wp-block-comment-content { margin-block: 0.75rem; }
.wp-block-comment-reply-link { font-family: var(--sans); font-size: 0.8125rem; }
.wp-block-post-comments-form { margin-top: 2.5rem; }
.wp-block-post-comments-form label { font-family: var(--sans); font-size: 0.8125rem; font-weight: 600; }
.wp-block-post-comments-form :is(input[type="text"],input[type="email"],input[type="url"],textarea) {
	width: 100%;
	border: 1px solid var(--rule);
	border-radius: 2px;
	padding: 0.7rem 0.9rem;
	font-family: var(--sans);
	font-size: 1rem;
	background: var(--paper);
	color: var(--ink);
}
.wp-block-post-comments-form :is(input,textarea):focus { border-color: var(--primary); outline: none; }

/* ============================================================
   PRINT
   Research gets printed and saved as PDF. Strip the furniture,
   keep the argument, and expose link targets.
   ============================================================ */
@media print {
	.site-header,
	.site-footer,
	.reading-progress,
	.post-nav,
	.post-cta,
	.rail-optin,
	.optin-inline,
	.upgrade,
	.related-wrap,
	.wp-block-comments,
	.wp-block-query-pagination { display: none !important; }

	body { background: #fff; color: #000; font-size: 11pt; }
	.post-layout { display: block !important; }
	.post-rail { position: static !important; }
	a { text-decoration: underline; }
	.prose a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: 9pt;
		word-break: break-all;
	}
	:is(h1,h2,h3) { break-after: avoid; }
	figure, .wp-block-table, .takeaways { break-inside: avoid; }
}

.faq-block { margin-block: 2.5rem; }
.faq-block h2 { margin-block: 0 1.5rem; }

/* ============================================================
   SOCIAL PROOF + START HERE
   ============================================================ */
.proof-row { margin-top: 2.5rem; gap: 2.5rem; }
.proof-quote {
	font-family: var(--serif);
	font-size: 1.125rem;
	line-height: 1.5;
	color: var(--ink);
	border-left: 2px solid var(--accent);
	padding-left: 1.25rem;
	margin-block: 0 1rem;
}
.proof-cite {
	font-family: var(--sans);
	font-size: 0.8125rem;
	letter-spacing: 0.04em;
	color: var(--muted);
	padding-left: 1.25rem;
	margin: 0;
}

.start-here h2 { margin-block: 0 2.5rem; }
.start-num {
	font-family: var(--sans);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	color: var(--accent-text);
	margin-block: 0 0.75rem;
	padding-bottom: 0.75rem;
	border-bottom: 1px solid var(--rule);
}
.start-here h3 { font-size: 1.1875rem; line-height: 1.3; margin-block: 0 0.6rem; }
.start-here h3 a { color: var(--ink); text-decoration: none; }
.start-here h3 a:hover { color: var(--primary); text-decoration: underline; text-decoration-color: var(--accent); }
.start-here p { font-size: 1rem; color: var(--body); }

/* 404 recent-posts block sits closer than a normal related section */
.error-code + h1 { margin-top: 0; }

/* Image variations */
.wp-block-image.is-style-framed img { border: 1px solid var(--rule); padding: 0.5rem; background: var(--paper); }
.wp-block-image.is-style-plain img { border: 0; }

/* ============================================================
   LANDING PAGE

   The template pairs these with header-minimal and footer-minimal,
   which carry no navigation. A page whose only job is one action
   should not offer eleven ways to leave.
   ============================================================ */
.site-header-minimal { padding-block: 1.5rem; }
.site-footer-minimal {
	background: transparent;
	border-top: 1px solid var(--rule);
	margin-top: clamp(3rem, 6vw, 5rem);
	padding-block: 2rem;
}
.site-footer-minimal .legal { border: 0; margin: 0; padding: 0; }

.landing-hero { padding-block: clamp(3.5rem, 8vw, 6rem) 0; }
.landing-hero h1 {
	font-size: var(--wp--preset--font-size--display);
	line-height: 1.04;
	letter-spacing: -0.028em;
	margin-block: 0.75rem 1.5rem;
	max-width: 18ch;
}

.landing-form { margin-block: 2.5rem 0; }
.form-note {
	font-family: var(--sans);
	font-size: 0.8125rem;
	color: var(--muted);
	margin-block: 0.85rem 0;
}
.band-primary .form-slot { border-color: rgba(255,255,255,.35); color: rgba(255,255,255,.8); }

.benefit-list { margin-top: 1.75rem; padding-left: 1.15rem; }
.benefit-list li { margin-block: 0.9rem; }
.benefit-list li::marker { color: var(--accent-text); }
.benefit-list strong { color: var(--ink); }
.band-wash .benefit-list strong { color: var(--ink); }

/* ------------------------------------------------------------
   POST DECK

   The excerpt under a post title is a summary of the piece, not
   its opening paragraph. Italic serif is the newspaper standfirst
   convention and separates it from the body without changing size
   or weight.

   Scoped to .post-head so archive card excerpts and the hero lede
   are unaffected — those are doing different jobs.
   ------------------------------------------------------------ */
.post-head .wp-block-post-excerpt,
.post-head .wp-block-post-excerpt__excerpt {
	font-style: italic;
	color: var(--muted);
}
.post-head .wp-block-post-excerpt__excerpt { margin-block: 0; }

/* ============================================================
   SIGNUP FORM

   Markup comes from the Broadsheet Signup for Sender plugin;
   every line of styling lives here.

   Values are taken from the theme's own controls rather than
   approximated: the button matches theme.json's button element
   exactly, and the input matches the search and comment fields,
   so a signup form reads as part of the site rather than a
   component bolted onto it.
   ============================================================ */
.bs-signup { margin-block: 1.5rem 0; }
.bs-signup__row { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* A placeholder is not a label. */
.bs-signup__label {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Input and button share vertical padding and line-height so they end up
   the same height — browsers give inputs and buttons different intrinsic
   line boxes, and matching them is the difference between a form that
   looks designed and one that looks assembled. */
.bs-signup__input,
.bs-signup__button {
	font-family: var(--sans);
	line-height: 1.4;
	padding-block: 0.5rem;
	border-radius: 2px;
	border: 1px solid;
	margin: 0;
	/* Both controls pinned to the same height so they line up exactly —
	   a button's intrinsic line box differs from an input's, so left to
	   themselves they land a couple of pixels apart.
	   42px on pointer devices; touch gets the 44px minimum below. */
	min-height: 42px;
}
.bs-signup__button { font-size: 0.9375rem; }

/* 16px is not a design choice — iOS Safari zooms the viewport when a focused
   input is set below it, and does not zoom back out. Anything under 1rem here
   makes the page lurch the moment someone taps the field on an iPhone. */
.bs-signup__input { font-size: 1rem; }

.bs-signup__input {
	flex: 1 1 13rem;
	min-width: 0;
	padding-inline: 0.95rem;
	border-color: var(--rule);
	background: var(--paper);
	color: var(--ink);
	transition: border-color .15s ease;
}
.bs-signup__input::placeholder { color: var(--muted); opacity: 1; }
.bs-signup__input:hover { border-color: var(--primary-light); }
/* Border shift only — the outline is left to the global :focus-visible rule,
   so keyboard users keep a visible ring. */
.bs-signup__input:focus { border-color: var(--primary); }

.bs-signup__button {
	flex: 0 0 auto;
	padding-inline: 1.5rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	border-color: var(--primary);
	background: var(--primary);
	color: #fff;
	cursor: pointer;
	transition: background .15s ease, border-color .15s ease;
}
.bs-signup__button:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.bs-signup__button:disabled { opacity: .55; cursor: default; }

/* Same treatment as figure sources and other small print */
.bs-signup__note {
	font-family: var(--sans);
	font-size: 0.75rem;
	letter-spacing: 0.02em;
	line-height: 1.5;
	color: var(--muted);
	margin-block: 0.75rem 0;
}

/* Collapsed until there is something to announce, so it never reserves space */
.bs-signup__message {
	font-family: var(--sans);
	font-size: 0.875rem;
	line-height: 1.5;
	margin-block: 0.75rem 0;
	padding-left: 0.75rem;
	border-left: 2px solid transparent;
}
.bs-signup__message:empty { display: none; }
.is-success .bs-signup__message,
.bs-signup__message.is-success { color: #2E6B4F; border-left-color: #2E6B4F; }
.is-error .bs-signup__message,
.bs-signup__message.is-error { color: #B4432F; border-left-color: #B4432F; }
.is-busy .bs-signup__button { opacity: .55; }

/* ------------------------------------------------------------
   STACKED — the 260px rail, and anywhere layout="stacked"

   Resetting flex here is not optional: flex-basis follows the
   MAIN axis, so the input's `flex: 1 1 13rem` — a minimum width
   in a row — becomes a 208px minimum HEIGHT once the direction
   flips to column.
   ------------------------------------------------------------ */
.bs-signup--stacked .bs-signup__row,
.post-rail .bs-signup__row {
	flex-direction: column;
	gap: 0.5rem;
}
/* The field takes the full width because it needs the room. The button does
   not — a stacked pair of full-width blocks reads as heavy and generic, and
   a button sized to its own label looks considered. align-self is what stops
   a column flex container stretching it. */
.bs-signup--stacked .bs-signup__input,
.post-rail .bs-signup__input {
	flex: 0 0 auto;
	width: 100%;
}
.bs-signup--stacked .bs-signup__button,
.post-rail .bs-signup__button,
.site-footer .bs-signup__button {
	flex: 0 0 auto;
	width: auto;
	align-self: flex-start;
	padding-inline: 1.75rem;
}
.post-rail .bs-signup { margin-top: 1rem; }
/* Rail runs a touch smaller, but the input holds at 1rem for the same iOS
   reason and both keep a usable target height. */
.post-rail .bs-signup__button { font-size: 0.875rem; }
.post-rail .bs-signup__input,
.post-rail .bs-signup__button { padding-block: 0.7rem; min-height: 44px; }
.post-rail .bs-signup__note { font-size: 0.6875rem; }

/* ------------------------------------------------------------
   CONTEXTS
   ------------------------------------------------------------ */

/* On the wash — post CTA, footer — the field keeps paper behind it
   so it still reads as an input rather than a panel. */
.band-wash .bs-signup__input,
.post-cta .bs-signup__input,
.site-footer .bs-signup__input { background: var(--paper); }

/* On the closing navy band the accent carries the action */
.band-primary .bs-signup__input { border-color: transparent; }
.band-primary .bs-signup__button {
	background: var(--accent);
	border-color: var(--accent);
	color: #16202E;
}
.band-primary .bs-signup__button:hover {
	background: var(--accent-light);
	border-color: var(--accent-light);
}
.band-primary .bs-signup__note { color: rgba(255,255,255,.72); }
.band-primary .is-success .bs-signup__message,
.band-primary .is-error .bs-signup__message { color: #fff; border-left-color: rgba(255,255,255,.6); }

/* The footer column is around 300px at every breakpoint, so an inline row
   always wraps and leaves the button at its natural width. Stack it outright
   instead of waiting for a media query that never helps. */
.site-footer .bs-signup__row { flex-direction: column; gap: 0.5rem; }
.site-footer .bs-signup__input { flex: 0 0 auto; width: 100%; }

/* Fallback rendered by the theme when the plugin is inactive, so a missing
   plugin degrades to the old link rather than printing shortcode text. */
.bs-signup__fallback { margin-block: 1rem 0; }
.bs-signup__fallback .bs-signup__button {
	display: inline-block;
	width: auto;
	text-decoration: none;
}

/* The form emits only visible elements — every value the request needs rides
   on the form's own data attributes — so it needs no defensive resets. Its
   spacing is set here and nowhere else. */
.bs-signup { margin-block: 1.25rem 0; }
.post-rail .bs-signup { margin-block: 0.9rem 0; }
/* Deliberately no display rule on <noscript>: the browser hides it while
   scripting is on, and overriding that puts an invisible block back into the
   flow. Only style what is inside it, which renders solely when JS is off. */
.bs-signup noscript .bs-signup__button { display: inline-block; text-decoration: none; }

/* ------------------------------------------------------------
   NARROW SCREENS

   An inline row needs roughly 350px before the field and button
   sit comfortably side by side. Below that the row wraps and
   leaves the button stranded, so stack it deliberately instead.
   ------------------------------------------------------------ */
@media (max-width: 560px) {
	/* Touch targets want 44px; a mouse does not. */
	.bs-signup__input,
	.bs-signup__button { min-height: 44px; padding-block: 0.6rem; }

	.bs-signup__row { flex-direction: column; gap: 0.5rem; }
	.bs-signup__input { flex: 0 0 auto; width: 100%; }
	.bs-signup__button {
		flex: 0 0 auto;
		width: auto;
		align-self: flex-start;
		padding-inline: 1.75rem;
	}
}
