/* About page — mission mode toggle + founder story */

/* ═══════════════════════════════════════
   TEXT PAGES
   ═══════════════════════════════════════ */
.text-page {
	min-height: 100svh;
	min-height: 100svh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-4xl) var(--space-xl);
	background: var(--bg);
	position: relative;
}

.text-page__inner {
	max-width: 580px;
	text-align: center;
}

.text-page__label {
	font-family: var(--serif);
	font-size: 0.95rem;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--secondary);
	margin-bottom: var(--space-lg);
}

.text-page__line {
	width: 32px;
	height: 1px;
	/* Bake the fade into the color so `.reveal.in-view > *` bumping
	   opacity to 1 doesn't make this line look more solid than the
	   identical dividers on non-reveal pages (e.g. /contact). */
	background: var(--divider);
	margin: 0 auto var(--space-2xl);
}

.text-page__headline {
	font-size: 3rem;
	font-weight: 300;
	line-height: 1.15;
	letter-spacing: -0.03em;
	color: var(--ink);
}

.text-page__lede {
	font-family: var(--serif);
	font-size: 1.65rem;
	font-weight: 300;
	line-height: 1.55;
	color: var(--ink);
	opacity: 0.65;
	letter-spacing: -0.01em;
}

/* Mission text stack — all three variants overlap in the same grid cell,
   each is centered vertically. Fade + scale + blur transition between them. */
.mission-stack {
	position: relative;
	/* about.js pins this to the ACTIVE text's height, so short modes
	   don't inherit the six-clause variant's slack — and the change
	   between modes GLIDES on the same curve as the crossfade. Every
	   variant is absolutely centered below, so the pinned height is
	   the ONLY thing deciding the section's rhythm. */
	transition: height 0.6s cubic-bezier(0.23, 1, 0.32, 1);
	overflow: visible;
}

.mission-text {
	/* Absolutely centered via the standalone `translate` property —
	   NOT transform, which the crossfade animates with scale. Out of
	   flow, so no variant's height leaks into another mode's layout. */
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	translate: 0 -50%;
	/* No p margins: the photo-to-mission and mission-to-picker beats
	   are set explicitly, once, and must match. */
	margin: 0;
	opacity: 0;
	transform: scale(0.97);
	filter: blur(6px);
	transition: opacity 0.6s cubic-bezier(0.23, 1, 0.32, 1),
		transform 0.6s cubic-bezier(0.23, 1, 0.32, 1),
		filter 0.6s cubic-bezier(0.23, 1, 0.32, 1);
	pointer-events: none;
	align-self: center;
}

.mission-text.active {
	opacity: 1;
	transform: scale(1);
	filter: blur(0);
	pointer-events: auto;
}

/* Inline links inside the esoteric mission — amber dotted underline,
   subtle scholarly footnote feel */
.mission-link {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px dotted var(--amber);
	padding-bottom: 1px;
	transition: color 0.25s ease, border-color 0.25s ease;
}

.mission-link:hover {
	color: var(--amber);
	border-bottom-color: var(--amber);
	border-bottom-style: solid;
}

/* Big tall section titles — Cormorant at poster size, stretched
   vertically past its natural proportions. transform doesn't grow the
   layout box, so the head room the stretch borrows comes back as
   margin-top. */
.section-title {
	font-family: var(--serif);
	font-weight: 300;
	font-size: clamp(2.8rem, 7.5vw, 5.2rem);
	line-height: 1;
	letter-spacing: 0.01em;
	text-align: center;
	color: var(--ink);
	margin: 0 0 1.8rem;
}

/* The film's head joins the family — same weight and scale, its own
   light ink from home.css. Later stylesheet, so this also outranks
   home.css's mobile shrink; the clamp floor is the mobile size. */
.parts__head {
	font-weight: 300;
	font-size: clamp(2.2rem, 5.5vw, 4.2rem);
}

