/*
Theme Name: Project Liberal Foundation
Theme URI: https://projectliberal.foundation
Description: Block child theme of Twenty Twenty-Five for projectliberal.foundation. Forked from the projectliberal.org theme (pl-theme 0.1.2). Native blocks only — no page builder.
Author: Project Liberal Foundation
Author URI: https://projectliberal.foundation
Template: twentytwentyfive
Version: 0.1.0
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: plf-theme
Tags: block-theme, full-site-editing
*/

/* ==========================================================================
   Project Liberal Foundation — child theme CSS

   Almost everything lives in theme.json. This file carries only what
   theme.json cannot express: focus rings, sticky behaviour, headline
   markers, the values accordion, and reduced-motion handling.

   Rules: vanilla CSS only. No framework, no build step, no utility classes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Accessibility — keyboard focus
   Never remove the ring. :focus-visible so pointer users do not see it.
   -------------------------------------------------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 3px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Fallback for engines without :focus-visible */
@supports not selector(:focus-visible) {
	:where(a, button, input, select, textarea, summary, [tabindex]):focus {
		outline: 3px solid var(--wp--preset--color--accent);
		outline-offset: 2px;
	}
}

/* Skip link — visible only once focused */
.pl-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 1000;
	padding: 0.75rem 1.25rem;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	text-decoration: none;
	font-weight: 600;
}

.pl-skip-link:focus {
	left: 0;
}

/* --------------------------------------------------------------------------
   2. Header — sticky (spec §5)
   -------------------------------------------------------------------------- */

.pl-header-sticky {
	position: sticky;
	top: 0;
	z-index: 100;
	background-color: var(--wp--preset--color--base);
}

/* Utility bar sits above the sticky header and scrolls away */
.pl-utility-bar {
	font-size: var(--wp--preset--font-size--small);
}

.pl-site-logo img {
	height: auto;
	max-width: 220px;
}

/* --------------------------------------------------------------------------
   4. Person cards (/about/ and home — person CPT + Query Loop)
   -------------------------------------------------------------------------- */

.pl-person-card {
	height: 100%;
}

.pl-person-card img {
	aspect-ratio: 1 / 1;
	object-fit: cover;
	width: 100%;
	height: auto;
}

/* --------------------------------------------------------------------------
   3b. Animated headline markers (replaces Elementor animated-headline
       "highlight" mode). SVG is injected by assets/js/motion.js.
   -------------------------------------------------------------------------- */

.pl-mark {
	position: relative;
	display: inline-block;
	white-space: nowrap;
	color: inherit;
}

/* Underline family sits below the baseline; strikethrough crosses the text. */
.pl-mark__svg {
	position: absolute;
	left: -0.06em;
	width: calc(100% + 0.12em);
	height: 0.42em;
	bottom: -0.12em;
	overflow: visible;
	color: var(--wp--preset--color--accent);
	pointer-events: none;
}

.pl-mark[data-mark="strikethrough"] .pl-mark__svg {
	top: 50%;
	bottom: auto;
	transform: translateY(-50%);
	height: 0.5em;
}

.pl-mark[data-mark="double_underline"] .pl-mark__svg {
	height: 0.55em;
	bottom: -0.2em;
}

/* Stroke draw-on. path length is unknown, so use a dasharray large enough for
   any of these paths and animate the offset to 0. */
.pl-mark__svg path {
	stroke-dasharray: 320;
	stroke-dashoffset: 320;
}

.pl-mark.is-drawn .pl-mark__svg path {
	transition: stroke-dashoffset 700ms cubic-bezier(0.65, 0, 0.35, 1);
	stroke-dashoffset: 0;
}

.pl-mark.is-drawn .pl-mark__svg path:nth-child(2) {
	transition-delay: 160ms;
}

/* Long highlighted phrases must be allowed to wrap on small screens, even
   though that splits the marker. Unreadable text is worse than a broken line. */
@media (max-width: 600px) {
	.pl-mark {
		white-space: normal;
	}
}

/* --------------------------------------------------------------------------
   3c. Scroll fade-in (replaces Elementor section "fadeIn" entrance animation)
   -------------------------------------------------------------------------- */

/* Content is visible by DEFAULT. The hidden start state only applies once JS
   has confirmed it can observe and reveal (html.pl-motion-ready), so a JS
   failure, a parse error, or an old browser can never leave the page blank. */
