/*
Theme Name: Edison 2026
Theme URI: https://www.theedisonschool.com/
Author: Acton House
Description: Block theme for The Edison School. Full-bleed colour-band sections, Instrument Serif display type, and reading-comfort controls for families who need them. Built on core Gutenberg blocks so staff can edit every word without touching code.
Version: 1.1.1
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: edison-2026
Tags: full-site-editing, block-patterns, education, one-column, custom-colors
*/

/* ==========================================================================
   1. Reading comfort — driven by the header controls, persisted per visitor.
   ========================================================================== */

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	overflow-x: hidden;
	scroll-padding-top: 84px;
}

/* One red, everywhere. Every filled red button and chip on the site — the
   "Come see the school" chip, the "Give" chip, the closing call to action —
   reads from these two, so they can never drift apart again. Edison red is
   the fill; crimson is the darker press state. Change them here, once. */
:root {
	--tes-red: var(--wp--preset--color--edison-red, #BC1823);
	--tes-red-hover: var(--wp--preset--color--crimson, #8E1119);
}

html[data-text="larger"]  { font-size: 112%; }
html[data-text="largest"] { font-size: 126%; }
html[data-spacing="wide"] body { letter-spacing: 0.035em; }

body {
	margin: 0;
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
}

*, *::before, *::after { box-sizing: border-box; }

img { max-width: 100%; height: auto; }

:focus-visible {
	outline: 2px solid var(--wp--preset--color--aqua);
	outline-offset: 4px;
}

::selection {
	background: var(--wp--preset--color--aqua);
	color: var(--wp--preset--color--night);
}

.tes-skip-link {
	position: absolute;
	left: -9999px;
	top: 8px;
	z-index: 99;
	background: var(--wp--preset--color--bone);
	color: var(--wp--preset--color--night);
	padding: 12px 20px;
	font: 600 15px/1 var(--wp--preset--font-family--body);
	text-decoration: none;
}
.tes-skip-link:focus { left: 16px; }

/* ==========================================================================
   2. Section bands. Each band sets the ink/rule variables its children read,
      so an editor only ever chooses a background colour.
   ========================================================================== */

.tes-band {
	--tes-ink: var(--wp--preset--color--bone);
	--tes-body: #9FADAA;
	--tes-muted: #8B9C99;
	--tes-accent: var(--wp--preset--color--rose);
	--tes-rule: rgba(244, 237, 226, 0.16);
	--tes-min: 290px;

	padding: clamp(70px, 10vh, 130px) clamp(20px, 6vw, 80px);
	position: relative;
}

.tes-band > * { max-width: 1180px; margin-inline: auto; }

/* --- the colour journey, dark to light ---------------------------------- */

.tes-band.has-night-background-color      { --tes-body: #9FADAA; --tes-muted: #8B9C99; --tes-accent: #8B9C99; }
.tes-band.has-dusk-background-color       { --tes-body: #A9BAB7; --tes-muted: #8B9C99; --tes-accent: var(--wp--preset--color--rose); }
.tes-band.has-deep-teal-background-color  { --tes-body: #7C8D8A; --tes-muted: #8B9C99; --tes-accent: var(--wp--preset--color--rose); }
.tes-band.has-forest-background-color     { --tes-body: #8FA5A2; --tes-muted: #8FA5A2; --tes-accent: var(--wp--preset--color--rose); }
.tes-band.has-pine-background-color       { --tes-body: #9CB2AF; --tes-muted: #9CB2AF; --tes-accent: var(--wp--preset--color--rose); }

.tes-band.has-plum-background-color {
	--tes-ink: #FCEFE7; --tes-body: #D6ADA6; --tes-muted: #D6ADA6;
	--tes-accent: var(--wp--preset--color--rose); --tes-rule: rgba(252, 239, 231, 0.2);
}
.tes-band.has-brick-dark-background-color {
	--tes-ink: #FCEFE7; --tes-body: #E4C3BE; --tes-muted: #E4C3BE;
	--tes-accent: #F5C3BD; --tes-rule: rgba(252, 239, 231, 0.2);
}
.tes-band.has-brick-background-color {
	--tes-ink: #FFF6F0; --tes-body: #F6D3CC; --tes-muted: #FBDDD6;
	--tes-accent: #FBDDD6; --tes-rule: rgba(255, 246, 240, 0.28);
}
.tes-band.has-sand-background-color,
.tes-band.has-warm-sand-background-color,
.tes-band.has-cream-background-color {
	--tes-ink: #241812; --tes-body: #5E4A3C; --tes-muted: #5E4A3C;
	--tes-accent: var(--wp--preset--color--crimson); --tes-rule: #241812;
}
.tes-band.has-warm-sand-background-color { --tes-rule: #E0D3C0; }
.tes-band.has-cream-background-color { --tes-rule: #DFD0BB; }

/* Light bands need dark links and buttons that read on cream. */
.tes-band.has-sand-background-color a:not(.wp-element-button),
.tes-band.has-warm-sand-background-color a:not(.wp-element-button),
.tes-band.has-cream-background-color a:not(.wp-element-button) { color: #05605F; }
.tes-band.has-sand-background-color a:not(.wp-element-button):hover,
.tes-band.has-warm-sand-background-color a:not(.wp-element-button):hover,
.tes-band.has-cream-background-color a:not(.wp-element-button):hover { color: var(--wp--preset--color--crimson); }

.tes-band :where(h1, h2, h3, h4) { color: var(--tes-ink); }
.tes-band :where(p, li) { color: var(--tes-body); }

/* A tall band that centres its content — used for the hero and the question. */
.tes-band--tall {
	min-height: 100svh;
	display: grid;
	align-content: center;
	padding-block: clamp(80px, 10vh, 130px) clamp(76px, 9vh, 116px);
}
.tes-band--tall-92 { min-height: 92svh; display: grid; align-content: center; }

/* The hero runs flush to the page padding rather than inside the 1180px
   measure, so every line starts on the same left edge. */
.tes-band--tall > * { max-width: none; margin-inline: 0; }
.tes-band--tall > h1 { max-width: 16ch; }
.tes-band--tall > .tes-search { max-width: 820px; }
.tes-band--tall > .tes-grid--pair { max-width: 1000px; }

/* ==========================================================================
   3. Type utilities — registered as block styles so they are clickable.
   ========================================================================== */

.tes-eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: 13px;
	font-weight: 400;
	line-height: 1.6;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--tes-accent) !important;
	margin: 0 0 26px;
}

.tes-display {
	font-family: var(--wp--preset--font-family--display);
	letter-spacing: -0.02em;
	text-wrap: balance;
}

.tes-serif-note {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 2vw, 27px);
	line-height: 1.45;
	color: var(--tes-ink) !important;
}

.tes-lede { font-size: 17.5px; line-height: 1.75; text-wrap: pretty; max-width: 56ch; }

.tes-fineprint { font-size: 14px; line-height: 1.6; color: var(--tes-muted) !important; }

/* "Specialized instruction for students with learning deficits."
   The line is drawn on scroll: edison.js wraps the text in .tes-strike__ink
   and adds .is-struck when the paragraph reaches the reader. Nothing in the
   editor has to change — the wrapper is added at runtime. */
.tes-strike {
	text-decoration: none;
	color: var(--tes-muted) !important;
}
.tes-strike .tes-strike__ink {
	background-image: linear-gradient(var(--wp--preset--color--coral), var(--wp--preset--color--coral));
	background-repeat: no-repeat;
	background-position: 0 0.62em;
	background-size: 0% 2px;
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
	/* No transition on purpose — edison.js sets this width directly off the
	   scroll position every frame, so the line fills in lockstep with the
	   scroll itself rather than playing a timed animation once triggered. */
}
.tes-strike.is-struck .tes-strike__ink { background-size: 100% 2px; }

/* No JavaScript, no animation: fall back to a plain rule through the text. */
.no-js .tes-strike,
html[data-motion="off"] .tes-strike { text-decoration: line-through; text-decoration-color: var(--wp--preset--color--coral); text-decoration-thickness: 2px; }
html[data-motion="off"] .tes-strike .tes-strike__ink { background-image: none; }

@media (prefers-reduced-motion: reduce) {
	.tes-strike { text-decoration: line-through; text-decoration-color: var(--wp--preset--color--coral); text-decoration-thickness: 2px; }
	.tes-strike .tes-strike__ink { background-image: none; }
}

/* The 29 / K–12 / 2012 / 6:1 figures, and the 1-2-3 step numerals. */
.tes-figure {
	display: block;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(48px, 6vw, 88px);
	line-height: 0.9;
	letter-spacing: -0.02em;
	color: var(--tes-ink) !important;
	margin: 0;
}
.tes-figure + p { margin-top: 16px; font-size: 15.5px; line-height: 1.65; }

.tes-step-num {
	display: block;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(44px, 5vw, 68px);
	line-height: 1;
	color: var(--wp--preset--color--crimson) !important;
	margin: 0 0 18px;
}

.tes-timestamp {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: 14px;
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.16em;
	color: var(--tes-muted) !important;
	margin: 0 0 16px;
}

/* ==========================================================================
   4. Layout utilities — grids that stay sane when an editor adds a child.
   ========================================================================== */

.tes-grid {
	display: grid;
	gap: clamp(24px, 3.4vw, 48px);
	grid-template-columns: repeat(auto-fit, minmax(var(--tes-min), 1fr));
}
.tes-grid--wide   { --tes-min: 300px; gap: clamp(30px, 4.5vw, 64px); }
.tes-grid--stats  { --tes-min: 190px; gap: clamp(28px, 4vw, 44px); }
.tes-grid--steps  { --tes-min: 260px; }
.tes-grid--pair   { --tes-min: 290px; gap: clamp(18px, 3vw, 54px); }

/* Bordered rows: promises, the kids here, the daily schedule. */
.tes-rows { display: grid; }
.tes-rows > * {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(var(--tes-min), 1fr));
	gap: 14px 48px;
	padding: clamp(24px, 3.2vh, 40px) 0;
	border-top: 1px solid var(--tes-rule);
	margin: 0;
}
.tes-rows > *:last-child { border-bottom: 1px solid var(--tes-rule); }

/* The promises close without a rule under the last one. */
#promises .tes-rows > *:last-child { border-bottom: 0; }

/* "The kids here" keeps only the dividers between rows — no rule top or bottom. */
#kids .tes-rows > *:first-child { border-top: 0; }
#kids .tes-rows > *:last-child { border-bottom: 0; }

/* The section head above those rows, plus the ragging in the column beside them.
   Each description was leaving a word or two stranded on its last line; balance
   evens the lines out instead, and the 54/46 split hands the extra width to the
   headings, which keeps most of them on a single line. Below 800px the rows are
   back to one column, where neither applies. */
.tes-band .tes-kids__head {
	max-width: 22ch;
	margin: 0 0 clamp(30px, 4.5vh, 56px);
	text-wrap: balance;
}
#kids .tes-rows > * > p { text-wrap: balance; }
/* Same treatment on the day timeline — "Lunch and moving around" was ending on
   a single stranded word. */
.tes-timeline__stop p:not(.tes-timestamp) { text-wrap: balance; }
@media (min-width: 800px) {
	#kids .tes-rows > * { grid-template-columns: 1.08fr 0.92fr; }
}
.tes-rows > * > p { align-self: center; margin: 0; }
.tes-rows > * > h3 { margin: 0; }

/* The numbered promise headings carry their index above the line. */
.tes-rows .tes-index {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: 13px;
	line-height: 1;
	letter-spacing: 0.2em;
	color: var(--wp--preset--color--aqua);
	margin-bottom: 16px;
}
.tes-band.has-brick-dark-background-color .tes-rows .tes-index,
.tes-band.has-plum-background-color .tes-rows .tes-index { color: var(--wp--preset--color--rose); }

/* Steps 1–3. The numeral carries the step; no rule needed above it. */
.tes-step { border-top: 0; padding-top: 0; }

/* Sticky column beside the schedule. */
.tes-sticky { position: sticky; top: 100px; align-self: start; }
@media (max-width: 900px) { .tes-sticky { position: static; } }

/* ==========================================================================
   5. Photography
   ========================================================================== */

/* Edge-to-edge strip of portrait photos between sections. */
.tes-strip {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 0;
	padding: 0;
	max-width: none;
}
.tes-strip > * { margin: 0; max-width: none; }
.tes-strip figure, .tes-strip .wp-block-image { margin: 0; overflow: hidden; }
.tes-strip img {
	width: 100%;
	height: 100%;
	aspect-ratio: 2 / 3;
	object-fit: cover;
	display: block;
	/* Lifted from .72/.22 once the stock photography was replaced with real
	   students: at the old settings faces went muddy, and faces are the point. */
	filter: grayscale(0.10);
	opacity: 0.88;
	transition: opacity 300ms ease, filter 300ms ease;
}
/* Hover has to hang off the figure, not the img: once the lightbox wraps the
   image the trigger button sits on top of it, so `img:hover` never fires. */
.tes-strip figure:hover img, .tes-strip a:hover img, .tes-strip img:hover { opacity: 0.95; filter: grayscale(0); }

/* The strip images open in the theme's own lightbox (initStripLightbox in
   edison.js) rather than core's, because one page's block markup has already
   been flattened by an editor round-trip and core's lightbox goes with it. */
.tes-strip img { cursor: zoom-in; }
.tes-strip img:focus-visible { outline: 3px solid #FBF3E6; outline-offset: -5px; }

.tes-lightbox {
	position: fixed;
	inset: 0;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(16px, 4vw, 56px);
	background: rgba(26, 16, 10, .92);
	backdrop-filter: blur(3px);
}
.tes-lightbox[hidden] { display: none; }
html.tes-lightbox-open { overflow: hidden; }
.tes-lightbox__figure {
	margin: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	max-width: 100%;
	max-height: 100%;
}
.tes-lightbox__figure img {
	display: block;
	max-width: 100%;
	max-height: 78vh;
	width: auto;
	height: auto;
	border-radius: 10px;
	box-shadow: 0 40px 80px -40px rgba(0, 0, 0, .9);
}
.tes-lightbox button {
	position: absolute;
	background: rgba(251, 243, 230, .12);
	border: 1px solid rgba(251, 243, 230, .28);
	color: #FBF3E6;
	border-radius: 50%;
	cursor: pointer;
	line-height: 1;
	transition: background 200ms ease;
}
.tes-lightbox button:hover { background: rgba(251, 243, 230, .26); }
.tes-lightbox button:focus-visible { outline: 2px solid #FBF3E6; outline-offset: 3px; }
.tes-lightbox__close { top: clamp(12px, 2vw, 24px); right: clamp(12px, 2vw, 24px); width: 46px; height: 46px; font-size: 30px; }
.tes-lightbox__nav { top: 50%; transform: translateY(-50%); width: 50px; height: 50px; font-size: 32px; }
.tes-lightbox__nav--prev { left: clamp(8px, 2vw, 24px); }
.tes-lightbox__nav--next { right: clamp(8px, 2vw, 24px); }
@media (max-width: 600px) {
	.tes-lightbox__nav { top: auto; bottom: clamp(12px, 3vw, 24px); transform: none; }
}

/* A single wide banner photo. */
.tes-banner { max-width: none; }
.tes-banner img { width: 100%; aspect-ratio: 24 / 9; object-fit: cover; display: block; opacity: 0.9; }

/* Background photo washed behind a band. */
.tes-band--photo > .tes-bg {
	position: absolute;
	inset: 0;
	max-width: none;
	margin: 0;
	overflow: hidden;
	pointer-events: none;
}
.tes-band--photo > .tes-bg img {
	width: 100%; height: 100%;
	object-fit: cover;
	opacity: 0.28;
	filter: grayscale(0.32) contrast(1.05);
}
.tes-band--photo > .tes-bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg, var(--tes-wash) 6%, color-mix(in srgb, var(--tes-wash) 66%, transparent) 62%, color-mix(in srgb, var(--tes-wash) 28%, transparent));
}
.tes-band--photo.has-dusk-background-color { --tes-wash: #071A20; }
.tes-band--photo.has-plum-background-color { --tes-wash: #3E1B20; }
.tes-band--photo.has-plum-background-color > .tes-bg img { opacity: 0.16; filter: grayscale(0.3); }
.tes-band--photo.has-plum-background-color > .tes-bg::after {
	background: linear-gradient(180deg, #3E1B20 4%, rgba(62, 27, 32, 0.7) 55%, #3E1B20);
}
.tes-band--photo > :not(.tes-bg) { position: relative; }

/* The sunrise wedge between the brick and sand bands.
   The 1px negative margins matter: block positions land on fractional pixels
   this far down the page, and without the overlap the near-black page
   background shows through as a hairline at each end of the gradient. */
.tes-sunrise {
	display: block;
	height: clamp(92px, 16vh, 192px);
	background: linear-gradient(180deg, #93332B, #C9704F 42%, #E9D9C6);
	max-width: none;
	margin-block: -1px;
	position: relative;
	z-index: 1;
}

/* ==========================================================================
   6. Header
   ========================================================================== */

.tes-header {
	position: sticky;
	top: 0;
	z-index: 60;
	background: rgba(5, 8, 12, 0.86);
	backdrop-filter: blur(12px);
	border-bottom: 1px solid rgba(244, 237, 226, 0.16);
}
.tes-header__inner {
	max-width: 1180px;
	margin: 0 auto;
	padding: 9px clamp(20px, 6vw, 80px);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 16px;
}
.tes-header__logo { margin-right: auto; display: flex; align-items: center; }
.tes-header__logo img { height: clamp(34px, 3.4vw, 44px); width: auto; display: block; }

/* Everything that isn't the logo rides on the right-hand end of the bar. */
.tes-header__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	gap: 10px 12px;
}

.tes-pill {
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	padding: 0 16px;
	border-radius: 999px;
	border: 1px solid rgba(244, 237, 226, 0.28);
	background: transparent;
	color: var(--wp--preset--color--bone);
	font: 500 13px/1 var(--wp--preset--font-family--body);
	text-decoration: none;
	cursor: pointer;
	transition: background 160ms ease, color 160ms ease;
}
.tes-pill:hover { background: var(--wp--preset--color--bone); color: var(--wp--preset--color--night); }

.tes-pill--cta {
	background: var(--tes-red);
	border-color: var(--tes-red);
	color: #FFF8F2;
	padding: 0 20px;
	font-size: 13.5px;
}
.tes-pill--cta:hover { background: var(--tes-red-hover); border-color: var(--tes-red-hover); color: #fff; }

/* Reading settings popover */
.tes-comfort { position: relative; }
.tes-comfort__panel {
	display: none;
	position: absolute;
	top: 100%;
	right: 0;
	margin-top: 9px;
	padding: 16px;
	border-radius: 18px;
	background: rgba(5, 8, 12, 0.97);
	backdrop-filter: blur(12px);
	border: 1px solid rgba(244, 237, 226, 0.22);
	gap: 8px;
	width: 250px;
	z-index: 70;
}
.tes-comfort__panel[data-open="true"] { display: grid; }
.tes-comfort__panel p {
	font: 400 13.5px/1.5 var(--wp--preset--font-family--body);
	color: #9FADAA;
	margin: 0 0 4px;
}
.tes-comfort__panel .tes-pill { min-height: 42px; font-size: 13.5px; text-align: left; justify-content: flex-start; }

/* ==========================================================================
   7. Footer
   ========================================================================== */

.tes-footer { background: var(--wp--preset--color--espresso); color: #A99483; }
.tes-footer a { color: #EADCCC; text-decoration: none; }
.tes-footer a:hover { color: #fff; text-decoration: underline; }
.tes-footer__inner {
	max-width: 1180px;
	margin: 0 auto;
	padding: clamp(46px, 6vh, 74px) clamp(20px, 6vw, 80px);
	display: grid;
	gap: clamp(28px, 4vw, 48px);
	grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
}
.tes-footer p, .tes-footer li { color: #BCA795; font-size: 16px; line-height: 1.7; }
.tes-footer h2, .tes-footer h3 { color: #EADCCC; }
.tes-footer__label {
	display: block;
	font: 400 12px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: #A18B78;
	margin-bottom: 18px;
}
.tes-footer__label--stacked { margin-top: 22px; }

/* The one call to action in the footer. Same red pill as the header CTA, so a
   family that has scrolled past the top of the page still has a way in. */
.tes-footer__cta { margin-top: 26px; }
.tes-footer__cta .wp-element-button {
	background: var(--tes-red);
	color: #FFF6F0;
	border-radius: 999px;
	padding: 15px 28px;
	font-size: 16px;
	text-decoration: none;
}
.tes-footer .tes-footer__cta a.wp-element-button:hover,
.tes-footer .tes-footer__cta a.wp-element-button:focus-visible {
	background: var(--tes-red-hover);
	color: #FFF6F0;
	text-decoration: none;
}
.tes-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.tes-footer__logo { height: 54px; width: auto; display: block; margin-bottom: 22px; }
.tes-footer__bar { border-top: 1px solid #3A2C22; }
.tes-footer__bar > div {
	max-width: 1180px;
	margin: 0 auto;
	padding: 20px clamp(20px, 6vw, 80px);
	display: flex;
	flex-wrap: wrap;
	gap: 12px 24px;
	align-items: center;
	justify-content: space-between;
}
.tes-footer__bar ul { display: flex; flex-wrap: wrap; gap: 18px; }
.tes-badges { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0; padding: 0; }
.tes-badges a {
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	padding: 0 16px;
	border-radius: 999px;
	border: 1px solid #48372B;
	font: 500 14px/1 var(--wp--preset--font-family--body);
}
.tes-badges a:hover { border-color: #EADCCC; text-decoration: none; }

/* ==========================================================================
   8. Buttons inside light bands
   ========================================================================== */

.tes-band.has-sand-background-color .wp-block-button.is-style-outline .wp-element-button,
.tes-band.has-warm-sand-background-color .wp-block-button.is-style-outline .wp-element-button,
.tes-band.has-paper-background-color .wp-block-button.is-style-outline .wp-element-button,
.tes-band.has-cream-background-color .wp-block-button.is-style-outline .wp-element-button {
	border: 2px solid #241812;
	color: #241812;
	background: transparent;
	/* Core's outline style ships its own em-based padding, which overrides the
	   theme.json button padding and renders an outline button ~11px shorter
	   than a filled one. That only goes unnoticed when the two sit in the same
	   flex row and stretch to match; alone, the button is visibly too small. */
	padding: 18px 30px;
}
.tes-band.has-sand-background-color .wp-block-button.is-style-outline .wp-element-button:hover,
.tes-band.has-warm-sand-background-color .wp-block-button.is-style-outline .wp-element-button:hover,
.tes-band.has-paper-background-color .wp-block-button.is-style-outline .wp-element-button:hover,
.tes-band.has-cream-background-color .wp-block-button.is-style-outline .wp-element-button:hover {
	background: #241812;
	color: #FBF6EC;
}
.tes-btn-espresso .wp-element-button { background: #241812; color: #F6EDE0; }
.tes-btn-espresso .wp-element-button:hover { background: var(--tes-red); color: #fff; }

/* ==========================================================================
   9. Hero search animation
   ========================================================================== */

.tes-search {
	display: flex;
	align-items: center;
	gap: 14px;
	max-width: 820px;
	padding: 18px 22px;
	border: 1px solid rgba(244, 237, 226, 0.2);
	border-radius: 999px;
	margin: 0 0 clamp(40px, 6vh, 70px);
	background: rgba(244, 237, 226, 0.03);
}
.tes-search svg { flex: none; }
.tes-search__text {
	font: 400 clamp(15px, 1.9vw, 21px)/1.4 var(--wp--preset--font-family--body);
	color: #C9D2D0;
	min-height: 1.4em;
}
.tes-search__caret {
	width: 2px;
	height: 1.25em;
	background: var(--wp--preset--color--aqua);
	display: inline-block;
	animation: tes-blink 1.1s steps(1) infinite;
	flex: none;
}

.tes-scrollcue {
	margin-top: clamp(34px, 5.5vh, 70px);
	/* The cue animates 8px downward, so it needs room under it or the last
	   line of type clips against the bottom of the viewport. */
	padding-bottom: 18px;
	display: flex;
	align-items: center;
	gap: 12px;
	font: 400 12.5px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tes-muted);
}
.tes-scrollcue span { animation: tes-sink 2.6s ease-in-out infinite; display: inline-block; }

@keyframes tes-blink { 0%, 45% { opacity: 1; } 50%, 95% { opacity: 0; } 100% { opacity: 1; } }
@keyframes tes-sink { 0%, 100% { transform: translateY(0); opacity: 0.55; } 50% { transform: translateY(8px); opacity: 1; } }

/* Reveal on scroll */
.tes-reveal { opacity: 0; transform: translateY(18px); transition: opacity 700ms ease, transform 700ms ease; }
.tes-reveal.is-visible { opacity: 1; transform: none; }

html[data-motion="off"] *,
html[data-motion="off"] *::before,
html[data-motion="off"] *::after { animation: none !important; transition: none !important; }
html[data-motion="off"] .tes-reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after { animation: none !important; transition: none !important; }
	.tes-reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   10. Fluent Forms — styled to match the mockup's underlined fields
   ========================================================================== */

.tes-form .fluentform .ff-el-group { margin-bottom: 22px; }
.tes-form .fluentform .ff-el-input--label label {
	font: 500 14px/1.5 var(--wp--preset--font-family--body);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: #5E4A3C;
	margin-bottom: 8px;
}
.tes-form .fluentform .ff-el-input--label label .ff-el-is-required { color: var(--wp--preset--color--crimson); }
.tes-form .fluentform input[type="text"],
.tes-form .fluentform input[type="email"],
.tes-form .fluentform input[type="tel"],
.tes-form .fluentform textarea {
	min-height: 54px;
	padding: 0 2px;
	border: 0;
	border-bottom: 2px solid #C8B69F;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
	font: 400 20px/1.4 var(--wp--preset--font-family--body);
	color: #241812;
	width: 100%;
}
.tes-form .fluentform textarea { padding: 10px 2px; resize: vertical; min-height: 96px; }
.tes-form .fluentform input:focus,
.tes-form .fluentform textarea:focus {
	border-bottom-color: var(--wp--preset--color--crimson);
	outline: none;
	box-shadow: none;
}
.tes-form .fluentform input::placeholder,
.tes-form .fluentform textarea::placeholder { color: #A18B78; }
.tes-form .fluentform .ff-btn-submit {
	min-height: 56px;
	padding: 0 34px;
	border-radius: 999px;
	border: 0;
	background: var(--wp--preset--color--teal);
	color: #FFF8F2;
	font: 500 16px/1 var(--wp--preset--font-family--body);
	cursor: pointer;
	transition: background 160ms ease;
}
.tes-form .fluentform .ff-btn-submit:hover { background: #05605F; }
.tes-form .ff-message-success {
	font: 400 17px/1.75 var(--wp--preset--font-family--body);
	color: #241812;
	background: rgba(0, 128, 128, 0.08);
	border: 1px solid rgba(0, 128, 128, 0.35);
	border-radius: 14px;
	padding: 18px 20px;
}

/* ==========================================================================
   11. Coming-up list in the visit band
   ========================================================================== */

.tes-events { list-style: none; margin: 0; padding: 0; display: grid; }
.tes-events li {
	display: grid;
	gap: 5px;
	padding: 12px 0;
	border-bottom: 1px solid #DFD0BB;
}
.tes-events li:last-child { border-bottom: 0; }
.tes-events .tes-events__when {
	font: 500 12.5px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: #5E4A3C;
}
.tes-events li:first-child .tes-events__when { color: var(--wp--preset--color--crimson); }
.tes-events .tes-events__what { font: 400 17.5px/1.5 var(--wp--preset--font-family--body); color: #241812; }

.tes-phone {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(28px, 3vw, 40px);
	line-height: 1.2;
	color: #241812 !important;
	text-decoration: none;
}
.tes-phone:hover { color: var(--wp--preset--color--crimson) !important; text-decoration: underline; }

/* ==========================================================================
   12. Editor-only nudges
   ========================================================================== */

.editor-styles-wrapper .tes-band { border: 1px dashed rgba(128, 128, 128, 0.25); }

/* ==========================================================================
   13. Vertical rhythm. blockGap is 0 in theme.json so that these explicit
       margins — which match the mockup — are the single source of truth.
   ========================================================================== */

.tes-band h2 { margin: 0 0 18px; }
.tes-band h3 { margin: 0 0 10px; }
.tes-band p  { margin: 0 0 18px; }
.tes-band p:last-child { margin-bottom: 0; }
.tes-band .wp-block-buttons { margin: 0; }
.tes-band figure { margin: 0; }

.tes-band p.tes-eyebrow { margin: 0 0 26px; }
.tes-band p.tes-figure { margin: 0; }
.tes-band p.tes-timestamp { margin: 0 0 16px; }
.tes-band p.tes-step-num { margin: 0 0 18px; }

.tes-rows > * > p:last-child { margin-bottom: 0; }

/* ==========================================================================
   14. Band modifiers used by the home page
   ========================================================================== */

/* Photo bands sit flush — no padding, children run edge to edge. */
.tes-band--flush { padding: 0; }
.tes-band--flush > * { max-width: none; margin-inline: 0; }

/* Slightly shorter band for the statistics row. */
.tes-band--tight { padding-block: clamp(56px, 8vh, 100px); }

/* The two cream bands at the foot of the page. */
.tes-band--light { padding-block: clamp(60px, 9vh, 120px); }
.tes-band--closer { padding-top: 0; padding-bottom: clamp(70px, 10vh, 120px); }
.tes-band--closer > * { border-top: 2px solid #241812; padding-top: clamp(40px, 6vh, 72px); }

.tes-hero__logo img { height: clamp(38px, 4vw, 50px); width: auto; opacity: 0.85; }
.tes-hero__logo { margin: 0 0 clamp(38px, 6vh, 72px); }

/* ==========================================================================
   15. Grid variants
   ========================================================================== */

.tes-grid--top { align-items: start; }
.tes-grid--closer { --tes-min: 300px; gap: clamp(26px, 4vw, 56px); align-items: center; }

/* Rows that stack rather than split into two columns (the daily schedule). */
.tes-rows--stack > * { display: block; }
.tes-rows--snug > * { padding: clamp(22px, 3vh, 32px) 0; gap: 10px 48px; }

/* ==========================================================================
   16. The parent quotation
   ========================================================================== */

.tes-band p.tes-pullquote {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(30px, 5.4vw, 80px);
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--tes-ink) !important;
	max-width: 19ch;
	margin: 0 0 34px;
	text-wrap: pretty;
}

.tes-attribution {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: clamp(18px, 3vw, 40px);
}
.tes-attribution__who {
	font: 400 14px/1.6 var(--wp--preset--font-family--body);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: #D6ADA6;
	margin: 0;
}
.tes-attribution a { color: #FCEFE7; text-decoration: underline; text-decoration-color: rgba(252, 239, 231, 0.45); }
.tes-attribution a:hover { color: #fff; text-decoration-color: #fff; }

.tes-quote-photo { margin: clamp(40px, 6vh, 72px) 0 0 !important; max-width: 640px; }
.tes-quote-photo img { width: 100%; aspect-ratio: 32 / 9; object-fit: cover; display: block; opacity: 0.9; }

.tes-day-photo img { width: 100%; aspect-ratio: 5 / 4; object-fit: cover; display: block; }
.tes-visit-photo { margin: 0 0 clamp(18px, 2.4vw, 28px) !important; }
.tes-visit-photo img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }

/* ==========================================================================
   17. Getting started + visit details
   ========================================================================== */

.tes-payfor {
	margin-top: clamp(36px, 5vh, 64px);
	padding-top: clamp(28px, 4vh, 44px);
	border-top: 2px solid #241812;
	display: grid;
	gap: 24px;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	align-items: center;
}

.tes-visit-cols { gap: clamp(26px, 3.6vw, 56px); align-items: start; }
.tes-comingup { border-top: 2px solid #DFD0BB; padding-top: 22px; margin-top: clamp(18px, 2.4vw, 28px); }
.tes-comingup h3 { font-size: 22px; margin: 0 0 16px; }

/* The band rule variable is the heavy ink colour on sand; lists want the
   lighter hairline instead. */
.tes-band.has-sand-background-color .tes-rows > * { border-color: rgba(36, 24, 18, 0.2); }

/* ==========================================================================
   18. Hero — headline on the left, the search box and the two paragraphs
       stacked beside it on the right.
   ========================================================================== */

.tes-hero__cols {
	display: grid;
	grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
	gap: clamp(28px, 4vw, 68px);
	align-items: start;
	max-width: none;
}
@media (max-width: 960px) { .tes-hero__cols { grid-template-columns: 1fr; } }

.tes-band--tall > .tes-hero__cols { max-width: none; margin-inline: 0; }
.tes-hero__cols > h1 { max-width: 13ch; margin: 0; }

.tes-hero__aside { padding-top: clamp(4px, 1vw, 16px); }
.tes-hero__aside .tes-search { max-width: none; margin: 0 0 clamp(26px, 3.6vh, 40px); overflow: hidden; }
/* The box is half the width it used to be, so the typed line is set smaller
   and kept on one line. Keep new search queries under about 50 characters. */
.tes-hero__aside .tes-search__text {
	font-size: clamp(14.5px, 1.35vw, 17.5px);
	min-width: 0;
	white-space: nowrap;
	overflow: hidden;
}
.tes-hero__aside p:last-child { margin-bottom: 0; }

/* ==========================================================================
   19. A centred serif line that closes a section.
   ========================================================================== */

.tes-band .tes-centerline {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(23px, 2.9vw, 38px);
	line-height: 1.25;
	letter-spacing: -0.015em;
	color: var(--tes-ink) !important;
	text-align: center;
	text-wrap: balance;
	max-width: 24ch;
	margin: clamp(38px, 5.5vh, 72px) auto 0;
}

/* ==========================================================================
   20. A day here — the scroll timeline.

       The rail is drawn by the container: ::before is the full-length track,
       ::after is the filled portion, whose height edison.js writes into
       --tes-progress as the page scrolls. Each stop lights up when its dot
       passes the middle of the screen.
   ========================================================================== */

.tes-timeline {
	--tes-pad: clamp(34px, 4vw, 58px);
	--tes-rail-x: 5px;
	--tes-dot: 14px;
	--tes-gap: clamp(30px, 7vh, 74px);
	--tes-dotbg: #93332B;

	position: relative;
	padding-left: var(--tes-pad);
}

.tes-timeline::before,
.tes-timeline::after {
	content: "";
	position: absolute;
	left: var(--tes-rail-x);
	width: 2px;
	border-radius: 2px;
}
.tes-timeline::before { top: 4px; bottom: 4px; background: var(--tes-rule); }
.tes-timeline::after {
	top: 4px;
	height: var(--tes-progress, 0px);
	max-height: calc(100% - 8px);
	background: var(--tes-ink);
}

.tes-timeline__stop {
	position: relative;
	padding-block: var(--tes-gap);
	opacity: 0.34;
	transform: translateY(12px);
	transition: opacity 600ms ease, transform 600ms ease;
}
.tes-timeline__stop:first-child { padding-top: 0; }
.tes-timeline__stop:last-child  { padding-bottom: 0; }
.tes-timeline__stop.is-past,
.tes-timeline__stop.is-current { opacity: 1; transform: none; }

.tes-timeline__stop::before {
	content: "";
	position: absolute;
	left: calc(var(--tes-rail-x) - var(--tes-pad) + 1px - (var(--tes-dot) / 2));
	top: calc(var(--tes-gap) + 2px);
	width: var(--tes-dot);
	height: var(--tes-dot);
	border-radius: 50%;
	background: var(--tes-dotbg);
	box-shadow: inset 0 0 0 2px var(--tes-rule);
	transition: box-shadow 400ms ease, transform 400ms ease, background 400ms ease;
}
.tes-timeline__stop:first-child::before { top: 2px; }

.tes-timeline__stop.is-past::before {
	background: var(--tes-ink);
	box-shadow: inset 0 0 0 2px var(--tes-ink);
}
.tes-timeline__stop.is-current::before {
	background: var(--tes-ink);
	transform: scale(1.3);
	box-shadow: inset 0 0 0 3px var(--tes-ink), 0 0 0 7px color-mix(in srgb, var(--tes-ink) 20%, transparent);
}

.tes-timeline__stop h3 { margin: 0 0 10px; }
.tes-timeline__stop p:last-child { margin-bottom: 0; }

html[data-motion="off"] .tes-timeline__stop { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
	.tes-timeline__stop { opacity: 1; transform: none; }
}

/* ==========================================================================
   21. The strong call to action that sends a family to the form.
   ========================================================================== */

.tes-cta-strong { margin-top: clamp(36px, 5.5vh, 64px) !important; }
.tes-cta-strong .wp-element-button {
	background: var(--tes-red);
	color: #FFF6F0;
	font-size: 18px;
	padding: 23px 42px;
}
.tes-cta-strong .wp-element-button:hover { background: var(--tes-red-hover); color: #FFF6F0; }
.tes-cta-strong .wp-element-button:hover { background: #241812; color: #FBF6EC; }
.tes-band p.tes-cta-note { margin: 14px 0 0; font-size: 14.5px; color: var(--tes-muted) !important; text-wrap: pretty; }
/* In the visit band the button sits straight under the lede, whose own bottom
   margin already sets the gap — the section-closing margin above is too much. */
.tes-visit-cols .tes-cta-strong { margin-top: 0 !important; }

/* ==========================================================================
   22. Tennessee funding — its own band, written as three plain cards.
   ========================================================================== */

.tes-funding {
	display: grid;
	gap: clamp(18px, 2.4vw, 30px);
	grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
	margin-top: clamp(34px, 5vh, 58px);
}
.tes-fundcard {
	background: rgba(255, 255, 255, 0.58);
	border: 1px solid #E0D3C0;
	border-radius: 20px;
	padding: clamp(22px, 2.6vw, 32px);
}
.tes-band .tes-fundcard h3 { font-size: clamp(20px, 1.9vw, 26px); margin: 0 0 10px; }
.tes-band .tes-fundcard p { font-size: 16px; line-height: 1.65; margin: 0; }
.tes-band .tes-fundcard p.tes-fund-tag {
	font: 500 12px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--wp--preset--color--crimson) !important;
	margin: 0 0 14px;
}
.tes-fund-actions { margin-top: clamp(30px, 4.5vh, 50px) !important; }

/* ==========================================================================
   23. A pair of buttons reads as one decision, so both get the same width
       and height. Applies to any two-button row on either design.
   ========================================================================== */

.tes-band .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))),
.tesl .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) {
	display: inline-grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	/* Core's button layout centres its children; stretch them instead, or the
	   outline button stays short because its padding is core's, not ours. */
	align-items: stretch;
	gap: 14px;
	vertical-align: top;
}
.tes-band .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) > .wp-block-button,
.tesl .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) > .wp-block-button {
	width: 100%;
}
.tes-band .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) .wp-element-button,
.tesl .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) .wp-element-button {
	display: flex;
	width: 100%;
	height: 100%;
	align-items: center;
	justify-content: center;
	text-align: center;
}

@media (max-width: 560px) {
	.tes-band .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))),
	.tesl .wp-block-buttons:has(> .wp-block-button:nth-child(2)):not(:has(> .wp-block-button:nth-child(3))) {
		display: grid;
		grid-auto-flow: row;
	}
}

/* ==========================================================================
   24. Multi-page site (2026 redesign) — tan/terracotta band colours.

       These sit alongside the section 2 colour journey and follow the same
       convention: a background colour sets --tes-ink/--tes-body/--tes-accent,
       every child reads the variables, nothing else has to change per band.
   ========================================================================== */

.tes-band.has-tan-background-color,
.tes-band.has-tan-deep-background-color,
.tes-band.has-paper-background-color,
.tes-band.has-white-background-color {
	--tes-ink: #2A1C13; --tes-body: #5C4632; --tes-muted: #6A5343;
	--tes-accent: #A6131D; --tes-rule: rgba(42, 28, 19, 0.16);
}
.tes-band.has-terracotta-background-color {
	--tes-ink: #FCEFE7; --tes-body: #E4C3BE; --tes-muted: #E4C3BE;
	--tes-accent: #F5C3BD; --tes-rule: rgba(252, 239, 231, 0.2);
}
.tes-band.has-maroon-background-color {
	--tes-ink: #FCEFE7; --tes-body: #D6ADA6; --tes-muted: #D6ADA6;
	--tes-accent: #F09098; --tes-rule: rgba(252, 239, 231, 0.2);
}
.tes-band.has-tan-background-color a:not(.wp-element-button),
.tes-band.has-tan-deep-background-color a:not(.wp-element-button),
.tes-band.has-paper-background-color a:not(.wp-element-button),
.tes-band.has-white-background-color a:not(.wp-element-button) { color: #05605F; }
.tes-band.has-tan-background-color a:not(.wp-element-button):hover,
.tes-band.has-tan-deep-background-color a:not(.wp-element-button):hover,
.tes-band.has-paper-background-color a:not(.wp-element-button):hover,
.tes-band.has-white-background-color a:not(.wp-element-button):hover { color: var(--wp--preset--color--crimson); }
.tes-band.has-tan-background-color .tes-rows > *,
.tes-band.has-tan-deep-background-color .tes-rows > *,
.tes-band.has-cream-background-color .tes-rows > * { border-color: rgba(42, 28, 19, 0.16); }

/* The warm-hero and warm-photo-wash bands share the tan gradient glow that
   also runs behind the header — see edison_header_glow() below. Pinned so
   the header and hero glow line up seamlessly across the sticky boundary. */
.tes-band--warmglow {
	background-image:
		radial-gradient(115% 92% at 82% 12%, rgba(240,150,74,.44), rgba(248,240,225,0) 66%),
		radial-gradient(75% 62% at 82% 12%, rgba(255,196,124,.52), rgba(248,240,225,0) 62%);
	background-size: 100% 900px, 100% 900px;
	background-position: 0 -106px, 0 -106px;
	background-repeat: no-repeat;
}

/* A plain page header: eyebrow, H1, one paragraph. Used by every page except
   Home, which gets the full warm hero below. */
.tes-pagehead { padding-block: clamp(52px, 9vh, 104px) !important; }
.tes-pagehead h1 { max-width: 16ch; margin-bottom: clamp(20px, 3vh, 32px); }
.tes-pagehead .tes-lede { max-width: 56ch; }

/* A page header that carries one photo beside the copy (What a day looks
   like). The photo is deliberately modest in width — it is a quiet moment
   with a caption, not a banner — and the caption is set in the display serif
   so it reads as a line of writing rather than a filename. */
.tes-pagehead--photo .tes-pagehead__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
	gap: clamp(30px, 5vw, 72px);
	align-items: center;
}
.tes-pagehead--photo .tes-pagehead__grid > * { max-width: none; margin-inline: 0; }
.tes-pagehead--photo .tes-pagehead__text > *:first-child { margin-top: 0; }
.tes-pagehead--photo .tes-pagehead__text h1 { max-width: 14ch; }
.tes-pagehead--photo .tes-pagehead__photo { margin: 0 !important; justify-self: end; width: 100%; max-width: 380px; }
.tes-pagehead--photo .tes-pagehead__photo img {
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: 50% 34%;
	display: block;
	border-radius: 16px;
	box-shadow: 0 30px 54px -28px rgba(42, 28, 19, .5);
}
.tes-pagehead--photo .tes-pagehead__photo figcaption {
	margin: 18px 0 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(17px, 1.5vw, 21px);
	line-height: 1.45;
	color: var(--tes-ink);
	text-align: left;
}
@media (max-width: 900px) {
	.tes-pagehead--photo .tes-pagehead__grid { grid-template-columns: 1fr; gap: clamp(28px, 5vh, 40px); }
	.tes-pagehead--photo .tes-pagehead__text h1 { max-width: 16ch; }
	.tes-pagehead--photo .tes-pagehead__photo { justify-self: start; max-width: 320px; }
}

/* ==========================================================================
   25. Home — warm hero (search typewriter, headline, photo bubbles)
   ========================================================================== */

.tes-hwarm {
	position: relative;
	min-height: 82svh;
	display: grid;
	align-content: center;
	padding: clamp(80px, 10vh, 130px) clamp(20px, 6vw, 80px) clamp(60px, 8vh, 100px);
}
.tes-hwarm > * { max-width: none; margin-inline: 0; position: relative; z-index: 1; }
.tes-hwarm h1 { max-width: 16ch; margin: 0 0 clamp(28px, 4vh, 44px); }
.tes-hwarm .tes-grid--pair { max-width: 1000px; }

.tes-hwarm .tes-search {
	max-width: 820px;
	height: 62px;
	padding: 0 22px;
	background: rgba(255, 252, 246, .55);
	border: 1.5px solid rgba(42, 28, 19, .3);
	box-shadow: 0 2px 10px -6px rgba(42, 28, 19, .35);
}
.tes-hwarm .tes-search svg { stroke: #6A5343; }
.tes-hwarm .tes-search__text { color: #4A3524; }
.tes-hwarm .tes-search__caret { background: var(--tes-red); }

/* The shared page-header wash puts its brightest point a few pixels below the
   menu. On an inner page that is the whole effect; on the home hero it read as
   a plume rising out of the top of the page, unrelated to anything.
   It cannot simply be moved down: the wash is a 900px-tall gradient box, and
   sliding it leaves the box's own top edge cutting across the gradient while
   it still has visible alpha — a hard horizontal seam. So the home hero drops
   the wash entirely and lets the circle-anchored halo below do all the work. */
.tes-hwarm.tes-band--warmglow { background-image: none; }

/* With the wash gone the top of the band is flat, and the old hero padding
   read as dead space under the menu rather than as part of the glow. */
.tes-hwarm { padding-top: clamp(40px, 5vh, 68px); }

/*
 * The halo is anchored to the big photo circle rather than to the band, so it
 * reads as warmth behind the picture instead of a shape of its own. Both
 * offsets are the circle's own centre minus half the halo — change the bubble
 * geometry below and this follows it.
 */
.tes-hwarm .tes-hero-glow {
	--tes-bubble: clamp(210px, 27vw, 380px);   /* matches the big circle */
	--tes-halo: clamp(440px, 48vw, 660px);

	position: absolute;
	right: calc(clamp(20px, 3vw, 56px) + (var(--tes-bubble) - var(--tes-halo)) / 2);
	top: calc(clamp(96px, 12vh, 128px) + (var(--tes-bubble) - var(--tes-halo)) / 2);
	width: var(--tes-halo);
	height: var(--tes-halo);
	border-radius: 50%;
	background: radial-gradient(circle at 50% 50%,
		rgba(255, 196, 124, 0.72) 0%,
		rgba(255, 176, 92, 0.38) 44%,
		rgba(248, 240, 225, 0) 72%);
	pointer-events: none;
	z-index: 0;
}
/*
 * Three circles, placed absolutely rather than stacked by margin: with two
 * photos a negative margin was enough, but a third has to tuck under the big
 * circle *and* beside the second, which flow layout cannot express. The box is
 * sized so the cluster clears the h1 on its left and the band's bottom edge —
 * keep figure 2's left edge right of the headline (max-width: 16ch) if these
 * numbers are ever changed.
 * Each photo's framing lives on the img's own object-position in the block, not
 * here, so swapping a picture does not mean editing CSS.
 */
.tes-hwarm .tes-hero-bubbles {
	position: absolute;
	right: clamp(20px, 3vw, 56px);
	top: clamp(96px, 12vh, 128px);
	width: clamp(300px, 34vw, 490px);
	height: clamp(390px, 47vw, 672px);
	pointer-events: none;
	z-index: 1;
}
.tes-hwarm .tes-hero-bubbles figure { position: absolute; margin: 0; overflow: hidden; isolation: isolate; border-radius: 50%; border: 9px solid #FBF3E6; box-shadow: 0 26px 48px -26px rgba(42,28,19,.5); }
.tes-hwarm .tes-hero-bubbles img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tes-hwarm .tes-hero-bubbles figure:nth-child(1) { right: 0; top: 0; width: clamp(210px, 27vw, 380px); aspect-ratio: 1; }
.tes-hwarm .tes-hero-bubbles figure:nth-child(2) { left: 0; top: clamp(150px, 18vw, 256px); width: clamp(170px, 21.5vw, 306px); aspect-ratio: 3 / 4; box-shadow: 0 22px 40px -24px rgba(42,28,19,.5); }
.tes-hwarm .tes-hero-bubbles figure:nth-child(3) { right: clamp(2px, .5vw, 8px); top: clamp(222px, 26vw, 372px); width: clamp(125px, 15.5vw, 220px); aspect-ratio: 1; box-shadow: 0 22px 40px -24px rgba(42,28,19,.5); }

/* Wider than the usual 1040px tablet breakpoint on purpose: the "Largest"
   reading-comfort setting zooms the whole page, which shrinks the effective
   viewport the same way pinch-zoom does, and the bubbles need to have
   already dropped into the stacked layout well before that happens or they
   overlap the headline. */
@media (max-width: 1180px) {
	.tes-hwarm .tes-hero-bubbles { position: static; width: auto; height: auto; display: flex; align-items: flex-end; gap: clamp(10px, 2vw, 16px); margin-top: clamp(28px, 5vh, 44px); }
	.tes-hwarm .tes-hero-bubbles figure { position: static; margin: 0 !important; inset: auto !important; width: clamp(84px, 24vw, 180px) !important; }
	.tes-hwarm .tes-hero-glow { position: relative; top: calc(-1 * clamp(100px, 19vw, 170px)); width: clamp(380px, 72vw, 560px); height: clamp(380px, 72vw, 560px); margin: clamp(28px, 5vh, 44px) auto calc(-1 * clamp(380px, 72vw, 560px)) calc(-1 * clamp(70px, 14vw, 110px)); }
}

/* Photo-wash quote band on the tan/warm palette (Home's parent quote). */
.tes-band--photo.has-tan-background-color { --tes-wash: #F8F0E1; }
.tes-band--photo.has-tan-background-color > .tes-bg img { opacity: .22; filter: sepia(.2) saturate(.95); }
.tes-band--photo.has-tan-background-color > .tes-bg::after {
	background: linear-gradient(180deg, #F8F0E1 4%, rgba(248,240,225,.76) 55%, #F8F0E1);
}
.tes-band--photo.has-maroon-background-color { --tes-wash: #4A251A; }
.tes-band--photo.has-maroon-background-color > .tes-bg img { opacity: .28; filter: sepia(.14) saturate(1.05); }
.tes-band--photo.has-maroon-background-color > .tes-bg::after {
	background: linear-gradient(180deg, #4A251A 4%, rgba(74,37,26,.7) 55%, #4A251A);
}
.tes-band.has-tan-background-color .tes-attribution__who,
.tes-band.has-white-background-color .tes-attribution__who { color: #6A5343 !important; }
.tes-band.has-tan-background-color .tes-attribution a,
.tes-band.has-white-background-color .tes-attribution a { color: #2A1C13; text-decoration: underline; text-decoration-color: rgba(42,28,19,.4); }
.tes-band.has-tan-background-color .tes-attribution a:hover,
.tes-band.has-white-background-color .tes-attribution a:hover { color: #A6131D; text-decoration-color: #A6131D; }
.tes-band.has-white-background-color .tes-pullquote { color: #2A1C13 !important; }

/* Gradient transition wedge used on Is Edison a fit / What a day looks like
   between a dark band and the cream closer. */
.tes-fade--maroon-cream { background: linear-gradient(180deg, #4A251A, #B25A38 42%, #E6C9A6 74%, #FBF6EC); }
.tes-fade--forest-cream { background: linear-gradient(180deg, #173029, #8C6A46 46%, #E6C9A6 76%, #FBF6EC); }

/* ==========================================================================
   26. Mega-menu header (multi-page site)
   ========================================================================== */

.tes-nav { position: sticky; top: 0; z-index: 60; }
.tes-nav__util { background: #2A1C13; }
.tes-nav__util-inner {
	max-width: 1180px; margin: 0 auto; padding: 0 clamp(20px, 6vw, 80px);
	display: flex; flex-wrap: wrap; align-items: center; gap: 2px 20px; min-height: 40px;
}
.tes-nav__util-label { font: 400 12px/1.4 var(--wp--preset--font-family--body); letter-spacing: .18em; text-transform: uppercase; color: #A18B78; margin-right: auto; }
.tes-nav__util-phone { font: 400 14.5px/1.4 var(--wp--preset--font-family--body); color: #EADCCC; text-decoration: none; padding: 9px 0; }
.tes-nav__util-phone:hover { color: #fff; text-decoration: underline; }

.tes-nav__util .tes-comfort { position: relative; }
.tes-nav__util .tes-pill { border-color: #584536; color: #EADCCC; padding: 0 20px; }
.tes-nav__util .tes-pill:hover { background: #EADCCC; color: #2A1C13; }
.tes-nav__util .tes-comfort__panel { background: #2A1C13; border-color: #584536; }
.tes-nav__util .tes-comfort__panel p { color: #BCA795; }

.tes-nav__row { position: relative; background: #F8F0E1; }
.tes-nav__row-inner {
	max-width: 1180px; margin: 0 auto; padding: 10px clamp(20px, 6vw, 80px);
	display: flex; flex-wrap: wrap; align-items: center; gap: 6px clamp(8px, 1.6vw, 20px);
}
.tes-nav__logo { margin-right: auto; display: flex; align-items: center; flex: none; padding-block: 4px; }
/* The v2 lockup carries the eagle's full height plus clearance, so it is a
   squarer file than the over-cropped one it replaces (2.95:1, was 3.55:1).
   The height is up ~13% to keep the wordmark reading at the same size. */
.tes-nav__logo img { display: block; height: clamp(38px, 3.9vw, 52px); width: auto; }

.tes-nav__group { position: static; }
.tes-nav__trigger {
	position: relative;
	display: inline-flex; align-items: center; gap: 8px;
	min-height: 46px; padding: 0 16px; border-radius: 10px;
	font: 500 clamp(14px, 1.2vw, 16px)/1 var(--wp--preset--font-family--body);
	color: #2A1C13; text-decoration: none; transition: background 140ms ease;
}
.tes-nav__group.is-current .tes-nav__trigger { border-bottom: 2px solid #A6131D; }
.tes-nav__caret { font-size: .72em; opacity: .6; }

.tes-nav__group:hover > .tes-nav__trigger,
.tes-nav__group:focus-within > .tes-nav__trigger { background: rgba(255, 252, 246, .72); }
.tes-nav__group:hover > .tes-nav__trigger::after,
.tes-nav__group:focus-within > .tes-nav__trigger::after {
	content: ''; position: absolute; top: 100%; left: -50vw; right: -50vw; height: 16px;
}

.tes-nav__trigger--cta {
	border-radius: 999px; background: var(--tes-red); color: #FFF8F2; padding: 0 clamp(14px, 1.6vw, 22px);
}
.tes-nav__group:hover > .tes-nav__trigger--cta,
.tes-nav__group:focus-within > .tes-nav__trigger--cta { background: var(--tes-red-hover); }

.tes-nav__panel {
	display: none;
	position: absolute; left: 0; right: 0; top: 100%;
	background: #F8F0E1; box-shadow: 0 26px 44px -28px rgba(42, 28, 19, .45);
	z-index: 65; max-height: calc(100vh - 106px); overflow-y: auto; overscroll-behavior: contain;
}
.tes-nav__group:hover > .tes-nav__panel,
.tes-nav__group:focus-within > .tes-nav__panel { display: block; }

.tes-nav__cols, .tes-nav__cards {
	max-width: 1180px; margin: 0 auto; padding: clamp(22px, 3vw, 34px) clamp(20px, 6vw, 80px);
	display: grid;
}
.tes-nav__cols { gap: clamp(16px, 2.4vw, 40px); grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.tes-nav__cards { gap: clamp(14px, 2vw, 26px); grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.tes-nav__eyebrow { display: block; font: 400 12px/1 var(--wp--preset--font-family--body); letter-spacing: .2em; text-transform: uppercase; color: #6A5343; margin: 0 0 12px; padding: 0 12px; }
.tes-nav__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.tes-nav__link, .tes-nav__card { display: block; text-decoration: none; border: 1px solid transparent; transition: background 140ms ease, border-color 140ms ease; }
.tes-nav__link { padding: 9px 12px; border-radius: 10px; }
.tes-nav__card { padding: 14px; border-radius: 12px; }
.tes-nav__link:hover, .tes-nav__card:hover { background: rgba(255, 252, 246, .78); border-color: rgba(42, 28, 19, .12); }
.tes-nav__t, .tes-nav__cardt { display: block; font: 500 15.5px/1.4 var(--wp--preset--font-family--body); color: #2A1C13; }
.tes-nav__cardt { font: 400 20px/1.3 var(--wp--preset--font-family--display); margin-bottom: 6px; }
.tes-nav__d, .tes-nav__cardd { display: block; font: 400 13.5px/1.5 var(--wp--preset--font-family--body); color: #6A5343; margin-top: 2px; }
.tes-nav__cardd { font-size: 15px; line-height: 1.6; }

.tes-nav__toggle { display: none; }

/* The menu wrapper only exists for the phone layout; on a wide screen its
   children have to stay direct flex items of .tes-nav__row-inner. */
.tes-nav__menu { display: contents; }
.tes-nav__burger { display: none; }
.tes-nav__cta-short { display: none; }

@media (max-width: 720px) {
	/* Phone header is one line: logo, the crimson visit chip, and a menu
	   button. Everything else lives behind the button. */
	.tes-nav__row-inner { row-gap: 4px; flex-wrap: wrap; gap: 6px 10px; }
	.tes-nav__logo { order: 1; }
	.tes-nav__logo img { height: 44px; width: auto; }
	.tes-nav__cta-long { display: none; }
	.tes-nav__cta-short { display: inline; }
	.tes-nav__group--cta { order: 2; }
	.tes-nav__burger { order: 3; }
	.tes-nav__menu { order: 4; }

	.tes-nav__burger {
		display: inline-flex; align-items: center; gap: 8px; flex: none;
		min-height: 44px; padding: 0 13px; border-radius: 10px;
		border: 1px solid rgba(42,28,19,.2); background: transparent;
		color: #2A1C13; cursor: pointer;
		font: 500 15px/1 var(--wp--preset--font-family--body);
	}
	.tes-nav__burger-bars { position: relative; width: 18px; height: 2px; background: currentColor; }
	.tes-nav__burger-bars::before,
	.tes-nav__burger-bars::after {
		content: ''; position: absolute; left: 0; width: 18px; height: 2px; background: currentColor;
		transition: transform 160ms ease, opacity 120ms ease;
	}
	.tes-nav__burger-bars::before { top: -6px; }
	.tes-nav__burger-bars::after { top: 6px; }
	.tes-nav.is-menu-open .tes-nav__burger-bars { background: transparent; }
	.tes-nav.is-menu-open .tes-nav__burger-bars::before { transform: translateY(6px) rotate(45deg); }
	.tes-nav.is-menu-open .tes-nav__burger-bars::after { transform: translateY(-6px) rotate(-45deg); }

	.tes-nav__menu { display: none; flex: 1 1 100%; }
	.tes-nav.is-menu-open .tes-nav__menu {
		display: block;
		max-height: calc(100vh - 168px);
		overflow-y: auto;
		padding-top: 6px;
		border-top: 1px solid rgba(42,28,19,.12);
		margin-top: 8px;
	}

	.tes-nav__menu .tes-nav__group { display: flex; flex-wrap: wrap; align-items: center; }
	.tes-nav__menu .tes-nav__trigger { margin-right: auto; }
	.tes-nav__group:hover > .tes-nav__trigger::after,
	.tes-nav__group:focus-within > .tes-nav__trigger::after { content: none; }

	/* The visit chip is a link on a phone, not a dropdown. */
	.tes-nav__group--cta .tes-nav__toggle,
	.tes-nav__group--cta .tes-nav__caret { display: none; }
	.tes-nav__group--cta .tes-nav__panel { display: none !important; }
	.tes-nav__trigger--cta { padding: 0 16px; }

	.tes-nav__menu .tes-nav__toggle {
		display: inline-flex; align-items: center; justify-content: center;
		width: 40px; height: 40px; flex: none; border: 1px solid rgba(42,28,19,.2); border-radius: 999px;
		background: transparent; color: #2A1C13; cursor: pointer; transition: background 140ms ease, transform 140ms ease;
	}
	.tes-nav__menu .tes-nav__group.is-open > .tes-nav__toggle { background: rgba(255,252,246,.72); transform: rotate(180deg); }

	.tes-nav__panel { position: static !important; box-shadow: none !important; max-height: none; }
	.tes-nav__group:hover > .tes-nav__panel,
	.tes-nav__group:focus-within > .tes-nav__panel { display: none; }
	.tes-nav__menu .tes-nav__group.is-open > .tes-nav__panel { display: block; }
	.tes-nav__cols, .tes-nav__cards { grid-template-columns: 1fr; gap: 14px; padding: 4px 0 18px; }
}

@media (max-width: 400px) {
	.tes-nav__burger-word { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
	.tes-nav__burger { padding: 0 12px; }
}

@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
	.tes-nav__burger-bars::before,
	.tes-nav__burger-bars::after { transition: none; }
	.tes-nav__menu .tes-nav__toggle { transition: none; }
}

/* ==========================================================================
   27. Who we are — leadership grid, find-us grid
   ========================================================================== */

.tes-leaders { display: grid; gap: clamp(20px, 3vw, 36px); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.tes-leaders figure { margin: 0 0 14px; overflow: hidden; aspect-ratio: 4/5; background: #E7DAC6; }
.tes-leaders img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tes-leaders h3 { font-size: 22px; margin: 0 0 4px; }
.tes-leaders p { font-size: 15.5px; margin: 0; color: var(--tes-muted) !important; }

.tes-findus { display: grid; gap: clamp(26px, 4vw, 56px); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.tes-findus h3 { font-size: 22px; margin: 0 0 14px; }

/* ==========================================================================
   28. Frontend behaviour for the new mega-nav (mobile toggle + current-page
       underline) lives in edison.js under initTesNav().
   ========================================================================== */

/* ==========================================================================
   29. One student — Austin's journal.

       A sticky illustrated portrait beside a run of handwritten notes. Both
       halves are driven by one number: how far the reader has moved through
       the section. edison.js writes that into --tes-warm (0 to 1) and the
       portrait warms from grey to full colour as the notes are read, so her
       picture and her story arrive together. Individual notes surface on
       their own as they enter the viewport, the same is-visible convention
       section 3's reveal uses.

       Every string in here is a plain paragraph in the editor. The rail, the
       dots, the progress line and the handwriting are all styling — staff can
       rewrite a note, or add one, without touching any of it.
   ========================================================================== */

.tes-diary {
	/* Ruled paper. 36px repeat, drawn faintly enough to read as texture. */
	background-image: repeating-linear-gradient(
		180deg,
		rgba(42, 28, 19, 0.05) 0 1px,
		rgba(42, 28, 19, 0) 1px 36px
	);
	padding-bottom: clamp(80px, 12vh, 150px);
}

/* The header keeps the band's own 1180px measure so its left edge lines up
   with the grid below it; the title and lede constrain themselves in ch. */
.tes-diary__head { margin-bottom: clamp(50px, 8vh, 90px); }
.tes-diary__head .tes-eyebrow { margin-bottom: 20px; }

.tes-diary__title {
	font-size: clamp(32px, 5vw, 72px);
	line-height: 1.05;
	max-width: 17ch;
	margin: 0 0 22px;
}

.tes-diary__head .tes-lede { max-width: 52ch; margin: 0; color: var(--tes-muted) !important; }

.tes-diary__grid {
	display: grid;
	grid-template-columns: minmax(260px, 0.8fr) minmax(320px, 1fr);
	gap: clamp(30px, 5vw, 80px);
	align-items: start;
}

/* --- the portrait ------------------------------------------------------- */

.tes-diary__portrait {
	position: sticky;
	top: clamp(84px, 12vh, 112px);
	display: grid;
	justify-items: center;
	width: 100%;
	max-width: 380px;
	text-align: center;
}

/* The glow and the lift both read off --tes-warm, so there is one source of
   truth for "how far through the section are we". */
.tes-diary__figure {
	position: relative;
	width: 100%;
	display: grid;
	place-items: center;
	margin: 0 0 clamp(4px, 1vh, 12px);
	transform: translateY(calc((1 - var(--tes-warm, 0)) * 26px - 8px)) scale(calc(0.965 + var(--tes-warm, 0) * 0.045));
}

.tes-diary__figure::before {
	content: "";
	position: absolute;
	left: 50%;
	top: 3%;
	width: min(134%, 540px);
	aspect-ratio: 1;
	border-radius: 50%;
	/* Three stops rather than two: a hot core, a broad shoulder that keeps the
	   light on the figure instead of only around it, then the fade out. */
	background: radial-gradient(circle at 50% 50%,
		rgba(255, 212, 152, 0.98) 0%,
		rgba(255, 184, 98, 0.60) 38%,
		rgba(239, 225, 200, 0) 72%);

	/*
	 * The glow up. It starts at almost nothing and small, then grows and
	 * brightens together as the notes are read, so the light peaks on the last
	 * entry rather than being there from the beginning. Scaling as well as
	 * fading is what buys the ending — opacity alone tops out at 1 and has
	 * nowhere left to go. This is the halo's own scale; the portrait's zoom is
	 * on .tes-diary__figure and is deliberately left alone.
	 */
	transform: translate(-50%, 0) scale(calc(0.70 + var(--tes-warm, 0) * 0.32));
	opacity: calc(0.05 + var(--tes-warm, 0) * 0.95);
	pointer-events: none;
}

/* Both journal heroes get the stronger glow — Austin on the homepage
   (`.tes-diary--home`) and Gabe on "Is Edison a fit?" (`.tes-diary--hero`,
   already on that section's wrapper from its original build, reused here
   rather than adding a redundant class). Wider, denser halo and a larger
   end scale (1.02 -> 1.11) than the plain default in the base rule above.
   Higher specificity than that rule (two classes vs one), so no !important
   needed. If a plainer journal section is ever added without either
   modifier, it falls back to the base glow untouched. */
.tes-diary--home .tes-diary__figure::before,
.tes-diary--hero .tes-diary__figure::before {
	width: min(168%, 690px);
	/*
	 * Feathering. Three stops leave a legible circular edge wherever the
	 * artwork doesn't cover it: Austin is a bust portrait whose hoodie hides
	 * the bright core, so her glow already reads as a soft wash, but Gabe is
	 * a full-body two-person shot with open background on both sides, which
	 * exposed the termination as a visible ring. Fixed for both at once, in
	 * this shared rule, by approximating a gaussian falloff — eight stops on
	 * an ease-out curve running all the way to 0 at 100%, so there is no
	 * radius at which alpha drops off a cliff. Keep the tail reaching 100%;
	 * ending it early is what produced the ring.
	 */
	background: radial-gradient(circle at 50% 50%,
		rgba(255, 221, 168, 1) 0%,
		rgba(255, 216, 156, 0.90) 16%,
		rgba(255, 203, 128, 0.71) 30%,
		rgba(255, 192, 107, 0.50) 43%,
		rgba(253, 199, 130, 0.31) 56%,
		rgba(250, 211, 158, 0.17) 69%,
		rgba(245, 220, 182, 0.07) 82%,
		rgba(239, 225, 200, 0) 100%);
	transform: translate(-50%, 0) scale(calc(0.70 + var(--tes-warm, 0) * 0.41));
	opacity: calc(0.06 + var(--tes-warm, 0) * 1.02);
}

.tes-diary__figure img {
	position: relative;
	width: 100%;
	display: block;
	filter: grayscale(calc((1 - var(--tes-warm, 0)) * 0.72)) saturate(calc(0.72 + var(--tes-warm, 0) * 0.28));
	opacity: calc(0.8 + var(--tes-warm, 0) * 0.2);
	/* Fades her out at the feet rather than cutting off on a hard edge. */
	-webkit-mask-image: linear-gradient(180deg, #000 82%, rgba(0, 0, 0, 0));
	mask-image: linear-gradient(180deg, #000 82%, rgba(0, 0, 0, 0));
}

.tes-diary__name {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(30px, 3.4vw, 46px);
	line-height: 1;
	color: var(--tes-ink) !important;
	margin: 0 0 10px;
}

.tes-diary__role {
	font-family: var(--wp--preset--font-family--body);
	font-size: 12px;
	line-height: 1.6;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: #6A5343 !important;
	margin: 0;
}

/* --- the notes ---------------------------------------------------------- */

.tes-diary__ink {
	font-family: var(--wp--preset--font-family--journal);
	line-height: 1.5;
	text-wrap: pretty;
}

.tes-diary__byline {
	font-size: clamp(17px, 1.7vw, 21px);
	color: #7A6047 !important;
	margin: 16px 0 0;
}

/* The rail: ::before is the full-length track, ::after the read portion,
   whose height edison.js writes into --tes-progress. Same mechanism as the
   day-here timeline in section 20. */
.tes-diary__entries {
	position: relative;
	margin: 0;
	padding: 0;
}

.tes-diary__entries::before,
.tes-diary__entries::after {
	content: "";
	position: absolute;
	left: 0;
	top: 0;
	width: 1px;
}

.tes-diary__entries::before { height: 100%; background: rgba(42, 28, 19, 0.18); }
.tes-diary__entries::after { height: var(--tes-progress, 0px); background: #A6131D; opacity: 0.75; }

.tes-diary__entry {
	position: relative;
	padding: 0 0 clamp(46px, 8vh, 96px) clamp(28px, 4vw, 54px);
	opacity: 0.13;
	transform: translateY(30px);
	transition: opacity 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.tes-diary__entry:last-child { padding-bottom: clamp(40px, 6vh, 72px); }
.tes-diary__entry.is-visible { opacity: 1; transform: translateY(0); }

.tes-diary__entry::before {
	content: "";
	position: absolute;
	left: -5px;
	top: 8px;
	width: 11px;
	height: 11px;
	border-radius: 50%;
	background: #D9C7AB;
	border: 2px solid var(--wp--preset--color--paper);
	transition: background 0.6s ease, transform 0.6s ease;
}

.tes-diary__entry.is-visible::before { background: #A6131D; transform: scale(1.15); }

.tes-diary__label {
	font-family: var(--wp--preset--font-family--body);
	font-size: 12px;
	line-height: 1.6;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: #6A5343 !important;
	margin: 0 0 14px;
}

.tes-diary__entry .tes-diary__ink {
	font-size: clamp(22px, 2.7vw, 36px);
	color: #3A2A1C !important;
	max-width: 22ch;
	margin: 0;
}

/* The two turning points in the story are set larger and darker, and their
   label takes the accent colour. */
.tes-diary__entry--key .tes-diary__label { color: var(--tes-accent) !important; }
.tes-diary__entry--key .tes-diary__ink {
	font-size: clamp(26px, 3.4vw, 48px);
	line-height: 1.42;
	color: var(--tes-ink) !important;
	max-width: 20ch;
}

/* --- the closing line --------------------------------------------------- */

.tes-diary__coda {
	grid-column: 2;
	padding-left: clamp(28px, 4vw, 54px);
	border-top: 1px solid rgba(42, 28, 19, 0.18);
	padding-top: clamp(28px, 4vh, 44px);
}

.tes-diary__coda p { max-width: 46ch; margin: 0 0 26px; }

/* --- narrow screens ----------------------------------------------------- */

@media (max-width: 1000px) {
	.tes-diary__grid { grid-template-columns: 1fr; }
	.tes-diary__portrait { position: static; margin: 0 auto clamp(28px, 5vh, 52px); }
	.tes-diary__coda { grid-column: 1; }
}

/* --- no script, or motion turned off ------------------------------------ */

.no-js .tes-diary__entry,
html[data-motion="off"] .tes-diary__entry { opacity: 1; transform: none; }
.no-js .tes-diary__entry::before,
html[data-motion="off"] .tes-diary__entry::before { background: #A6131D; }
.no-js .tes-diary__figure img,
html[data-motion="off"] .tes-diary__figure img { filter: none; opacity: 1; }
.no-js .tes-diary__figure,
html[data-motion="off"] .tes-diary__figure { transform: none; }

@media (prefers-reduced-motion: reduce) {
	.tes-diary__entry { opacity: 1; transform: none; transition: none; }
	.tes-diary__entry::before { background: #A6131D; }
	.tes-diary__figure { transform: none; }
	.tes-diary__figure img { filter: none; opacity: 1; }
}

/* ==========================================================================
   30. "Graduated" — one word, drawn under and grown into as the reader
       reaches it. Same scroll window as the jargon strike-through in section
       3 (start filling at 85% down the viewport, fully there by the vertical
       middle) so the two scroll-driven moments on the site feel like one
       mechanism rather than two.
   ========================================================================== */

.tes-diary__spark {
	display: inline-block;
	font-style: normal;
	color: var(--tes-accent) !important;
	background-image: linear-gradient(currentColor, currentColor);
	background-repeat: no-repeat;
	background-position: 0 1.08em;
	background-size: 0% 2px;
	transform: scale(1);
	/* No transition on purpose, same reasoning as .tes-strike__ink: this is
	   set directly off scroll position every frame, so it has to track the
	   scroll exactly rather than chase it on a timer. */
}

.tes-diary__spark.is-lit { background-size: 100% 2px; transform: scale(1.07); }

.no-js .tes-diary__spark,
html[data-motion="off"] .tes-diary__spark { background-size: 100% 2px; transform: none; }

@media (prefers-reduced-motion: reduce) {
	.tes-diary__spark { background-size: 100% 2px; transform: none; }
}

/* ==========================================================================
   31. Two photographs closing out a journal — the real people behind the
       illustration. Sits between the last note and the coda, in the same
       grid column as the notes and indented to the same left edge, so it
       lines up with the handwriting rather than with the rail.
   ========================================================================== */

.tes-diary__photos {
	grid-column: 2;
	padding-left: clamp(28px, 4vw, 54px);
	margin-bottom: clamp(36px, 6vh, 68px);
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(10px, 1.4vw, 18px);
}

/* The figures are grid items so the two columns stay equal height even when
   one caption wraps to more lines than the other; the square aspect-ratio on
   the image is what actually keeps the two photographs themselves matched,
   whatever the source files' own proportions are. */
.tes-diary__photos figure {
	margin: 0;
	display: grid;
	grid-template-rows: auto 1fr;
	align-content: start;
}

.tes-diary__photos img {
	width: 100%;
	aspect-ratio: 1;
	object-fit: cover;
	display: block;
}

.tes-diary__photos figcaption {
	font-family: var(--wp--preset--font-family--body);
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--tes-muted) !important;
	margin: 12px 0 0;
	text-wrap: pretty;
}

/* Matches the single-column collapse the grid already does at this width. */
@media (max-width: 1000px) {
	.tes-diary__photos { grid-column: 1; }
}

/* ==========================================================================
   32. "Start here" — the first column of the Explore Edison menu is the one
       a family arriving cold should read first, so it reads as a raised card
       while the other columns stay flat on the panel.

       Subtle on purpose: a warm wash and a hairline, no heavy border and no
       colour block. The tint is shifted in hue rather than lightness, because
       the panel is already pale and the link hover state is near-white — a
       lighter card would have swallowed the hover.
   ========================================================================== */

/* Every column carries the same padding so their eyebrows stay on one line
   across the row; only the first one is filled. */
.tes-nav__col { padding: 14px 0 12px; border-radius: 14px; }

.tes-nav__col--start {
	background: rgba(255, 232, 200, 0.5);
	box-shadow: inset 0 0 0 1px rgba(42, 28, 19, 0.09);
}

.tes-nav__col--start .tes-nav__eyebrow { color: var(--wp--preset--color--crimson); }

/* The light design's mega-menu, kept in step. */
.tesl-mega__col--start {
	background: rgba(255, 232, 200, 0.5);
	box-shadow: inset 0 0 0 1px rgba(42, 28, 19, 0.09);
	border-radius: 14px;
	padding: 14px 0 12px;
}

/* ==========================================================================
   33. Tennessee funding calculator — a family picks the one state program
       that fits (the state only allows one per child per year), and sees
       what's left of tuition either as one payment or spread monthly.
   ========================================================================== */

.tes-calc__programs {
	display: grid;
	gap: clamp(16px, 2.2vw, 24px);
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.tes-calc__program {
	display: block;
	width: 100%;
	text-align: left;
	background: rgba(255, 255, 255, 0.6);
	border: 2px solid #E0D3C0;
	border-radius: 20px;
	padding: clamp(20px, 2.4vw, 28px);
	cursor: pointer;
	font: inherit;
	color: inherit;
	transition: border-color 160ms ease, background 160ms ease, transform 160ms ease;
}
.tes-calc__program:hover { border-color: #C9B79C; }
.tes-calc__program.is-selected {
	border-color: var(--wp--preset--color--crimson);
	background: #FFFBF4;
	transform: translateY(-2px);
}

.tes-calc__ptag {
	font: 500 12px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--wp--preset--color--crimson);
	margin: 0 0 12px;
}
.tes-calc__pname {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 1.8vw, 23px);
	letter-spacing: -0.01em;
	margin: 0 0 6px;
	color: #241812;
}
.tes-calc__pamt {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(24px, 2.4vw, 30px);
	color: #241812;
	margin: 0 0 14px;
}
.tes-calc__plist { margin: 0 0 18px; padding: 0; list-style: none; font-size: 14.5px; line-height: 1.55; color: #5C4632; }
.tes-calc__plist li { padding-left: 18px; position: relative; margin-bottom: 7px; }
.tes-calc__plist li::before { content: "\2014"; position: absolute; left: 0; opacity: .45; }
.tes-calc__plist li:last-child { margin-bottom: 0; }

.tes-calc__radio {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-size: 13.5px;
	font-weight: 600;
	color: #241812;
}
.tes-calc__radio-dot {
	width: 18px;
	height: 18px;
	border-radius: 50%;
	border: 2px solid #C9B79C;
	position: relative;
	flex: none;
}
.tes-calc__program.is-selected .tes-calc__radio-dot { border-color: var(--wp--preset--color--crimson); }
.tes-calc__program.is-selected .tes-calc__radio-dot::after {
	content: "";
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background: var(--wp--preset--color--crimson);
}

/* Three numbered steps down the page: how many children, which state
   program each one uses, and the two figures behind an Edison estimate. */

.tes-calc__step { margin-bottom: clamp(30px, 4.4vh, 50px); }
.tes-calc__step[hidden] { display: none; }
/* Steps 2-4 are revealed by answering the one above, so they get the same
   arrival as the result panel. Step 1 is there on load and needs none. */
.tes-calc__step:not([data-step="1"]) {
	animation: tesCalcIn 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
html[data-motion="off"] .tes-calc__step { animation: none; }
@media (prefers-reduced-motion: reduce) {
	.tes-calc__step { animation: none; }
}

/* A way past the one optional question that still counts as answering it. */
.tes-calc__skip {
	margin-top: 18px;
	border: 0;
	background: none;
	padding: 6px 0;
	font: 600 15px/1.4 var(--wp--preset--font-family--body);
	color: var(--wp--preset--color--crimson);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-color: rgba(142, 17, 25, 0.4);
	cursor: pointer;
}
.tes-calc__skip:hover { text-decoration-color: currentColor; }

.tes-band p.tes-calc__steplabel {
	display: flex;
	align-items: center;
	gap: 12px;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 1.9vw, 24px);
	letter-spacing: -0.01em;
	color: #241812;
	margin: 0 0 10px;
}
.tes-calc__stepnum {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: var(--wp--preset--color--crimson);
	color: #FFF6F0;
	font: 600 15px/1 var(--wp--preset--font-family--body);
}
.tes-band p.tes-calc__stephelp {
	margin: 0 0 20px;
	max-width: 70ch;
	font-size: 15.5px;
	line-height: 1.6;
	color: #5C4632;
}

.tes-calc__seg {
	display: inline-flex;
	gap: 6px;
	padding: 5px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.6);
	border: 2px solid #E0D3C0;
}
.tes-calc__seg button {
	min-width: 52px;
	border: 0;
	background: transparent;
	color: #241812;
	font: 600 16px/1 var(--wp--preset--font-family--body);
	padding: 12px 16px;
	border-radius: 999px;
	cursor: pointer;
	transition: background 160ms ease, color 160ms ease;
}
.tes-calc__seg button:hover { background: rgba(142, 17, 25, 0.08); }
.tes-calc__seg--pay { flex-wrap: wrap; }
.tes-calc__seg--pay button { min-width: 0; padding: 12px 22px; }
.tes-calc__seg { transition: border-color 300ms ease, background 300ms ease; }

/* Step 1 is the only question on screen before anything is answered, and
   it sits under a heading and a lede on a busy band. Two cues, in order:
   the question underlines itself as it comes into view (.is-drawn, from
   edison.js), then its buttons breathe until one is picked (.is-awaiting).
   Same draw-on idea as .tes-strike, but played once as a sweep rather than
   tied to the scroll position — it has to catch an eye, not keep pace. */
.tes-calc__q-ink {
	background-image: linear-gradient(var(--tes-red), var(--tes-red));
	background-repeat: no-repeat;
	background-position: 0 100%;
	background-size: 0% 3px;
	/* Drops the line clear of the descenders in "many" and "enrolling". It
	   stays inside the label's generous leading, so a second line on a
	   phone doesn't collide with it. */
	padding-bottom: 0.22em;
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
	transition: background-size 1000ms cubic-bezier(0.65, 0, 0.35, 1) 150ms;
}
.tes-calc__step.is-drawn .tes-calc__q-ink { background-size: 100% 3px; }

@keyframes tesCalcBreathe {
	0%   { box-shadow: 0 0 0 0 rgba(188, 24, 35, 0.34); }
	70%  { box-shadow: 0 0 0 14px rgba(188, 24, 35, 0); }
	100% { box-shadow: 0 0 0 0 rgba(188, 24, 35, 0); }
}
.tes-calc.is-awaiting [data-step="1"] .tes-calc__seg {
	border-color: rgba(188, 24, 35, 0.5);
	background: rgba(255, 255, 255, 0.85);
}
/* Starts once the underline has finished, and stops the moment the family
   answers — .is-awaiting comes off in render(). */
.tes-calc.is-awaiting [data-step="1"].is-drawn .tes-calc__seg {
	animation: tesCalcBreathe 2.4s ease-out 1.1s infinite;
}

/* Motion off: the line is simply there, and the red-edged buttons are the
   cue on their own. */
html[data-motion="off"] .tes-calc__q-ink { transition: none; background-size: 100% 3px; }
html[data-motion="off"] .tes-calc.is-awaiting [data-step="1"].is-drawn .tes-calc__seg { animation: none; }
@media (prefers-reduced-motion: reduce) {
	.tes-calc__q-ink { transition: none; background-size: 100% 3px; }
	.tes-calc.is-awaiting [data-step="1"].is-drawn .tes-calc__seg { animation: none; }
}
.tes-calc__seg button.is-active {
	background: var(--wp--preset--color--crimson);
	color: #FFF6F0;
}

/* One chip per child, so it stays obvious whose program you are choosing. */
.tes-calc__students {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-bottom: 20px;
}
.tes-calc__student {
	display: grid;
	gap: 3px;
	text-align: left;
	background: rgba(255, 255, 255, 0.6);
	border: 2px solid #E0D3C0;
	border-radius: 14px;
	padding: 11px 18px;
	cursor: pointer;
	font: inherit;
	color: inherit;
	transition: border-color 160ms ease, background 160ms ease;
}
.tes-calc__student:hover { border-color: #C9B79C; }
.tes-calc__student.is-active {
	border-color: var(--wp--preset--color--crimson);
	background: #FFFBF4;
}
.tes-calc__student-n {
	font: 600 14px/1.2 var(--wp--preset--font-family--body);
	color: #241812;
}
.tes-calc__student-p { font-size: 13px; color: #5C4632; }
.tes-calc__student.is-active .tes-calc__student-p { color: var(--wp--preset--color--crimson); }

/* "No state funding" is a real answer, so it gets a real option — just a
   quieter one than the three programs above it. */
.tes-calc__program--none {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 6px 16px;
	margin-top: clamp(16px, 2.2vw, 24px);
	padding: 18px clamp(20px, 2.4vw, 28px);
	border-radius: 16px;
}
.tes-calc__nonenote { font-size: 14.5px; line-height: 1.5; color: #5C4632; }

.tes-calc__fields {
	display: grid;
	gap: clamp(16px, 2.2vw, 24px);
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	max-width: 720px;
}
.tes-calc__field { display: grid; gap: 7px; }
.tes-calc__field label {
	font: 600 14.5px/1.3 var(--wp--preset--font-family--body);
	color: #241812;
}
.tes-calc__field input {
	width: 100%;
	background: rgba(255, 255, 255, 0.75);
	border: 2px solid #E0D3C0;
	border-radius: 14px;
	padding: 14px 16px;
	font-family: var(--wp--preset--font-family--display);
	font-size: 21px;
	color: #241812;
	transition: border-color 160ms ease, background 160ms ease;
}
.tes-calc__field input:focus {
	outline: none;
	border-color: var(--wp--preset--color--crimson);
	background: #FFFBF4;
}
.tes-calc__field input::placeholder { color: #A99076; }

.tes-calc__money { position: relative; }
.tes-calc__money-sign {
	position: absolute;
	left: 16px;
	top: 50%;
	transform: translateY(-50%);
	font-family: var(--wp--preset--font-family--display);
	font-size: 21px;
	color: #8A7259;
	pointer-events: none;
}
.tes-calc__money input { padding-left: 34px; }

.tes-calc__hint { font-size: 13.5px; line-height: 1.45; color: #6E5741; }

.tes-calc__result {
	margin-top: clamp(24px, 3.4vh, 38px);
	background: #241812;
	border-radius: 22px;
	padding: clamp(26px, 3.6vw, 40px);
	color: #F6EDE0;
}
.tes-calc__result dl { margin: 0; }
.tes-calc__result-row {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 16px;
	padding: 14px 0;
	border-top: 1px solid rgba(246, 237, 224, 0.16);
}
.tes-calc__result-row:first-child { border-top: 0; padding-top: 0; }
.tes-calc__result-row dt { font-size: 15px; color: #C9B29D; }
.tes-calc__result-row dd { margin: 0; font-family: var(--wp--preset--font-family--display); font-size: clamp(19px, 2vw, 24px); }
.tes-calc__result-row--total dd { font-size: clamp(24px, 2.6vw, 30px); color: #FFD8A8; }

.tes-calc__pay { margin-top: clamp(22px, 3vh, 32px); padding-top: clamp(22px, 3vh, 32px); border-top: 1px solid rgba(246, 237, 224, 0.16); }
.tes-calc__toggle { display: inline-flex; border-radius: 999px; background: rgba(246, 237, 224, 0.1); padding: 4px; gap: 4px; }
.tes-calc__toggle button {
	border: 0;
	background: transparent;
	color: #F6EDE0;
	font: 600 13.5px/1 var(--wp--preset--font-family--body);
	padding: 10px 18px;
	border-radius: 999px;
	cursor: pointer;
}
.tes-calc__toggle button.is-active { background: #F6EDE0; color: #241812; }
.tes-calc__pay-amount {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(28px, 3.4vw, 38px);
	color: #FFD8A8;
	margin: 0 0 4px;
}
.tes-calc__pay-note { font-size: 13.5px; color: #C9B29D; margin: 0; }

.tes-calc__result-row--aid dd { color: #FFD8A8; }
.tes-band p.tes-calc__aidnote {
	margin: 16px 0 0;
	font-size: 14px;
	line-height: 1.6;
	color: #C9B29D;
	max-width: 72ch;
}

@media (max-width: 600px) {
	.tes-calc__seg { display: grid; grid-template-columns: repeat(4, 1fr); width: 100%; }
	.tes-calc__seg button { min-width: 0; }
	.tes-calc__seg--pay { grid-template-columns: 1fr; }
	/* Two per row, and a lone third one stays half width rather than
	   stretching across the whole line. */
	.tes-calc__student { flex: 0 1 calc(50% - 5px); }
}

/* ==========================================================================
   34. What a day looks like — one schedule per school level
   ==========================================================================
   Elementary, middle and high all live in the page as ordinary blocks; only
   one is on screen at a time. The inactive panels are taken out of flow with
   position:absolute rather than display:none, so the outgoing panel can still
   be seen fading while the incoming one arrives, and so the timeline inside
   each of them keeps real geometry for edison.js to measure.
   The panel wrapper's height is animated in JS, because the three schedules
   are deliberately different lengths and a hard jump would undo the fade.
   ========================================================================== */

.tes-sched__instruction { max-width: 52ch; margin-bottom: clamp(22px, 3vh, 30px); }

.tes-sched__toggle {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	width: fit-content;
	max-width: 100%;
	margin: 0 0 clamp(34px, 5vh, 60px);
	padding: 5px;
	background: rgba(251, 243, 230, .06);
	border: 1px solid rgba(251, 243, 230, .18);
	border-radius: 999px;
}
.tes-sched__btn {
	appearance: none;
	margin: 0;
	padding: 11px 22px;
	border: 0;
	border-radius: 999px;
	background: transparent;
	color: rgba(251, 243, 230, .74);
	font-family: var(--wp--preset--font-family--body);
	font-size: clamp(14px, 1.15vw, 16px);
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: background 260ms ease, color 260ms ease;
}
.tes-sched__btn:hover { color: #FBF3E6; background: rgba(251, 243, 230, .10); }
.tes-sched__btn[aria-selected="true"] { background: #FBF3E6; color: #241812; }
.tes-sched__btn:focus-visible { outline: 2px solid #FBF3E6; outline-offset: 3px; }

.tes-sched__panels { position: relative; transition: height 460ms cubic-bezier(.4, 0, .2, 1); }
.tes-sched__panel {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	opacity: 0;
	visibility: hidden;
	transform: translateY(16px);
	pointer-events: none;
	transition: opacity 340ms ease, transform 340ms ease, visibility 0s linear 340ms;
}
.tes-sched__panel.is-active {
	position: relative;
	opacity: 1;
	visibility: visible;
	transform: none;
	pointer-events: auto;
	transition: opacity 380ms ease 110ms, transform 380ms ease 110ms, visibility 0s;
}

@media (max-width: 560px) {
	.tes-sched__toggle { width: 100%; justify-content: stretch; }
	.tes-sched__btn { flex: 1 1 auto; padding: 11px 12px; text-align: center; }
}

html[data-motion="off"] .tes-sched__panels,
html[data-motion="off"] .tes-sched__panel { transition: none; transform: none; }
@media (prefers-reduced-motion: reduce) {
	.tes-sched__panels { transition: none; }
	.tes-sched__panel { transition: none; transform: none; }
}

/* ==========================================================================
   35. The magazine pull quote. A short parent line set large in the display
       serif, hung off an oversized quote mark and closed with a hairline and
       an attribution. Band-agnostic: it reads --tes-ink/--tes-accent/--tes-rule
       like everything else, so it works on cream, forest or maroon unchanged.

       Two variants. On its own it is a full-measure moment between sections.
       With --aside it floats into the right margin beside running text, the
       way a magazine sets one.
   ========================================================================== */

/* The measure is set on the quotation itself, not the figure: a ch on the
   figure resolves against the inherited 16px body size, which would make a
   30ch wrapper about 240px wide. The figure sizes to its content instead, so
   the attribution rule underneath always matches the line above it. */
.tes-quotemag {
	/* The glyph below used to be pulled up out of this box with a negative
	   top, so it landed on whatever paragraph came before it. The overhang
	   now lives inside the box as padding, which makes an overlap
	   structurally impossible and leaves the glyph in the same place
	   relative to the quotation itself. */
	--tes-quotemag-hang: clamp(14px, 3.4vw, 30px);
	position: relative;
	width: fit-content;
	max-width: 100%;
	margin: clamp(44px, 6.5vh, 84px) 0 0;
	padding-top: var(--tes-quotemag-hang);
	padding-left: clamp(46px, 6vw, 88px);
}

/* The quote mark is decoration, not content — it is drawn from CSS so a
   screen reader hears the sentence and nothing else. */
.tes-quotemag::before {
	content: "\201C";
	position: absolute;
	top: 0;
	left: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(96px, 12vw, 168px);
	line-height: 1;
	color: var(--tes-accent);
	opacity: 0.42;
	pointer-events: none;
}

.tes-band .tes-quotemag p.tes-quotemag__line {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(27px, 3.6vw, 50px);
	max-width: 20ch;
	line-height: 1.14;
	letter-spacing: -0.015em;
	color: var(--tes-ink) !important;
	margin: 0;
	text-wrap: pretty;
}

.tes-band .tes-quotemag p.tes-quotemag__who {
	font: 400 13px/1.6 var(--wp--preset--font-family--body);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tes-muted) !important;
	margin: clamp(20px, 2.6vh, 28px) 0 0;
	padding-top: clamp(16px, 2.2vh, 22px);
	border-top: 1px solid var(--tes-rule);
}

/* A long quotation cannot take the 80px display size the one-line parent
   quote does — it would run past the fold. Same component, smaller step,
   wider measure. */
.tes-band p.tes-pullquote--long {
	font-size: clamp(24px, 3.1vw, 42px);
	line-height: 1.18;
	max-width: 26ch;
}

/* ==========================================================================
   36. Careers — who we look for, the three virtues, the core values, and the
       hiring process. The virtue and value cards read the band variables so
       the same markup can move to a different colour band without edits.
   ========================================================================== */

.tes-virtues {
	display: grid;
	gap: clamp(20px, 2.6vw, 34px);
	grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
	margin-top: clamp(34px, 5vh, 58px);
}

.tes-virtue {
	border-top: 2px solid var(--tes-ink);
	padding-top: clamp(20px, 2.6vh, 28px);
}
.tes-band .tes-virtue p.tes-virtue__num {
	font: 400 13px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--tes-accent) !important;
	margin: 0 0 16px !important;
}
.tes-band .tes-virtue h3 {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(26px, 2.6vw, 36px);
	line-height: 1.08;
	margin: 0 0 12px;
}
.tes-band .tes-virtue p { font-size: 16.5px; line-height: 1.62; margin: 0; }

/* The core values: three plain cards on the light band, same shape as the
   funding cards so the two pages feel like one site. */
.tes-values {
	display: grid;
	gap: clamp(18px, 2.4vw, 30px);
	grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
	margin-top: clamp(30px, 4.5vh, 52px);
}
.tes-valuecard {
	background: rgba(255, 255, 255, 0.58);
	border: 1px solid #E0D3C0;
	border-radius: 20px;
	padding: clamp(22px, 2.6vw, 32px);
}
.tes-band .tes-valuecard h3 { font-size: clamp(21px, 2vw, 27px); margin: 0 0 10px; }
.tes-band .tes-valuecard p { font-size: 16px; line-height: 1.65; margin: 0; }

/* One long sentence set apart — the school's purpose, quoted as itself. */
.tes-purpose {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(24px, 3vw, 40px) !important;
	line-height: 1.18;
	letter-spacing: -0.015em;
	color: var(--tes-ink) !important;
	max-width: 24ch;
	margin: 0 0 clamp(24px, 3.4vh, 36px) !important;
	text-wrap: pretty;
}

/* The hiring process. Numbered rows rather than cards, because the order is
   the information — a candidate wants to know what happens after what. */
.tes-process { display: grid; margin-top: clamp(30px, 4.5vh, 52px); }
.tes-process__step {
	display: grid;
	grid-template-columns: clamp(52px, 6vw, 84px) minmax(0, 1fr);
	gap: 8px clamp(16px, 2.4vw, 34px);
	padding: clamp(22px, 3vh, 32px) 0;
	border-top: 1px solid var(--tes-rule);
}
.tes-process__step:last-child { border-bottom: 1px solid var(--tes-rule); }
.tes-band .tes-process__step p.tes-process__num {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(34px, 4vw, 54px);
	line-height: 0.9;
	color: var(--tes-accent) !important;
	margin: 0 !important;
}
.tes-band .tes-process__step h3 {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(22px, 2.2vw, 30px);
	line-height: 1.14;
	margin: 0 0 8px;
}
.tes-band .tes-process__step p { font-size: 16.5px; line-height: 1.62; margin: 0; }

@media (max-width: 620px) {
	.tes-process__step { grid-template-columns: 1fr; gap: 6px; }
	.tes-band .tes-process__step p.tes-process__num { font-size: clamp(28px, 8vw, 38px); }
}

/* A quiet, factual note that closes the process — background checks. */
.tes-band p.tes-note {
	font-size: 15.5px;
	line-height: 1.6;
	color: var(--tes-muted) !important;
	max-width: 62ch;
	margin: clamp(24px, 3.4vh, 34px) 0 0;
}

/* ==========================================================================
   37. A page header that carries a small cluster of photographs instead of
       one. Same idea as the home hero's bubbles, at page-header scale, and
       it repeats that hero's move of making the middle figure an ellipse so
       a tall photograph keeps its subject whole.
   ========================================================================== */

.tes-pagehead--pics .tes-pagehead__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
	gap: clamp(30px, 5vw, 72px);
	align-items: center;
}
.tes-pagehead--pics .tes-pagehead__grid > * { max-width: none; margin-inline: 0; }
.tes-pagehead--pics .tes-pagehead__text > *:first-child { margin-top: 0; }
.tes-pagehead--pics .tes-pagehead__text h1 { max-width: 15ch; }

.tes-headpics {
	position: relative;
	width: 100%;
	max-width: 430px;
	aspect-ratio: 1 / 1.15;
	justify-self: end;
	margin: 0;
}
.tes-headpics figure {
	position: absolute;
	margin: 0;
	overflow: hidden;
	border-radius: 50%;
	border: 8px solid #FBF3E6;
	box-shadow: 0 22px 42px -24px rgba(42, 28, 19, 0.5);
}
.tes-headpics img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tes-headpics figure:nth-child(1) { right: 0; top: 0; width: 58%; aspect-ratio: 1; }
.tes-headpics figure:nth-child(2) { left: 0; top: 30%; width: 46%; aspect-ratio: 3 / 4; }
.tes-headpics figure:nth-child(3) { right: 3%; top: 52%; width: 34%; aspect-ratio: 1; }

/* Below the two-column breakpoint the cluster unstacks into a plain row, the
   same way the home hero's bubbles do. */
@media (max-width: 900px) {
	.tes-pagehead--pics .tes-pagehead__grid { grid-template-columns: 1fr; gap: clamp(28px, 5vh, 40px); }
	.tes-headpics {
		position: static;
		width: auto;
		max-width: none;
		aspect-ratio: auto;
		display: flex;
		align-items: flex-end;
		gap: clamp(10px, 2vw, 16px);
	}
	.tes-headpics figure {
		position: static;
		inset: auto;
		width: clamp(84px, 26vw, 190px);
		border-width: 6px;
	}
}

/* ==========================================================================
   38. "What's coming up" — the next few calendar dates, dropped into a page
       as a card. The list itself is [edison_events], so it never goes stale.
   ========================================================================== */

.tes-upnext {
	display: grid;
	gap: clamp(24px, 4vw, 56px);
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	align-items: center;
}
.tes-upnext__card {
	background: rgba(255, 255, 255, 0.07);
	border: 1px solid var(--tes-rule);
	border-radius: 22px;
	padding: clamp(24px, 3vw, 38px);
}
.tes-band.has-cream-background-color .tes-upnext__card,
.tes-band.has-tan-background-color .tes-upnext__card,
.tes-band.has-tan-deep-background-color .tes-upnext__card {
	background: rgba(255, 255, 255, 0.58);
	border-color: #E0D3C0;
}
.tes-upnext__card .tes-events { margin: 0; }
.tes-band .tes-upnext__more { margin: clamp(20px, 2.6vh, 26px) 0 0; font-size: 16px; }

/* .tes-events was written for the cream visit column and hard-codes its
   colours. Inside the card, hand them back to the band variables so the
   component can sit on any band. */
.tes-upnext__card .tes-events li { border-bottom-color: var(--tes-rule); }
.tes-upnext__card .tes-events .tes-events__when { color: var(--tes-muted); }
.tes-upnext__card .tes-events .tes-events__what { color: var(--tes-ink); }
.tes-upnext__card .tes-events li:first-child .tes-events__when { color: var(--tes-accent); }

/* ==========================================================================
   39. Parent voices, read one at a time. The argument stays pinned in the
       left column while the quotations scroll past it in the right — the
       same two-column, sticky-rail shape the daily schedule uses, because
       both sections are doing the same job: hold the frame still, move the
       evidence through it.

       Only the quotation the reader is actually on is at full strength. The
       rest sit back at a quarter, which is what produces the one-at-a-time
       cadence — the height alone would not do it. edison.js writes the
       classes and the rail fill; every visual consequence lives here.
   ========================================================================== */

/* figure and blockquote both arrive with a browser default margin, and
   blockquote's is 40px of indent — enough to knock every quotation out of
   line with the rule drawn above it. */
.tes-voice > blockquote, .tes-quotemag > blockquote,
.tes-voice > figcaption, .tes-quotemag > figcaption { margin: 0; padding: 0; }

/* Below 900px .tes-sticky goes static and the auto-fit grid is already one
   column, so the split only needs stating above it. The rail is the narrower
   half on purpose: the quotations are the thing being read. */
@media (min-width: 900px) {
	.tes-voices { grid-template-columns: minmax(280px, 0.88fr) minmax(0, 1.12fr); }
}

/* The rail's own rhythm. Section 13 gives every paragraph an 18px bottom
   margin, which is right for running copy and too tight for a pinned column
   that has to hold its own against 46px quotations beside it. */
.tes-band .tes-voices__rail p.tes-lede { margin: 0; max-width: 34ch; }
.tes-band .tes-voices__rail h2 { margin: 0 0 22px; }

/* How far through the sequence the reader is. A hairline and two numbers —
   enough to say "there are more of these" without turning into a widget. */
.tes-voices__meter {
	display: flex;
	align-items: center;
	gap: 16px;
	margin-top: clamp(30px, 4.5vh, 48px);
}
.tes-voices__track {
	position: relative;
	width: 2px;
	height: 96px;
	background: var(--tes-rule);
	border-radius: 2px;
}
/* No transition: edison.js writes this height off the scroll position every
   frame, the way the timeline rail and the struck line do, so it moves in
   lockstep with the scroll rather than chasing it. */
.tes-voices__fill {
	position: absolute;
	left: 0;
	top: 0;
	width: 2px;
	height: var(--tes-progress, 0%);
	max-height: 100%;
	background: var(--tes-accent);
	border-radius: 2px;
}
.tes-band p.tes-voices__count {
	font: 500 13px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.16em;
	color: var(--tes-muted) !important;
	margin: 0;
}
.tes-voices__n { color: var(--tes-ink); }

/* 66vh is what makes a reader arrive at one quotation at a time. Much under
   60 and two of them share the screen, which undoes the whole section. */
.tes-voices__seq { display: flex; flex-direction: column; }
.tes-voice {
	min-height: 66vh;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: clamp(16px, 2.2vh, 24px);
	padding: clamp(28px, 4vh, 40px) 0;
	opacity: 0.26;
	transition: opacity 700ms ease;
}
.tes-voice.is-current { opacity: 1; }

/* The rule draws itself once, the first time the quotation comes up, and
   stays drawn — a quotation the reader has already passed should still look
   finished when they scroll back up to it. */
.tes-voice__rule {
	height: 2px;
	width: 0;
	background: var(--tes-ink);
	transition: width 1100ms cubic-bezier(0.16, 0.84, 0.24, 1);
}
.tes-voice.is-seen .tes-voice__rule { width: 100%; }

.tes-band .tes-voice p.tes-voice__line {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(26px, 3.5vw, 46px);
	line-height: 1.18;
	letter-spacing: -0.015em;
	color: var(--tes-ink) !important;
	max-width: 24ch;
	margin: 0;
	text-wrap: pretty;
}
.tes-band .tes-voice p.tes-voice__who {
	font: 400 12.5px/1.6 var(--wp--preset--font-family--body);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tes-muted) !important;
	margin: 0;
}

/* The last quotation in the sequence, set at the page's biggest step. It sits
   outside the grid so the rail lets go first and this one lands on its own,
   full measure, with nothing pinned beside it. Section 35 draws the quote
   mark, the hairline and the attribution; this only changes the size. */
.tes-quotemag--peak { margin-top: clamp(56px, 8vh, 110px); }
.tes-band .tes-quotemag--peak p.tes-quotemag__line {
	font-size: clamp(34px, 6.2vw, 92px);
	line-height: 1.04;
	letter-spacing: -0.03em;
}

/* One column, no rail, no dimming — on a phone the quotations are already
   arriving one at a time and the 66vh only adds scrolling. */
@media (max-width: 900px) {
	.tes-voices__meter { display: none; }
	.tes-voices__seq { gap: clamp(32px, 6vh, 54px); }
	.tes-voice {
		min-height: 0;
		padding: 0;
		opacity: 1;
	}
}

/* Motion off: everything at full strength, every rule already drawn. */
html[data-motion="off"] .tes-voice { opacity: 1; }
html[data-motion="off"] .tes-voice__rule { width: 100%; }

@media (prefers-reduced-motion: reduce) {
	.tes-voice { opacity: 1; }
	.tes-voice__rule { width: 100%; }
}

/* The three "where it goes" cards carry more copy than the funding cards do,
   so they get a rule rather than a filled card — the page already has a lot
   of boxes on it by this point. */
.tes-gifts {
	display: grid;
	gap: clamp(20px, 2.6vw, 36px);
	grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
	margin-top: clamp(32px, 4.5vh, 56px);
}
.tes-gift { border-top: 2px solid var(--tes-ink); padding-top: clamp(20px, 2.6vh, 28px); }
.tes-band .tes-gift h3 {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(24px, 2.3vw, 32px);
	line-height: 1.1;
	margin: 0 0 12px;
}
.tes-band .tes-gift p { font-size: 16.5px; line-height: 1.62; margin: 0; }

/* --------------------------------------------------------------------------
   Alignment fix. `.tes-band > *` centres the 1180px measure with
   `margin-inline: auto`, but section 13's vertical-rhythm rules set explicit
   margins on every heading and paragraph, so those end up flush against the
   band padding instead. Any component that arrives as a plain <div> keeps the
   auto margin and drifts right of the headline above it — only visible once
   the band is wider than 1180 + its padding, i.e. from about 1340px up.
   Left-aligned is what the design actually does, so say so.
   -------------------------------------------------------------------------- */
.tes-band > div { margin-inline: 0; }

/* The one link in the Current families menu that should catch the eye: a
   filled crimson chip rather than a plain row, using the same radius the
   other menu rows already have so it reads as one of them, promoted. */
.tes-nav__link--give {
	background: var(--tes-red);
	border-color: var(--tes-red);
}
.tes-nav__link--give .tes-nav__t,
.tes-nav__link--give .tes-nav__d { color: #FDF6EC; }
.tes-nav__link--give .tes-nav__t { font-weight: 600; }
.tes-nav__link--give .tes-nav__d { color: rgba(253, 246, 236, 0.82); }
.tes-nav__link--give:hover {
	background: var(--tes-red-hover);
	border-color: var(--tes-red-hover);
}

/* ==========================================================================
   40. Funding page — the calculator only appears once a family has picked a
       program, an accented note for the things we most want read, and a
       fine-print measure narrower than the panel above it.
   ========================================================================== */

/* Hidden outright rather than faded, so nothing below it shifts when the
   panel arrives — the animation runs on reveal. */
.tes-calc .tes-calc__result { display: none; }
.tes-calc.is-picked .tes-calc__result {
	display: block;
	animation: tesCalcIn 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes tesCalcIn {
	from { opacity: 0; transform: translateY(20px) scale(0.985); }
	to   { opacity: 1; transform: none; }
}
html[data-motion="off"] .tes-calc.is-picked .tes-calc__result { animation: none; }
@media (prefers-reduced-motion: reduce) {
	.tes-calc.is-picked .tes-calc__result { animation: none; }
}


/* The struck-through tuition and the discount line. */
.tes-calc__result-row dd s { color: #C9B29D; text-decoration-thickness: 1.5px; }
.tes-calc__result-row--discount dd { color: #FFD8A8; }
.tes-calc__result-row[hidden] { display: none; }

/* One line we actually want read, on any band. */
.tes-band p.tes-accentnote {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 1.9vw, 26px);
	line-height: 1.34;
	color: var(--tes-ink) !important;
	max-width: 48ch;
	margin: clamp(22px, 3vh, 32px) 0 0;
	padding-left: clamp(16px, 1.6vw, 22px);
	border-left: 3px solid var(--tes-accent);
	text-wrap: pretty;
}
.tes-band p.tes-accentnote em { color: var(--tes-accent); font-style: italic; }

/* Fine print reads as a footnote to the panel, so it should not run as wide
   as the panel does. */
.tes-band p.tes-fineprint { max-width: 68ch; margin-inline: auto; }
/* Under the calculator it reads as part of the panel, so it takes the same
   width rather than the narrower measure fine print usually gets. */
.tes-band#calculator p.tes-fineprint { max-width: none; }

/* A short quotation meant to hold one line. .tes-pullquote caps itself at
   19ch to stack a long sentence into a block, and that measure — not the type
   size — is what was breaking this one: the line only runs about 600px at the
   full 80px, inside a 1180px band. Lifting the cap is the whole fix, and it
   holds a single line down to phone widths. */
.tes-band p.tes-pullquote--oneline { max-width: none; }

/* The presenting sponsor's mark, under a hairline so it reads as a credit
   rather than as part of the copy. */
.tes-sponsor {
	margin-top: clamp(26px, 3.6vh, 40px);
	padding-top: clamp(20px, 2.8vh, 28px);
	border-top: 1px solid var(--tes-rule);
}
.tes-band .tes-sponsor p.tes-sponsor__label {
	font: 400 12.5px/1.6 var(--wp--preset--font-family--body);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tes-muted) !important;
	margin: 0 0 16px;
}
.tes-sponsor img {
	display: block;
	width: 100%;
	max-width: 250px;
	height: auto;
}

/* ==========================================================================
   41. Head of School blog. Everything here is prefixed .tesb- so it cannot
       collide with the marketing pages' .tes- components, and every colour
       still comes from the band variables in sections 2 and 24 — so the
       index, a post and a tag archive can each sit on whichever band colour
       reads best without a single hard-coded value in this section.
   ========================================================================== */

/* Nothing on this blog is dated. The posts answer questions that do not expire
   — what to do after a diagnosis, how a visit works — and a date beside them
   only tells a reader how old the answer is, not whether it still holds.
   In the slot where a date would sit, the head of school's own posts carry a
   small mark instead, so his voice is findable among the school's. */
.tesb-cards > li.tag-head-of-school .tesb-card__text::before,
.tesb-lead > li.tag-head-of-school .tesb-lead__title::before {
	content: "Head of School";
	display: block;
	width: fit-content;
	font: 500 12px/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--tes-accent);
	border: 1px solid currentColor;
	border-radius: 999px;
	padding: 6px 13px 5px;
	margin: 0 0 16px;
}

/* "← Head of School blog", above the title on a post and a tag archive. */
.tes-band p.tesb-back { margin: 0 0 clamp(22px, 3vh, 32px); font-size: 15.5px; }
.tes-band p.tesb-back a { text-decoration: none; }
.tes-band p.tesb-back a:hover { text-decoration: underline; }

/* --- The index's page header portrait ------------------------------------
   The illustrated portraits are drawn on white, so the 4/5 photo crop the
   page header normally applies would leave a slab of white beside a warm tan
   band. Contained on a circle instead, which is how the site treats a face
   everywhere else. */
.tes-pagehead--photo .tesb-portrait { max-width: 320px; }
.tes-pagehead--photo .tesb-portrait img {
	aspect-ratio: 1;
	object-fit: cover;
	object-position: 50% 18%;
	border-radius: 50%;
	border: 8px solid #FBF3E6;
	box-shadow: 0 22px 42px -24px rgba(42, 28, 19, 0.5);
}
.tes-pagehead--photo .tesb-portrait figcaption { text-align: center; }
/* On a phone the portrait is stacked above the posts, and at the 320px the
   page header normally allows it fills the screen before a reader reaches a
   single headline. */
@media (max-width: 900px) {
	.tes-pagehead--photo .tesb-portrait { max-width: 190px; }
	.tes-pagehead--photo .tesb-portrait figcaption { text-align: left; }
}

/* --- The latest post, given the width the others don't get ---------------- */

/* post-template renders a <ul>, so the two columns belong to the <li> that
   holds the post — putting the grid on the list itself only ever lays out one
   item and leaves the second column empty. */
.tesb-lead { list-style: none; margin: 0; padding: 0; }
.tesb-lead > li {
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
	gap: clamp(28px, 4.5vw, 66px);
	align-items: center;
	margin: 0;
}
.tesb-lead > li > * { max-width: none; margin-inline: 0; }
.tesb-lead__img { margin: 0; }
.tesb-lead__img img {
	width: 100%;
	aspect-ratio: 5 / 4;
	object-fit: cover;
	display: block;
	border-radius: 20px;
	box-shadow: 0 30px 54px -28px rgba(42, 28, 19, 0.5);
}
.tesb-lead__text > *:first-child { margin-top: 0; }
.tes-band .tesb-lead__title { margin: 0 0 clamp(16px, 2.2vh, 22px); text-wrap: balance; }
.tes-band .tesb-lead__title a { color: var(--tes-ink); text-decoration: none; }
.tes-band .tesb-lead__title a:hover { color: var(--tes-accent); }
.tes-band .tesb-lead__ex { font-size: 17.5px; line-height: 1.72; max-width: 52ch; margin: 0; }

/* The read-more link is the only thing on the index styled as a call to
   action, so it gets the underline the card titles deliberately don't. */
.tes-band .tesb-more,
.tes-band .tesb-lead__ex + .tesb-more {
	display: inline-block;
	margin-top: clamp(20px, 2.6vh, 28px);
	font: 500 16px/1 var(--wp--preset--font-family--body);
	color: var(--tes-accent) !important;
	text-decoration: none;
	border-bottom: 2px solid currentColor;
	padding-bottom: 4px;
}
.tes-band .tesb-more::after { content: " \2192"; }
.tes-band .tesb-more:hover { color: var(--tes-ink) !important; }

@media (max-width: 860px) {
	.tesb-lead > li { grid-template-columns: 1fr; gap: clamp(24px, 4vh, 34px); }
	.tesb-lead__img img { aspect-ratio: 3 / 2; }
}

/* --- The list of posts ---------------------------------------------------
   One post per row, each butting straight up against the next with a hairline
   between and no gap at all. As a grid of cards these ran ragged: every post
   has a different title length, a different excerpt, and two have no
   photograph, so the cards ended at eleven different heights and the section
   read as a page of holes. A list has none of that — every row starts at the
   same left edge, and the rhythm comes from the rule, not from guessing at a
   card height that suits all thirteen.
   ------------------------------------------------------------------------ */

.tes-band .tesb-archive__head { margin: 0 0 clamp(24px, 3.4vh, 40px); }

.tesb-cards {
	display: block;
	list-style: none;
	margin: 0;
	padding: 0;
}
.tesb-cards > li { margin: 0; }

.tesb-card {
	display: grid;
	grid-template-columns: minmax(0, 1fr) clamp(160px, 20vw, 260px);
	gap: clamp(24px, 3.5vw, 56px);
	align-items: center;
	padding: clamp(26px, 3.6vh, 40px) 0;
	border-top: 1px solid var(--tes-rule);
}
/* The picture is on the right so that the titles all begin on the same line
   down the page whether or not a post has one. */
.tesb-card:not(:has(.tesb-card__img)) { grid-template-columns: minmax(0, 1fr); }
.tesb-cards > li:first-child .tesb-card { border-top: 0; padding-top: 0; }

.tesb-card__text > *:first-child { margin-top: 0; }
.tesb-card__text > *:last-child { margin-bottom: 0; }

.tes-band .tesb-card__title {
	margin: 0;
	text-wrap: balance;
	font-size: clamp(23px, 2.4vw, 33px);
	max-width: 28ch;
}
.tes-band .tesb-card__ex {
	margin: 12px 0 0;
	font-size: 16.5px;
	line-height: 1.68;
	color: var(--tes-body) !important;
	max-width: 62ch;
}

.tesb-card__img { margin: 0; }
.tesb-card__img > a { display: block; width: 100%; }
.tesb-card__img img {
	width: 100%;
	aspect-ratio: 4 / 3;
	display: block;
	object-fit: cover;
	/* Group photographs and portraits both sit high in the frame, so the crop
	   is taken off the bottom rather than through anyone's head. */
	object-position: 50% 34%;
	border-radius: 14px;
	box-shadow: 0 16px 30px -22px rgba(42, 28, 19, 0.55);
}

/* The whole row is the target, not just the words in the title. */
.tesb-card { position: relative; }
.tes-band .tesb-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
}
.tesb-card__img > a { position: relative; z-index: 1; }

@media (max-width: 720px) {
	.tesb-card { grid-template-columns: minmax(0, 1fr); gap: clamp(16px, 3vh, 22px); }
	/* Picture first on a phone, where there is no column beside the words. */
	.tesb-card__img { order: -1; }
	.tes-band .tesb-card__title { max-width: none; }
}

/* --- Pagination ----------------------------------------------------------- */

.tes-band .tesb-pagination {
	margin-top: clamp(44px, 6vh, 72px);
	padding-top: clamp(24px, 3vh, 32px);
	border-top: 1px solid var(--tes-rule);
	align-items: center;
	gap: 16px;
	font-family: var(--wp--preset--font-family--body);
	font-size: 15.5px;
}
.tes-band .tesb-pagination a { text-decoration: none; }
.tes-band .tesb-pagination a:hover { text-decoration: underline; }
.tes-band .tesb-pagination .page-numbers { padding: 0 6px; }
.tes-band .tesb-pagination .current { color: var(--tes-ink); font-weight: 600; }
/* With one page of posts there is nothing to page to, and core still renders
   the empty flex row — which would leave a rule floating under the grid. */
.tes-band .tesb-pagination:not(:has(a)):not(:has(.page-numbers)) { display: none; }

/* The school byline, on posts the head of school did not write. Without a
   portrait beside it the text alone would sit too high against the title. */
.tesb-byline--school { padding-block: 4px; }

/* --- A single post -------------------------------------------------------- */

.tesb-head { padding-bottom: 0 !important; }
.tesb-head h1 { max-width: 20ch; margin: 0 0 clamp(22px, 3vh, 30px); }
.tes-band .tesb-head__date { margin-bottom: 18px; }

.tesb-byline { display: flex; align-items: center; gap: 16px; }
.tesb-byline__face {
	width: 56px;
	height: 56px;
	border-radius: 50%;
	object-fit: cover;
	object-position: 50% 16%;
	background: #FBF3E6;
	border: 2px solid #FBF3E6;
	flex: none;
}
.tesb-byline span {
	font-family: var(--wp--preset--font-family--body);
	font-size: 15.5px;
	line-height: 1.45;
	color: var(--tes-muted);
}
.tesb-byline strong { color: var(--tes-ink); font-weight: 600; }

/* The lead photograph bridges the header band and the reading band, so it
   hangs below the tan and the cream starts behind its lower half. */
.tesb-hero {
	margin: clamp(34px, 5vh, 54px) 0 calc(-1 * clamp(40px, 6vh, 78px));
	width: fit-content;
	max-width: 900px;
}
/* Bounded by height, not width. Jon photographs a lot of these on a phone held
   upright, and a portrait scaled to the full 900px would be taller than the
   screen before a reader reached the first sentence. Landscape shots still
   fill the width; tall ones simply come out narrower. */
.tesb-hero img {
	width: auto;
	max-width: 100%;
	max-height: min(560px, 62vh);
	display: block;
	border-radius: 20px;
	box-shadow: 0 34px 60px -30px rgba(42, 28, 19, 0.55);
}

/* --- The post itself ------------------------------------------------------
   contentSize is 1180px for the marketing bands, which is far too wide to
   read a thousand words in. The prose gets its own measure and everything
   inside it inherits that, apart from images, which may break out. */
.tesb-body { padding-top: clamp(58px, 9vh, 104px) !important; }
/* Left-aligned, not centred: the title, byline and lead photograph above all
   start at the band's left padding, and a centred column of prose under a
   left-aligned header reads as a mistake. The space this leaves on the right
   is where the floated photographs go. */
.tesb-prose { max-width: 68ch; margin-inline: 0; }
.tes-band .tesb-prose > * { max-width: none; }
.tes-band .tesb-prose p,
.tes-band .tesb-prose li {
	font-size: 18px;
	line-height: 1.78;
	color: var(--tes-body) !important;
}
.tes-band .tesb-prose p { margin: 0 0 1.35em; }
.tes-band .tesb-prose p:last-child { margin-bottom: 0; }
.tes-band .tesb-prose strong { color: var(--tes-ink); font-weight: 600; }
.tes-band .tesb-prose h2,
.tes-band .tesb-prose h3 { margin: 1.9em 0 0.6em; }

.tes-band .tesb-prose ul,
.tes-band .tesb-prose ol { margin: 0 0 1.35em; padding-left: 1.4em; }
.tes-band .tesb-prose li { margin-bottom: 0.55em; }
.tes-band .tesb-prose li::marker { color: var(--tes-accent); }

/* A photograph inside the prose. The scraped posts carry left/right floats
   from the old editor; they are honoured on a wide screen and dropped on a
   narrow one, where a 40%-wide float would strand two words per line. */
.tesb-prose .tesb-fig { margin: clamp(26px, 4vh, 38px) 0; }
.tesb-prose .tesb-fig img {
	width: 100%;
	display: block;
	border-radius: 14px;
	box-shadow: 0 22px 40px -26px rgba(42, 28, 19, 0.5);
}
@media (min-width: 720px) {
	/* 42% left about 48 characters beside the picture, which is too narrow a
	   column to read a paragraph in. */
	.tesb-prose .tesb-fig.alignleft,
	.tesb-prose .tesb-fig.alignright { max-width: 34%; margin-top: 6px; }
	.tesb-prose .tesb-fig.alignleft  { float: left;  margin-right: clamp(24px, 3vw, 38px); }
	.tesb-prose .tesb-fig.alignright { float: right; margin-left:  clamp(24px, 3vw, 38px); }
}
@media (max-width: 719px) {
	.tesb-prose .tesb-fig.alignleft,
	.tesb-prose .tesb-fig.alignright { float: none; max-width: none; margin-inline: 0; }
}

/* In Flanders Fields closes the Memorial Day post. A verse block keeps
   McCrae's indented lines, which a paragraph would collapse. */
.tes-band .tesb-verse {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 1.9vw, 24px);
	line-height: 1.55;
	color: var(--tes-ink);
	white-space: pre-wrap;
	margin: clamp(26px, 4vh, 38px) 0;
	padding-left: clamp(18px, 2vw, 26px);
	border-left: 3px solid var(--tes-accent);
	overflow-x: auto;
}

/* --- Tags, and the post either side of this one --------------------------- */

.tesb-foot {
	max-width: 68ch;
	margin: clamp(44px, 6vh, 70px) 0 0;
	padding-top: clamp(22px, 3vh, 30px);
	border-top: 1px solid var(--tes-rule);
	clear: both;
}
.tes-band .tesb-tags {
	font-family: var(--wp--preset--font-family--body);
	font-size: 14px;
	line-height: 2.1;
	color: var(--tes-muted) !important;
	margin: 0;
}
.tes-band .tesb-tags a {
	display: inline-block;
	padding: 4px 13px;
	margin-right: 4px;
	border: 1px solid var(--tes-rule);
	border-radius: 999px;
	text-decoration: none;
	color: var(--tes-muted) !important;
}
.tes-band .tesb-tags a:hover {
	color: var(--tes-ink) !important;
	border-color: var(--tes-ink);
}
.tes-band .tesb-tags .wp-block-post-terms__separator { display: none; }

.tesb-nextprev {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
	gap: clamp(20px, 3vw, 40px);
	max-width: 68ch;
	margin: clamp(34px, 4.5vh, 52px) 0 0;
}
.tes-band .tesb-nextprev__link {
	font-family: var(--wp--preset--font-family--body);
	font-size: 15px;
	color: var(--tes-muted) !important;
}
.tes-band .tesb-nextprev__link a {
	display: block;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(19px, 1.8vw, 23px);
	line-height: 1.3;
	color: var(--tes-ink) !important;
	text-decoration: none;
	margin-top: 6px;
}
.tes-band .tesb-nextprev__link a:hover { color: var(--tes-accent) !important; }
.tes-band .tesb-nextprev__link--next { text-align: right; }
/* The newest post has nothing after it and the oldest nothing before it, and
   core still prints the empty container — which would leave half the row
   holding open space under the last paragraph. */
.tes-band .tesb-nextprev__link:empty { display: none; }
@media (max-width: 620px) {
	.tes-band .tesb-nextprev__link--next { text-align: left; }
}

/* Each light band paints its links teal through a three-class selector
   (section 24), which is right for a link inside a sentence and wrong for a
   headline — a grid of teal serif titles reads as a list of links rather than
   as a page of writing. These match that weight so the titles stay ink, and
   move to the band's accent on hover, where the link cue belongs. */
.tes-band .tesb-lead__title a:not(.wp-element-button),
.tes-band .tesb-card__title a:not(.wp-element-button),
.tes-band .tesb-nextprev__link a:not(.wp-element-button) { color: var(--tes-ink); }
.tes-band .tesb-lead__title a:not(.wp-element-button):hover,
.tes-band .tesb-card__title a:not(.wp-element-button):hover,
.tes-band .tesb-nextprev__link a:not(.wp-element-button):hover { color: var(--tes-accent); }

/* --- Search box on the results page --------------------------------------- */

.tesb-search { max-width: 480px; margin-top: clamp(22px, 3vh, 30px); }
.tesb-search .wp-block-search__input {
	border: 1px solid var(--tes-rule);
	border-radius: 999px 0 0 999px;
	padding: 14px 22px;
	font: 400 16px/1.4 var(--wp--preset--font-family--body);
	background: rgba(255, 255, 255, 0.6);
	color: var(--tes-ink);
}
.tesb-search .wp-block-search__button {
	border: 0;
	border-radius: 0 999px 999px 0;
	padding: 14px 26px;
	font: 500 16px/1.4 var(--wp--preset--font-family--body);
	background: var(--tes-red);
	color: #FFF8F2;
	cursor: pointer;
}
.tesb-search .wp-block-search__button:hover { background: var(--tes-red-hover); }