/* Mode toggle */
.mode-toggle {
	display: flex;
	align-items: center;
	gap: 14px;
	width: min(440px, 100%);
	margin-inline: auto;
	margin-top: var(--space-2xl);
}

/* The links are the site's own capsule .btn (app.css) — the pair
   still splits the mission column so they read big. */
.mode-toggle a.btn {
	flex: 1;
	justify-content: center;
	background: transparent;
	color: var(--ink);
	font-size: 0.95rem;
	padding-top: 12px;
	padding-bottom: 12px;
}

.mode-toggle a.btn:hover {
	color: var(--amber);
}

/* ═══════════════════════════════════════
   FOUNDER SECTION
   ═══════════════════════════════════════ */
.founder {
	max-width: 660px;
	text-align: center;
}

.founder__name {
	font-family: var(--serif);
	font-size: 2.4rem;
	font-weight: 300;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: var(--ink);
	margin-bottom: var(--space-sm);
}

.founder__title {
	font-family: var(--serif);
	font-size: 0.97rem;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--amber);
	opacity: 0.7;
	margin-bottom: var(--space-2xl);
}

.founder__body {
	text-align: left;
	display: flex;
	flex-direction: column;
	gap: var(--space-lg);
}

.founder__body p {
	font-family: var(--serif);
	font-size: 1.05rem;
	line-height: 1.85;
	color: var(--ink);
	opacity: 0.7;
}

/* ═══════════════════════════════════════
   BELIEFS — list of italic statements
   ═══════════════════════════════════════ */
.beliefs {
	display: flex;
	flex-direction: column;
	gap: var(--space-md);
}

.beliefs p {
	font-family: var(--serif);
	font-style: italic;
	font-size: 1.2rem;
	line-height: 1.6;
	color: var(--ink);
	opacity: 0.65;
}

/* ═══════════════════════════════════════
   IMAGE PAGE
   ═══════════════════════════════════════ */
.image-page {
	height: var(--vh-stable, 100svh);
	overflow: hidden;
	padding: 0;
}

.image-page img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center center;
}

/* ═══════════════════════════════════════
   CTA — newsletter signup
   ═══════════════════════════════════════ */
.cta {
	min-height: 100svh;
	min-height: 100svh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-4xl) var(--space-xl);
	background: var(--bg);
	position: relative;
}

.cta__inner {
	max-width: 600px;
	text-align: center;
}

.cta__label {
	font-family: var(--serif);
	font-size: 0.95rem;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--amber);
	margin-bottom: var(--space-lg);
}

.cta h2 {
	font-size: 2.6rem;
	line-height: 1.15;
	margin-bottom: 0;
}

.cta__line {
	width: 32px;
	height: 1px;
	background: var(--divider);
	margin: var(--space-xl) auto;
}

.cta__lede {
	color: var(--secondary);
	font-size: 1.05rem;
	line-height: 1.9;
	margin-bottom: var(--space-2xl);
}

.signup {
	display: flex;
	gap: 8px;
	max-width: 440px;
	margin: 0 auto;
}

.signup__input {
	flex: 1;
	padding: 14px 20px;
	border: 1px solid var(--border);
	border-radius: 100px;
	background: transparent;
	font-family: var(--serif);
	font-size: 0.9rem;
	color: var(--ink);
	transition: border-color 0.2s ease;
}

.signup__input::placeholder {
	color: var(--secondary);
	opacity: 0.5;
}

.signup__input:focus {
	outline: none;
	border-color: var(--amber);
}

.signup__btn {
	padding: 14px 28px;
	background: var(--ink);
	color: var(--bg);
	border: none;
	border-radius: 100px;
	font-family: var(--serif);
	font-size: 0.85rem;
	font-weight: 500;
	cursor: pointer;
	transition: all 0.25s ease;
	white-space: nowrap;
}

.signup__btn:hover {
	background: #1e3a30;
	transform: translateY(-1px);
}

.cta__fineprint {
	margin-top: var(--space-lg);
	font-size: 0.8rem;
	color: var(--secondary);
	opacity: 0.6;
}

