/* ============================================================================
   VANGUARD  —  /luxury-website-design/
   A theme page that is also a landing page. Loads NO css/style.css and NO
   js/main.js; this file is the whole design.

   THE MATERIAL: an architectural viewfinder. Obsidian, one bronze, Roman
   capitals. Every section is a frame that a stage moves through, and scroll
   position is the camera. Nothing on the page is decorated: the frame, the
   rule and the glowing dot are the only ornament there is.

   THE COLOUR RULE, one line so it can be checked:

       One bronze, on black, and it only ever marks the thing being
       pointed at. Alabaster carries the words; bronze carries the aim.

   Bronze on obsidian is 8.3:1 and bronze on alabaster is 2.29:1, so BRONZE
   NEVER LANDS ON A LIGHT SURFACE. If any band on this page ever inverts, its
   annotation goes obsidian, not bronze. That is the whole reason the
   collection band at the foot keeps the page's own black wall instead of
   taking the lit one the other landing pages use.

   ---------------------------------------------------------------------------
   THE PEN SHIPS. Adam's CodePen is reproduced below between THE PEN BEGINS and
   THE PEN ENDS. Its palette, its type, its keyframes and its ranges are his.
   Additions and fixes are written as ADDED n blocks AFTER the pen, never as
   edits inside it: a later same-name rule wins, so there is exactly one place
   to revert. If you are about to edit anything between the markers, stop and
   ask him.

   WHAT WAS CHANGED FROM THE PEN, and nothing else:
     1. THE FULL-SCREEN "CHOOSE YOUR EXPERIENCE" GATE IS CUT (Adam, 2026-08-20).
        A load-time interstitial that covers the content is exactly what
        Google's intrusive-interstitial penalty targets, and the site already
        has a real experience selector that this one could not drive. Its look
        is not lost: the badge and the two bronze outline buttons are the
        hero's CTA pair now. Its CSS is not reproduced below.
     2. The copy is entirely new. The pen pitched architecture firms;
        /architecture-firm-websites/ already owns that term, so this page
        pitches the tier and names architecture once, linking down.
     3. Sections added, all built from mechanisms the pen already has: the
        eight-row spec sheet reuses the louvers, the fit grid reuses the
        matrix, and the questions, contact, PS note and collection band reuse
        the fade-up.
     4. The fixes in ADDED 1..12. Read those before touching anything.
   ============================================================================ */


/* ============================================================
   FONTS — self-hosted, generated by tools/fonts.py.
   This page is a THEME PAGE: it loads no style.css, so these faces are
   declared here and no other page fetches them. NO fonts.googleapis.com
   link anywhere; the site's NO CROSS-ORIGIN REQUESTS invariant holds.

   Same latin / latin-ext split policy as the rest of the site: the ext
   halves are never fetched unless an accented character is actually
   rendered, which today none is. The ranges must match LATIN / LATIN_EXT
   in tools/fonts.py EXACTLY and must not overlap.

   Cinzel is a Roman inscriptional face: it has no true lowercase design
   worth the weight and the page never sets it below ~1.3rem, so its
   hairlines always have the size to survive.
   ============================================================ */
@font-face {
	font-family: "Cinzel";
	src: url("/assets/fonts/cinzel-latin-v1.woff2") format("woff2");
	font-weight: 400 700;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+00B0, U+00B7, U+2010-2027, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2190-2193, U+2212;
}

@font-face {
	font-family: "Cinzel";
	src: url("/assets/fonts/cinzel-latinext-v1.woff2") format("woff2");
	font-weight: 400 700;
	font-style: normal;
	font-display: swap;
	unicode-range: U+00A1-00A8, U+00AA-00AD, U+00AF, U+00B1-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC;
}

@font-face {
	font-family: "Plus Jakarta Sans";
	src: url("/assets/fonts/jakarta-latin-v1.woff2") format("woff2");
	font-weight: 300 600;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+00B0, U+00B7, U+2010-2027, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2190-2193, U+2212;
}

@font-face {
	font-family: "Plus Jakarta Sans";
	src: url("/assets/fonts/jakarta-latinext-v1.woff2") format("woff2");
	font-weight: 300 600;
	font-style: normal;
	font-display: swap;
	unicode-range: U+00A1-00A8, U+00AA-00AD, U+00AF, U+00B1-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC;
}

/* ---- Poster faces, for the collection band at the foot of the page.
   style.css's own subsets, declared verbatim: .poster_daylight asks for
   JetBrains Mono and .poster_silver asks for Cinzel Decorative, and this
   page loads no style.css. Long View's poster declares no face at all and
   letters in spaced capitals on the system sans, so it costs nothing.
   The unicode-ranges must match tools/fonts.py's LATIN / LATIN_EXT exactly
   and must not overlap.

   NEVER PRELOADED. The band is the last thing on a page that runs nine
   sections before it, and nothing above it waits on these. ---- */
