/*
Theme Name:  Coleman Digital — Yield Safeguard
Theme URI:   https://colemandigital.com/
Author:      Coleman Digital LLC
Description: Child theme of Twenty Twenty-Four carrying the Yield Safeguard identity: black, Archivo, orange accent, hard edges, no rounded corners anywhere.
Template:    twentytwentyfour
Version:     0.11.9
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 8.1
License:     GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: colemandigital-ys

═══════════════════════════════════════════════════════════════════════
  ⚠  DESIGN TOKENS LIVE IN theme.json — NOT IN SITE EDITOR → STYLES
═══════════════════════════════════════════════════════════════════════

  Anything saved through Appearance → Editor → Styles is written to the
  DATABASE (as a wp_global_styles post) and SILENTLY OVERRIDES this
  theme's theme.json.

  If you change a color or font in theme.json and nothing happens on the
  front end, this is why. It is the single most common cause.

  To clear the database layer:
      Appearance → Editor → Styles → ⋮ (three dots) → Reset to defaults

  Rule: change design tokens in theme.json. Never in the Styles panel.

═══════════════════════════════════════════════════════════════════════
*/

/* ---------------------------------------------------------------
   Fonts are declared in theme.json (settings.typography.fontFamilies)
   and self-hosted from assets/fonts/. They are deliberately NOT
   loaded from fonts.googleapis.com: hotlinking Google Fonts sends
   every visitor's IP to Google, which contradicts this site's own
   privacy policy and adds a third party for no benefit.
   --------------------------------------------------------------- */

/* ---------- global hard-edge rule ---------- */
/* The design has no rounded corners anywhere. This is deliberate and
   sitewide, so it is asserted once here rather than per component. */
.wp-block-button__link,
.wp-block-search__button,
.wp-block-image img,
input,
textarea,
select,
button {
	border-radius: 0 !important;
}

/* ---------- sticky header ---------- */
.ys-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: var(--wp--preset--color--contrast);
	color: #fff;
	padding: 16px clamp(22px, 5vw, 40px);
	display: flex;
	align-items: center;
	gap: 28px;
}

.ys-header a {
	text-decoration: none;
}

/* WordPress's block-gap spacing (its automatic "space out stacked
   children" rule, meant for flow content) still fires on this block
   even though it's a flex row via our own CSS — it applies margin-top
   to every child except the first, based on the block's own type, with
   no awareness we changed the layout. That leftover margin was the
   real cause of the header's vertical misalignment, confirmed via
   direct measurement, not the flex-centering itself. Neutralize it
   here rather than let two unrelated layout systems keep fighting. */
.ys-header > * {
	margin-top: 0 !important;
}

.ys-header__brand {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-right: auto;
	color: #fff;
}

.ys-header__brand img {
	height: 42px;
	width: auto;
	display: block;
}

.ys-header__wordmark {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 800;
	font-size: 15px;
	line-height: 1;
	text-transform: uppercase;
	letter-spacing: -0.01em;
	color: #fff;
}

.ys-header__nav {
	display: flex;
	align-items: center;
	gap: 26px;
	/* Set here, not just on the link: the nav items are now Paragraph blocks,
	   and a <p> inheriting the header's larger body size builds a 24px line box
	   around a 13px link, dropping the text 1px below where the old bare <a>
	   flex items sat. Sizing the container keeps the <p> and its link on the
	   same metrics. */
	font-size: 13px;
}

.ys-header__nav a {
	color: rgba(255, 255, 255, 0.7);
	font-size: 13px;
	font-weight: 500;
	white-space: nowrap;
	transition: color 0.12s;
}

.ys-header__nav a:hover,
.ys-header__nav a:focus-visible {
	color: #fff;
}

/* Same wrapper problem as .ys-btnrow above: the core Button block puts a
   custom className on <div class="wp-block-button">, never on the inner <a>,
   so .ys-header__cta alone cannot reach it. Map the treatment onto the block's
   link as well, so the CTA renders identically whichever shape is used. */
.ys-header__cta,
.ys-header .wp-block-button__link {
	background: var(--wp--preset--color--accent);
	color: #fff;
	font-weight: 700;
	font-size: 12px;
	line-height: 1;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	padding: 10px 18px;
	white-space: nowrap;
	transition: background 0.12s;
}

