/*
Theme Name: Through Faith Therapy
Theme URI: https://throughfaiththerapy.com
Author: Through Faith Therapy
Author URI: https://throughfaiththerapy.com
Description: A custom block theme for Through Faith Therapy — faith-centered, trauma-informed online counseling for adult Christian women in Texas. Editorial typography, a warm green-and-cream palette drawn from the practice mark, and a library of purpose-built patterns for specialty, approach, and long-form pages.
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 8.0
Version: 1.5.1
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: through-faith
Tags: blog, one-column, custom-colors, custom-menu, block-patterns, block-styles, full-site-editing, editor-style, wide-blocks, accessibility-ready
*/

/* =========================================================================
   1. Base
   ========================================================================= */

:root {
	--tft-header-h: 118px;
	--tft-ease: cubic-bezier(0.2, 0, 0.2, 1);
}

html {
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--tft-header-h) + 1.5rem);
	-webkit-text-size-adjust: 100%;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-variant-ligatures: common-ligatures contextual;
	text-rendering: optimizeLegibility;
	overflow-x: clip;
}

/* Fraunces reads warmer with a little optical softness and no "wonk". */
h1, h2, h3, h4,
.tft-display,
.tft-pull,
.tft-scripture,
.tft-quote {
	/* One setting for every instance of the display face. Varying the optical
	   size and softness per element made a single typeface read as three. */
	font-variation-settings: "SOFT" 20, "WONK" 0, "opsz" 48;
	text-wrap: balance;
}

h3, h4 {
}

p, li {
	text-wrap: pretty;
}

::selection {
	background: var(--wp--preset--color--blush);
	color: var(--wp--preset--color--ink);
}

:where(a, button, summary, input, textarea, select, .wp-block-button__link):focus-visible {
	outline: 2px solid var(--wp--preset--color--green);
	outline-offset: 3px;
	border-radius: 3px;
}

.tft-skip-link:focus {
	position: fixed;
	top: 1rem;
	left: 1rem;
	z-index: 9999;
	padding: 0.85rem 1.4rem;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--sm);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	text-decoration: none;
}

/* =========================================================================
   2. Header
   ========================================================================= */

.tft-header {
	position: sticky;
	top: 0;
	z-index: 500;
	border-bottom: 1px solid transparent;
	transition: border-color 240ms var(--tft-ease);
}

/* The blur lives on a pseudo-element, not on .tft-header itself: an element
   with backdrop-filter becomes the containing block for `position: fixed`
   descendants, which would trap the navigation block's full-screen mobile
   overlay inside the header's own 72px box. */
.tft-header::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: color-mix(in srgb, var(--wp--preset--color--base) 82%, transparent);
	backdrop-filter: saturate(150%) blur(14px);
	-webkit-backdrop-filter: saturate(150%) blur(14px);
	transition: background-color 240ms var(--tft-ease);
}

.tft-header.is-stuck {
	border-bottom-color: var(--wp--preset--color--linen);
}

.tft-header.is-stuck::before {
	background: color-mix(in srgb, var(--wp--preset--color--base) 94%, transparent);
}

/* The wordmark is her logo as supplied — the stacked THROUGH FAITH / THERAPY
   lockup, geometry untouched. Only the lettering colour is themeable, so one
   file serves the cream header and the deep-green footer. */
.tft-wordmark-link {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
	color: var(--wp--preset--color--green);
	transition: opacity 180ms var(--tft-ease);
}

.tft-wordmark-link:hover {
	opacity: 0.72;
}

.tft-wordmark {
	display: block;
	height: 62px;
	width: auto;
}

.tft-panel--dark .tft-wordmark-link,
.tft-wordmark-link--footer {
	color: var(--wp--preset--color--base);
}

.tft-wordmark-link--footer .tft-wordmark {
	height: 54px;
}

@media (max-width: 781px) {
	.tft-wordmark {
		height: 42px;
	}

	.tft-wordmark-link--footer .tft-wordmark {
		height: 44px;
	}
}

/* The lockup ships with the theme, so it renders on a fresh install before
   anyone has set a Site Logo. */
.tft-lockup {
	display: inline-flex;
	align-items: center;
	gap: clamp(0.75rem, 1.6vw, 1.35rem);
	text-decoration: none;
	color: var(--wp--preset--color--green);
	transition: opacity 180ms var(--tft-ease);
}

.tft-lockup:hover {
	opacity: 0.75;
}

.tft-lockup .tft-mark-img {
	display: block;
	height: 86px;
	width: auto;
	max-width: none;
	flex: 0 0 auto;
}

@media (max-width: 781px) {
	.tft-lockup .tft-mark-img {
		height: 56px !important;
	}
}

/* On a phone the emblem, wordmark, toggle and CTA have to share one line, so
   everything shrinks together rather than the wordmark being dropped — the
   name is the point of a wordmark. */
@media (max-width: 640px) {
	.tft-lockup {
		gap: 0.6rem;
	}

	.tft-lockup .tft-mark-img {
		height: 46px !important;
	}

	.tft-wordmark {
		height: 28px;
	}

	.tft-header__cta .wp-block-button__link {
		padding: 0.65rem 0.95rem;
		font-size: 0.7rem;
		letter-spacing: 0.02em;
	}

	.tft-header .wp-block-navigation__responsive-container-open {
		padding: 0;
	}
}

@media (max-width: 400px) {
	.tft-lockup {
		gap: 0.45rem;
	}

	.tft-lockup .tft-mark-img {
		height: 40px !important;
	}

	.tft-wordmark {
		height: 24px;
	}

	.tft-header__cta .wp-block-button__link {
		padding: 0.6rem 0.8rem;
		font-size: 0.66rem;
	}
}

/* Sizing lives here rather than as inline block styles, so the mobile media
   query below can actually override it. */
.tft-header__cta .wp-block-button__link {
	padding: 0.85rem 1.5rem;
	font-size: 0.8125rem;
	white-space: nowrap;
}

/* Navigation */
.tft-nav .wp-block-navigation-item__content {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 500;
	letter-spacing: 0.012em;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	padding-block: 0.4rem;
	position: relative;
}