@font-face {
	font-family: "Cinzel Decorative";
	src: url("/assets/fonts/cinzel-decorative-poster-v1.woff2") format("woff2");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "JetBrains Mono";
	src: url("/assets/fonts/jetbrains-mono-latin-v1.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+00B0, U+00B7, U+2010-2027, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2190-2193, U+2212;
}

@font-face {
	font-family: "JetBrains Mono";
	src: url("/assets/fonts/jetbrains-mono-latinext-v1.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
	unicode-range: U+00A1-00A8, U+00AA-00AD, U+00AF, U+00B1-00B6, U+00B8-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC;
}


/* ============================================================
   ================  T H E   P E N   B E G I N S  =============
   The owner's CodePen, verbatim. Do not retime it and do not restyle
   it. Additions and fixes go after THE PEN ENDS.

   The one part not reproduced here is the experience gate's CSS
   (.experience-gate, .gate-title, .gate-options, .gate-btn and the
   #experience-toggle:checked rule); the gate is cut, see the header note.
   ============================================================ */

/* ==========================================================================
   ARCHITECTURAL LUXURY DESIGN SYSTEM
   ========================================================================== */
:root {
	--obsidian: #050505;
	--charcoal: #0e0e10;
	--bronze: #c5a059;
	--bronze-glow: rgba(197, 160, 89, 0.15);
	--alabaster: #f7f5f0;
	--muted: #85827a;
	--border-light: rgba(247, 245, 240, 0.08);
	--font-serif: "Cinzel", serif;
	--font-sans: "Plus Jakarta Sans", sans-serif;
}

* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

body {
	background-color: var(--obsidian);
	color: var(--alabaster);
	font-family: var(--font-sans);
	overflow-x: hidden;
	line-height: 1.6;
}

/* Semantic Typography */
h1,
h2,
h3,
h4 {
	font-family: var(--font-serif);
	font-weight: 400;
	letter-spacing: 0.02em;
	color: var(--alabaster);
}

p {
	color: var(--muted);
}

.badge {
	display: inline-flex;
	align-items: center;
	gap: 0.75rem;
	font-family: var(--font-sans);
	font-size: 0.7rem;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	padding: 0.5rem 1.2rem;
	border: 1px solid rgba(197, 160, 89, 0.3);
	background: var(--charcoal);
	color: var(--bronze);
	margin-bottom: 2rem;
}

.badge-dot {
	width: 4px;
	height: 4px;
	background: var(--bronze);
	box-shadow: 0 0 6px var(--bronze);
}

/* ==========================================================================
   SCROLL ENGINE (NO JAVASCRIPT)
   ========================================================================== */
.scroll-section {
	position: relative;
	height: 300vh;
}

.scroll-section.short {
	height: 150vh;
}

.sticky-stage {
	position: sticky;
	top: 0;
	height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

/* ==========================================================================
   SECTION 1: SPATIAL VIEWFINDER (HERO)
   ========================================================================== */
.hero-viewport {
	position: relative;
	width: 100%;
	height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	perspective: 1200px;
}

.viewfinder-frame {
	position: absolute;
	width: 80vw;
	height: 70vh;
	border: 1px solid var(--border-light);
	background: var(--charcoal);
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	padding: 4rem;
	box-shadow: 0 40px 100px rgba(0, 0, 0, 0.9);
	animation: frameExpand linear both;
	animation-timeline: --hero-scroll;
	animation-range: contain 0% cover 100%;
}

@keyframes frameExpand {
	0% {
		transform: translateZ(-300px) rotateX(10deg);
		opacity: 0.8;
	}

	50% {
		transform: translateZ(0) rotateX(0deg);
		opacity: 1;
	}

	100% {
		transform: scale(1.15) translateZ(200px);
		opacity: 0;
		filter: blur(10px);
	}
}

.hero-title {
	font-size: clamp(2.5rem, 4vw, 4.5rem);
	line-height: 1.1;
	max-width: 950px;
}

.hero-title span {
	color: var(--bronze);
	font-style: italic;
}

/* ==========================================================================
   SECTION 2: ASYMMETRIC PARALLAX PLANES (THE PITCH)
   ========================================================================== */
.split-plane-layout {
	display: grid;
	grid-template-columns: 1fr 1fr;
	width: 100%;
	max-width: 1400px;
	padding: 0 4rem;
	gap: 6rem;
	align-items: center;
}

.plane-fixed-content {
	animation: contentFade linear both;
	animation-timeline: --split-scroll;
	animation-range: entry 20% exit 80%;
}

.plane-stack {
	position: relative;
	height: 500px;
	perspective: 1000px;
}

.architectural-panel {
	position: absolute;
	inset: 0;
	background: rgba(14, 14, 16, 0.85);
	border: 1px solid var(--border-light);
	backdrop-filter: blur(20px);
	padding: 3rem;
	display: flex;
	flex-direction: column;
	justify-content: center;
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
}

.panel-1 {
	animation: panelGlide1 linear both;
	animation-timeline: --split-scroll;
	animation-range: cover 0% cover 100%;
}

.panel-2 {
	animation: panelGlide2 linear both;
	animation-timeline: --split-scroll;
	animation-range: cover 0% cover 100%;
}

@keyframes panelGlide1 {
	0% {
		transform: translateY(100%) translateZ(-200px);
		opacity: 0;
	}

	30%,
	60% {
		transform: translateY(0) translateZ(0);
		opacity: 1;
	}

	100% {
		transform: translateY(-120%) translateZ(100px);
		opacity: 0;
	}
}

@keyframes panelGlide2 {

	0%,
	30% {
		transform: translateY(120%) translateZ(-100px);
		opacity: 0;
	}

	60%,
	85% {
		transform: translateY(0) translateZ(0);
		opacity: 1;
		border-color: var(--bronze);
	}

	100% {
		transform: translateY(-100%) translateZ(100px);
		opacity: 0;
	}
}

/* ==========================================================================
   SECTION 3: AEO FAQ / SEMANTIC ANSWER ENGINE BLOCK
   ========================================================================== */
.aeo-container {
	max-width: 1000px;
	width: 100%;
	padding: 0 2rem;
	perspective: 1000px;
}

.qa-block {
	border-bottom: 1px solid var(--border-light);
	padding: 3rem 0;
	animation: qaFadeUp linear both;
	animation-timeline: --aeo-scroll;
}

@keyframes qaFadeUp {
	0% {
		opacity: 0;
		transform: translateY(50px) rotateX(10deg);
	}

	100% {
		opacity: 1;
		transform: translateY(0) rotateX(0deg);
	}
}

.qa-question {
	font-size: 1.8rem;
	margin-bottom: 1rem;
	color: var(--bronze);
}

/* ==========================================================================
   SECTION 4: 3D TECHNICAL LOUVERS
   ========================================================================== */
.louver-container {
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
	width: 100%;
	max-width: 1100px;
	padding: 0 2rem;
	perspective: 1500px;
}

.louver-slat {
	background: var(--charcoal);
	border: 1px solid var(--border-light);
	padding: 2.5rem 3rem;
	display: grid;
	grid-template-columns: 80px 1fr 2fr;
	align-items: center;
	transform-origin: center top;
	animation: louverFlip linear both;
	animation-timeline: --louver-scroll;
}

@keyframes louverFlip {
	0% {
		transform: rotateX(-75deg) translateZ(-100px);
		opacity: 0;
	}

	40%,
	80% {
		transform: rotateX(0deg) translateZ(0);
		opacity: 1;
	}

	100% {
		transform: rotateX(75deg) translateZ(-100px);
		opacity: 0;
	}
}

.louver-num {
	font-family: var(--font-serif);
	font-size: 1.5rem;
	color: var(--bronze);
}

/* ==========================================================================
   SECTION 5: BLUEPRINT MATRIX (SERVICES)
   ========================================================================== */
.blueprint-matrix {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	width: 100%;
	max-width: 1200px;
	gap: 1px;
	background: var(--border-light);
	position: relative;
}

.matrix-cell {
	background: var(--obsidian);
	padding: 3.5rem 2.5rem;
	position: relative;
	overflow: hidden;
	animation: matrixCellIn linear both;
	animation-timeline: --matrix-scroll;
	animation-range: cover 10% cover 70%;
}

@keyframes matrixCellIn {
	0% {
		opacity: 0;
		transform: translateY(40px);
	}

	50%,
	80% {
		opacity: 1;
		transform: translateY(0);
	}

	100% {
		opacity: 0;
		transform: translateY(-40px);
	}
}

.matrix-cell::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 2px;
	background: var(--bronze);
	transform: scaleX(0);
	transform-origin: left;
	animation: lineDraw linear both;
	animation-timeline: --matrix-scroll;
	animation-range: cover 20% cover 60%;
}

@keyframes lineDraw {
	to {
		transform: scaleX(1);
	}
}

/* ==========================================================================
   SECTION 6: MANIFESTO & CTA
   ========================================================================== */
.manifesto-view {
	text-align: center;
	max-width: 1000px;
	padding: 0 2rem;
}

.manifesto-text {
	font-family: var(--font-serif);
	font-size: clamp(2.2rem, 4vw, 3.5rem);
	line-height: 1.25;
	margin-bottom: 3rem;
	background: linear-gradient(180deg, #fff 0%, var(--muted) 100%);
	-webkit-background-clip: text;
	-webkit-text-fill-color: transparent;
}

.cta-button {
	display: inline-block;
	background: transparent;
	color: var(--alabaster);
	border: 1px solid var(--bronze);
	padding: 1.25rem 3.5rem;
	font-family: var(--font-sans);
	font-size: 0.8rem;
	letter-spacing: 0.25em;
	text-transform: uppercase;
	text-decoration: none;
	transition: all 0.4s ease;
	box-shadow: 0 0 20px var(--bronze-glow);
}

.cta-button:hover {
	background: var(--bronze);
	color: var(--obsidian);
	box-shadow: 0 0 40px rgba(197, 160, 89, 0.4);
}

/* Responsive */
@media (max-width: 900px) {
	.split-plane-layout {
		grid-template-columns: 1fr;
		gap: 3rem;
	}

	.blueprint-matrix {
		grid-template-columns: 1fr;
	}

	.louver-slat {
		grid-template-columns: 1fr;
		gap: 1rem;
	}

	.viewfinder-frame {
		width: 92vw;
		padding: 2rem;
	}
}

/* ============================================================
   ==================  T H E   P E N   E N D S  ===============
   Everything below is this page's own, and none of it reaches back
   up into the pen. Read the header note before editing.
   ============================================================ */


/* ============================================================
   ADDED 1 — VIEWPORT UNITS

   The pen is written in vh. On a phone that is the LARGE viewport, so a
   300vh track and a 100vh stage are both measured against a window that
   only exists once the browser chrome has retracted: the stage overflows
   its own frame on load and the last screen of every track is dead.

   The site's rule, from THE LONG VIEW: the TRACK is svh and the STAGE is
   dvh. Mixed units, deliberately. The track must be the small viewport so
   it can never be shorter than the space it has to cover, and the stage
   must be the dynamic one so the pinned frame is always exactly the window
   in front of the reader.
   ============================================================ */
.scroll-section {
	height: 300svh;
}

.scroll-section.short {
	height: 150svh;
}

.sticky-stage {
	height: 100dvh;
}

.hero-viewport {
	height: 100dvh;
}


/* ============================================================
   ADDED 2 — THE PAGE BOUND

   `overflow-x: hidden` on <body> is the one declaration of the pen's that
   had to go. `hidden` on one axis computes `auto` on the other, which
   makes <body> a SCROLL CONTAINER — and every mechanism on this page is a
   `position: sticky` stage inside it. A sticky element inside a scroll
   container that does not itself scroll never releases, and the view
   timelines resolve against the wrong box.

   `clip` bounds the same overflow without creating a scroll container, and
   `overflow-y: visible` beside it is the one legal mixed pair. This is the
   sitewide rule (see main[data-flow] in css/style.css); it is stated here
   because this page loads none of that file.
   ============================================================ */
body {
	overflow-x: clip;
	overflow-y: visible;
}


/* ============================================================
   ADDED 3 — @keyframes contentFade

   `.plane-fixed-content` asks for an animation the pen never defines. An
   undefined name is dropped, so the copy column simply sat still while the
   panels beside it moved. Defined here rather than removed, because the
   column holding still through a 300svh track is the one thing that makes
   the panels read as moving PAST it rather than the page scrolling.

   It is an arrival and a departure with a long hold between them, so the
   copy is legible for the whole middle of the track. Opacity and translate
   only: this element is the section's reading matter.
   ============================================================ */
@keyframes contentFade {
	0% {
		opacity: 0;
		transform: translateY(2.5rem);
	}

	18%,
	82% {
		opacity: 1;
		transform: translateY(0);
	}

	100% {
		opacity: 0;
		transform: translateY(-2.5rem);
	}
}

/* the pen ranges this on `entry 20% exit 80%`, which on a 300svh track
   resolves almost entirely OUTSIDE the pinned stretch — the copy finished
   arriving before the frame locked and started leaving before the panels
   had. Re-anchored to the same `cover` span the panels ride, so all three
   elements in the section share one clock. */
.plane-fixed-content {
	animation-range: cover 0% cover 100%;
}


/* ============================================================
   ADDED 4 — THE SPENT FRAME MUST STOP PAINTING

   frameExpand ends at opacity 0 with blur(10px), held there by
   `fill-mode: both` for the whole rest of the document. At opacity 0 the
   frame is still rasterised every frame: 80vw x 70vh, projected 1.2x by
   its own translateZ, through a 10px blur, behind eight more sections.
   Invisible and expensive.

   `visibility` is discrete, so it flips at the last keyframe and nothing
   is seen to change. This is the tunnel-close-out lesson from css/style.css
   applied to the pen's own frame: a spent frame must stop PAINTING, not
   just fade. Paint cost, not appearance.

   THE PERSPECTIVE POLE IS SAFE HERE and this note is so nobody re-checks
   it: translateZ(200px) against the .hero-viewport's perspective: 1200px
   is 0.167 of the plane, well inside the 0.75 ceiling, and the projection
   is 1200/(1200-200) = 1.2x. It is only worth watching because the same
   keyframe also carries a filter, which is the combination that turns an
   over-poled Z into a GPU crash rather than jank.
   ============================================================ */
@keyframes frameExpand {
	0% {
		transform: translateZ(-300px) rotateX(10deg);
		opacity: 0.8;
		visibility: visible;
	}

	50% {
		transform: translateZ(0) rotateX(0deg);
		opacity: 1;
	}

	100% {
		transform: scale(1.15) translateZ(200px);
		opacity: 0;
		filter: blur(10px);
		visibility: hidden;
	}
}


/* ============================================================
   ADDED 5 — LINKS IN RUNNING COPY

   The pen styles .cta-button and nothing else, so an <a> inside a
   sentence rendered as the browser default: link blue on near-black,
   which is both ugly and under the contrast floor. This page carries a
   lot of links in running copy, because the altitude rule means it links
   DOWN to the pages that own each term instead of re-arguing them.

   Bronze on obsidian is 8.30:1. The underline is the affordance and it
   is always on: on a page this dark, colour alone is not enough of a
   signal, and colour alone is not a WCAG-legal one either.
   ============================================================ */
a {
	color: var(--bronze);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	text-decoration-color: rgba(197, 160, 89, 0.45);
	transition: text-decoration-color .25s ease, color .25s ease;
}

@media (hover: hover) and (pointer: fine) {
	a:hover {
		text-decoration-color: currentColor;
	}
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
	outline: 2px solid var(--bronze);
	outline-offset: 3px;
	border-radius: 2px;
}

/* the two link classes that are NOT running copy: the pen's own button,
   and the masthead. Both undo the underline the rule above just set. */
.cta-button,
.masthead a,
.tt_card,
.slide_explore {
	text-decoration: none;
}

.skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	background: var(--bronze);
	color: var(--obsidian);
	padding: .75rem 1.25rem;
	font-size: .8rem;
	letter-spacing: .2em;
	text-transform: uppercase;
	text-decoration: none;
}

.skip:focus {
	left: 0;
}

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}


/* ============================================================
   ADDED 6 — PAGE FURNITURE

   The pen is six stages and no page. These are the parts a page needs:
   a measure, a heading scale, an annotation, a lede and the definition
   block. All of them are built from the pen's own two faces and its one
   bronze, so nothing here is a new look.

   THE MEASURE IS 68ch AND IT IS THE POINT. This page argues that the tier
   is a standard rather than a style, and the cheapest visible proof of a
   standard is that the copy is set to a measure somebody chose.
   ============================================================ */
body {
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

h2 {
	font-size: clamp(1.9rem, 3.4vw, 3rem);
	line-height: 1.15;
	margin-bottom: 1.5rem;
}

h3 {
	font-size: clamp(1.25rem, 1.9vw, 1.5rem);
	line-height: 1.25;
}

p {
	max-width: 68ch;
}

p + p {
	margin-top: 1.1rem;
}

strong {
	color: var(--alabaster);
	font-weight: 600;
}

em {
	font-style: italic;
}

/* the annotation: the pen's badge type without the box. Section numbers,
   titleblock lines and the PS label all wear it. --muted is 5.3:1 on
   obsidian, which is the floor this page holds everywhere. */
.anno {
	font-family: var(--font-sans);
	font-size: .7rem;
	font-weight: 500;
	letter-spacing: .3em;
	text-transform: uppercase;
	color: var(--muted);
	max-width: none;
}

.lede {
	font-size: clamp(1.02rem, 1.5vw, 1.18rem);
	font-weight: 300;
	color: var(--muted);
}

.lede strong {
	font-weight: 500;
}

/* THE DEFINITION BLOCK — the answer an answer engine lifts whole. Set
   apart by measure and weight, never by a box: a box makes it read as an
   aside rather than as the section's own first sentence. The <strong>
   carries the definition and nothing else in the paragraph does. */
.define {
	font-size: clamp(1.05rem, 1.7vw, 1.22rem);
	line-height: 1.62;
	color: var(--muted);
}

.define strong {
	color: var(--alabaster);
	font-weight: 600;
}

/* every stage holds its content in one measured column */
.stage-inner {
	width: 100%;
	max-width: 1200px;
	padding: 0 clamp(1.5rem, 5vw, 4rem);
}

.section-head {
	margin-bottom: clamp(1.75rem, 4vh, 2.75rem);
}

.section-head h2 {
	margin-bottom: 0;
}

/* the hero's action pair, which is where the cut experience gate went.
   The primary is the pen's own .cta-button; the secondary wears the
   badge's chrome so the two read as a pair rather than as a button and
   an afterthought. */
.hero-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 2rem;
}

.cta-ghost {
	display: inline-block;
	padding: 1.25rem 2.5rem;
	border: 1px solid var(--border-light);
	color: var(--alabaster);
	font-size: 0.8rem;
	letter-spacing: 0.25em;
	text-transform: uppercase;
	text-decoration: none;
	transition: border-color .4s ease, box-shadow .4s ease;
}

@media (hover: hover) and (pointer: fine) {
	.cta-ghost:hover {
		border-color: var(--bronze);
		box-shadow: 0 0 20px var(--bronze-glow);
	}
}

/* the badge is an inline-flex box with a bottom margin, which is right
   where it opens a section and wrong everywhere else */
.badge--tight {
	margin-bottom: 1rem;
}


/* ============================================================
   ADDED 7 — THE MASTHEAD AND THE INDEX

   This page is not in anybody's nav, so it carries its own way back to
   the site: a wordmark and the seven chain pages, as real links, present
   at every width. Crawl parity is the whole reason the panel is built
   this way rather than hidden below the breakpoint.

   Above 900px it is a row across the top. Below, it collapses to a
   toggle and the seven links become a full-height sheet. The panel is
   `inert` while closed AND ONLY while the query matches, or the desktop
   nav would be killed outright; the page behind it is `inert` while it
   is open, which is the cheapest correct focus trap there is. The script
   is inline in the page, because this page loads no main.js.
   ============================================================ */
.masthead {
	position: fixed;
	inset: 0 0 auto;
	z-index: 40;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.1rem clamp(1.25rem, 4vw, 3rem);
	background: linear-gradient(180deg, rgba(5, 5, 5, .92) 0%, rgba(5, 5, 5, .72) 60%, rgba(5, 5, 5, 0) 100%);
}

.wordmark {
	font-family: var(--font-serif);
	font-size: .95rem;
	font-weight: 600;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--alabaster);
	white-space: nowrap;
}