.ys-header__cta:hover,
.ys-header__cta:focus-visible,
.ys-header .wp-block-button__link:hover,
.ys-header .wp-block-button__link:focus-visible {
	background: #e64a19;
	color: #fff;
}

/* Tablet/phone: nav links drop, brand + the one action remain.
   820px undershot this — at ~833px, brand + nav + button together
   genuinely don't fit (measured, not guessed: roughly 866px of content
   trying to fit in ~753px of available width after padding), so nav
   was still showing in a zone where the row was already too crowded,
   forcing the button to wrap with nothing on its line to align against.
   900px gives real margin above where the full row stops fitting. */
@media (max-width: 900px) {
	.ys-header__nav {
		display: none;
	}
}

/* Small phone: brand + wordmark + button stop fitting on one line
   well below where nav already hid. Rather than wrap (which needs a
   button to align against on its own line, and got complicated fast)
   the wordmark and button both drop together, leaving just the logo —
   one line, always, no wrap logic to maintain. 520px has real margin
   above the ~517px where brand+button alone stop fitting once nav is
   already gone. */
@media (max-width: 520px) {
	.ys-header__wordmark,
	.ys-header__cta,
	/* Scoped, not bare. The CTA is a core Buttons block now, and core ships
	   `body .is-layout-flex { display: flex }` — the body prefix makes that
	   (0,1,1), which outranks a bare .ys-header__ctarow at (0,1,0), so the
	   button simply refused to hide here. Descendant-scoping to
	   .ys-header .ys-header__ctarow reaches (0,2,0) and wins cleanly. */
	.ys-header .ys-header__ctarow {
		display: none;
	}
}

/* ---------- footer ---------- */
.ys-footer {
	background: var(--wp--preset--color--contrast);
	color: rgba(255, 255, 255, 0.62);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 12px;
	line-height: 1.7;
	padding: 28px clamp(22px, 5vw, 40px);
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 20px;
	flex-wrap: wrap;
}

.ys-footer a {
	color: rgba(255, 255, 255, 0.62);
	text-decoration: none;
	transition: color 0.12s;
}

.ys-footer a:hover,
.ys-footer a:focus-visible {
	color: #fff;
}

.ys-footer__tagline {
	display: block;
	color: var(--wp--preset--color--accent);
	margin-top: 4px;
}

.ys-footer__links {
	display: flex;
	gap: 22px;
	flex-wrap: wrap;
}

/* ---------- landing-page display typography ----------
   The full dramatic Yield Safeguard treatment — uppercase, black
   weight, tight tracking — is scoped to the landing page only, via
   the .ys-landing class functions.php applies to <body> when that
   template is active. Everywhere else (blog posts, ordinary pages)
   headings use theme.json's calmer sitewide default: permanent
   uppercase display type reads as shouting once it's a list of
   article titles instead of a single hero line. */
.ys-landing h1,
.ys-landing h2,
.ys-landing h3,
.ys-landing h4,
.ys-landing h5,
.ys-landing h6 {
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -0.035em;
	text-transform: uppercase;
}

.ys-landing h1 {
	font-size: var(--wp--preset--font-size--display);
	line-height: 0.93;
	letter-spacing: -0.045em;
}

/* ---------- accessibility ---------- */
/* Never remove the focus ring. Orange on black clears 3:1 as UI chrome. */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

/* Honeypot wrapper used by the contact form. Off-screen rather than
   display:none, because some spam tooling now skips display:none
   fields specifically. Paired with aria-hidden + tabindex="-1" in the
   markup so screen readers and keyboard users never reach it. */
.ys-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ═══════════════════════════════════════════════════════════════════
   Landing page (templates/page-yield-safeguard.html)
   Every value below is transcribed from the design handoff's own
   Yield Safeguard Site.dc.html, not re-derived — this is the one
   place in the theme where pixel fidelity to that source matters
   more than tidiness.
   ═══════════════════════════════════════════════════════════════════ */

/* ---------- shared type helpers ---------- */
.ys-eyebrow {
	display: block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 11px;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	margin-bottom: 18px;
}

.ys-kicker {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 11px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: rgba(13, 13, 13, 0.58);
}

.ys-kicker--accent {
	color: var(--wp--preset--color--accent);
	display: block;
	margin-bottom: 12px;
}

.ys-h2 {
	margin: 0 0 8px;
	font-size: 48px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.035em;
	line-height: 1;
}

.ys-h2--sm {
	margin-bottom: 18px;
	font-size: 44px;
}

