/* ==========================================================================
   PAGE HEADER — page-header@1.0
   The top band of an INTERIOR page. Three bands, six slots, two axes.
   Contract: skills/page-header/SPEC.md + page-header.schema.json
   Rendered by includes/header/class-page-header-renderer.php

   Every colour in this file is a theme token (var(--color-*)). There is no
   hex, no rgb() and no named colour anywhere, which is what makes a header
   on-brand across all 18 theme families by construction rather than by review.

   Sizes ARE real values here — that is what a stylesheet is for. What the
   contract forbids is a pixel in an ENTRY: the renderer hands this file a
   height BAND (compact/standard/tall/full) and the clamp() below decides what
   that means at a given viewport.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Block
   -------------------------------------------------------------------------- */

.plexa-page-header {
	display: block;
	width: 100%;
}

/* --------------------------------------------------------------------------
   Bands — one strip primitive (bands 0 and B) plus one designed band (A)
   -------------------------------------------------------------------------- */

.plexa-page-header__band {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	color: var(--ph-content, var(--color-base-content));
}

.plexa-page-header__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem 2rem;
	width: 100%;
	max-width: var(--ph-container, 80rem);
	margin-inline: auto;
	padding-inline: clamp(1rem, 4vw, 2rem);
}

/* Band 0 and band B: thin, plain, aligned to the site container. */
.plexa-page-header__band--nav,
.plexa-page-header__band--meta {
	padding-block: 0.75rem;
}

.plexa-page-header__band--nav {
	padding-block: 0.625rem;
}

/* --------------------------------------------------------------------------
   Derived: height_band. A band, never a measurement.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--h-compact {
	padding-block: clamp(1.5rem, 3vw, 2.5rem);
}

.plexa-page-header__band--h-standard {
	padding-block: clamp(2.5rem, 5vw, 4rem);
}

.plexa-page-header__band--h-tall {
	padding-block: clamp(3.5rem, 7vw, 5.5rem);
	min-height: clamp(17rem, 32vh, 24rem);
}

.plexa-page-header__band--h-full {
	padding-block: clamp(4.5rem, 9vw, 7rem);
	min-height: clamp(22rem, 50vh, 36rem);
}

/* --------------------------------------------------------------------------
   Derived: vertical_align. Text centres in a tall band, tops in a compact one.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--v-top {
	justify-content: flex-start;
}

.plexa-page-header__band--v-center {
	justify-content: center;
}

.plexa-page-header__band--v-bottom {
	justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   align — left | center | right | split. The whole layout model.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--align-left .plexa-page-header__inner {
	justify-content: flex-start;
	text-align: start;
}

.plexa-page-header__band--align-center .plexa-page-header__inner {
	justify-content: center;
	text-align: center;
}

.plexa-page-header__band--align-center .plexa-page-header__text {
	align-items: center;
}

.plexa-page-header__band--align-right .plexa-page-header__inner {
	justify-content: flex-end;
	text-align: end;
}

.plexa-page-header__band--align-right .plexa-page-header__text {
	align-items: flex-end;
}

.plexa-page-header__band--align-split .plexa-page-header__inner {
	justify-content: space-between;
	text-align: start;
}

/* Derived: band_distribution. Two elements in a band is space-between,
   whatever align says. */
.plexa-page-header__band--dist-space-between .plexa-page-header__inner {
	justify-content: space-between;
}

/* --------------------------------------------------------------------------
   Derived: the single rule, drawn in the band's own content colour at
   reduced opacity. Rule budget is one across all three bands and the
   renderer will not emit a second, so there is no cascade to police here.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--rule-top {
	border-top: 1px solid color-mix(in oklch, var(--ph-content, var(--color-base-content)) 18%, transparent);
}

.plexa-page-header__band--rule-bottom {
	border-bottom: 1px solid color-mix(in oklch, var(--ph-content, var(--color-base-content)) 18%, transparent);
}

/* --------------------------------------------------------------------------
   Derived: contrast_pairing. Role-paired and automatic — a primary background
   takes primary-content, base-200 takes base-content. Asserted here, never
   eyeballed, never authored in an entry.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--content-base {
	--ph-content: var(--color-base-content);
}

.plexa-page-header__band--content-primary {
	--ph-content: var(--color-primary-content);
}

.plexa-page-header__band--content-secondary {
	--ph-content: var(--color-secondary-content);
}

.plexa-page-header__band--content-accent {
	--ph-content: var(--color-accent-content);
}

.plexa-page-header__band--content-neutral {
	--ph-content: var(--color-neutral-content);
}

/* --------------------------------------------------------------------------
   Surface tier 1 — the flat mode surface. Its whole value is that it cannot
   fail: the band paints nothing and inherits the mode it is in.
   -------------------------------------------------------------------------- */