.index_sheet {
	display: flex;
	align-items: center;
	gap: clamp(1rem, 2.2vw, 2rem);
}

.index_sheet a {
	font-family: var(--font-sans);
	font-size: .68rem;
	font-weight: 500;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--muted);
	transition: color .25s ease;
}

@media (hover: hover) and (pointer: fine) {
	.index_sheet a:hover {
		color: var(--bronze);
	}
}

.index_sheet a:focus-visible {
	color: var(--bronze);
}

.nav_toggle {
	display: none;
	width: 44px;
	height: 44px;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	color: var(--alabaster);
}

.nav_toggle svg {
	width: 24px;
	height: 24px;
	display: block;
	margin: 0 auto;
}

@media (max-width: 900px) {
	.nav_toggle {
		display: block;
	}

	.index_sheet {
		position: fixed;
		inset: 0;
		flex-direction: column;
		align-items: flex-start;
		justify-content: center;
		gap: 1.5rem;
		padding: 6rem clamp(1.5rem, 8vw, 4rem) 4rem;
		background: var(--obsidian);
		border-right: 1px solid var(--border-light);
		translate: -100% 0;
		visibility: hidden;
		transition: translate .45s cubic-bezier(.54, .35, .29, .99), visibility .45s;
	}

	html.nav-open .index_sheet {
		translate: 0 0;
		visibility: visible;
	}

	.index_sheet a {
		font-family: var(--font-serif);
		font-size: 1.35rem;
		letter-spacing: .1em;
		color: var(--alabaster);
	}
}

/* the fixed masthead is ~66px of chrome, so every in-page jump has to
   clear it or the target heading lands underneath */