.tft-nav .wp-block-navigation-item__content::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 1px;
	background: var(--wp--preset--color--green);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 220ms var(--tft-ease);
}

.tft-nav .wp-block-navigation-item:hover > .wp-block-navigation-item__content::after,
.tft-nav .wp-block-navigation-item.current-menu-item > .wp-block-navigation-item__content::after {
	transform: scaleX(1);
}

.tft-nav .wp-block-navigation-item.current-menu-item > .wp-block-navigation-item__content {
	color: var(--wp--preset--color--green);
}

/* Submenus */
/* `.wp-block-navigation` is on the same element as `.tft-nav`. Naming both
   outranks core's own `.wp-block-navigation .wp-block-navigation__submenu-container`,
   which matches at the same weight and is enqueued after the theme — without
   it, core's 200px min-width wins and the longer labels wrap. */
.wp-block-navigation.tft-nav .wp-block-navigation__submenu-container {
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--linen);
	border-radius: var(--wp--custom--radius--md);
	box-shadow: var(--wp--preset--shadow--lift);
	padding: 0.5rem;
	/* Wide enough for the longest specialty label to hold one line. */
	min-width: 300px;
}

/* Core re-asserts `min-width: 200px` on every *open* state of the submenu —
   hover, focus-within, and the expanded toggle — each at a weight the
   closed-state rule above cannot reach. Widening the open dropdown means
   matching those same states with `.tft-nav` added. */
@media (min-width: 782px) {
	.wp-block-navigation.tft-nav .has-child:not(.open-on-click):hover > .wp-block-navigation__submenu-container,
	.wp-block-navigation.tft-nav .has-child:not(.open-on-click):not(.open-on-hover-click):focus-within > .wp-block-navigation__submenu-container,
	.wp-block-navigation.tft-nav .has-child .wp-block-navigation-submenu__toggle[aria-expanded="true"] ~ .wp-block-navigation__submenu-container {
		min-width: 300px;
	}
}

/* Submenu items stack, so they can take the tight leading that wrapped list
   items need — at menu leading the second line of a long label drifts far
   enough from the first to look like a separate entry. The top-level menu is
   left alone: it runs horizontally, where none of this applies. */
.wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	line-height: 1.35;
}

.tft-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding: 0.6rem 0.9rem;
	border-radius: var(--wp--custom--radius--sm);
	width: 100%;
}

.tft-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content::after {
	display: none;
}

.tft-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
	background: var(--wp--preset--color--sand);
	color: var(--wp--preset--color--green);
}

/* Mobile overlay */
.wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--base) !important;
}

/* The desktop bar right-aligns its items; in a full-screen overlay that reads
   as broken, so re-anchor everything to the left. */
/* The block emits `items-justified-right` for the desktop bar; that class wins
   on specificity inside the overlay too, so override it explicitly. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container.items-justified-right,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	align-items: flex-start !important;
	justify-content: flex-start !important;
	text-align: left;
	width: 100%;
	gap: 0.35rem;
}

/* Submenu <li>s are flex containers of their own and inherit `flex-end` from
   the desktop bar's right justification; reset them individually. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu {
	align-items: flex-start !important;
	align-self: flex-start;
	width: 100%;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 400;
	padding-block: 0.45rem;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content::after {
	display: none;
}

/* Submenus are inline, indented lists here — not floating cards. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	background: transparent;
	border: 0;
	border-left: 1px solid var(--wp--preset--color--linen);
	border-radius: 0;
	box-shadow: none;
	padding: 0.25rem 0 0.75rem;
	margin-left: 0.2rem;
	min-width: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md);
	padding: 0.4rem 0 0.4rem 1.1rem;
	border-radius: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
	background: transparent;
}

/* =========================================================================
   3. Type utilities
   ========================================================================= */

.tft-eyebrow {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--eyebrow--font-size);
	font-weight: 600;
	letter-spacing: var(--wp--custom--eyebrow--letter-spacing);
	text-transform: uppercase;
	color: var(--wp--preset--color--green);
	margin-bottom: 0;
}

.tft-eyebrow::before {
	content: "";
	flex: 0 0 auto;
	width: 30px;
	height: 1px;
	background: currentColor;
	opacity: 0.55;
}

/* Eyebrow typography without the h6 rank — for headings that are section
   labels rather than a sixth level of hierarchy. */
.tft-label {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--eyebrow--font-size);
	font-weight: 600;
	letter-spacing: var(--wp--custom--eyebrow--letter-spacing);
	text-transform: uppercase;
	line-height: 1.4;
	color: var(--wp--preset--color--green);
}

.tft-panel--dark .tft-label {
	color: var(--wp--preset--color--clay);
}

/* The post date uses the eyebrow treatment; it must not pick up link styling. */
.tft-eyebrow a,
.tft-eyebrow time {
	color: inherit;
	text-decoration: none;
}

.tft-eyebrow.is-centered {
	justify-content: center;
}

.tft-eyebrow.is-centered::after {
	content: "";
	flex: 0 0 auto;
	width: 30px;
	height: 1px;
	background: currentColor;
	opacity: 0.55;
}

/* An italic Fraunces phrase used inside a roman headline. */
.tft-accent,
em.tft-accent {
	font-style: italic;
	color: var(--wp--preset--color--green);
}

.has-green-deep-background-color .tft-accent,
.tft-panel--dark .tft-accent {
	color: var(--wp--preset--color--blush);
}

.tft-lede {
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.62;
	color: var(--wp--preset--color--ink-soft);
}

.tft-measure {
	max-width: 84ch;
}

.tft-measure-tight {
	max-width: 48ch;
}

/* Display headlines need a much tighter measure than body copy — a 1180px
   line of 84px Fraunces is unreadable. */
.tft-measure-display {
	max-width: 24ch;
}

@media (max-width: 781px) {
	.tft-measure-display {
		max-width: none;
	}
}

/* =========================================================================
   4. Sections & decorative rules
   ========================================================================= */

/* Header, main and footer each manage their own vertical space, so the site
   level block gap between them only ever shows as a stripe of page background
   between two full-bleed bands. */
.wp-site-blocks > * + * {
	margin-block-start: 0;
}