.plexa-page-header__band--tier-1 {
	background-color: transparent;
}

/* --------------------------------------------------------------------------
   Surface tier 3 — the token mesh.
   data-bg-mesh="custom" with --mesh-color-1..4 bound by the renderer to the
   PRIMARY at three tones plus the ground (never secondary/accent: on most
   families those are contrasting hues and the mesh went rainbow). The
   fallbacks below mirror the renderer's `brand` spread. This rule is
   deliberately more specific than the effects
   library's own [data-bg-mesh="custom"] > .bg-layers__base::before, so an
   interior header paints correctly whether or not the engine's bg-mesh effect
   category was enqueued. Both are built from the same four custom properties.
   Motion is off: an interior header's job is to locate the reader.

   width/height are stated, not left to `inset: 0`, because the library's base
   rule ([data-bg-mesh] > .bg-layers__base::before) sets inset:-50% with
   width:200%;height:200% to oversize the pseudo for its drift transform. If a
   page-level mesh background pulls mesh.css onto the same page, that rule's
   sizing would otherwise survive here and blow the mesh out past the band.
   `will-change: auto` sheds the compositor layer the library asks for with
   `will-change: transform` — nothing animates on this header, so the layer is
   pure cost.
   -------------------------------------------------------------------------- */

.plexa-page-header__band[data-bg-mesh="custom"] > .bg-layers__base::before {
	content: "";
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	background:
		radial-gradient(ellipse 80% 60% at 20% 30%, var(--mesh-color-1, color-mix(in oklch, var(--color-primary) 60%, transparent)), transparent 70%),
		radial-gradient(ellipse 60% 80% at 80% 20%, var(--mesh-color-2, color-mix(in oklch, color-mix(in oklch, var(--color-primary) 65%, var(--color-primary-content)) 38%, transparent)), transparent 70%),
		radial-gradient(ellipse 70% 50% at 50% 80%, var(--mesh-color-3, color-mix(in oklch, color-mix(in oklch, var(--color-primary) 40%, var(--color-base-100)) 28%, transparent)), transparent 70%),
		radial-gradient(ellipse 90% 90% at 50% 50%, var(--mesh-color-4, var(--color-base-100)), transparent);
	animation: none;
	will-change: auto;
}

/* --------------------------------------------------------------------------
   Surface tier 4 — pattern over a token tint. The tint is named by role so the
   paired -content colour follows automatically (see content-* above).
   -------------------------------------------------------------------------- */

.plexa-page-header__band--tint-base-200 {
	background-color: var(--color-base-200);
}

.plexa-page-header__band--tint-base-300 {
	background-color: var(--color-base-300);
}

.plexa-page-header__band--tint-primary {
	background-color: var(--color-primary);
}

.plexa-page-header__band--tint-secondary {
	background-color: var(--color-secondary);
}

.plexa-page-header__band--tint-accent {
	background-color: var(--color-accent);
}

.plexa-page-header__band--tint-neutral {
	background-color: var(--color-neutral);
}

.plexa-page-header__band--tint-none {
	background-color: transparent;
}

/* --------------------------------------------------------------------------
   Media — a separate axis, not a slot. One asset, one home.
   -------------------------------------------------------------------------- */

.plexa-page-header__media {
	display: block;
	width: 100%;
	min-width: 0;
}

.plexa-page-header__image {
	display: block;
	width: 100%;
	height: auto;
	object-fit: cover;
	border-radius: var(--radius-box, 0.75rem);
}

.plexa-page-header__image--auto {
	max-height: 60vh;
	object-fit: contain;
}