[id] {
	scroll-margin-top: 5.5rem;
}


/* ============================================================
   ADDED 8 — THE LADDERS

   THE PEN'S nth-child SELECTORS ARE CORRECT AS WRITTEN and this note
   exists so nobody "fixes" them: the badge is the first child of both
   .louver-container and .aeo-container, so .louver-slat:nth-child(2) IS
   the first slat. Keep the badge inside the container and the pen's
   three rules keep meaning what they meant.

   WHAT DID CHANGE IS HOW MANY THERE ARE, and it is a geometry limit
   rather than a preference. A .sticky-stage is one viewport with
   `overflow: hidden`, so whatever it holds has to fit inside a short
   laptop window or it is clipped at a hard edge with no visible cause,
   which is the NO INVISIBLE WALLS rule. Four slats and six cells fit.
   Eight answers do not, which is why #questions is not a stage at all.
   ============================================================ */

/* --- the spec sheet: four slats, the pen's +10 ladder continued ------- */
.louver-slat:nth-child(2) {
	animation-range: cover 8% cover 58%;
}

.louver-slat:nth-child(3) {
	animation-range: cover 18% cover 68%;
}

.louver-slat:nth-child(4) {
	animation-range: cover 28% cover 78%;
}

.louver-slat:nth-child(5) {
	animation-range: cover 38% cover 88%;
}

.louver-title {
	font-size: clamp(1.15rem, 1.6vw, 1.4rem);
}

.louver-slat p {
	font-size: .95rem;
}

/* --- the fit grid: six cells over two rows -------------------------- */
/* The pen states one range for every cell, so all six arrive together.
   Staggering them by DOM order is what makes the grid assemble rather
   than appear, and the second row is held back a beat behind the first
   so the eye reads across before it reads down. */
.matrix-cell:nth-child(1) {
	animation-range: cover 8% cover 68%;
}

.matrix-cell:nth-child(2) {
	animation-range: cover 12% cover 72%;
}

.matrix-cell:nth-child(3) {
	animation-range: cover 16% cover 76%;
}

.matrix-cell:nth-child(4) {
	animation-range: cover 20% cover 80%;
}

.matrix-cell:nth-child(5) {
	animation-range: cover 24% cover 84%;
}

.matrix-cell:nth-child(6) {
	animation-range: cover 28% cover 88%;
}

.matrix-cell:nth-child(1)::before {
	animation-range: cover 14% cover 54%;
}

.matrix-cell:nth-child(2)::before {
	animation-range: cover 18% cover 58%;
}

.matrix-cell:nth-child(3)::before {
	animation-range: cover 22% cover 62%;
}

.matrix-cell:nth-child(4)::before {
	animation-range: cover 26% cover 66%;
}

.matrix-cell:nth-child(5)::before {
	animation-range: cover 30% cover 70%;
}

.matrix-cell:nth-child(6)::before {
	animation-range: cover 34% cover 74%;
}

.matrix-cell h3 {
	margin-bottom: .75rem;
}

.matrix-cell p {
	font-size: .95rem;
}

/* the matrix carries its own heading above it, inside the stage */
.matrix-head {
	margin-bottom: clamp(1.5rem, 3.5vh, 2.5rem);
}


/* ============================================================
   ADDED 9 — #questions IS NOT A STAGE

   Eight self-contained answers is roughly 1,800px of type. There is no
   window it fits in, and the whole point of the section is that every
   answer is present, at full size, in the document, on load: it is the
   part of this page an answer engine is meant to lift.

   So the section flows normally and each block arrives on its OWN
   view() timeline, which is exactly what the site's own kit does for a
   card grid on a phone. The pen's fade-up keyframe is reused unchanged.

   IT IS AN INTRO, NOT A SCRUB. `forwards`, not `both`, and the range
   ends while the block is still climbing the screen: a triggered outro
   plays to a viewport that has already moved on, and an answer that
   fades back out is an answer that is not there to be quoted.

   The pen's .qa-block names --aeo-scroll. That timeline does not exist
   on this page any more, and an unresolvable timeline with `both` fill
   parks the element on its FROM keyframe, which here is opacity 0. The
   override below is therefore not a preference: without it the section
   is eight invisible paragraphs.
   ============================================================ */
.qa-block {
	animation-name: qaFadeUp;
	animation-timing-function: linear;
	animation-fill-mode: forwards;
	animation-timeline: view();
	animation-range: entry 15% cover 18%;
	transform-origin: 50% 100%;
}

.qa-block:last-child {
	border-bottom: 0;
}

.qa-question {
	font-size: clamp(1.3rem, 2.1vw, 1.8rem);
}

.qa-block p {
	font-size: 1rem;
}

/* the questions section is a plain block, so it states its own rhythm */
.flow-section {
	padding: clamp(4rem, 12vh, 8rem) 0;
}

.flow-section .stage-inner {
	margin-inline: auto;
}

.qa-more {
	margin-top: 2.5rem;
}


/* ============================================================
   ADDED 10 — INSIDE THE FRAME, AND THE REVERSED SPLIT

   The pen's hero frame is a flex column set to space-between with three
   children: the badge, the title, and a footer row. The footer row is
   the only part it left as an inline style, so it is written out here.

   The frame is 70vh of a 100dvh stage with 4rem of padding, and the
   heading is the largest type on the page, so on a short window the three
   children have to be allowed to close up rather than push each other
   out through `overflow: hidden`.

   .reversed mirrors the split so two consecutive split sections do not
   land the art on the same side twice. That is the site's own rule for
   its feature splits and it is the same reasoning here: consecutive
   splits alternate, so adding one means checking its neighbour.
   ============================================================ */
.hero-foot {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: flex-end;
	gap: 1.5rem;
}

.hero-foot p {
	max-width: 46ch;
	margin: 0;
}

.frame-mark {
	font-family: var(--font-serif);
	font-size: .9rem;
	letter-spacing: .18em;
	color: var(--bronze);
	white-space: nowrap;
}

@media (max-height: 760px) {
	.viewfinder-frame {
		padding: 2.25rem;
		gap: 1.25rem;
	}

	.hero-title {
		font-size: clamp(1.9rem, 3.4vw, 3rem);
	}
}

.split-plane-layout.reversed .plane-fixed-content {
	order: 2;
}

.split-plane-layout.reversed .plane-stack {
	order: 1;
}

@media (max-width: 900px) {

	/* stacked, the copy always leads: the panels are the illustration of
	   the argument above them, not a column beside it. And the stack has
	   to leave the absolute-positioned panels a box to sit in. */
	.split-plane-layout.reversed .plane-fixed-content,
	.split-plane-layout.reversed .plane-stack {
		order: 0;
	}

	.plane-stack {
		height: 380px;
	}

	.architectural-panel {
		padding: 2rem;
	}
}

.panel-tag {
	color: var(--bronze);
	font-size: 0.8rem;
	font-weight: 500;
	letter-spacing: 0.2em;
	text-transform: uppercase;
}

.architectural-panel h3 {
	margin: 0.5rem 0 1rem;
}

/* THE PEN DECLARES --manifesto-scroll AND NEVER USES IT. Rather than
   delete the name, this is the animation it was plainly for: without one
   the closing section is a 150svh track holding a completely static
   screen, which is dead scroll on the page that argues nothing is
   accidental. contentFade is reused, so no new motion is invented. */
.manifesto-view {
	animation: contentFade linear both;
	animation-timeline: --manifesto-scroll;
	animation-range: cover 0% cover 100%;
}

.manifesto-note {
	margin: -1.5rem auto 2.5rem;
}

.manifesto-view p {
	margin-inline: auto;
}


/* ============================================================
   ADDED 11 — THE CONTACT SECTION, THE PS CLOSE AND THE TITLEBLOCK

   A real form posting to /api/contact, the same Cloudflare Pages function
   every other page uses, with the `company` honeypot. The handler is
   inline in the page: this page loads no main.js.

   The section flows rather than pinning. A form inside a 300svh pinned
   stage means a visitor scrolls three screens while the thing they are
   trying to fill in sits still and then leaves; and a scrubbed frame
   wrapped around form controls is the same failure as a scrubbed frame
   around a card grid, one level worse because this one is interactive.

   THE PS CLOSE is the last block inside #contact, above the titleblock,
   exactly where /architecture-firm-websites/ puts it. No price and no
   comparison in it: a theme costs about what starting from scratch costs,
   and the only saving that may be claimed is that it settles the design.
   ============================================================ */
.contact-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(2rem, 5vw, 5rem);
	align-items: start;
}

@media (max-width: 900px) {
	.contact-grid {
		grid-template-columns: 1fr;
	}
}

.contact_form {
	display: grid;
	gap: 1.1rem;
}

.field {
	display: grid;
	gap: .45rem;
}

.field label {
	font-family: var(--font-sans);
	font-size: .68rem;
	font-weight: 500;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--muted);
}

.field input,
.field textarea {
	width: 100%;
	font-family: var(--font-sans);
	font-size: 1rem;
	color: var(--alabaster);
	background: var(--charcoal);
	border: 1px solid var(--border-light);
	padding: .85rem 1rem;
	transition: border-color .25s ease;
}