/* Same problem one level down: full-bleed sections carry their own padding, so
   the constrained layout's gap between them is a visible seam. WordPress sets
   that gap through a zero-specificity :where() rule, so a plain class selector
   is enough to clear it. */
.wp-block-post-content > .alignfull + .alignfull,
main > .alignfull + .alignfull,
.alignfull + .wp-block-cover.alignfull,
.wp-block-cover.alignfull + .alignfull {
	margin-block-start: 0;
}

.tft-section {
	position: relative;
}

.tft-section--hairline::before {
	content: "";
	position: absolute;
	inset-inline: clamp(1.25rem, 5vw, 3rem);
	top: 0;
	height: 1px;
	background: var(--wp--preset--color--linen);
}

/* A soft paper grain so large cream fields do not read as flat.
   Painted as a background layer on the section itself rather than as a blended
   overlay: background-image sits above background-color but below content, so
   it tints the field without touching text and without creating a stacking
   context that compositors handle inconsistently. */
.tft-grain {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
	background-repeat: repeat;
	background-size: 180px 180px;
}

/* -------------------------------------------------------------------------
   The mark, used as architecture
   -------------------------------------------------------------------------
   The tree-of-life emblem is the strongest thing the practice owns, so it
   earns more than a 44px slot in the header. Three treatments, all decorative
   and all `pointer-events: none` so they never intercept a click. */

/* A. Blown-up tree, bleeding off one edge of a section.

   The shape is a traced SVG rather than the logo PNG, so it stays crisp at
   860px and is painted through a mask — which means it takes its colour from
   the theme instead of being locked to whatever was in the bitmap. */
.tft-mark {
	position: relative;
	isolation: isolate;
	overflow: clip;
}

.tft-mark::after {
	content: "";
	position: absolute;
	z-index: -1;
	pointer-events: none;
	width: clamp(420px, 52vw, 860px);
	aspect-ratio: 1;
	background-color: var(--tft-mark-color, var(--wp--preset--color--green));
	opacity: var(--tft-mark-opacity, 0.07);
	-webkit-mask-image: url("assets/img/tree.svg");
	mask-image: url("assets/img/tree.svg");
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-position: center;
	mask-position: center;
}

/* Bleeds past the right edge, vertically centred. */
.tft-mark--right::after {
	top: 50%;
	right: clamp(-320px, -14vw, -90px);
	transform: translateY(-50%);
}

.tft-mark--left::after {
	top: 50%;
	left: clamp(-320px, -14vw, -90px);
	transform: translateY(-50%);
}

/* Rooted at the bottom edge — the tree reads as growing out of the section. */
.tft-mark--bottom::after {
	left: 50%;
	bottom: clamp(-300px, -22vw, -140px);
	transform: translateX(-50%);
	width: clamp(520px, 70vw, 1100px);
}

/* On dark panels the mark is cream and needs to sit back further. */
.tft-panel--dark.tft-mark {
	--tft-mark-color: var(--wp--preset--color--base);
	--tft-mark-opacity: 0.06;
}

/* B. The ring: concentric arcs with orbiting dots, echoing the emblem's
   halo — redrawn in brand colours, since the logo's yellow glow is not part
   of the palette. Pure CSS/SVG, so it scales and themes cleanly. */
.tft-ring {
	position: relative;
	isolation: isolate;
	/* The rings are larger than the band that holds them, so they have to be
	   clipped or they bleed into the neighbouring section. */
	overflow: clip;
}

.tft-ring::before {
	content: "";
	position: absolute;
	z-index: -1;
	pointer-events: none;
	top: 50%;
	left: 50%;
	translate: -50% -50%;
	width: clamp(520px, 62vw, 900px);
	aspect-ratio: 1;
	opacity: 0.2;
	/* Three hairline rings, one per step. A radial gradient with hard stops
	   draws outlines; box-shadow spread would fill solid discs instead. */
	background: radial-gradient(
		circle at 50% 50%,
		transparent 0 calc(33.3% - 0.5px),
		currentColor calc(33.3% - 0.5px) calc(33.3% + 0.5px),
		transparent calc(33.3% + 0.5px) calc(66.6% - 0.5px),
		currentColor calc(66.6% - 0.5px) calc(66.6% + 0.5px),
		transparent calc(66.6% + 0.5px) calc(100% - 0.5px),
		currentColor calc(100% - 0.5px) 100%,
		transparent 100%
	);
}

/* C. A quiet leaf lattice for large flat fields, at the density of a
   letterpress tint rather than a wallpaper. */
.tft-lattice {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cg fill='none' stroke='%23566E50' stroke-width='1.1' stroke-linecap='round' opacity='0.16'%3E%3Cpath d='M30 46c0-9 7-16 16-16 0 9-7 16-16 16z'/%3E%3Cpath d='M30 46c9 0 16 7 16 16-9 0-16-7-16-16z'/%3E%3Cpath d='M46 30v32'/%3E%3Cpath d='M90 106c0-9-7-16-16-16 0 9 7 16 16 16z'/%3E%3Cpath d='M90 106c-9 0-16 7-16 16 9 0 16-7 16-16z'/%3E%3Cpath d='M74 90v32'/%3E%3C/g%3E%3C/svg%3E");
	background-size: 120px 120px;
	background-repeat: repeat;
}

@media (prefers-reduced-motion: no-preference) {
	/* The rooted tree drifts a few pixels on scroll — enough to feel alive,
	   far too little to distract. */
	@supports (animation-timeline: view()) {
		.tft-mark--bottom::after {
			animation: tft-drift linear both;
			animation-timeline: view();
			animation-range: entry 0% exit 100%;
		}

		@keyframes tft-drift {
			from { transform: translateX(-50%) translateY(26px); }
			to   { transform: translateX(-50%) translateY(-26px); }
		}
	}
}

/* Dark panels: force readable descendants without per-block overrides. */
.tft-panel--dark,
.tft-panel--dark :is(h1, h2, h3, h4, h5, p, li, figcaption, cite) {
	color: var(--wp--preset--color--base);
}

.tft-panel--dark .tft-eyebrow,
.tft-panel--dark :is(h6) {
	color: var(--wp--preset--color--clay);
}

.tft-panel--dark .tft-lede {
	color: color-mix(in srgb, var(--wp--preset--color--base) 82%, transparent);
}