.cta__fineprint a {
	color: var(--amber);
	text-decoration: none;
}

.cta__fineprint a:hover {
	text-decoration: underline;
}

/* ═══════════════════════════════════════
   SCROLL-LINKED ANIMATIONS
   ═══════════════════════════════════════ */
@supports (animation-timeline: view()) {
	/* Fade IN on entry, then hold at full opacity through the rest of the
	   scroll range. No exit fade — previously dropped to 0.35 as the story
	   scrolled off the bottom, which made the last paragraphs hard to read
	   while the user was still actively reading them. */
	@keyframes fade-sweet-spot {
		0%   { opacity: 0.55; }
		100% { opacity: 1; }
	}

	.text-page__inner,
	.founder {
		animation: fade-sweet-spot linear both;
		animation-timeline: view();
		/* The whole ramp lives inside ENTRY: fully bright before the
		   element is even halfway in. The old entry-25/exit-75 range
		   held the dim nearly to the top of the screen — this was the
		   "decolor effect", not the .reveal system. */
		animation-range: entry 0% entry 45%;
	}

	/* Override the global reveal so it doesn't fight */
	.text-page__inner.reveal > *,
	.founder.reveal > * {
		opacity: 1;
		transition: none;
	}
}

/* ═══════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════ */
@media (max-width: 768px) {
	.text-page {
		padding: var(--space-3xl) var(--space-lg);
	}

	.text-page__headline {
		font-size: 2.2rem;
	}

	.text-page__lede {
		font-size: 1.25rem;
	}

	.founder__name {
		font-size: 2rem;
	}

	.founder__body p {
		font-size: 0.98rem;
	}

	.beliefs p {
		font-size: 1.05rem;
	}

	.cta {
		padding: var(--space-3xl) var(--space-lg);
	}

	.cta h2 {
		font-size: 1.8rem;
	}

	.signup {
		flex-direction: column;
		max-width: 320px;
	}

	.signup__btn {
		width: 100%;
	}
}

/* The founders, in the flesh — a rounded square above each
   name, the app's own card radius. */
.founder__portrait {
	width: 200px;
	height: 200px;
	border-radius: 25px;
	object-fit: cover;
	display: block;
	margin: 0 auto var(--space-md);
}

/* The two of us where the mission eyebrow used to sit — the words
   below are ours, so the picture introduces the speakers. */
.mission-photo {
	width: 100%;
	border-radius: 25px;
	display: block;
	margin: 0 auto 0.9rem;
	/* Triple-tap easter egg lives here: manipulation kills iOS
	   double-tap zoom mid-sequence, no-select keeps rapid taps from
	   highlighting. No cursor change — it's a secret. */
	touch-action: manipulation;
	-webkit-user-select: none;
	user-select: none;
	-webkit-touch-callout: none;
}

/* Tightened under the mission so the whole ensemble — photo, words,
   picker — reads on one screen. */
.mission-stack ~ .mode-toggle {
	margin-top: 1.4rem;
}

/* The mission section carries a full-width photo, so it sheds the
   text-page's tall padding — the ensemble fills the screen instead
   of pushing past it. */
.text-page--mission {
	padding-top: var(--space-2xl);
	padding-bottom: var(--space-2xl);
}

/* Esoteric runs six clauses; at the lede's full size it alone eats a
   screen. It reads at pull-quote size instead — still the lede's
   voice, sized to share the stage. */
.mission-text[data-mode="esoteric"] {
	font-size: 1.18rem;
	line-height: 1.62;
}

/* The two stories, shoulder to shoulder — one section, one beat, on
   a shade deeper than the page's cream so the band reads as its own. */
.text-page--founders {
	background: color-mix(in srgb, var(--bg) 94%, var(--ink) 6%);
	/* The base .text-page is a flex ROW — left alone it seats the big
	   title beside the bios instead of above them. */
	flex-direction: column;
	justify-content: center;
}