.field textarea {
	resize: vertical;
	min-height: 8rem;
}

.field input:focus,
.field textarea:focus {
	border-color: var(--bronze);
}

/* the honeypot. Off-screen rather than display:none, because a bot that
   reads computed style skips a hidden field and fills a visible one. */
.hp_field {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.contact_form button {
	justify-self: start;
	cursor: pointer;
	background: transparent;
	color: var(--alabaster);
	border: 1px solid var(--bronze);
	padding: 1.1rem 3rem;
	font-family: var(--font-sans);
	font-size: 0.8rem;
	letter-spacing: 0.25em;
	text-transform: uppercase;
	transition: background .4s ease, color .4s ease, box-shadow .4s ease;
	box-shadow: 0 0 20px var(--bronze-glow);
}

@media (hover: hover) and (pointer: fine) {
	.contact_form button:hover:not(:disabled) {
		background: var(--bronze);
		color: var(--obsidian);
		box-shadow: 0 0 40px rgba(197, 160, 89, 0.4);
	}
}

.contact_form button:disabled {
	opacity: .55;
	cursor: default;
}

.form_status {
	font-size: .9rem;
	min-height: 1.4em;
	margin: 0;
}

.form_status.ok {
	color: var(--bronze);
}

.form_status.err {
	color: #e8a49a;
}

.ps_note {
	position: relative;
	margin-top: clamp(2.5rem, 6vh, 4rem);
	padding-top: clamp(1.5rem, 3vh, 2.25rem);
	border-top: 1px solid var(--border-light);
}

.ps_note .anno {
	color: var(--bronze);
	margin-bottom: .75rem;
}

.titleblock {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 1rem;
	margin-top: clamp(2rem, 5vh, 3rem);
	padding-top: 1rem;
	border-top: 1px solid var(--border-light);
}


/* ============================================================
   ADDED 12 — THE COLLECTION BAND

   "Like this theme? You might also like:" — global for the themes and the
   landing pages. Built to travel, so nothing here is named for this page
   and nothing is an id.

   The three cards are HOME'S POSTERS, PORTED VERBATIM: .slide_poster,
   .poster_bg, .poster_title, .poster_sub, .poster_kicker and each theme's
   own block, copied unchanged out of css/style.css, which this page does
   not load. NOT ported: the 3-D hover pops and the fan poses, both of
   which need the carousel's preserve-3d rig. A change to style.css's
   POSTERS block is a change to this copy.

   THE BAND KEEPS THIS PAGE'S BLACK WALL, and that is the one thing it
   does differently from the other three. Everywhere else the band sits on
   a lit wall; here it cannot, because this theme's annotation and links
   are bronze, and bronze on a light surface measures 2.29:1. The colophon
   under it takes the same wall, and the band's own bottom hairline is the
   only rule between them.
   ============================================================ */
.alsolike {
	position: relative;
	padding: clamp(3.5rem, 9vh, 7rem) clamp(1.5rem, 5vw, 4rem);
	border-top: 1px solid var(--border-light);
	background:
		radial-gradient(120% 90% at 50% 0%, rgba(197, 160, 89, .07) 0%, transparent 62%),
		var(--obsidian);
}

.alsolike_inner {
	width: min(100%, 1200px);
	margin-inline: auto;
}

.alsolike_eyebrow {
	color: var(--bronze);
	margin-bottom: .9rem;
}

.alsolike h2 {
	max-width: 22ch;
}

.alsolike_lead {
	margin-bottom: clamp(2rem, 5vh, 3.25rem);
}

.alsolike_grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.25rem, 2.5vw, 2.25rem);
}

@media (max-width: 860px) {
	.alsolike_grid {
		grid-template-columns: 1fr;
	}
}

.alsolike_more {
	margin-top: clamp(1.75rem, 4vh, 2.75rem);
}

/* one card = one poster. No card chrome: the poster is the object, and
   the caption below it reads as a caption rather than as furniture.
   container-type is what gives the poster its em scale, exactly as
   .theme_stack_col does for the home fan, and with no padding 100cqw IS
   the poster's width. */
.tt_card {
	display: block;
	container-type: inline-size;
	transition: translate .3s ease;
}

/* the lift is on `translate`, never on `transform`: the poster elements
   inside own transform, and a hover written as one would fight them */
@media (hover: hover) and (pointer: fine) {
	.tt_card:hover {
		translate: 0 -4px;
	}

	.tt_card:hover .tt_art {
		box-shadow: 0 22px 46px rgb(0 0 0 / .55);
	}
}

.tt_art {
	position: relative;
	overflow: hidden;
	aspect-ratio: 700 / 450;
	--u: calc(100cqw / 700);
	font-size: calc(16 * var(--u));
	border: 1px solid var(--border-light);
	box-shadow: 0 16px 36px rgb(0 0 0 / .45);
	transition: box-shadow .3s ease;
}

.tt_note {
	margin-top: .9rem;
	font-size: .92rem;
}

.tt_card .titleblock {
	margin-top: .9rem;
	padding-top: .75rem;
}

.tt_card .titleblock .anno:last-child {
	color: var(--bronze);
}

/* ---- the poster base, ported verbatim from css/style.css ---------- */
.slide_poster {
	position: relative;
	width: 100%;
	height: 100%;
	border-radius: inherit;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .4em;
	text-align: center;
	transform-style: preserve-3d;
}

/* Decor layer: carries the poster's background art and anything that
   needs corner clipping (the sold ribbon). Kept as its own layer because
   overflow:hidden on .slide_poster itself would flatten the translateZ
   pops of the title/button. */
.poster_bg {
	position: absolute;
	inset: 0;
	overflow: hidden;
	border-radius: inherit;
	transform: translateZ(0);
}

/* Every poster element rests 2px off the card face (translateZ(2px)) —
   never coplanar with the opaque .poster_bg at Z 0, so the preserve-3d
   depth sort never has a tie to resolve against the bg. (The mouseout
   blink this was first blamed on was really the --bounce overshoot —
   see the pops comment below — but the lift stays as cheap insurance.)
   The hover pops overwrite from this 2px base; give any NEW poster
   element the same rest lift. Raw px on purpose, matching the pops
   (45/30px). */
.poster_title {
	margin: 0;
	position: relative;
	font-size: 3.4em;
	line-height: 1.05;
	letter-spacing: 2px;
	transform: translateZ(2px);
	transition: transform .35s ease;
}

.poster_sub {
	margin: 0;
	position: relative;
	font-size: 1.3em;
	line-height: 1.2;
	transform: translateZ(2px);
	transition: transform .35s ease;
}

.poster_kicker {
	margin: 0 0 .4em;
	position: relative;
	font-size: .8em;
	letter-spacing: .28em;
	text-transform: uppercase;
	font-family: 'Courier New', monospace;
	transform: translateZ(2px);
}