.ys-h2--case {
	margin-bottom: 32px;
	letter-spacing: -0.04em;
	max-width: 20em;
}

.ys-h2--book {
	margin-bottom: 18px;
	font-size: 56px;
	letter-spacing: -0.04em;
	line-height: 0.98;
}

.ys-intro {
	margin: 0 0 40px;
	font-size: 17px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.65);
	max-width: 34em;
}

.ys-intro--dark {
	color: rgba(255, 255, 255, 0.55);
	max-width: 36em;
}

.ys-body {
	margin: 0 0 20px;
	font-size: 17px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.68);
	max-width: 32em;
}

.ys-lead {
	margin: 0;
	font-size: 20px;
	line-height: 1.55;
	color: rgba(13, 13, 13, 0.7);
	max-width: 31em;
}

.ys-lead--book {
	font-size: 18px;
	max-width: 30em;
}

/* ---------- buttons (landing-specific sizes) ---------- */
/* The core Button block puts a custom className on the wrapper
   <div class="wp-block-button">, never on the inner <a>, so .ys-btn alone
   cannot reach it. These selectors map the same treatment onto the block's
   link so a real, editable Button block renders identically to the old
   hand-written <a class="ys-btn ys-btn--primary">. (0,2,0) also clears
   theme.json's button element styles, which land at :root :where(...).
   Note this assumes buttons inside a .ys-btnrow are primary; the outline
   variant in single.html sits outside a btnrow, so there is no clash. */
.ys-btn,
.ys-btnrow .wp-block-button__link {
	display: inline-block;
	text-decoration: none;
	font-weight: 700;
	font-size: 15px;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	font-family: var(--wp--preset--font-family--body);
}

.ys-btn--primary,
.ys-btnrow .wp-block-button__link {
	background: var(--wp--preset--color--accent);
	color: #fff;
	padding: 17px 28px;
}

.ys-btn--primary:hover,
.ys-btn--primary:focus-visible,
.ys-btnrow .wp-block-button__link:hover,
.ys-btnrow .wp-block-button__link:focus-visible {
	background: #e64a19;
	color: #fff;
}

.ys-btn--outline {
	border: 2px solid var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
	padding: 15px 26px;
}

.ys-btnrow {
	display: flex;
	gap: 16px;
	flex-wrap: wrap;
}

.ys-btnrow--right {
	justify-content: flex-end;
}


/* ═══════════════════════════════════════════════════════════════════
   Block-gap armor
   ═══════════════════════════════════════════════════════════════════

   Required once landing-page sections are real blocks rather than one
   static wp:html island.

   WordPress emits, for any block with layout type default/flow:

       .wp-container-…-is-layout-<hash> > *     { margin-block-start: 0;
                                                  margin-block-end: 0 }
       .wp-container-…-is-layout-<hash> > * + * { margin-block-start: 1.2rem }

   That selector is a single generated class — specificity (0,1,0),
   exactly TIED with .ys-h2, .ys-intro, .ys-eyebrow and friends. Ties
   break on source order, and core's stored styles print after this
   stylesheet, so core wins every one of them. Left alone it flattens
   the bespoke vertical rhythm below into a uniform 19.2px.

   The 1.2rem itself is inherited from Twenty Twenty-Four's
   styles.spacing.blockGap; this child theme.json sets padding but never
   blockGap, and theme.json merges key-by-key, so the parent's value
   survives.

   Fix: repeat the class to reach (0,2,0) and win outright. No
   !important, and unlike the .ys-landing body class this works inside
   the editor iframe too, since the class travels with the block.

   ONLY vertical margins are listed. Core's rules are margin-block-*,
   so horizontal margins (.ys-headshot's margin-left:auto,
   .ys-header__brand's margin-right:auto) are not at risk — and must
   NOT be armored, since the 820px block legitimately overrides them at
   (0,1,0) and would lose.

   For the same reason this block sets margins only. .ys-h2--book's
   font-size is deliberately absent: the 820px block drops it to 40px
   and armoring it here would break that.

   PLACEMENT MATTERS — keep this block ABOVE the component sections.
   (0,2,0) beats core's (0,1,0) regardless of source order, so sitting
   early costs nothing. But two component rules are ALSO (0,2,0):
   .ys-step .ys-kicker--accent (10px) and .ys-caserow .ys-kicker--accent
   (7px). They need to win the tie on source order. Move this block
   below them and both silently become 12px. */