.tft-panel--dark a:where(:not(.wp-block-button__link)) {
	color: var(--wp--preset--color--blush);
	text-decoration-color: color-mix(in srgb, var(--wp--preset--color--blush) 45%, transparent);
}

.tft-panel--dark .wp-block-button__link {
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--green-deep);
}

.tft-panel--dark .wp-block-button__link:hover {
	background: var(--wp--preset--color--blush);
	color: var(--wp--preset--color--green-deep);
}

.tft-panel--dark .is-style-outline .wp-block-button__link,
.tft-panel--dark .wp-block-button.is-style-outline > .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--base);
	border-color: color-mix(in srgb, var(--wp--preset--color--base) 45%, transparent);
}

.tft-panel--dark .is-style-outline .wp-block-button__link:hover {
	background: color-mix(in srgb, var(--wp--preset--color--base) 12%, transparent);
	border-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--base);
}

/* =========================================================================
   5. Buttons
   ========================================================================= */

.wp-block-button__link {
	transition: background-color 200ms var(--tft-ease), color 200ms var(--tft-ease),
		transform 200ms var(--tft-ease), box-shadow 200ms var(--tft-ease), border-color 200ms var(--tft-ease);
	will-change: transform;
}

.wp-block-button__link:hover {
	transform: translateY(-2px);
	box-shadow: 0 12px 28px -14px rgba(75, 51, 59, 0.55);
}

.wp-block-button.is-style-outline > .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--green-deep);
	border: 1px solid var(--wp--preset--color--clay);
	padding: 1.05rem 2.1rem;
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover {
	background: var(--wp--preset--color--green-deep);
	border-color: var(--wp--preset--color--green-deep);
	color: var(--wp--preset--color--base);
}

/* Quiet text button with a travelling arrow. */
.wp-block-button.is-style-tft-text > .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--green);
	padding: 0.35rem 0;
	border-radius: 0;
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--green) 30%, transparent);
	letter-spacing: 0.04em;
}

.wp-block-button.is-style-tft-text > .wp-block-button__link::after {
	content: " →";
	display: inline-block;
	transition: transform 200ms var(--tft-ease);
}

.wp-block-button.is-style-tft-text > .wp-block-button__link:hover {
	transform: none;
	box-shadow: none;
	color: var(--wp--preset--color--green-deep);
	border-bottom-color: var(--wp--preset--color--green-deep);
}

.wp-block-button.is-style-tft-text > .wp-block-button__link:hover::after {
	transform: translateX(5px);
}

/* =========================================================================
   6. Cards
   ========================================================================= */

.tft-card {
	position: relative;
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--linen);
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.6rem, 3vw, 2.25rem);
	transition: transform 260ms var(--tft-ease), box-shadow 260ms var(--tft-ease), border-color 260ms var(--tft-ease);
	/* Needed where the card is a block child of a stretched column, which does
	   not pass its height down on its own. */
	height: 100%;
}

/* A grid item already stretches to the tallest in its row. Asking for 100% on
   top of that makes the row resolve against max-content, so every card grows
   taller than its content needs and the short ones end in a pool of blank. */
.is-layout-grid > .tft-card {
	height: auto;
}

.tft-card:hover {
	transform: translateY(-4px);
	border-color: color-mix(in srgb, var(--wp--preset--color--clay) 70%, transparent);
	box-shadow: var(--wp--preset--shadow--lift);
}

.tft-card :is(h2, h3, h4) {
	margin-top: 0;
}

/* Make the whole card clickable when it contains a .tft-stretch link. */
.tft-card:has(.tft-stretch) {
	cursor: pointer;
}

.tft-stretch::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	z-index: 1;
}

/* Bordered card variant for dark panels. */
.tft-panel--dark .tft-card {
	background: color-mix(in srgb, var(--wp--preset--color--base) 7%, transparent);
	border-color: color-mix(in srgb, var(--wp--preset--color--base) 16%, transparent);
}

.tft-panel--dark .tft-card:hover {
	background: color-mix(in srgb, var(--wp--preset--color--base) 11%, transparent);
	border-color: color-mix(in srgb, var(--wp--preset--color--clay) 60%, transparent);
	box-shadow: none;
}

/* A quieter card with only a top rule — used for dense grids. */
.tft-card--flush {
	background: transparent;
	border: 0;
	border-top: 1px solid var(--wp--preset--color--linen);
	border-radius: 0;
	padding: clamp(1.4rem, 2.6vw, 1.9rem) 0 0;
}

.tft-card--flush:hover {
	transform: none;
	box-shadow: none;
	border-top-color: var(--wp--preset--color--green);
}

/* =========================================================================
   7. Numbered steps
   ========================================================================= */

.tft-step {
	counter-increment: tft-step;
	position: relative;
	padding-top: 2.4rem;
}

.tft-steps {
	counter-reset: tft-step;
}

.tft-step::before {
	content: counter(tft-step, decimal-leading-zero);
	position: absolute;
	top: 1.1rem;
	left: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--md);
	color: var(--wp--preset--color--clay);
	letter-spacing: 0.06em;
}

/* =========================================================================
   8. Lists
   ========================================================================= */

/* A wrapped item has to read as one item. At body leading the second line
   drifts so far from the first that it looks like a separate entry, which is
   exactly what goes wrong in a narrow column. So the leading inside an item
   goes tight, and the separation moves to the gap between items — where it
   actually carries meaning. */
/* Content lists only. A navigation menu is a list too, and giving its items a
   vertical gap shunts a horizontal menu out of line. */
:is(.wp-block-list, .tft-list-check ul, ul.tft-list-check, .tft-prose :is(ul, ol)) > li {
	line-height: 1.45;
}

:is(.wp-block-list, .tft-list-check ul, ul.tft-list-check, .tft-prose :is(ul, ol)) > li + li {
	margin-top: 0.7rem;
}

.tft-list-check ul,
ul.tft-list-check {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

.tft-list-check :is(ul, ol) > li,
ul.tft-list-check > li {
	position: relative;
	padding-left: 1.85rem;
}

.tft-list-check :is(ul, ol) > li::before,
ul.tft-list-check > li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.48em;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--green);
	background: color-mix(in srgb, var(--wp--preset--color--blush) 70%, transparent);
}