/* ---- Silver Plate, ported verbatim ------------------------------- */
.poster_silver .poster_bg {
	background:
		radial-gradient(circle 16em at 30% 20%, #38475b, transparent 70%),
		#242c38;
}

/* THE BAND IS ANCHORED BY ITS CENTRE ON THE CORNER, not by a tuned top/right
   pair (2026-07-31, Adam: on the previews the badge read "too far up and too
   far in"). translate(50%, -50%) parks the box's centre exactly on the card's
   top-right corner; the 4em diagonal then steps it back inside along the
   band's own normal. The label is centred in the BOX, and only this puts the
   box centre on the middle of the VISIBLE chord — the old offsets left it
   1.5em up-left of it here, and further off on the landing pages, where the
   ribbon inherits the host theme's face and measures differently again.
   4em is the one choice in the rule: it is half the chord's diagonal, so the
   visible band is 4em times 2 times root-2 long (~11.3em, which is what it
   already measured — this re-centres the label, it does not resize the band).
   Keep the horizontal padding generous: the box has to stay LONGER than that
   chord or the gold runs out before the corner does. The real theme does the
   same thing with translate(28%, 55%) on a fixed 260px width
   (portfolio/themes/silver-plate/theme.css .purchased-banner). */
.poster_silver .poster_ribbon {
	position: absolute;
	top: 0;
	right: 0;
	transform: translate(50%, -50%) translate(-4em, 4em) rotate(45deg);
	padding: .3em 3em;
	font-size: .8em;
	letter-spacing: .25em;
	text-transform: uppercase;
	font-weight: 700;
	background: linear-gradient(180deg, #f0c96c, #c89a34);
	color: #241a05;
}

/* Same pair as the real theme: one asset, mirrored to the opposite corner
   (portfolio/themes/silver-plate/theme.css .teapot / .teapot--mirror) */
.poster_silver .poster_teapot {
	position: absolute;
	left: -.5em;
	bottom: -.5em;
	width: 4.6em;
	height: auto;
	opacity: .6;
	filter: drop-shadow(0 .1em .2em rgba(0, 0, 0, .5));
}

.poster_silver .poster_teapot--mirror {
	left: auto;
	right: -.5em;
	transform: scaleX(-1);
}

.poster_silver .poster_title {
	font-family: "Cinzel Decorative", Georgia, 'Times New Roman', serif;
	letter-spacing: .06em;
	background: linear-gradient(180deg, #fdfdfd 15%, #8d8d96 55%, #ececf4 90%);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	filter: drop-shadow(0 .04em .05em rgba(0, 0, 0, .85));
}

.poster_silver .poster_sub {
	color: #9d9da6;
}

/* ---- Long View, ported verbatim ---------------------------------- */
.poster_longview .poster_bg {
	background:
		/* the sheet, warmed unevenly the way vellum is */
		radial-gradient(ellipse 90% 80% at 32% 24%, #f2eee5 0%, #e7e1d4 68%),
		#e7e1d4;
}

.poster_longview .poster_bg::after {
	content: "";
	position: absolute;
	inset: .65em;
	border: 1px solid rgba(31, 42, 33, .3);
}

/* THE MARK — the maturity circle. Two rings on one element: the dashed
   promise is the border, the planted thing is the small inset disc. */
.poster_longview .poster_mark {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 7.4em;
	height: 7.4em;
	translate: -50% -50%;
	transform: translateZ(1px);
	border: 1px dashed rgba(31, 42, 33, .55);
	border-radius: 50%;
}

.poster_longview .poster_mark::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 1.5em;
	height: 1.5em;
	translate: -50% -50%;
	border: 1px solid rgba(31, 42, 33, .75);
	border-radius: 50%;
	background: rgba(31, 42, 33, .12);
}

.poster_longview .poster_kicker {
	color: #46523f;
}

.poster_longview .poster_title {
	font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	font-size: 2em;
	font-weight: 600;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: #1f2a21;
}

.poster_longview .poster_sub {
	color: #46523f;
}

/* ---- Daylight Study, ported verbatim ----------------------------- */
.poster_daylight .poster_bg {
	background:
		linear-gradient(118deg, rgba(240, 215, 164, .58) 0 20%, rgba(240, 215, 164, 0) 62%),
		linear-gradient(168deg, #eceded 0%, #dfe1dd 100%);
}

/* the sheet edge. ::after because .poster_bg::before is unused and this
   is the layer that clips — the border must not ride the type's Z pops */
.poster_daylight .poster_bg::after {
	content: "";
	position: absolute;
	inset: .65em;
	border: 1px solid rgba(21, 24, 26, .28);
}

.poster_daylight .poster_kicker {
	font-family: "JetBrains Mono", ui-monospace, monospace;
	color: #676c6e;
}

.poster_daylight .poster_title {
	font-family: "JetBrains Mono", ui-monospace, monospace;
	font-size: 2.3em;
	letter-spacing: .01em;
	text-transform: uppercase;
	color: #15181a;
}

.poster_daylight .poster_sub {
	color: #676c6e;
}


/* ============================================================
   ADDED 13 — THE COLOPHON, AND THE FORCED-COLOURS FLOOR
   ============================================================ */
.colophon {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.5rem clamp(1.5rem, 5vw, 4rem) 2.5rem;
	background: var(--obsidian);
}

/* the band closes itself with a hairline and a second one immediately
   under it reads as a 2px double rule. Written through main:has()
   because the band is the LAST THING INSIDE <main> and the colophon is
   main's sibling: `.alsolike + .colophon` looks right and never matches. */
main:has(.alsolike) + .colophon {
	border-top: 0;
}

/* The manifesto quote is the single most quotable sentence on the page
   and it is painted by clipping a gradient to the glyphs. In Windows
   High Contrast the gradient is dropped and the transparent fill is
   kept, so the sentence renders as nothing at all. */
@media (forced-colors: active) {
	.manifesto-text {
		background: none;
		-webkit-text-fill-color: currentColor;
		color: CanvasText;
	}

	.badge,
	.cta-button,
	.cta-ghost,
	.tt_art {
		border-color: CanvasText;
	}
}


/* ============================================================================
   ============        A D D E D   1 4  —  T H E   S E T T L E D   P A G E
   ============================================================================

   THIS BLOCK IS THE REASON THE PAGE IS NOT BLANK, and it is the single most
   load-bearing thing in the file.

   The pen is 100% scroll-timeline driven and every one of its keyframes runs
   `fill-mode: both` off a FROM state of `opacity: 0`. Where the timeline
   cannot resolve, the animation becomes a 0s time animation parked on that
   FROM state: six full screens of nothing, with 300svh of scroll under each
   one. That is not a degraded page, it is a broken one, and it is what
   Firefox, an older Safari, a reduced-motion reader and anyone who picked
   Standard or Slide Deck on this site would all have seen.

   A COLLAPSED RUNWAY MUST HAVE ITS SCRUB KILLED IN THE SAME RULE. Killing the
   track without killing the animation leaves the content invisible; killing
   the animation without killing the track leaves screens of dead scroll.

   THREE GUARDS, ONE OUTCOME, and they are three copies on purpose:

     1. @supports not (animation-timeline: view())
        the browser cannot do this at all. Firefox today.
     2. @media (prefers-reduced-motion: reduce)
        the reader asked their operating system for stillness, and they get
        it without needing this site's own stamp or any JavaScript.
     3. html.no-runway
        the site's own stamp, set pre-paint for reduced motion AND for the
        'standard' and 'deck' experiences. A class cannot be tested inside
        @supports, which is why this one cannot be folded into the first.
        The experience selector is not on this page, but a choice stored
        anywhere else on the site still stamps the flag here.

   Editing one of these means editing all three. They must stay identical.
   ============================================================================ */

@supports not (animation-timeline: view()) {

	.scroll-section,
	.scroll-section.short {
		height: auto;
		min-height: 100svh;
	}

	.sticky-stage {
		position: static;
		height: auto;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 7rem);
	}

	.hero-viewport {
		position: static;
		display: block;
		height: auto;
		perspective: none;
	}

	.viewfinder-frame {
		position: static;
		width: auto;
		height: auto;
		animation: none;
		transform: none;
		filter: none;
		opacity: 1;
		visibility: visible;
	}

	.plane-fixed-content {
		animation: none;
		transform: none;
		opacity: 1;
	}

	.plane-stack {
		position: static;
		display: grid;
		gap: 1.25rem;
		height: auto;
		perspective: none;
	}

	.architectural-panel {
		position: static;
		inset: auto;
		animation: none;
		transform: none;
		opacity: 1;
		backdrop-filter: none;
		background: var(--charcoal);
		border-color: var(--border-light);
	}

	.aeo-container,
	.louver-container {
		perspective: none;
	}

	.qa-block,
	.louver-slat,
	.matrix-cell,
	.manifesto-view {
		animation: none;
		transform: none;
		opacity: 1;
	}

	.matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}
}

@media (prefers-reduced-motion: reduce) {

	.scroll-section,
	.scroll-section.short {
		height: auto;
		min-height: 100svh;
	}

	.sticky-stage {
		position: static;
		height: auto;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 7rem);
	}

	.hero-viewport {
		position: static;
		display: block;
		height: auto;
		perspective: none;
	}

	.viewfinder-frame {
		position: static;
		width: auto;
		height: auto;
		animation: none;
		transform: none;
		filter: none;
		opacity: 1;
		visibility: visible;
	}

	.plane-fixed-content {
		animation: none;
		transform: none;
		opacity: 1;
	}

	.plane-stack {
		position: static;
		display: grid;
		gap: 1.25rem;
		height: auto;
		perspective: none;
	}

	.architectural-panel {
		position: static;
		inset: auto;
		animation: none;
		transform: none;
		opacity: 1;
		backdrop-filter: none;
		background: var(--charcoal);
		border-color: var(--border-light);
	}

	.aeo-container,
	.louver-container {
		perspective: none;
	}

	.qa-block,
	.louver-slat,
	.matrix-cell,
	.manifesto-view {
		animation: none;
		transform: none;
		opacity: 1;
	}

	.matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}

	.cta-button,
	.cta-ghost,
	.tt_card,
	.tt_art,
	a,
	.field input,
	.field textarea,
	.contact_form button {
		transition: none;
	}
}

/* ---- guard 3: the site's own stamp. Same collapse, class-scoped. ---- */
html.no-runway .scroll-section,
html.no-runway .scroll-section.short {
	height: auto;
	min-height: 100svh;
}

html.no-runway .sticky-stage {
	position: static;
	height: auto;
	overflow: visible;
	padding-block: clamp(3.5rem, 10vh, 7rem);
}

html.no-runway .hero-viewport {
	position: static;
	display: block;
	height: auto;
	perspective: none;
}

html.no-runway .viewfinder-frame {
	position: static;
	width: auto;
	height: auto;
	animation: none;
	transform: none;
	filter: none;
	opacity: 1;
	visibility: visible;
}

html.no-runway .plane-fixed-content {
	animation: none;
	transform: none;
	opacity: 1;
}

html.no-runway .plane-stack {
	position: static;
	display: grid;
	gap: 1.25rem;
	height: auto;
	perspective: none;
}