.ys-eyebrow.ys-eyebrow { margin-bottom: 18px; }
/* Colour is armored here too, not just margin. Converting a kicker from a
   <span> to a Paragraph block drops it into the scope of .ys-step p /
   .ys-threat p / .ys-caserow p, whose muted colour is (0,1,1) and so beats
   .ys-kicker--accent's orange at (0,1,0). Caught on staging in 0.7.0: the
   method step numbers 01-04 rendered grey instead of orange. Neither
   .ys-threat .ys-kicker--accent nor .ys-caserow .ys-kicker--accent sets a
   colour, so nothing legitimately overrides this. */
.ys-kicker--accent.ys-kicker--accent {
	color: var(--wp--preset--color--accent);
	margin-bottom: 12px;
}

.ys-display.ys-display { margin: 0 0 32px; }
.ys-h2.ys-h2 { margin: 0 0 8px; }
.ys-h2--sm.ys-h2--sm { margin-bottom: 18px; }
.ys-h2--case.ys-h2--case { margin-bottom: 32px; }
.ys-h2--book.ys-h2--book { margin-bottom: 18px; }

.ys-intro.ys-intro { margin: 0 0 40px; }
.ys-body.ys-body { margin: 0 0 20px; }
.ys-lead.ys-lead { margin: 0; }

.ys-hero__explainer.ys-hero__explainer { margin: 20px 0 0; }
.ys-stat__cap.ys-stat__cap { margin: 12px 0 0; }

.ys-domainbox__real.ys-domainbox__real { margin-bottom: 12px; }
.ys-domainbox__caught.ys-domainbox__caught { margin-bottom: 8px; }

.ys-formcard__title.ys-formcard__title { margin-bottom: 18px; }
.ys-formcard__note.ys-formcard__note { margin-top: 10px; }

.ys-footer__tagline.ys-footer__tagline { margin-top: 4px; }

/* ---------- hero ---------- */
.ys-hero {
	box-sizing: border-box;
	padding: 76px clamp(22px, 5vw, 40px) 60px;
	border-bottom: 3px solid var(--wp--preset--color--contrast);
}

.ys-display {
	margin: 0 0 32px;
	font-size: clamp(48px, 8vw, 96px);
	line-height: 0.93;
	letter-spacing: -0.045em;
	font-weight: 800;
	text-transform: uppercase;
}

.ys-display .line {
	display: block;
}

.ys-hero__row {
	align-items: end;
}

.ys-hero__cta-col {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
}

.ys-hero__explainer {
	margin: 20px 0 0;
	font-size: 20px;
	line-height: 1.55;
	color: rgba(13, 13, 13, 0.7);
	/* Left, not right — right-aligned running text (ragged-left) reads
	   awkwardly, and with only one button above it now, a wider
	   left-reading paragraph under a narrower right-flush button was
	   what actually looked like "button left, text right." The BOX
	   still lines up with the button via align-items:flex-end on the
	   parent column; only the text inside it reads normally now. */
	text-align: left;
	max-width: 32em;
}

.ys-hero__explainer strong {
	color: var(--wp--preset--color--contrast);
}

/* Headings inside dark sections must re-inherit the section's white.
   theme.json emits `h1,h2,h3,h4,h5,h6 { color: var(--contrast) }` as a BARE
   element rule, applied directly to the heading. .ys-dark sets color:#fff on
   the section and expects headings to inherit it, but a directly-applied
   rule beats an inherited value regardless of specificity, so the heading
   rendered ink-on-ink and was literally invisible. (0,1,1) here wins, and
   `inherit` means any future dark section works without another rule.
   Found 2026-09-02 by a contrast audit; it had been wrong since launch,
   because every earlier check measured geometry rather than legibility. */
.ys-dark h1,
.ys-dark h2,
.ys-dark h3,
.ys-dark h4,
.ys-dark h5,
.ys-dark h6 {
	color: inherit;
}

/* ---------- logo strip ---------- */
.ys-logos {
	box-sizing: border-box;
	padding: 20px clamp(22px, 5vw, 40px);
	background: var(--wp--preset--color--base-2);
	border-top: 1px solid rgba(13, 13, 13, 0.12);
	border-bottom: 1px solid rgba(13, 13, 13, 0.12);
	display: flex;
	align-items: center;
	gap: 30px;
	flex-wrap: wrap;
}