.tft-panel--dark ul.tft-list-check > li::before {
	border-color: var(--wp--preset--color--clay);
	background: color-mix(in srgb, var(--wp--preset--color--clay) 40%, transparent);
}

/* =========================================================================
   8b. Devices for breaking up long copy
   ========================================================================= */

/* Fill-in-the-blank reflection prompts, in the spirit of Mad Libs.

   The blanks are real inputs and the hint under each one is the giveaway that
   makes it read as a game rather than a form. Nothing is submitted, stored or
   transmitted — there is deliberately no <form> element here, because on a
   trauma practice's site a field that looks like it might send somewhere is
   worse than no field at all. */
.tft-prompts {
	max-width: 92ch;
	margin-inline-start: 0;
	margin-inline-end: auto;
}

.tft-madlib {
	margin-top: var(--wp--preset--spacing--40);
}

.tft-madlib__line {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.15rem 0.5ch;
	margin: 0;
	padding: 1.5rem 0 1.9rem;
	border-top: 1px solid var(--wp--preset--color--linen);
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 400;
	line-height: 1.85;
}

.tft-madlib__line:last-child {
	border-bottom: 1px solid var(--wp--preset--color--linen);
}

.tft-madlib__line label {
	cursor: text;
}

.tft-madlib__mid {
	flex: 0 0 auto;
}

/* The blank: an input on a baseline rule, with its hint hanging beneath. */
.tft-madlib__blank {
	position: relative;
	flex: 1 1 12ch;
	min-width: 9ch;
	display: inline-flex;
	flex-direction: column;
}

.tft-madlib__blank input {
	width: 100%;
	font: inherit;
	color: var(--wp--preset--color--green);
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--wp--preset--color--bark);
	border-radius: 0;
	padding: 0 0.4ch 0.15rem;
	transition: border-color 180ms var(--tft-ease), background-color 180ms var(--tft-ease);
}

.tft-madlib__blank input:hover {
	background: color-mix(in srgb, var(--wp--preset--color--bark) 12%, transparent);
}

.tft-madlib__blank input:focus {
	outline: none;
	border-bottom-color: var(--wp--preset--color--green);
	background: color-mix(in srgb, var(--wp--preset--color--bark) 14%, transparent);
}

.tft-madlib__blank input:focus-visible {
	outline: 2px solid var(--wp--preset--color--green);
	outline-offset: 3px;
}

/* The hint — the thing that makes it Mad Libs. */
.tft-madlib__blank em {
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.72rem;
	font-style: normal;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--wp--preset--color--bark);
	line-height: 1.3;
	margin-top: 0.4rem;
	padding-left: 0.4ch;
	transition: color 180ms var(--tft-ease), opacity 180ms var(--tft-ease);
}

.tft-madlib__blank:focus-within em {
	color: var(--wp--preset--color--green);
}

/* Once answered, the hint steps back so the sentence reads cleanly. */
.tft-madlib__blank input:not(:placeholder-shown):not(:focus) + em {
	opacity: 0.75;
}

@media (max-width: 600px) {
	.tft-madlib__line {
		font-size: var(--wp--preset--font-size--md);
		line-height: 2;
	}

	.tft-madlib__blank {
		flex: 1 1 100%;
	}
}

/* The closing line of the prompts shares the one accent treatment. */
.tft-prompt-close {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 400;
	font-style: normal;
	line-height: 1.34;
	color: var(--wp--preset--color--green);
}

/* A line lifted out of the prose at display size. Sits in the wide column so
   it visibly interrupts the reading measure rather than continuing it. */
.tft-pull {
	max-width: 34ch;
	margin-inline: 0 auto;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 400;
	font-style: normal;
	line-height: 1.32;
	letter-spacing: -0.012em;
	color: var(--wp--preset--color--green);
	text-wrap: balance;
	position: relative;
	padding-left: 1.1em;
}

.tft-pull::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.22em;
	bottom: 0.22em;
	width: 2px;
	background: var(--wp--preset--color--clay);
}

.tft-panel--dark .tft-pull {
	color: var(--wp--preset--color--base);
}

/* Opening paragraph of a long piece, set larger to ease the reader in. */
.tft-prose-column > p:first-of-type {
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.6;
	color: var(--wp--preset--color--ink);
}

/* -------------------------------------------------------------------------
   The tree as a decorative glyph
   -------------------------------------------------------------------------
   One mask, reused wherever a section needs a small brand punctuation mark.
   Everything below is decoration, so it is masked (never an <img>) and takes
   its colour from context. */

.tft-leaf,
.tft-divider span,
.tft-scripture-ref::before,
.wp-block-separator.is-style-tft-tree::after,
.tft-eyebrow.is-centered::before,
.tft-eyebrow.is-centered::after {
	background-color: currentColor;
	-webkit-mask: url("assets/img/tree.svg") no-repeat center / contain;
	mask: url("assets/img/tree.svg") no-repeat center / contain;
}

/* Inline glyph, usable anywhere in copy. */
.tft-leaf {
	display: inline-block;
	width: 1em;
	height: 1em;
	vertical-align: -0.14em;
	color: var(--wp--preset--color--clay);
}

/* A tree-marked divider for pauses inside long copy. */
.tft-divider {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.4rem;
	margin-block: var(--wp--preset--spacing--50);
	color: var(--wp--preset--color--clay);
}

.tft-divider::before,
.tft-divider::after {
	content: "";
	flex: 1 1 auto;
	max-width: 8rem;
	height: 1px;
	background: currentColor;
	opacity: 0.55;
}

.tft-divider span {
	flex: 0 0 auto;
	width: 34px;
	height: 34px;
}

.tft-panel--dark .tft-divider {
	color: color-mix(in srgb, var(--wp--preset--color--base) 55%, transparent);
}

/* The core separator block gets the same treatment, so the tree is reachable
   from the editor without hand-written HTML. */
.wp-block-separator.is-style-tft-tree {
	position: relative;
	border: 0;
	height: 34px;
	max-width: 22rem;
	margin-inline: auto;
	background: none;
	color: var(--wp--preset--color--clay);
	overflow: visible;
}