html.no-runway .architectural-panel {
	position: static;
	inset: auto;
	animation: none;
	transform: none;
	opacity: 1;
	backdrop-filter: none;
	background: var(--charcoal);
	border-color: var(--border-light);
}

html.no-runway .aeo-container,
html.no-runway .louver-container {
	perspective: none;
}

html.no-runway .qa-block,
html.no-runway .louver-slat,
html.no-runway .matrix-cell,
html.no-runway .manifesto-view {
	animation: none;
	transform: none;
	opacity: 1;
}

html.no-runway .matrix-cell::before {
	animation: none;
	transform: scaleX(1);
}


/* ============================================================================
   ============   A D D E D   1 5  —  A   S T A G E   P I N S   O N L Y
   ============   W H E R E   I T S   C O N T E N T   F I T S
   ============================================================================

   A .sticky-stage is ONE viewport with `overflow: hidden`, and the pen centres
   its content inside it. So the moment the content is taller than the window,
   the overflow splits top and bottom and the frame eats both ends of it: the
   section's own badge disappears off the top behind a hard edge with no visible
   cause. That is the NO INVISIBLE WALLS rule, and it was live here at every
   viewport shorter or narrower than about 1440x900.

   MEASURED, not guessed (the settled wrapper against its stage):

       1440x900   split 500/900    louvers 814/900    matrix  761/900   fits
       1280x720   split 500/720    louvers 809/720    matrix  750/720
        900x700   split 702/700    louvers 1168/700   matrix 1367/700
        390x844   split 1113/844   louvers 1494/844   matrix 1749/844

   THE FIX IS NOT TO SHRINK THE CONTENT. Tightening the pen's padding or
   dropping rows would be a change to the pitch, and the pen ships. It is to
   stop PINNING where the pin cannot honestly hold what it is given: below the
   thresholds the section becomes an ordinary full-screen block, the content
   flows, and each piece arrives on its own view() timeline and STAYS.

   That is the site's own answer, not a new one. `.grid-section` in
   css/style.css keeps its pinned runway on DESKTOP ONLY and lets a phone bring
   the cards in individually, for exactly this reason: "a phone cannot pin six
   single-column cards".

   TWO THRESHOLDS, because the two shapes need different room, and each states
   what it actually measured:
     · the splits stack below 901px and need ~1100px stacked, so they pin above
       that width and above 620px of height (they need ~500px two-column).
     · the louvers and the matrix need ~820px even multi-column, so they also
       want 880px of height. A 1280x720 laptop therefore reads those two as
       ordinary sections. That is deliberate: 809px of slats in a 720px window
       is not a pinned frame, it is a clipped one.

   `forwards`, never `both`, on everything below: unpinned, these are intros to
   content the reader is scrolling past, and an outro would fade the copy back
   out behind them.
   ============================================================================ */

@media (max-width: 900px), (max-height: 620px) {

	#definition,
	#default {
		height: auto;
		min-height: 100svh;
	}

	#definition .sticky-stage,
	#default .sticky-stage {
		position: static;
		height: auto;
		min-height: 100svh;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 6rem);
	}

	/* the copy column stops being scrubbed and simply arrives */
	#definition .plane-fixed-content,
	#default .plane-fixed-content {
		animation-name: qaFadeUp;
		animation-fill-mode: forwards;
		animation-timeline: view();
		animation-range: entry 12% cover 16%;
		transform-origin: 50% 100%;
	}

	/* THE PANELS COME OUT OF THE ABSOLUTE STACK. They are `position: absolute;
	   inset: 0` inside a fixed-height .plane-stack precisely so they can glide
	   through a pinned frame one after another; with no frame to glide through
	   they are two cards, and they stack. */
	#definition .plane-stack,
	#default .plane-stack {
		height: auto;
		display: grid;
		gap: 1.25rem;
		perspective: none;
	}

	#definition .architectural-panel,
	#default .architectural-panel {
		position: static;
		inset: auto;
		animation-name: qaFadeUp;
		animation-fill-mode: forwards;
		animation-timeline: view();
		animation-range: entry 10% cover 14%;
		transform-origin: 50% 100%;
	}

	/* panel-2 wears the bronze border at the top of its glide; unpinned there
	   is no glide, so it takes it at rest and the pair still reads as a
	   sequence rather than as two identical cards. */
	#definition .panel-2,
	#default .panel-2 {
		border-color: var(--bronze);
	}
}

@media (max-width: 900px), (max-height: 879px) {

	#standard,
	#fit {
		height: auto;
		min-height: 100svh;
	}

	#standard .sticky-stage,
	#fit .sticky-stage {
		position: static;
		height: auto;
		min-height: 100svh;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 6rem);
	}

	#standard .louver-container {
		perspective: none;
	}

	/* the slats stop flipping through a frame and simply open, in order. The
	   pen's own keyframe is reused at half its rotation, because a 75deg flip
	   with no frame around it reads as a glitch rather than as a louver. */
	#standard .louver-slat {
		animation-name: louver-open;
		animation-fill-mode: forwards;
		animation-timeline: view();
		animation-range: entry 8% cover 12%;
	}

	#fit .matrix-cell {
		animation-name: qaFadeUp;
		animation-fill-mode: forwards;
		animation-timeline: view();
		animation-range: entry 8% cover 12%;
		transform-origin: 50% 100%;
	}

	/* the bronze rule still draws, it just draws on arrival */
	#fit .matrix-cell::before {
		animation-fill-mode: forwards;
		animation-timeline: view();
		animation-range: entry 20% cover 20%;
	}
}

@keyframes louver-open {
	from {
		transform: rotateX(-38deg);
		opacity: 0;
	}

	to {
		transform: rotateX(0deg);
		opacity: 1;
	}
}


/* ============================================================================
   ADDED 16 — THE GUARDS, RESTATED AT ADDED 15's SPECIFICITY

   ADDED 15 had to write `#standard .louver-slat` to beat the pen, which is
   (1,1,0). The three collapse guards in ADDED 14 are written on classes alone,
   (0,2,0) at best — so an ID selector added later silently outranks every one
   of them, and a reader who asked for no motion would have got the mobile
   intros anyway. Specificity, not source order, is the trap here.

   THESE MUST STAY IN STEP WITH ADDED 14. Same three triggers, same outcome:
   nothing animates, nothing is left parked on a FROM keyframe.
   ============================================================================ */

@supports not (animation-timeline: view()) {

	#definition .plane-fixed-content,
	#default .plane-fixed-content,
	#definition .architectural-panel,
	#default .architectural-panel,
	#standard .louver-slat,
	#fit .matrix-cell {
		animation: none;
		transform: none;
		opacity: 1;
	}

	#fit .matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}
}

@media (prefers-reduced-motion: reduce) {

	#definition .plane-fixed-content,
	#default .plane-fixed-content,
	#definition .architectural-panel,
	#default .architectural-panel,
	#standard .louver-slat,
	#fit .matrix-cell {
		animation: none;
		transform: none;
		opacity: 1;
	}

	#fit .matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}
}

html.no-runway #definition .plane-fixed-content,
html.no-runway #default .plane-fixed-content,
html.no-runway #definition .architectural-panel,
html.no-runway #default .architectural-panel,
html.no-runway #standard .louver-slat,
html.no-runway #fit .matrix-cell {
	animation: none;
	transform: none;
	opacity: 1;
}

html.no-runway #fit .matrix-cell::before {
	animation: none;
	transform: scaleX(1);
}


/* ============================================================================
   ADDED 17 — THE COVER FRAME SIZES TO WHAT IS IN IT

   The pen fixes the frame at `height: 70vh` and lays it out
   `justify-content: space-between`, which is right on the wide screen it was
   drawn on and wrong the moment the copy needs more room than that. Measured
   at 390px wide the frame is 466px holding 613px of content, and at 390x667 it
   is 368px holding 562px: the badge and the hero foot simply sat outside the
   frame's own border, on top of the page. Not clipped, but plainly broken.

   The pen's own mobile rule only ever changed the frame's WIDTH and padding,
   so its height was never given an answer at this size. This is that answer,
   and it is the smallest one that works: below the breakpoint the frame stops
   being a fixed box and becomes a box that fits its contents, capped so it can
   never grow past the stage that holds it. `space-between` has nothing to
   distribute at auto height, so the gap takes over the spacing.

   Above the breakpoint NOTHING here applies and the pen's 70vh stands.
   ============================================================================ */
@media (max-width: 900px), (max-height: 760px) {
	.viewfinder-frame {
		height: auto;
		max-height: 86dvh;
		gap: clamp(1rem, 2.5vh, 1.75rem);
	}

	.viewfinder-frame .badge {
		margin-bottom: 1rem;
	}

	.hero-foot {
		gap: 1rem;
	}
}

/* the hero actions wrap to their own line before they ever squeeze the
   frame-mark off the end of the foot row */
@media (max-width: 560px) {
	.hero-actions {
		width: 100%;
	}

	.cta-button,
	.cta-ghost {
		flex: 1 1 auto;
		text-align: center;
		padding-inline: 1.5rem;
	}
}