.ys-logos .ys-kicker {
	font-size: 11.5px;
	letter-spacing: 0.14em;
}

.ys-logos__row {
	display: flex;
	gap: 28px;
	flex-wrap: wrap;
	font-size: 14px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: rgba(13, 13, 13, 0.6);
}

/* ---------- stats bar ---------- */
.ys-stats {
	box-sizing: border-box;
	border-bottom: 3px solid var(--wp--preset--color--contrast);
}

.ys-stat {
	padding: 44px 32px;
	border-right: 1px solid rgba(13, 13, 13, 0.15);
}

.ys-stat:last-child {
	border-right: none;
}

.ys-stat__num {
	font-size: 58px;
	font-weight: 800;
	letter-spacing: -0.04em;
	color: var(--wp--preset--color--accent);
	line-height: 1;
}

.ys-stat__cap {
	margin: 12px 0 0;
	font-size: 15px;
	line-height: 1.55;
	color: rgba(13, 13, 13, 0.65);
	font-weight: 500;
}

/* ---------- section chrome ---------- */
.ys-pad {
	box-sizing: border-box;
	padding: 72px clamp(22px, 5vw, 40px);
}

.ys-dark {
	background: var(--wp--preset--color--contrast);
	color: #fff;
}

.ys-tint {
	background: var(--wp--preset--color--base-2);
}

.ys-rule-b {
	border-bottom: 3px solid var(--wp--preset--color--contrast);
}

/* ---------- grid utilities ----------
   minmax(0, 1fr), not bare 1fr — a bare 1fr track refuses to shrink
   below its content's natural width (default min-width:auto on grid
   items), so nowrap content like the hero buttons can push a column
   wider than its share and overflow the viewport instead of wrapping.
   minmax(0, 1fr) lets the track actually shrink to the 1fr share and
   forces the content to wrap within it instead. */
.ys-two {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 44px;
}

.ys-two--center {
	align-items: center;
}

.ys-two--top {
	align-items: start;
}

.ys-three {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ys-four {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 26px;
}

.ys-grid2 {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1px;
	background: rgba(255, 255, 255, 0.15);
}

/* ---------- threat cards ---------- */
.ys-threat {
	background: var(--wp--preset--color--contrast);
	padding: 30px;
}

.ys-threat p {
	margin: 0;
	font-size: 15.5px;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.66);
}

.ys-threat .ys-kicker--accent {
	font-size: 11px;
}

/* ---------- framed image (mechanic diagram) ---------- */
.ys-frame {
	border: 2px solid var(--wp--preset--color--contrast);
	background: #fff;
}

.ys-frame--pad {
	padding: 24px;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
}

.ys-frame img {
	max-width: 100%;
	height: auto;
	display: block;
}

/* Core's Image block wraps the <img> in <figure class="wp-block-image">,
   which ships margin: 0 0 1em. Inside .ys-frame--pad that figure is the
   flex item, so the 1em would sit below the image and break the frame's
   symmetric 24px padding. .ys-frame img above still matches through the
   figure (descendant selector), so only the wrapper needs neutralizing. */
.ys-frame .wp-block-image {
	margin: 0;
}

/* ---------- method steps ---------- */
.ys-step {
	border-top: 3px solid var(--wp--preset--color--contrast);
	padding-top: 18px;
}

.ys-step .ys-kicker--accent {
	font-size: 12px;
	margin-bottom: 10px;
}

.ys-step h3 {
	margin: 0 0 8px;
	font-size: 19px;
	font-weight: 700;
	text-transform: none;
	letter-spacing: normal;
}

.ys-step p {
	margin: 0;
	font-size: 14.5px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.65);
}

/* ---------- upside rows ---------- */
.ys-upside__row {
	border-top: 1px solid rgba(13, 13, 13, 0.2);
	padding: 20px 0;
}

.ys-upside__row--last {
	border-bottom: 1px solid rgba(13, 13, 13, 0.2);
}

.ys-upside__row h3 {
	margin: 0 0 6px;
	font-size: 18px;
	font-weight: 700;
	text-transform: none;
	letter-spacing: normal;
}

.ys-upside__row p {
	margin: 0;
	font-size: 15px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.65);
}

/* ---------- cases ---------- */
.ys-caserow {
	border-top: 1px solid rgba(13, 13, 13, 0.2);
	padding: 18px 0;
}