.wp-block-separator.is-style-tft-tree::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 50%;
	height: 1px;
	background: currentColor;
	opacity: 0.5;
}

.wp-block-separator.is-style-tft-tree::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	translate: -50% -50%;
	width: 34px;
	height: 34px;
	/* Mask out the rule behind the glyph so the two never overlap. */
	box-shadow: 0 0 0 10px var(--wp--preset--color--base);
}

.has-sand-background-color .wp-block-separator.is-style-tft-tree::after {
	box-shadow: 0 0 0 10px var(--wp--preset--color--sand);
}

.tft-panel--dark .wp-block-separator.is-style-tft-tree {
	color: color-mix(in srgb, var(--wp--preset--color--base) 50%, transparent);
}

.tft-panel--dark .wp-block-separator.is-style-tft-tree::after {
	box-shadow: 0 0 0 10px var(--wp--preset--color--green-deep);
}

/* A centred eyebrow gets trees instead of plain rules. */
.tft-eyebrow.is-centered::before,
.tft-eyebrow.is-centered::after {
	content: "";
	width: 17px;
	height: 17px;
	background-color: currentColor;
	opacity: 0.85;
}

/* =========================================================================
   9. Scripture
   ========================================================================= */

.tft-scripture {
	position: relative;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 400;
	font-style: normal;
	line-height: 1.34;
	letter-spacing: -0.012em;
	text-wrap: balance;
}

.tft-scripture-ref {
	display: block;
	margin-top: 1.4rem;
	font-family: var(--wp--preset--font-family--body);
	font-style: normal;
	font-size: var(--wp--custom--eyebrow--font-size);
	font-weight: 600;
	letter-spacing: var(--wp--custom--eyebrow--letter-spacing);
	text-transform: uppercase;
	color: var(--wp--preset--color--clay);
}

/* GoDaddy's DesignSetGo plugin prints an inline rule that forces every
   `.wp-block-cover p:not(.has-text-color)` to its own text colour with
   `!important`, which turns this citation ink-dark on the scripture band. The
   pattern now ships an explicit colour, which is the exemption that selector
   itself honours — but pages already saved in the database predate that, so
   this keeps them legible without rebuilding their content. */
.tft-panel--dark .tft-scripture-ref:not(.has-text-color) {
	color: var(--wp--preset--color--base) !important;
}

/* =========================================================================
   10. FAQ (details/summary)
   ========================================================================= */

.tft-faq .wp-block-details {
	border-top: 1px solid var(--wp--preset--color--linen);
	padding: 0;
}

.tft-faq .wp-block-details:last-child {
	border-bottom: 1px solid var(--wp--preset--color--linen);
}

.tft-faq .wp-block-details summary {
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.5rem 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 400;
	line-height: 1.34;
	color: var(--wp--preset--color--ink);
	transition: color 180ms var(--tft-ease);
}

.tft-faq .wp-block-details summary::-webkit-details-marker,
.tft-faq .wp-block-details summary::marker {
	display: none;
	content: "";
}