.founders {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(40px, 6vw, 88px);
	max-width: 1160px;
}

@media (max-width: 900px) {
	.founders {
		grid-template-columns: repeat(1, minmax(0, 1fr));
		gap: 72px;
	}
}

/* ═══════════════════════════════════════
   OUR APP — the ritual, in one breath on the film's ink ground
   ═══════════════════════════════════════ */
.text-page--app {
	background: var(--ink);
}

.text-page--app .text-page__label {
	color: var(--amber);
	opacity: 0.95;
}

.app-blurb__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.9rem, 3.2vw, 2.6rem);
	letter-spacing: -0.02em;
	color: var(--bg);
	margin-bottom: var(--space-lg);
}

.app-blurb {
	font-family: var(--serif);
	font-size: 1.25rem;
	line-height: 1.8;
	text-align: left;
	color: rgba(242, 243, 239, 0.82);
	margin: 0;
}

.text-page--app .page-num {
	color: rgba(242, 243, 239, 0.4);
}


/* The film's lone caption is a PARAGRAPH, not a five-word beat — it
   reads at lede size, left-aligned, with the learn-more beneath. */
/* About only: the film's word column widens for the paragraph —
   and the columns' overall stage widens with it. */
.parts__columns {
	width: min(1320px, 100%);
	grid-template-columns: auto minmax(0, 62ch);
}

.parts__caption--blurb h3 {
	font-size: clamp(1.2rem, 1.9vw, 1.6rem);
	font-weight: 400;
	line-height: 1.75;
	letter-spacing: 0;
	text-align: left;
	white-space: normal;
}

/* Handset film: the phone and the paragraph share one seat — the
   phone opens the scene, home.js dissolves it into the words. The
   pair centres vertically in the stage and the words take the full
   width. */
@media (max-width: 820px) {
	.parts[data-film] .parts__stage {
		grid-template-rows: auto 1fr auto;
		padding-top: 4rem;
	}
	.parts[data-film] .parts__head {
		align-self: start;
	}
	.parts__columns {
		width: 100%;
		grid-template-columns: 1fr;
		align-self: center;
	}
	.parts__frame,
	.parts__station {
		grid-area: 1 / 1;
		align-self: center;
	}
	.parts__station {
		width: 92%;
	}
	/* Centred in the phone's seat; about.js fits the size to it. */
	.parts__caption--blurb h3 {
		text-align: center;
	}
}

/* The contact form borrows contact.css inside the centred mission
   column — re-anchored left, and seated in a quiet card: the mission
   photo's 25px radius, a hairline instead of a shadow. */
.text-page--contact .text-page__inner {
	/* The card rack below runs 960 wide; the form matches it. */
	max-width: 960px;
	width: 100%;
}

.text-page--contact .contact__form {
	text-align: left;
	margin-top: var(--space-xl);
	background: #f7f8f4;
	border: 1px solid rgba(45, 74, 62, 0.1);
	border-radius: 25px;
	padding: 3rem 3.4rem 2.6rem;
	/* Wide card, so name and email share a row; the message, the
	   error line and the button span it. */
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1.7rem 2.6rem;
}

.text-page--contact .field:has(textarea),
.text-page--contact .contact__error {
	grid-column: 1 / -1;
}

.text-page--contact .contact__submit {
	grid-column: 1 / -1;
	justify-self: center;
}

@media (max-width: 700px) {
	.text-page--contact .contact__form {
		grid-template-columns: 1fr;
		padding: 2rem 1.4rem 1.8rem;
	}
}

/* No small caps here — the labels speak the page's own serif,
   in full ink so they read against the card. */
.text-page--contact .field label {
	font-family: var(--serif);
	font-size: 1.05rem;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ink);
	opacity: 1;
}

/* The contact invitation sits under a poster title — a step quieter
   than the mission lede. */
/* The Pill Cloud: each question a tappable pill — picks ride the
   form as canonical keys, and the broker words every combination
   into the email's subject line. */