.plexa-page-header__image--16-9 { aspect-ratio: 16 / 9; }
.plexa-page-header__image--3-2  { aspect-ratio: 3 / 2; }
.plexa-page-header__image--4-3  { aspect-ratio: 4 / 3; }
.plexa-page-header__image--1-1  { aspect-ratio: 1 / 1; }
.plexa-page-header__image--4-5  { aspect-ratio: 4 / 5; }
.plexa-page-header__image--3-1  { aspect-ratio: 3 / 1; }
.plexa-page-header__image--4-1  { aspect-ratio: 4 / 1; }

/* below: full width under band A, above band B — square corners, it is a band
   of its own rather than a card. */
.plexa-page-header__media--below {
	max-width: var(--ph-container, 80rem);
	margin-inline: auto;
	padding-inline: clamp(1rem, 4vw, 2rem);
	margin-block-start: clamp(1rem, 2vw, 1.5rem);
}

/* beside-*: the band's second column. Stacks on a phone; two columns from a
   tablet up, with the text centred against the image. */
.plexa-page-header__band--media-beside-start .plexa-page-header__inner,
.plexa-page-header__band--media-beside-end .plexa-page-header__inner {
	display: grid;
	grid-template-columns: 1fr;
	align-items: center;
}

@media (min-width: 48rem) {
	.plexa-page-header__band--media-beside-start .plexa-page-header__inner,
	.plexa-page-header__band--media-beside-end .plexa-page-header__inner {
		grid-template-columns: 1fr 1fr;
	}

	.plexa-page-header__band--media-beside-start .plexa-page-header__text {
		order: 2;
	}

	.plexa-page-header__band--media-beside-start .plexa-page-header__media {
		order: 1;
	}
}

/* --------------------------------------------------------------------------
   The text column and the six slots, in their fixed order:
   classify -> name -> elaborate -> attribute -> act
   -------------------------------------------------------------------------- */

.plexa-page-header__text {
	display: flex;
	flex: 1 1 22rem;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.75rem;
	min-width: 0;
}

.plexa-page-header__group {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 1rem;
	min-width: 0;
}

.plexa-page-header__group--actions {
	flex: 0 0 auto;
}

/* Inline actions in a stacked band A: a row of their own under the text,
   following the band's align. Pinned actions make the band space-between
   instead (derive_band_distribution) and keep the rule above. */
.plexa-page-header__band--title.plexa-page-header__band--dist-stacked .plexa-page-header__group--actions {
	flex: 1 1 100%;
	justify-content: inherit;
}

.plexa-page-header__band--title.plexa-page-header__band--dist-stacked .plexa-page-header__group--actions .plexa-page-header__cta {
	justify-content: inherit;
}

/* Slot 1 — marker */
.plexa-page-header__marker {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.5rem;
	height: 3.5rem;
	font-size: 1.5rem;
	color: var(--color-primary-content);
	background-color: var(--color-primary);
	border-radius: var(--radius-full, 9999px);
}

/* Slot 2 — classifier. Same asset, two possible homes; in band A it reads as
   an eyebrow above the H1, in band B it reads as filing. */
.plexa-page-header__classifier {
	margin: 0;
	font-size: 0.8125rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ph-content, var(--color-base-content));
	text-decoration: none;
	/* NO OPACITY HERE. A classifier is already 13px, 600, uppercase and
	   letterspaced — it does not need a fourth signal that it is secondary, and
	   the fourth one was the only one that cost contrast. At 0.75 over the light
	   region of a brand mesh it measured 1.67:1 against a 4.5:1 bar; the ink
	   carries no opacity now and the ground carries the overlay instead. */
}

a.plexa-page-header__classifier:hover,
a.plexa-page-header__classifier:focus-visible {
	text-decoration: underline;
}

.plexa-page-header__band--meta .plexa-page-header__classifier {
	letter-spacing: 0.04em;
	text-transform: none;
}

/* Slot 3 — the H1. It lives in band A and only there. */
.plexa-page-header__title {
	margin: 0;
	font-size: var(--text-h1-size, clamp(2rem, 4vw + 1rem, 3.25rem));
	font-weight: 700;
	line-height: 1.15;
	color: var(--ph-content, var(--color-base-content));
	text-wrap: balance;
}

.plexa-page-header__band--h-compact .plexa-page-header__title {
	font-size: var(--text-h2-size, clamp(1.75rem, 3vw + 0.75rem, 2.5rem));
}