.tft-faq .wp-block-details summary::after {
	content: "";
	flex: 0 0 auto;
	width: 15px;
	height: 15px;
	margin-top: 0.38em;
	background: var(--wp--preset--color--green);
	transition: transform 260ms var(--tft-ease);
	/* plus sign drawn with a mask so it can rotate into a minus */
	-webkit-mask: linear-gradient(#000 0 0) center/100% 1px no-repeat,
		linear-gradient(#000 0 0) center/1px 100% no-repeat;
	mask: linear-gradient(#000 0 0) center/100% 1px no-repeat,
		linear-gradient(#000 0 0) center/1px 100% no-repeat;
}

.tft-faq .wp-block-details[open] summary {
	color: var(--wp--preset--color--green);
}

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

.tft-faq .wp-block-details > :not(summary) {
	margin: 0 0 1.5rem;
	max-width: 74ch;
	color: var(--wp--preset--color--ink-soft);
}

/* =========================================================================
   11. Hero
   ========================================================================= */

.tft-hero {
	position: relative;
	isolation: isolate;
}

.tft-hero__media img {
	border-radius: var(--wp--custom--radius--lg);
}

/* Portrait frame with an offset green plate behind it. */
.tft-framed {
	position: relative;
}

.tft-framed::before {
	content: "";
	position: absolute;
	inset: 1.6rem -1.6rem -1.6rem 1.6rem;
	border: 1px solid var(--wp--preset--color--clay);
	border-radius: var(--wp--custom--radius--lg);
	z-index: -1;
}

.tft-framed img {
	border-radius: var(--wp--custom--radius--lg);
	position: relative;
	z-index: 1;
}

/* A cut-out portrait on a transparent ground. It carries its own botanical
   framing, so it gets no crop, no border and no card — just a soft wash behind
   it so it sits on the page rather than floating off it. */
.tft-cutout {
	position: relative;
	margin: 0;
}

.tft-cutout::before {
	content: "";
	position: absolute;
	z-index: 0;
	left: 50%;
	top: 46%;
	translate: -50% -50%;
	width: 92%;
	aspect-ratio: 1;
	border-radius: 50%;
	background: radial-gradient(
		circle at 50% 50%,
		color-mix(in srgb, var(--wp--preset--color--sage) 34%, transparent) 0%,
		color-mix(in srgb, var(--wp--preset--color--sage) 12%, transparent) 55%,
		transparent 72%
	);
}

.tft-cutout img {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	height: auto;
	border-radius: 0;
	/* The cut-out has no baseline of its own, so it is pinned to the bottom of
	   its column to sit on the same line as the text beside it. */
	margin-bottom: -1px;
}

.is-vertically-aligned-bottom .tft-cutout {
	margin-bottom: 0;
	align-self: flex-end;
}

/* A cut-out figure reads as standing on the band, not floating in it.

   Taking it out of flow is what makes this work: an in-flow figure either has
   to inflate the text column (which pushes empty space above the photo) or be
   nudged by an offset that drifts with the viewport. Positioned, it costs no
   layout height at all, and `bottom` anchors its base to the band edge exactly. */
@media (min-width: 782px) {
	.tft-section--seated .wp-block-column:has(.tft-cutout--flush) {
		position: relative;
		align-self: stretch;
	}

	.tft-cutout--flush {
		position: absolute;
		inset-inline: 0;
		bottom: calc(var(--wp--preset--spacing--40) * -1);
	}
}

/* =========================================================================
   12. Testimonials
   ========================================================================= */

.tft-testimonial {
	text-align: left;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.1rem;
}

/* The card uses WordPress's constrained layout, which gives every child
   `margin-inline: auto` — on a flex item that centres it. Undo it so the stars
   and attribution line up with the quote. */
.tft-testimonial > * {
	margin-inline: 0;
	width: 100%;
}

.tft-stars {
	color: var(--wp--preset--color--clay);
	letter-spacing: 0.24em;
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1;
}

.tft-testimonial blockquote,
.tft-testimonial .tft-quote {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 400;
	font-style: normal;
	line-height: 1.42;
	margin: 0;
}

/* Deliberately not pushed to the foot of the card. Testimonials never run to
   the same length, so a caption pinned to the bottom leaves a hole in the
   middle of the short ones. Sitting under its quote, the trailing space falls
   below the text where it reads as breathing room instead of a gap. */
.tft-attrib {
	margin-top: 0.4rem;
	font-size: var(--wp--preset--font-size--xs);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-soft);
	margin: 0;
}

/* =========================================================================
   13. Post / editorial content
   ========================================================================= */

/* The hero sets its own pattern: an `alignwide` container that core centres
   at wideSize, with the reading measure capped on the children inside it.
   Doing the same here means the prose lands on the hero's left edge without
   fighting core's alignwide margins, which set `auto` on both sides and win
   over anything short of !important. */
.tft-prose-column > * {
	/* Full bleed to the wide grid, as asked. A line this long needs more
	   leading than usual — with little vertical separation the eye overshoots
	   on the return sweep and re-reads the line it just finished. */
	max-width: none;
	margin-inline-end: auto;
}

/* Body copy only. The accent styles are paragraphs too, and a display quote
   at 1.8 leading falls apart. */
.tft-prose-column > :is(p, ul, ol):not([class*="tft-"]) {
	line-height: 1.8;
}

/* The gap between paragraphs has to clearly exceed the gap between lines, or
   the block reads as one undifferentiated run of text. At 1.9 leading with a
   1.5rem gap the two were nearly equal. */
.tft-prose-column > * + * {
	margin-top: 2.1rem;
}

/* Lift-outs get room around them but stay tight internally. */
.tft-prose-column > .tft-pull {
	margin-block: 2.8rem;
	line-height: 1.3;
}

.tft-prose-column > :is(h2, h3) {
	margin-top: 3.6rem;
}

/* Children that set their own width keep it — the blanket measure above is a
   default, not a cap. */
.tft-prose-column > .alignfull,
.tft-prose-column > .tft-divider,
.tft-prose-column > figure {
	max-width: none;
}

.tft-prose-column > .tft-pull {
	max-width: 46ch;
}

.tft-prose-column > .tft-scripture-block {
	max-width: 62ch;
}

/* Small print inside prose keeps its own size. */
.wp-block-group.tft-prose-column :is(.has-sm-font-size, .has-xs-font-size, .tft-aside, .tft-attrib) {
	font-size: var(--wp--preset--font-size--sm);
}



.tft-prose > * + * {
	margin-top: 1.5rem;
}

.tft-prose :is(h2) {
	margin-top: 3.25rem;
	margin-bottom: 1rem;
}

.tft-prose :is(h3) {
	margin-top: 2.5rem;
	margin-bottom: 0.75rem;
}

.tft-prose :is(ul, ol) {
	padding-left: 1.25rem;
}

.tft-prose li::marker {
	color: var(--wp--preset--color--clay);
}

.tft-prose img,
.tft-prose .wp-block-image img {
	border-radius: var(--wp--custom--radius--md);
}

.tft-prose a {
	text-underline-offset: 0.18em;
	text-decoration-thickness: 1px;
	text-decoration-color: color-mix(in srgb, var(--wp--preset--color--green) 38%, transparent);
}

.tft-prose a:hover {
	text-decoration-color: currentColor;
}

/* Post cards in loops */
.tft-post-card .wp-block-post-featured-image img {
	border-radius: var(--wp--custom--radius--md);
	transition: transform 500ms var(--tft-ease);
}

.tft-post-card:hover .wp-block-post-featured-image img {
	transform: scale(1.035);
}

.tft-post-card .wp-block-post-featured-image {
	overflow: hidden;
	border-radius: var(--wp--custom--radius--md);
	margin-bottom: 1.25rem;
}

.tft-post-card .wp-block-post-title a {
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	background-image: linear-gradient(var(--wp--preset--color--green), var(--wp--preset--color--green));
	background-size: 0% 1px;
	background-repeat: no-repeat;
	background-position: 0 100%;
	transition: background-size 280ms var(--tft-ease), color 200ms var(--tft-ease);
}

.tft-post-card:hover .wp-block-post-title a {
	color: var(--wp--preset--color--green);
	background-size: 100% 1px;
}

/* =========================================================================
   14. Forms
   ========================================================================= */

.tft-form :is(input[type="text"], input[type="email"], input[type="tel"], input[type="url"], textarea, select),
.wp-block-form :is(input[type="text"], input[type="email"], input[type="tel"], input[type="url"], textarea, select) {
	width: 100%;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md);
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--linen);
	border-radius: var(--wp--custom--radius--sm);
	padding: 0.95rem 1.1rem;
	transition: border-color 180ms var(--tft-ease), box-shadow 180ms var(--tft-ease);
}

.tft-form :is(input, textarea, select):focus,
.wp-block-form :is(input, textarea, select):focus {
	outline: none;
	border-color: var(--wp--preset--color--green);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--blush) 55%, transparent);
}

.tft-form label,
.wp-block-form label,
.wp-block-form-input__label-content {
	display: block;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	letter-spacing: 0.02em;
	margin-bottom: 0.45rem;
	color: var(--wp--preset--color--ink);
}

.tft-form textarea,
.wp-block-form textarea {
	min-height: 168px;
	resize: vertical;
}

/* The contact card carries no form by design — see the copy on the page. The
   email address is the primary action, so it gets the emphasis a submit button
   would otherwise have. */