.pl-motion-ready .pl-fade-in {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 600ms ease-out, transform 600ms ease-out;
}

.pl-motion-ready .pl-fade-in.is-visible {
	opacity: 1;
	transform: none;
}

/* --------------------------------------------------------------------------
   4b. Checklist (/member/ benefits)
   The original inlined a checkmark SVG into every <li>. A plain list is the
   correct semantics — the tick is decoration, so it belongs in CSS.
   -------------------------------------------------------------------------- */

.pl-checklist {
	list-style: none;
	padding-left: 0;
}

.pl-checklist li {
	position: relative;
	padding-left: 2rem;
	margin-block-end: 0.75rem;
}

.pl-checklist li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.45em;
	width: 1.1rem;
	height: 0.6rem;
	border-left: 3px solid var(--wp--preset--color--accent);
	border-bottom: 3px solid var(--wp--preset--color--accent);
	transform: rotate(-45deg);
}

/* --------------------------------------------------------------------------
   4c. Zoho opt-in embed (/manifesto/)
   Third-party markup with fixed pixel widths. Contain it so it cannot cause
   horizontal page scroll on narrow screens.
   -------------------------------------------------------------------------- */

#zcampaignOptinForm,
#zcampaignOptinForm * {
	max-width: 100%;
	box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   4d. Forms (spec §2) — three shapes, one stylesheet
   -------------------------------------------------------------------------- */

.pl-form-wrap {
	max-width: 34rem;
}

.pl-field {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	margin-block-end: 1.25rem;
}

.pl-field label {
	font-weight: 600;
}

.pl-req {
	color: var(--wp--preset--color--link);
	margin-inline-start: 0.15em;
}

.pl-field input,
.pl-field textarea,
.pl-field select {
	font: inherit;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--base);
	border: 2px solid var(--wp--preset--color--secondary);
	border-radius: 3px;
	padding: 0.6rem 0.75rem;
	width: 100%;
	box-sizing: border-box;
}

.pl-field input:focus-visible,
.pl-field textarea:focus-visible,
.pl-field select:focus-visible {
	border-color: var(--wp--preset--color--accent);
}

/* Error state is never colour-only: the message text carries the meaning. */
.pl-field input[aria-invalid="true"],
.pl-field textarea[aria-invalid="true"],
.pl-field select[aria-invalid="true"] {
	border-color: var(--wp--preset--color--link);
}