/* Slot 4 — lead. Subtitle and excerpt were never two things. */
.plexa-page-header__lead {
	margin: 0;
	max-width: 60ch;
	font-size: var(--text-lead-size, 1.125rem);
	line-height: 1.6;
	color: var(--ph-content, var(--color-base-content));
	opacity: 0.8;
	text-wrap: pretty;
}

/* Slot 5 — attribution */
.plexa-page-header__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.875rem;
	line-height: 1.5;
	color: var(--ph-content, var(--color-base-content));
	opacity: 0.8;
}

.plexa-page-header__meta a {
	color: inherit;
	text-decoration: none;
}

.plexa-page-header__meta a:hover,
.plexa-page-header__meta a:focus-visible {
	text-decoration: underline;
}

.plexa-page-header__meta-separator {
	opacity: 0.5;
}

.plexa-page-header__author {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
}

.plexa-page-header__author-avatar {
	width: 1.75rem;
	height: 1.75rem;
	object-fit: cover;
	border-radius: var(--radius-full, 9999px);
}

.plexa-page-header__author-bio {
	margin: 0;
	max-width: 50ch;
	font-size: 0.875rem;
	opacity: 0.75;
}

/* Band B — terms */
.plexa-page-header__terms {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.375rem;
}

.plexa-page-header__term {
	display: inline-block;
	padding: 0.125rem 0.625rem;
	font-size: 0.75rem;
	line-height: 1.6;
	color: var(--ph-content, var(--color-base-content));
	background-color: color-mix(in oklch, var(--ph-content, var(--color-base-content)) 10%, transparent);
	border-radius: var(--radius-full, 9999px);
	text-decoration: none;
}

.plexa-page-header__term:hover,
.plexa-page-header__term:focus-visible {
	background-color: color-mix(in oklch, var(--ph-content, var(--color-base-content)) 18%, transparent);
}

/* Slot 6 — actions: share OR cta, never both. */
.plexa-page-header__share {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.375rem;
}

.plexa-page-header__share-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	font-size: 0.9375rem;
	color: var(--ph-content, var(--color-base-content));
	background-color: color-mix(in oklch, var(--ph-content, var(--color-base-content)) 10%, transparent);
	border: 0;
	border-radius: var(--radius-full, 9999px);
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.plexa-page-header__share-btn:hover,
.plexa-page-header__share-btn:focus-visible {
	background-color: color-mix(in oklch, var(--ph-content, var(--color-base-content)) 20%, transparent);
}

.plexa-page-header__cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}

.plexa-page-header__cta-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.625rem 1.25rem;
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.2;
	border: 1px solid transparent;
	border-radius: var(--radius-field, 0.5rem);
	text-decoration: none;
}

.plexa-page-header__cta-btn--primary {
	color: var(--color-primary-content);
	background-color: var(--color-primary);
}

.plexa-page-header__cta-btn--secondary {
	color: var(--color-secondary-content);
	background-color: var(--color-secondary);
}

.plexa-page-header__cta-btn--accent {
	color: var(--color-accent-content);
	background-color: var(--color-accent);
}

.plexa-page-header__cta-btn--neutral {
	color: var(--color-neutral-content);
	background-color: var(--color-neutral);
}

.plexa-page-header__cta-btn--outline {
	color: var(--ph-content, var(--color-base-content));
	background-color: transparent;
	border-color: color-mix(in oklch, var(--ph-content, var(--color-base-content)) 40%, transparent);
}

.plexa-page-header__cta-btn--ghost {
	color: var(--ph-content, var(--color-base-content));
	background-color: transparent;
}

.plexa-page-header__cta-btn:hover,
.plexa-page-header__cta-btn:focus-visible {
	filter: brightness(0.94);
}

/* --------------------------------------------------------------------------
   Band 0 — breadcrumbs
   -------------------------------------------------------------------------- */

.plexa-page-header__breadcrumbs {
	min-width: 0;
	max-width: 100%;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ph-content, var(--color-base-content));
	opacity: 0.7;
}

/* The trail is one line that truncates; it never wraps and never overlaps.
   Ellipsis has to live on the LABEL, not on the crumb: a crumb is an inline-flex
   box and text-overflow does not apply to one, which is why an over-long trail
   used to paint its crumbs on top of each other instead of cutting them off. */
.plexa-page-header__crumbs {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 0.375rem;
	margin: 0;
	padding: 0;
	list-style: none;
	min-width: 0;
	overflow: hidden;
}