.tft-contact a[href^="mailto:"]:not(.wp-block-button__link) {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lg);
	overflow-wrap: anywhere;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

/* =========================================================================
   15. Footer
   ========================================================================= */

.tft-footer a:where(:not(.wp-block-button__link)) {
	text-decoration: none;
	color: color-mix(in srgb, var(--wp--preset--color--base) 80%, transparent);
	transition: color 180ms var(--tft-ease);
}

.tft-footer a:where(:not(.wp-block-button__link)):hover {
	color: var(--wp--preset--color--blush);
}

.tft-footer .wp-block-social-links .wp-social-link {
	background: color-mix(in srgb, var(--wp--preset--color--base) 10%, transparent);
	transition: background-color 180ms var(--tft-ease), transform 180ms var(--tft-ease);
}

/* The block's own icon-colour attribute does not survive hand-authored markup,
   so set the glyph fill here where the dark panel context is known. */
.tft-footer .wp-block-social-links .wp-social-link svg {
	fill: var(--wp--preset--color--base);
	transition: fill 180ms var(--tft-ease);
}

.tft-footer .wp-block-social-links .wp-social-link:hover {
	background: var(--wp--preset--color--blush);
	transform: translateY(-2px);
}

.tft-footer .wp-block-social-links .wp-social-link:hover svg {
	fill: var(--wp--preset--color--green-deep);
}

/* A long address in a narrow footer column would otherwise overflow. */
.tft-footer a[href^="mailto:"] {
	overflow-wrap: anywhere;
}

.tft-footer__legal {
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.65;
	color: color-mix(in srgb, var(--wp--preset--color--base) 62%, transparent);
}

/* Crisis notice — deliberately high-contrast, never decorative. */
.tft-crisis {
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--clay) 55%, transparent);
	border-radius: var(--wp--custom--radius--md);
	padding: 1.15rem 1.35rem;
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.6;
}

/* =========================================================================
   16. Reveal on scroll
   ========================================================================= */

/* Content is visible by default. The animation is only armed once the head
   script has confirmed IntersectionObserver support and no reduced-motion
   preference — so nothing is ever hidden by a script that did not run. */
.tft-js .tft-reveal {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 700ms var(--tft-ease), transform 700ms var(--tft-ease);
	transition-delay: var(--tft-delay, 0ms);
}

.tft-js .tft-reveal.is-visible {
	opacity: 1;
	transform: none;
}

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

	.tft-reveal {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* =========================================================================
   17. Responsive
   ========================================================================= */

@media (max-width: 781px) {
	/* The wordmark is already in the logo; dropping the repeated site title
	   leaves room for the booking button beside the menu toggle. */
	.tft-header .wp-block-site-title {
		display: none;
	}

	.tft-header__cta .wp-block-button__link {
		padding: 0.7rem 1.05rem;
		font-size: 0.75rem;
		letter-spacing: 0.03em;
	}

	.tft-framed::before {
		inset: 1rem -1rem -1rem 1rem;
	}

	.tft-faq .wp-block-details summary {
		font-size: var(--wp--preset--font-size--md);
	}

	.tft-hide-mobile {
		display: none !important;
	}
}

@media (min-width: 782px) {
	.tft-hide-desktop {
		display: none !important;
	}
}

/* =========================================================================
   18. Print
   ========================================================================= */

@media print {
	.tft-header,
	.tft-footer,
	.wp-block-buttons {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
	}
}

/* =========================================================================
   19. Post cards — layout asserted independently of saved markup
   ========================================================================= */

/* Pages saved before the post template carried a grid layout render with
   `is-layout-flow`, which stacks the cards at full width and blows each
   featured image up to the width of the page.
 *
 * The fix belongs here rather than in the page content: those pages may since
 * have been edited by hand, and rewriting them to correct a layout class would
 * destroy that work. Asserting the grid in CSS fixes every copy of the pattern,
 * old and new, and touches nobody's words. */
.wp-block-post-template:has(.tft-post-card) {
	display: grid;
	/* auto-fit, not auto-fill: with three posts on the homepage, auto-fill would
	   reserve a fourth empty track on a wide screen and squeeze the cards. The
	   260px floor is what lets three sit across the ~950px content column —
	   300px needed 974px once the gaps were counted, so the third wrapped. */
	grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
	gap: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
	padding: 0;
	list-style: none;
}

/* Saved markup still carries `is-layout-flow`, and WordPress gives flow-layout
   siblings a `margin-block-start` of one block gap. Switching the container to
   grid does not remove those margins, so every card after the first was pushed
   down by exactly one gap — the cards in a row started at different heights
   while their images were identical. Zeroing them is what actually aligns the
   row; the grid's own `gap` already provides the spacing. */
.wp-block-post-template:has(.tft-post-card) > * {
	margin-block: 0;
}

/* Featured images carry their ratio in the block's inline style on new saves.
   Older markup has none, so the intrinsic height of a 2000px photograph wins. */
.tft-post-card .wp-block-post-featured-image {
	margin-bottom: 0;
}

.tft-post-card .wp-block-post-featured-image img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--md);
}

/* =========================================================================
   20. Journal filter
   ========================================================================= */

.tft-term-filter {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 0.65rem;
	margin-top: var(--wp--preset--spacing--40);
}

.tft-term-filter .tft-term {
	display: inline-block;
	padding: 0.4em 0.95em;
	border: 1px solid var(--wp--preset--color--linen);
	border-radius: 999px;
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--ink-soft);
	font-size: var(--wp--preset--font-size--xs);
	letter-spacing: 0.04em;
	text-decoration: none;
	transition: border-color 180ms var(--tft-ease), color 180ms var(--tft-ease);
}

.tft-term-filter a.tft-term:hover,
.tft-term-filter a.tft-term:focus-visible {
	border-color: var(--wp--preset--color--sage);
	color: var(--wp--preset--color--green);
}

/* The current filter is marked by fill as well as colour, so it still reads
   where hue alone would not. */
.tft-term-filter .tft-term.is-current {
	background: var(--wp--preset--color--green);
	border-color: var(--wp--preset--color--green);
	color: var(--wp--preset--color--base);
}