.text-page--contact .contact-reasons {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	/* Full column — the same 960 the card below runs. */
	width: 100%;
	margin: 0 auto 1.4rem;
}

.contact-reason {
	font-family: var(--serif);
	font-size: 1.02rem;
	font-weight: 400;
	color: var(--ink);
	background: transparent;
	border: 1px solid rgba(45, 74, 62, 0.18);
	border-radius: 100px;
	padding: 10px 22px;
	cursor: pointer;
	transition: all 0.25s ease;
}

.contact-reason:hover {
	border-color: var(--ink);
	color: var(--ink);
}

.contact-reason.is-on {
	background: var(--ink);
	border-color: var(--ink);
	color: #fff;
}

/* ═══════════════════════════════════════
   FOUNDER SECTION
   ═══════════════════════════════════════ */
.founder {
	max-width: 660px;
	text-align: center;
}

.founder__name {
	font-family: var(--serif);
	font-size: 2.4rem;
	font-weight: 300;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: var(--ink);
	margin-bottom: var(--space-sm);
}

.founder__title {
	font-family: var(--serif);
	font-size: 0.97rem;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--amber);
	opacity: 0.7;
	margin-bottom: var(--space-2xl);
}

.founder__body {
	text-align: left;
	display: flex;
	flex-direction: column;
	gap: var(--space-lg);
}

.founder__body p {
	font-family: var(--serif);
	font-size: 1.05rem;
	line-height: 1.85;
	color: var(--ink);
	opacity: 0.7;
}

/* ═══════════════════════════════════════
   BELIEFS — list of italic statements
   ═══════════════════════════════════════ */
.beliefs {
	display: flex;
	flex-direction: column;
	gap: var(--space-md);
}

.beliefs p {
	font-family: var(--serif);
	font-style: italic;
	font-size: 1.2rem;
	line-height: 1.6;
	color: var(--ink);
	opacity: 0.65;
}

/* ═══════════════════════════════════════
   IMAGE PAGE
   ═══════════════════════════════════════ */
.image-page {
	height: var(--vh-stable, 100svh);
	overflow: hidden;
	padding: 0;
}

.image-page img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center center;
}

/* ═══════════════════════════════════════
   CTA — newsletter signup
   ═══════════════════════════════════════ */
.cta {
	min-height: 100svh;
	min-height: 100svh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-4xl) var(--space-xl);
	background: var(--bg);
	position: relative;
}

.cta__inner {
	max-width: 600px;
	text-align: center;
}

.cta__label {
	font-family: var(--serif);
	font-size: 0.95rem;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--amber);
	margin-bottom: var(--space-lg);
}

.cta h2 {
	font-size: 2.6rem;
	line-height: 1.15;
	margin-bottom: 0;
}

.cta__line {
	width: 32px;
	height: 1px;
	background: var(--divider);
	margin: var(--space-xl) auto;
}

.cta__lede {
	color: var(--secondary);
	font-size: 1.05rem;
	line-height: 1.9;
	margin-bottom: var(--space-2xl);
}

.signup {
	display: flex;
	gap: 8px;
	max-width: 440px;
	margin: 0 auto;
}

.signup__input {
	flex: 1;
	padding: 14px 20px;
	border: 1px solid var(--border);
	border-radius: 100px;
	background: transparent;
	font-family: var(--serif);
	font-size: 0.9rem;
	color: var(--ink);
	transition: border-color 0.2s ease;
}

.signup__input::placeholder {
	color: var(--secondary);
	opacity: 0.5;
}

.signup__input:focus {
	outline: none;
	border-color: var(--amber);
}

.signup__btn {
	padding: 14px 28px;
	background: var(--ink);
	color: var(--bg);
	border: none;
	border-radius: 100px;
	font-family: var(--serif);
	font-size: 0.85rem;
	font-weight: 500;
	cursor: pointer;
	transition: all 0.25s ease;
	white-space: nowrap;
}