.ys-caserow--first {
	border-top: 3px solid var(--wp--preset--color--contrast);
}

.ys-caserow--last {
	border-bottom: 1px solid rgba(13, 13, 13, 0.2);
}

.ys-caserow .ys-kicker--accent {
	font-size: 11px;
	margin-bottom: 7px;
}

.ys-caserow p {
	margin: 0;
	font-size: 16px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.7);
}

.ys-domainbox {
	box-sizing: border-box;
	border: 3px solid var(--wp--preset--color--contrast);
	padding: 28px;
	background: #fff;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 12.5px;
	line-height: 1.5;
}

.ys-domainbox__cols {
	gap: 26px;
}

.ys-domainbox__real {
	display: flex;
	align-items: baseline;
	gap: 10px;
	border-bottom: 1px solid rgba(13, 13, 13, 0.2);
	padding-bottom: 10px;
	margin-bottom: 12px;
}

.ys-domainbox__real .ys-kicker {
	font-size: 11.5px;
	letter-spacing: 0.12em;
}

.ys-domainbox__realname {
	font-weight: 500;
}

.ys-domainbox__caught {
	font-size: 11.5px;
	letter-spacing: 0.12em;
	margin-bottom: 8px;
}

/* Now a core List block (<ul class="wp-block-list ys-domainbox__list">) so the
   evidence is maintainable in the editor, hence the list-chrome reset. The flex
   column and 5px gap work on the <ul> exactly as they did on the old <div>. */
.ys-domainbox__list {
	display: flex;
	flex-direction: column;
	gap: 5px;
	color: var(--wp--preset--color--accent-2);
	list-style: none;
	padding-left: 0;
	margin: 0;
}

.ys-domainbox__list li {
	text-decoration: line-through;
}

/* ---------- bio ---------- */
.ys-byline {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 12px;
	color: rgba(13, 13, 13, 0.55);
	line-height: 1.9;
}

.ys-byline a {
	color: inherit;
}

.ys-headshot {
	border: 2px solid var(--wp--preset--color--contrast);
	overflow: hidden;
	aspect-ratio: 1;
	max-width: 280px;
	margin-left: auto;
	box-sizing: border-box;
}

.ys-headshot img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 25%;
	display: block;
}

/* Core's Image block inserts <figure class="wp-block-image"> between
   .ys-headshot and the <img>, which breaks the square crop two ways: the
   figure is height:auto, so the img's height:100% resolves against it and
   collapses to nothing; and core ships .wp-block-image img { height: auto }
   at (0,1,1), tying with .ys-headshot img and winning on source order.
   Give the figure the full box, then re-assert the crop at (0,2,1). */
.ys-headshot .wp-block-image {
	display: block;
	height: 100%;
	margin: 0;
}

.ys-headshot .wp-block-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 25%;
}


/* ---------- book / contact form ---------- */
.ys-formcard {
	box-sizing: border-box;
	border: 3px solid var(--wp--preset--color--contrast);
	padding: 28px;
	background: #fff;
}

.ys-formcard__title {
	font-size: 12px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	margin-bottom: 18px;
}

.ys-formcard__note {
	font-size: 12.5px;
	color: rgba(13, 13, 13, 0.62);
	line-height: 1.5;
	margin-top: 10px;
}

/* Contact Form 7's real output, styled to match the spec.
   .wpcf7-form-control-wrap is CF7's own wrapper span. */