.plexa-page-header__crumb {
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	min-width: 0;
	/* Ancestors are short and fixed; they never shrink. Squeezing them instead
	   bought 4ch stubs that still did not free enough room for a long title, so
	   the labels overlapped. All the shrink belongs to the current page. */
	flex: none;
}

.plexa-page-header__crumb:last-child {
	flex: 0 1 auto;
	min-width: 0;
}

.plexa-page-header__crumb + .plexa-page-header__crumb::before {
	content: "\203A";
	opacity: 0.6;
	/* The separator is structure, not text — it must never be clipped. */
	flex: none;
}

.plexa-page-header__crumb > a,
.plexa-page-header__crumb > span {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* A narrow strip has room for one label, not two. Keeping a parent here only
   bought a squeezed stub ("PE…") next to the page you are already on, so below
   40rem the trail is just the current page. Dropping a crumb takes its
   separator with it, so the strip always begins with a label. */
@media (max-width: 40rem) {
	.plexa-page-header__crumb:not(:last-child) {
		display: none;
	}

	.plexa-page-header__crumb:last-child::before {
		content: none;
	}
}

.plexa-page-header__crumb a {
	color: inherit;
	text-decoration: none;
}

.plexa-page-header__crumb a:hover,
.plexa-page-header__crumb a:focus-visible {
	text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Focus — visible on every surface, drawn in the band's own content colour.
   -------------------------------------------------------------------------- */

.plexa-page-header a:focus-visible,
.plexa-page-header button:focus-visible {
	outline: 2px solid var(--ph-content, var(--color-base-content));
	outline-offset: 2px;
	border-radius: var(--radius-field, 0.25rem);
}

/* --------------------------------------------------------------------------
   Derived: mobile_collapse_order. Fixed, not a per-entry choice — drop
   actions, then terms, keep author and date. The order is emitted by the
   renderer as data-collapse-order so the rule lives in one place.
   -------------------------------------------------------------------------- */

@media (max-width: 48rem) {
	.plexa-page-header__band--meta[data-collapse-order*="actions"] .plexa-page-header__group--actions {
		display: none;
	}
}

@media (max-width: 32rem) {
	.plexa-page-header__band--meta[data-collapse-order*="terms"] .plexa-page-header__terms {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   Reduced motion — nothing in a page header animates, but the effects library
   underneath one might.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.plexa-page-header__band *,
	.plexa-page-header__band *::before,
	.plexa-page-header__band *::after {
		animation: none !important;
		transition: none !important;
	}
}

/* --------------------------------------------------------------------------
   Print — the designed band is ink nobody asked for.
   -------------------------------------------------------------------------- */

@media print {
	.plexa-page-header__band {
		min-height: 0;
		padding-block: 0.5rem;
		background: none !important;
	}

	.plexa-page-header .bg-layers__base,
	.plexa-page-header .bg-layers__pattern,
	.plexa-page-header .bg-layers__noise,
	.plexa-page-header .bg-layers__overlay,
	.plexa-page-header__group--actions {
		display: none !important;
	}
}

/* A DISPLAY SIZE IS A SIZE FOR SHORT TITLES.

   .plexa-page-header__title takes --text-h1-size from the site's type scale.
   On `dramatic` that is 7.594rem — 121px — which is the whole point of the
   scale for "Termite Season" and a wall for "German Cockroaches vs American
   Cockroaches: Control Strategies for Alabama Homes": six lines, filling a
   1080px viewport before a word of the article. Blog titles are long by
   nature, so this is most posts rather than an edge case.

   The scale is untouched. Plexa_Page_Header_Parts::title() counts the
   characters and marks the two cases the scale cannot carry, and each steps
   down to a size that can still be read as a title. Both keep a clamp so they
   stay responsive; the min is the mobile end of the same scale.

   Thresholds are where a title stops fitting two and three lines at the full
   size — about 32 characters to a line there. */

.plexa-page-header__title--medium {
    font-size: clamp(1.75rem, 3.2vw + 0.75rem, min(var(--text-h1-size, 3rem), 3.5rem));
}

.plexa-page-header__title--long {
    font-size: clamp(1.5rem, 2.6vw + 0.625rem, min(var(--text-h1-size, 3rem), 2.75rem));
    line-height: 1.2;
}