.signup__btn:hover {
	background: #1e3a30;
	transform: translateY(-1px);
}

.cta__fineprint {
	margin-top: var(--space-lg);
	font-size: 0.8rem;
	color: var(--secondary);
	opacity: 0.6;
}

.cta__fineprint a {
	color: var(--amber);
	text-decoration: none;
}

.cta__fineprint a:hover {
	text-decoration: underline;
}

/* ═══════════════════════════════════════
   SCROLL-LINKED ANIMATIONS
   ═══════════════════════════════════════ */
@supports (animation-timeline: view()) {
	/* Fade IN on entry, then hold at full opacity through the rest of the
	   scroll range. No exit fade — previously dropped to 0.35 as the story
	   scrolled off the bottom, which made the last paragraphs hard to read
	   while the user was still actively reading them. */
	@keyframes fade-sweet-spot {
		0%   { opacity: 0.55; }
		100% { opacity: 1; }
	}

	.text-page__inner,
	.founder {
		animation: fade-sweet-spot linear both;
		animation-timeline: view();
		/* The whole ramp lives inside ENTRY: fully bright before the
		   element is even halfway in. The old entry-25/exit-75 range
		   held the dim nearly to the top of the screen — this was the
		   "decolor effect", not the .reveal system. */
		animation-range: entry 0% entry 45%;
	}

	/* Override the global reveal so it doesn't fight */
	.text-page__inner.reveal > *,
	.founder.reveal > * {
		opacity: 1;
		transition: none;
	}
}

/* ═══════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════ */
@media (max-width: 768px) {
	.text-page {
		padding: var(--space-3xl) var(--space-lg);
	}

	.text-page__headline {
		font-size: 2.2rem;
	}

	.text-page__lede {
		font-size: 1.25rem;
	}

	.founder__name {
		font-size: 2rem;
	}

	.founder__body p {
		font-size: 0.98rem;
	}

	.beliefs p {
		font-size: 1.05rem;
	}

	.cta {
		padding: var(--space-3xl) var(--space-lg);
	}

	.cta h2 {
		font-size: 1.8rem;
	}

	.signup {
		flex-direction: column;
		max-width: 320px;
	}

	.signup__btn {
		width: 100%;
	}
}

/* The founders, in the flesh — a rounded square above each
   name, the app's own card radius. */
.founder__portrait {
	width: 200px;
	height: 200px;
	border-radius: 25px;
	object-fit: cover;
	display: block;
	margin: 0 auto var(--space-md);
}

/* The two of us where the mission eyebrow used to sit — the words
   below are ours, so the picture introduces the speakers. */
.mission-photo {
	width: 100%;
	border-radius: 25px;
	display: block;
	margin: 0 auto 0.9rem;
	/* Triple-tap easter egg lives here: manipulation kills iOS
	   double-tap zoom mid-sequence, no-select keeps rapid taps from
	   highlighting. No cursor change — it's a secret. */
	touch-action: manipulation;
	-webkit-user-select: none;
	user-select: none;
	-webkit-touch-callout: none;
}

/* Tightened under the mission so the whole ensemble — photo, words,
   picker — reads on one screen. */
.mission-stack ~ .mode-toggle {
	margin-top: 1.4rem;
}

/* The mission section carries a full-width photo, so it sheds the
   text-page's tall padding — the ensemble fills the screen instead
   of pushing past it. */
.text-page--mission {
	padding-top: var(--space-2xl);
	padding-bottom: var(--space-2xl);
}

/* Esoteric runs six clauses; at the lede's full size it alone eats a
   screen. It reads at pull-quote size instead — still the lede's
   voice, sized to share the stage. */
.mission-text[data-mode="esoteric"] {
	font-size: 1.18rem;
	line-height: 1.62;
}

/* The two stories, shoulder to shoulder — one section, one beat, on
   a shade deeper than the page's cream so the band reads as its own. */