.ys-formcard .wpcf7-form {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

/* Turnstile auto-injects itself between the assent checkbox and the
   submit button — reorder it to sit AFTER submit instead, tight to
   the button that matters. The plugin sets its own inline
   margin-bottom (a negative value, its own attempt at tightening),
   so ours needs !important to actually win. */
.ys-formcard .wpcf7-form > p:has(.wpcf7-submit) {
	order: 1;
	margin-top: 2px;
}

.ys-formcard .cf7-cf-turnstile {
	order: 2;
	margin-top: 10px !important;
	margin-bottom: 0 !important;
}

/* CF7 emits a different shape depending on where the shortcode renders.
   From a template the submit button, its <br> and the spinner all arrive
   wrapped in one <p>, which the :has() rule above catches. From post_content
   they arrive as loose siblings: a bare <input>, a stray <br> and the spinner
   each becoming its own flex row, which added 54px and broke the grouping.
   These rules normalise the loose shape back to the wrapped one's layout, and
   are harmless when the wrapped shape is what renders. */
.ys-formcard .wpcf7-form > br {
	display: none;
}

.ys-formcard .wpcf7-form > p:empty {
	display: none;
}

.ys-formcard .wpcf7-form > input.wpcf7-submit {
	order: 1;
	margin-top: 2px;
}

/* The spinner is CF7's only "sending" cue, so keep it rather than hiding it,
   but let it take no vertical space until the form is actually submitting. */
.ys-formcard .wpcf7-form > .wpcf7-spinner {
	order: 1;
	height: 0;
	margin: 0;
	overflow: hidden;
}

.ys-formcard .wpcf7-form.submitting > .wpcf7-spinner {
	height: auto;
	margin-top: 8px;
}

.ys-formcard .wpcf7-form-control-wrap {
	display: block;
}

.ys-formcard input[type="text"].wpcf7-form-control,
.ys-formcard input[type="email"].wpcf7-form-control,
.ys-formcard textarea.wpcf7-form-control {
	width: 100%;
	/* size="40" gives these a ~300px intrinsic width; without this they
	   refuse to shrink inside the card on narrow phones. */
	min-width: 0;
	border: 1px solid rgba(13, 13, 13, 0.25);
	padding: 13px;
	font-size: 14px;
	font-family: var(--wp--preset--font-family--body);
	background: #fff;
	color: var(--wp--preset--color--contrast);
	outline: none;
	min-height: 44px;
	box-sizing: border-box;
}

.ys-formcard input[type="text"].wpcf7-form-control:focus-visible,
.ys-formcard input[type="email"].wpcf7-form-control:focus-visible,
.ys-formcard textarea.wpcf7-form-control:focus-visible {
	border-color: var(--wp--preset--color--accent);
}

/* Textarea-specific on top of the shared field styling above. display:block
   kills the inline-block baseline gap textareas otherwise sit on, and
   resize:vertical stops anyone dragging it wider than the card. CF7 emits
   cols/rows attributes; width:100% and min-height override both. */
.ys-formcard textarea.wpcf7-form-control {
	display: block;
	line-height: 1.5;
	resize: vertical;
	/* Explicit height, not just min-height: CF7 emits rows="10" on textareas,
	   which min-height cannot override, giving a 238px box that dwarfs the
	   44px fields above it. 92px is three lines (3 x 21px) plus the shared
	   13px padding and 1px borders — enough to read as "write a sentence or
	   two" without the card running away. resize:vertical still lets anyone
	   drag it taller if they need the room. */
	height: 92px;
	min-height: 92px;
}

.ys-formcard .ys-assent {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	font-size: 12.5px;
	line-height: 1.5;
	color: rgba(13, 13, 13, 0.65);
	margin: 4px 0;
}

.ys-formcard .ys-assent a {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}

.ys-formcard .wpcf7-list-item {
	margin: 0;
}

/* The checkbox needs a real CF7 item to be checkable at all (an empty
   [checkbox* assent] tag has nothing to check — that was the bug).
   Its own auto-generated label text is redundant with the actual
   sentence + live links written around it in the Form tab, so hide
   just the label span, not the input itself. */
.ys-formcard .wpcf7-list-item-label {
	display: none;
}

.ys-formcard input[type="submit"].wpcf7-form-control {
	width: 100%;
	box-sizing: border-box;
	background: var(--wp--preset--color--accent);
	color: #fff;
	font-weight: 700;
	font-size: 14px;
	padding: 16px;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	border: none;
	font-family: var(--wp--preset--font-family--body);
	cursor: pointer;
	min-height: 44px;
	margin-top: 2px;
}

.ys-formcard input[type="submit"].wpcf7-form-control:hover {
	background: #e64a19;
}

.ys-formcard .wpcf7-not-valid-tip {
	color: var(--wp--preset--color--accent-2);
	font-size: 12px;
	margin-top: 2px;
}

.ys-formcard .wpcf7-response-output {
	border: none;
	margin: 12px 0 0;
	padding: 0;
	font-size: 13px;
}

/* ---------- responsive collapse (820px, per the handoff spec) ---------- */
@media (max-width: 820px) {
	/* minmax(0, …) matters MORE here than at desktop, not less. A bare 1fr
	   track keeps grid's default min-width:auto, so the track grows to its
	   item's min-content instead of the container's width. The CF7 inputs
	   carry size="40" (~300px intrinsic), which pushed .ys-formcard to a
	   fixed 362px and overflowed every viewport under ~384px. */
	.ys-two,
	.ys-three,
	.ys-four,
	.ys-grid2 {
		grid-template-columns: minmax(0, 1fr);
	}

	.ys-stat {
		border-right: none;
		border-bottom: 1px solid rgba(13, 13, 13, 0.15);
	}

	.ys-stat:last-child {
		border-bottom: none;
	}

	.ys-btnrow--right {
		justify-content: flex-start;
	}

	.ys-hero__cta-col {
		align-items: flex-start;
	}

	.ys-headshot {
		margin-left: 0;
	}

	.ys-h2--book {
		font-size: 40px;
	}
}

/* ═══════════════════════════════════════════════════════════════════
   Blog (templates/single.html, templates/archive.html)
   Not covered by the design handoff — extended from the same tokens
   (Archivo, IBM Plex Mono, black/white/tint/orange, hard edges) but
   using theme.json's calm heading default, not the landing page's
   shouting display type. A wall of uppercase black post titles reads
   fine once, fatiguing as a list.
   ═══════════════════════════════════════════════════════════════════ */

.ys-rule-t {
	border-top: 3px solid var(--wp--preset--color--contrast);
}

/* ---------- single post ---------- */
.ys-post__header {
	padding-bottom: 24px;
	max-width: 720px;
}

.ys-post__header .wp-block-post-terms {
	display: block;
}

.ys-post__header h1 {
	margin: 8px 0 0;
	/* Static, not the theme's fluid/viewport-based default — the column
	   is now a fixed 720px, so the font shouldn't keep scaling with the
	   browser window once the window's wider than that. Fluid sizing
	   tied to viewport width stops making sense once the container it
	   sits in has stopped changing. */
	font-size: 40px;
}

.ys-post__meta {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 12.5px;
	color: rgba(13, 13, 13, 0.62);
	margin-top: 12px;
}

.ys-post__hero {
	border-top: 3px solid var(--wp--preset--color--contrast);
	border-bottom: 3px solid var(--wp--preset--color--contrast);
}

.ys-post__hero img {
	display: block;
	width: 100%;
	height: auto;
}

.ys-post__body {
	padding-top: 48px;
	padding-bottom: 48px;
}

.ys-post__body .wp-block-post-content > * {
	max-width: 720px;
	margin-left: 0;
	margin-right: 0;
}

.ys-post__body p {
	font-size: 17px;
	line-height: 1.65;
	color: rgba(13, 13, 13, 0.75);
}

.ys-post__body h2 {
	margin-top: 48px;
}

.ys-post__body a {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}

.ys-post__body a:hover {
	color: var(--wp--preset--color--accent);
}

.ys-post__foot {
	display: flex;
	justify-content: center;
}

/* ---------- archive ---------- */
.ys-postlist {
	display: flex;
	flex-direction: column;
}

.ys-postcard {
	border-top: 1px solid rgba(13, 13, 13, 0.2);
	padding: 32px 0;
}

.ys-postcard:first-child {
	border-top: none;
}

.ys-postcard .wp-block-post-date {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 11.5px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(13, 13, 13, 0.58);
}

.ys-postcard__title {
	margin: 8px 0 0;
}

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

.ys-postcard__title a:hover {
	color: var(--wp--preset--color--accent);
}

.ys-postcard__excerpt {
	margin-top: 8px;
	font-size: 15px;
	line-height: 1.6;
	color: rgba(13, 13, 13, 0.65);
}

.ys-pagination {
	display: flex;
	justify-content: space-between;
	gap: 16px;
	padding-top: 32px;
	margin-top: 8px;
	border-top: 3px solid var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

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

.ys-pagination a:hover {
	color: var(--wp--preset--color--accent);
}

.ys-pagination .wp-block-query-pagination-numbers {
	display: flex;
	gap: 12px;
}

.ys-pagination .current {
	color: var(--wp--preset--color--accent);
}

/* Smooth in-page scrolling for the landing page's nav/anchor links,
   with scroll-margin so the sticky header never covers the target. */
html {
	scroll-behavior: smooth;
}

#top,
#threats,
#method,
#cases,
#book {
	scroll-margin-top: 90px;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	* {
		transition: none !important;
		animation: none !important;
	}
}