/* ============================================================================
   ============   A D D E D   1 8  —  T H E   P E N   R E A C H E S
   ============   A   S H O R T   W I N D O W
   ============================================================================

   REPORTED BY ADAM (2026-08-20): "the animation for the .louver-slat looks
   completely different... I gave you exactly the animations I liked", and
   "section 4 doesn't do anything".

   BOTH COMPLAINTS ARE ONE CAUSE, AND THE CAUSE IS ADDED 15, NOT THE PEN.
   ADDED 15 unpins #standard and #fit below 880px of viewport HEIGHT and swaps
   the pen's motion for a substitute. Measured at 1536x760 — a 1080p screen at
   Windows' default 125% scaling, which is the single most common desktop
   viewport there is:

                        what ADDED 15 served     the pen
       keyframe         louver-open              louverFlip
       perspective      none                     1500px
       pin              position: static         sticky
       range            entry 8% cover 12%       cover 8% cover 58%

   No 3D, no lock, and about 90px of scroll to play it in. A sweep at 90px
   steps caught each slat mid-flip exactly once. #fit got the same treatment
   with qaFadeUp, which is why the matrix "doesn't do anything" either.

   ADDED 15's TRIGGER WAS REAL AND ITS CURE WAS WORSE THAN THE DISEASE. The
   louver container measures 839px against a 760px stage, so it genuinely
   overflowed by 79px with `overflow: hidden` eating ~40px off each end — the
   NO INVISIBLE WALLS rule. But the answer to "the content is 79px too tall"
   is to reclaim 79px, not to throw away the animation. ADDED 15's own note
   ruled that out ("THE FIX IS NOT TO SHRINK THE CONTENT") and then traded the
   pen's motion away to protect the pen's padding. That is the wrong way round:
   the padding is a proportion, the animation is the pitch.

   ADAM'S CALL (2026-08-20), asked because it changes how his pen looks:
   trim the padding, keep the motion.

   THE HEIGHT IS ALMOST ENTIRELY PADDING. 2.5rem top and bottom on four slats
   is 320px of the 839. Trimming to 1.5rem and the gap to 1rem reclaims 160px:

       1536x760   container 839 -> 679   fits, 81px spare
       1366x720   container 839 -> 677   fits, 43px spare
       1280x700   container 839 -> 673   fits, 27px spare

   #fit needed far less, and at Adam's own viewport it needed NOTHING — the
   wrapper measures 756px against a 760px stage, so ADDED 15 was firing there
   for a 4px margin it already had. One notch off the cell padding (3.5rem ->
   2.5rem) carries it down to 700px too:

       1536x760   wrapper 756 -> 692   fits, 68px spare
       1280x700   wrapper 749 -> 685   fits, 15px spare

   SO ADDED 15'S FLOOR MOVES FROM 880px TO 690px. Below that it still owns the
   two sections, unchanged, and it still owns every width <= 900px, where the
   slats stack single-column and get taller rather than shorter. That width
   arm is why this is a THREE-WAY split and not a threshold edit.

   WHAT THIS BLOCK DELIBERATELY DOES NOT DO: retime anything. An earlier pass
   re-anchored the slats from `cover` to `contain` to keep the whole wave
   inside the pin, and Adam rejected it on sight — the pen's slats BLEED across
   the section edges on purpose, which is the "slight lock" he was describing.
   `contain` clamps exactly that away. THE PEN'S RANGES ARE HIS. The ladders
   restated below are ADDED 8's values, character for character; they are here
   only because ADDED 15's `#fit .matrix-cell` is (1,1,0) and outranks ADDED
   8's (0,2,0), so a range set on classes alone would not survive this branch.
   If you change a number here, change ADDED 8 too, or they will disagree.
   ============================================================================ */

@media (min-width: 901px) and (min-height: 690px) and (max-height: 879px) {

	/* --- put the pin back exactly as the pen has it ------------------- */
	#standard,
	#fit {
		height: 150svh;
	}

	#standard .sticky-stage,
	#fit .sticky-stage {
		position: sticky;
		height: 100dvh;
		min-height: 0;
		overflow: hidden;
		padding-block: 0;
	}

	/* --- the louvers: the pen's motion, on reclaimed room ------------- */
	#standard .louver-container {
		perspective: 1500px;
		gap: 1rem;
	}

	#standard .louver-slat {
		padding-block: 1.5rem;
		animation-name: louverFlip;
		animation-timing-function: linear;
		animation-fill-mode: both;
		animation-timeline: --louver-scroll;
	}

	/* ADDED 8's ladder, restated at (1,2,0) to clear ADDED 15's (1,1,0).
	   nth-child counts from the badge, so (2) is slat 01. */
	#standard .louver-slat:nth-child(2) {
		animation-range: cover 8% cover 58%;
	}

	#standard .louver-slat:nth-child(3) {
		animation-range: cover 18% cover 68%;
	}

	#standard .louver-slat:nth-child(4) {
		animation-range: cover 28% cover 78%;
	}

	#standard .louver-slat:nth-child(5) {
		animation-range: cover 38% cover 88%;
	}

	/* --- the matrix: the pen's motion, one notch off the cell padding -- */
	#fit .matrix-cell {
		padding-block: 2.5rem;
		animation-name: matrixCellIn;
		animation-timing-function: linear;
		animation-fill-mode: both;
		animation-timeline: --matrix-scroll;
		transform-origin: 50% 50%;
	}

	#fit .matrix-cell:nth-child(1) {
		animation-range: cover 8% cover 68%;
	}

	#fit .matrix-cell:nth-child(2) {
		animation-range: cover 12% cover 72%;
	}

	#fit .matrix-cell:nth-child(3) {
		animation-range: cover 16% cover 76%;
	}

	#fit .matrix-cell:nth-child(4) {
		animation-range: cover 20% cover 80%;
	}

	#fit .matrix-cell:nth-child(5) {
		animation-range: cover 24% cover 84%;
	}

	#fit .matrix-cell:nth-child(6) {
		animation-range: cover 28% cover 88%;
	}

	/* the bronze rule draws on the pen's own timeline again */
	#fit .matrix-cell::before {
		animation-name: lineDraw;
		animation-timing-function: linear;
		animation-fill-mode: both;
		animation-timeline: --matrix-scroll;
	}

	#fit .matrix-cell:nth-child(1)::before {
		animation-range: cover 14% cover 54%;
	}

	#fit .matrix-cell:nth-child(2)::before {
		animation-range: cover 18% cover 58%;
	}

	#fit .matrix-cell:nth-child(3)::before {
		animation-range: cover 22% cover 62%;
	}

	#fit .matrix-cell:nth-child(4)::before {
		animation-range: cover 26% cover 66%;
	}

	#fit .matrix-cell:nth-child(5)::before {
		animation-range: cover 30% cover 70%;
	}

	#fit .matrix-cell:nth-child(6)::before {
		animation-range: cover 34% cover 74%;
	}
}

/* ADDED 16's lesson, restated at this block's specificity. Everything above is
   (1,1,0) or (1,2,0), so the three collapse guards — written on classes in
   ADDED 14 and on `#standard`/`#fit` in ADDED 16 — must be repeated here or a
   reader who asked for no motion gets the pen anyway, parked on a FROM
   keyframe. THESE MUST STAY IN STEP WITH ADDED 14 AND ADDED 16. */
@supports not (animation-timeline: view()) {

	#standard,
	#fit {
		height: auto;
		min-height: 100svh;
	}

	#standard .sticky-stage,
	#fit .sticky-stage {
		position: static;
		height: auto;
		min-height: 100svh;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 7rem);
	}

	#standard .louver-container {
		perspective: none;
	}

	#standard .louver-slat,
	#fit .matrix-cell {
		animation: none;
		transform: none;
		opacity: 1;
	}

	#fit .matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}
}

@media (prefers-reduced-motion: reduce) {

	#standard,
	#fit {
		height: auto;
		min-height: 100svh;
	}

	#standard .sticky-stage,
	#fit .sticky-stage {
		position: static;
		height: auto;
		min-height: 100svh;
		overflow: visible;
		padding-block: clamp(3.5rem, 10vh, 7rem);
	}

	#standard .louver-container {
		perspective: none;
	}

	#standard .louver-slat,
	#fit .matrix-cell {
		animation: none;
		transform: none;
		opacity: 1;
	}

	#fit .matrix-cell::before {
		animation: none;
		transform: scaleX(1);
	}
}

html.no-runway #standard,
html.no-runway #fit {
	height: auto;
	min-height: 100svh;
}

html.no-runway #standard .sticky-stage,
html.no-runway #fit .sticky-stage {
	position: static;
	height: auto;
	min-height: 100svh;
	overflow: visible;
	padding-block: clamp(3.5rem, 10vh, 7rem);
}

html.no-runway #standard .louver-container {
	perspective: none;
}

html.no-runway #standard .louver-slat,
html.no-runway #fit .matrix-cell {
	animation: none;
	transform: none;
	opacity: 1;
}

html.no-runway #fit .matrix-cell::before {
	animation: none;
	transform: scaleX(1);
}