.pl-field__error {
	color: var(--wp--preset--color--link);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.pl-form__status {
	min-height: 1.5em;
	font-weight: 600;
}

.pl-form__submit[disabled] {
	opacity: 0.6;
	cursor: progress;
}

/* Honeypot: hidden from sight AND from assistive tech, but still fillable by a
   bot. Not display:none — some bots skip those. */
.pl-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.pl-form-notice {
	border-left: 4px solid var(--wp--preset--color--accent);
	background: var(--wp--preset--color--surface);
	padding: 0.75rem 1rem;
	font-size: var(--wp--preset--font-size--small);
}

/* Visually hidden but still announced. Not defined by the parent theme, and
   the required-field markup already depends on it. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Inline layout — the homepage hero, matching the old site: fields and button
   on one row, labels carried by the placeholder. The <label> is still in the
   DOM (see pl-forms.php) because a placeholder is not an accessible name. */
.pl-form-wrap--inline {
	max-width: 52rem;
}

.pl-form--inline {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 0.75rem;
}

.pl-form--inline .pl-field {
	/* 8rem, not the .org's 10rem: the Foundation hero column is 620px, and
	   3 x 160px fields + gaps + button came to ~628px, so Join wrapped by 8px.
	   The fields still grow to fill the row; this is only their minimum. */
	flex: 1 1 8rem;
	/* Both margins, not just the end: the <p> keeps a 1em top margin otherwise,
	   which drops the fields below the button. */
	margin-block: 0;
	/* Anchors the absolutely-positioned error message below the input. */
	position: relative;
}

/* The email field earns more room than the two name fields. */
.pl-form--inline .pl-field:has( input[type="email"] ) {
	flex-grow: 1.6;
}

/* Lighter than the stacked forms — at hero size a 2px border reads as heavy. */
.pl-form--inline .pl-field input {
	border-width: 1px;
	padding-block: 0.7rem;
}

.pl-form--inline .pl-form__actions {
	flex: 0 0 auto;
	margin-block: 0;
	/* Stretch to the row's height so the button matches the inputs instead of
	   sizing to its own padding. */
	align-self: stretch;
	display: flex;
}

.pl-form--inline .pl-form__submit {
	height: 100%;
	/* height:100% of a wrapped row is only the button's own line, which
	   collapsed it to a sliver. Never shorter than the inputs. */
	min-height: 2.9rem;
	padding-block: 0;
	padding-inline: 2rem;
}

/* Errors sit under their own input instead of stretching the row. */
.pl-form--inline .pl-field__error {
	position: absolute;
	inset-block-start: 100%;
	inset-inline-start: 0;
	padding-block-start: 0.2rem;
}

.pl-form--inline .pl-form__status {
	flex: 1 0 100%;
	margin-block: 0;
}

/* Invisible Turnstile still needs to be in the DOM; keep it out of the row. */
.pl-form--inline .cf-turnstile {
	flex: 0 0 auto;
}

@media ( max-width: 40rem ) {
	.pl-form--inline {
		flex-direction: column;
		align-items: stretch;
	}

	/* Stacked, the row flex-basis becomes a HEIGHT: each field was 8-10rem
	   tall, leaving big empty gaps between the inputs. Size to content. */
	.pl-form--inline .pl-field {
		flex: 0 0 auto;
	}

	.pl-form--inline .pl-field__error {
		position: static;
	}

	.pl-form--inline .pl-form__submit {
		width: 100%;
	}
}

/* Consent checkbox (testimonial inquiry). Label sits beside the box, not above
   it, so the stacked column layout of the other fields does not apply. */
.pl-field--checkbox {
	flex-direction: row;
	align-items: flex-start;
	gap: 0.6rem;
	flex-wrap: wrap;
}

.pl-field--checkbox input {
	width: 1.25rem;
	height: 1.25rem;
	flex: 0 0 auto;
	margin-block-start: 0.2em;
	accent-color: var(--wp--preset--color--accent);
}

.pl-field--checkbox label {
	flex: 1 1 0;
	font-weight: 400;
}

.pl-field--checkbox .pl-field__error {
	flex: 1 0 100%;
}

/* --------------------------------------------------------------------------
   5. Foundation home page sections
   -------------------------------------------------------------------------- */

/* Eyebrow — the small orange label above each section heading. On the
   Elementor site this was a second <h2>; here it is a paragraph, so the page
   outline carries one heading per section instead of two. */
.pl-eyebrow {
	color: var(--wp--preset--color--link);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	margin-block-end: 0.25rem;
}

.pl-eyebrow + .wp-block-heading {
	margin-block-start: 0;
}

/* Four numbered "onramp" cards. */
.pl-step {
	height: 100%;
	border-top: 4px solid var(--wp--preset--color--accent);
}

.pl-step__num {
	color: var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 700;
	line-height: 1;
	margin: 0;
}

/* Matching-gift banner: the one band on the page that should interrupt. */
.pl-match {
	border-left: 6px solid var(--wp--preset--color--accent);
}

/* Values accordion (replaces the Elementor toggle widget) — native
   <details>, so it opens with the keyboard and without JavaScript. */
.pl-values details {
	border-bottom: 1px solid var(--wp--preset--color--secondary);
	padding-block: 1rem;
}

.pl-values details > summary {
	cursor: pointer;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	list-style: none;
	position: relative;
	padding-inline-end: 2rem;
}

.pl-values details > summary::-webkit-details-marker {
	display: none;
}

.pl-values details > summary::after {
	content: "+";
	position: absolute;
	inset-inline-end: 0;
	top: 50%;
	transform: translateY(-50%);
	color: var(--wp--preset--color--accent);
	font-size: 1.5em;
	font-weight: 400;
	line-height: 1;
	transition: transform 200ms ease-out;
}

.pl-values details[open] > summary::after {
	transform: translateY(-50%) rotate(45deg);
}

.pl-values details > :not(summary) {
	margin-block-start: 0.75rem;
}

/* --------------------------------------------------------------------------
   6. Reduced motion — kill every transition and animation
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}

	.pl-values details > summary::after {
		transition: none;
	}
}

/* --------------------------------------------------------------------------
   7. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 781px) {
	.pl-site-logo img {
		max-width: 160px;
	}
}

/* Never let a long unbroken URL blow out the layout. */
.entry-content a {
	overflow-wrap: break-word;
}