.text-page--founders {
	background: color-mix(in srgb, var(--bg) 94%, var(--ink) 6%);
	/* The base .text-page is a flex ROW — left alone it seats the big
	   title beside the bios instead of above them. */
	flex-direction: column;
	justify-content: center;
}

.founders {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(40px, 6vw, 88px);
	max-width: 1160px;
}

@media (max-width: 900px) {
	.founders {
		grid-template-columns: repeat(1, minmax(0, 1fr));
		gap: 72px;
	}
}

/* ═══════════════════════════════════════
   OUR APP — the ritual, in one breath on the film's ink ground
   ═══════════════════════════════════════ */
.text-page--app {
	background: var(--ink);
}

.text-page--app .text-page__label {
	color: var(--amber);
	opacity: 0.95;
}

.app-blurb__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.9rem, 3.2vw, 2.6rem);
	letter-spacing: -0.02em;
	color: var(--bg);
	margin-bottom: var(--space-lg);
}

.app-blurb {
	font-family: var(--serif);
	font-size: 1.25rem;
	line-height: 1.8;
	text-align: left;
	color: rgba(242, 243, 239, 0.82);
	margin: 0;
}

.text-page--app .page-num {
	color: rgba(242, 243, 239, 0.4);
}


/* The film's lone caption is a PARAGRAPH, not a five-word beat — it
   reads at lede size, left-aligned, with the learn-more beneath. */
/* About only: the film's word column widens for the paragraph —
   and the columns' overall stage widens with it. */
.parts__columns {
	width: min(1320px, 100%);
	grid-template-columns: auto minmax(0, 62ch);
}

.parts__caption--blurb h3 {
	font-size: clamp(1.2rem, 1.9vw, 1.6rem);
	font-weight: 400;
	line-height: 1.75;
	letter-spacing: 0;
	text-align: left;
	white-space: normal;
}

/* Handset film: the phone and the paragraph share one seat — the
   phone opens the scene, home.js dissolves it into the words. The
   pair centres vertically in the stage and the words take the full
   width. */
@media (max-width: 820px) {
	.parts[data-film] .parts__stage {
		grid-template-rows: auto 1fr auto;
		padding-top: 4rem;
	}
	.parts[data-film] .parts__head {
		align-self: start;
	}
	.parts__columns {
		width: 100%;
		grid-template-columns: 1fr;
		align-self: center;
	}
	.parts__frame,
	.parts__station {
		grid-area: 1 / 1;
		align-self: center;
	}
	.parts__station {
		width: 92%;
	}
	/* Centred in the phone's seat; about.js fits the size to it. */
	.parts__caption--blurb h3 {
		text-align: center;
	}
}

/* The contact form borrows contact.css inside the centred mission
   column — re-anchored left, and seated in a quiet card: the mission
   photo's 25px radius, a hairline instead of a shadow. */
.text-page--contact .text-page__inner {
	/* The card rack below runs 960 wide; the form matches it. */
	max-width: 960px;
	width: 100%;
}

.text-page--contact .contact__form {
	text-align: left;
	margin-top: var(--space-xl);
	background: #f7f8f4;
	border: 1px solid rgba(45, 74, 62, 0.1);
	border-radius: 25px;
	padding: 3rem 3.4rem 2.6rem;
	/* Wide card, so name and email share a row; the message, the
	   error line and the button span it. */
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1.7rem 2.6rem;
}

.text-page--contact .field:has(textarea),
.text-page--contact .contact__error {
	grid-column: 1 / -1;
}

.text-page--contact .contact__submit {
	grid-column: 1 / -1;
	justify-self: center;
}

@media (max-width: 700px) {
	.text-page--contact .contact__form {
		grid-template-columns: 1fr;
		padding: 2rem 1.4rem 1.8rem;
	}
}

/* No small caps here — the labels speak the page's own serif,
   in full ink so they read against the card. */
.text-page--contact .field label {
	font-family: var(--serif);
	font-size: 1.05rem;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ink);
	opacity: 1;
}

