/* ==================================================================
   Sagestone Homes, global base.
   Loaded on every page. Page-scoped section styles live in their own
   stylesheet and are enqueued conditionally in functions.php.
   ================================================================== */

/* ── Fallback metrics ─────────────────────────────────────────────
   Local faces adjusted to match the webfont metrics, so the swap does
   not shift layout. The percentages are close approximations and should
   be confirmed against a fallback-font generator before launch.
   ─────────────────────────────────────────────────────────────── */
@font-face {
	font-family: "Playfair Fallback";
	src: local("Georgia"), local("Times New Roman"), local("serif");
	size-adjust: 105%;
	ascent-override: 98%;
	descent-override: 22%;
	line-gap-override: 0%;
}
@font-face {
	font-family: "Raleway Fallback";
	src: local("Helvetica Neue"), local("Arial"), local("sans-serif");
	size-adjust: 96%;
	ascent-override: 95%;
	descent-override: 24%;
	line-gap-override: 0%;
}

:root {
	/* Brand palette, confirmed from the Sagestone .ai source */
	--sage:        #526A4E;
	--juniper:     #2C412D;
	--brand-accent:#A98553;   /* Bronze */
	--sandstone:   #DCC8A5;
	--limestone:   #F3F1EB;
	--tint:        #E8E4D9;   /* between Limestone and Sandstone, so two bright
	                             sections can sit side by side and still read
	                             as separate rooms */

	/* Site greens, darker than Juniper for the dark grounds */
	--forest:      #0E1D15;
	--forest-deep: #0A1610;

	/* Map markers. Evergreen from the JMI palette, a deliberate tie to the parent brand. */
	--marker:      #1F5B47;

	--font-display: "Playfair Display", "Playfair Fallback", Georgia, serif;
	--font-body:    "Raleway", "Raleway Fallback", system-ui, -apple-system, Helvetica, Arial, sans-serif;

	--gutter: calc((100vw - min(1280px, 88vw)) / 2);
}

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

html { scroll-behavior: smooth; }

body {
	margin: 0;
	background: var(--forest);
	color: var(--limestone);
	font-family: var(--font-body);
	font-weight: 300;
	font-size: 18px;
	line-height: 1.75;
	overflow-x: clip;
	-webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 400; line-height: 1.15; text-wrap: balance; margin: 0; }
p { margin: 0; text-wrap: pretty; }
a { color: inherit; }
img { display: block; max-width: 100%; }
section { position: relative; }

.wrap { width: min(1280px, 88vw); margin: 0 auto; }

/* ── Grounds ──────────────────────────────────────────────────── */
.g-light { background: var(--limestone); color: var(--forest); }
.g-tint  { background: var(--tint); color: var(--forest); }
.g-light h1, .g-light h2, .g-light h3,
.g-tint h1, .g-tint h2, .g-tint h3 { color: var(--forest); }
.g-light .eyebrow, .g-tint .eyebrow { color: var(--sage); }

/* ── Type utilities ───────────────────────────────────────────── */
.eyebrow {
	font-size: 11.5px;
	letter-spacing: .28em;
	text-transform: uppercase;
	color: var(--sandstone);
	font-weight: 500;
}
.rule { width: 54px; height: 1px; background: var(--brand-accent); }
.rule--c { margin: 22px auto; }   /* centred under a centred heading */

/* ── Buttons and links ────────────────────────────────────────── */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	line-height: 1;
	white-space: nowrap;
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 12px;
	letter-spacing: .18em;
	text-transform: uppercase;
	padding: 0 30px;
	min-height: 52px;
	text-box: trim-both cap alphabetic;
	cursor: pointer;
	background: var(--brand-accent);
	color: var(--forest-deep);
	border: 1px solid var(--brand-accent);
	transition: background .4s ease, color .4s ease, border-color .4s ease;
}
.btn:hover { background: var(--sandstone); border-color: var(--sandstone); color: var(--forest-deep); }

.btn--ghost { background: transparent; color: var(--limestone); border-color: rgba(243, 241, 235, .5); }
.btn--ghost:hover { background: var(--limestone); color: var(--forest-deep); border-color: var(--limestone); }
.g-light .btn--ghost, .g-tint .btn--ghost { color: var(--forest); border-color: rgba(14, 29, 21, .45); }
.g-light .btn--ghost:hover, .g-tint .btn--ghost:hover { background: var(--forest); color: var(--limestone); border-color: var(--forest); }

.arrowlink {
	font-size: 12px;
	letter-spacing: .18em;
	text-transform: uppercase;
	font-weight: 500;
	display: inline-flex;
	align-items: center;
	gap: 10px;
}
.arrowlink i { font-style: normal; transition: transform .4s ease; }
.arrowlink:hover i { transform: translateX(7px); }

/* ── Skip link ────────────────────────────────────────────────── */
.skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 200;
	background: var(--limestone);
	color: var(--forest);
	padding: 14px 22px;
	font-size: 13px;
	letter-spacing: .12em;
	text-transform: uppercase;
}
.skip:focus { left: 12px; top: 12px; }

/* ── Focus ────────────────────────────────────────────────────── */
:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 3px; }
.g-light :focus-visible { outline-color: var(--forest); }

/* ── Line icons ───────────────────────────────────────────────────
   Bronze on dark grounds, sage on light. Bronze on Limestone is about
   2:1 and a 1.2 stroke disappears at that ratio.
   ─────────────────────────────────────────────────────────────── */
 /* Icons. Primary is limestone on dark grounds and forest on light ones;
   the accent stays bronze on both. See icons.php for the drawing system. */
.ic { --ic-p: var(--limestone); --ic-a: var(--brand-accent); display: block; overflow: visible; }
.ic--light { --ic-p: var(--forest); }
.ic .p  { fill: var(--ic-p); stroke: none; }
.ic .a  { fill: var(--ic-a); stroke: none; }
.ic .ps { fill: none; stroke: var(--ic-p); stroke-linecap: round; stroke-linejoin: round; }
.ic .as { fill: none; stroke: var(--ic-a); stroke-linecap: round; stroke-linejoin: round; }

/* ── Sprig seam ───────────────────────────────────────────────────
   Positioned with negative margins, never a transform. .reveal sets a
   transform and would overwrite the centering.
   ─────────────────────────────────────────────────────────────── */
.seam {
	position: absolute;
	left: 50%;
	bottom: 0;
	z-index: 7;
	line-height: 0;
	width: 184px;
	margin-left: -92px;
	margin-bottom: -92px;
	pointer-events: none;
}
.seam img { width: 184px; }

/* ── Accordions ───────────────────────────────────────────────────
   Native details and summary, so the answers sit in the DOM for
   crawlers and the control works without JavaScript.
   ─────────────────────────────────────────────────────────────── */
details { border-bottom: 1px solid rgba(169, 133, 83, .3); }
details:first-of-type { border-top: 1px solid rgba(169, 133, 83, .3); }
.g-light details, .g-light details:first-of-type,
.g-tint details, .g-tint details:first-of-type { border-color: rgba(14, 29, 21, .2); }
summary {
	list-style: none;
	cursor: pointer;
	padding: 26px 40px 26px 0;
	position: relative;
	font-family: var(--font-display);
	font-size: clamp(19px, 1.7vw, 23px);
	line-height: 1.35;
}
summary::-webkit-details-marker { display: none; }
summary:after {
	content: "+";
	position: absolute;
	right: 0;
	top: 26px;
	color: var(--brand-accent);
	font-family: var(--font-body);
	font-size: 22px;
	font-weight: 300;
}
details[open] summary:after { content: "\2013"; }
details p { padding: 0 40px 28px 0; color: var(--sandstone); font-size: 16.5px; max-width: 62ch; }
.g-light details p, .g-tint details p { color: #4A4A44; }

/* ── Image placeholders ───────────────────────────────────────────
   Dimension labels render visibly inside each block so the size a
   photo needs is legible in the build, not only in the handoff notes.
   Replace each .ph with a real <img> as photography lands.
   ─────────────────────────────────────────────────────────────── */
.ph {
	position: relative;
	overflow: hidden;
	background:
		radial-gradient(120% 90% at 25% 15%, rgba(169, 133, 83, .22), transparent 60%),
		linear-gradient(150deg, #26372A 0%, #16281C 52%, #0E1D15 100%);
}
.ph--light {
	background:
		radial-gradient(120% 90% at 30% 20%, rgba(169, 133, 83, .30), transparent 62%),
		linear-gradient(150deg, #E4DFD2 0%, #D5CDBA 55%, #C3B79E 100%);
}
/* Legible on purpose. A dimension label nobody can read is the same as no
   label, and these exist so the size a photo needs is obvious in the build.

   Dead centre of every placeholder, solid white, large type, and above
   every overlay and content wrap on the page. They are temporary by
   nature, so legibility wins over the copy they may sit across. */
.ph span {
	position: absolute;
	top: 50%;
	left: 50%;
	right: auto;
	bottom: auto;
	transform: translate(-50%, -50%);
	z-index: 60;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	max-width: calc(100% - 32px);
	padding: 20px 30px;
	font-family: var(--font-body);
	font-size: 15px;
	line-height: 1.3;
	letter-spacing: .12em;
	text-transform: uppercase;
	text-align: center;
	font-weight: 700;
	color: #0E1D15;
	background: #FFFFFF;
	border: 2px solid #0E1D15;
	box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
	pointer-events: none;
}
.ph span b {
	display: block;
	font-size: 42px;
	line-height: 1;
	letter-spacing: .01em;
	font-weight: 700;
	color: #0E1D15;
	white-space: nowrap;
}
.ph--light span { color: #0E1D15; background: #FFFFFF; }

/* A transform on the placeholder turns it into its own stacking context,
   which traps the label underneath the card veils and titles beside it.
   A placeholder is a flat gradient, so the hover zoom and the reveal
   scale do nothing useful on it anyway. Real images keep both. */
.ph:not(.ph--img),
.sage-js .ph.fade-img:not(.ph--img),
.sage-js .ph.fade-img.is-visible:not(.ph--img),
.ccard:hover .ph:not(.ph--img),
.scardx:hover .ph:not(.ph--img),
.card:hover .ph:not(.ph--img) { transform: none !important; }

/* A placeholder with its photo in. The wrapper keeps its layout rules, its
   reveal and its hover zoom; the image fills it. */
/* the map modal swaps between a photo and the placeholder label */
.ph > [hidden] { display: none !important; }

/* Carousels can be dragged. Vertical swipes still scroll the page. */
.car-track, .strip-track { touch-action: pan-y; cursor: grab; -webkit-user-select: none; user-select: none; }
.car-track.is-dragging, .strip-track.is-dragging { cursor: grabbing; transition: none !important; }
.car-track img, .strip-track img { -webkit-user-drag: none; }

.ph--img > img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

@media (max-width: 768px) {
	.ph span { padding: 14px 18px; font-size: 12px; gap: 6px; }
	.ph span b { font-size: 28px; }
}

/* ── Navigation ───────────────────────────────────────────────── */
.nav {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 80;
	padding: 30px 0;
	transition: background .5s ease, padding .5s ease, backdrop-filter .5s ease;
}
.nav.is-stuck {
	background: rgba(10, 22, 16, .94);
	backdrop-filter: blur(10px);
	padding: 16px 0;
}
.nav .wrap { display: flex; align-items: center; justify-content: space-between; gap: 24px; }

.menubtn {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 6px;
	background: none;
	border: 0;
	cursor: pointer;
	min-width: 44px;
	min-height: 44px;
}
.menubtn span { display: block; width: 34px; height: 1px; background: var(--limestone); }

.nav-mark { width: 86px; opacity: .95; transition: width .5s ease; }
.nav.is-stuck .nav-mark { width: 52px; }

.nav-phone {
	font-size: 15.5px;
	letter-spacing: .22em;
	color: var(--limestone);
	font-weight: 500;
	position: relative;
	padding-bottom: 5px;
	transition: color .35s ease;
}
.nav-phone:after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 1px;
	background: var(--brand-accent);
	transform: scaleX(0);
	transform-origin: right;
	transition: transform .45s cubic-bezier(.22, .61, .36, 1);
}
.nav-phone:hover { color: var(--sandstone); }
.nav-phone:hover:after { transform: scaleX(1); transform-origin: left; }

/* ── Menu overlay ─────────────────────────────────────────────────
   Full screen, with its own bar so it never sits under the fixed nav.
   The nav beneath is hidden while it is open, which is what stopped the
   close button landing on the phone number.
   ─────────────────────────────────────────────────────────────── */
.menu {
	position: fixed;
	inset: 0;
	z-index: 90;
	background: var(--forest-deep);
	display: flex;
	flex-direction: column;
	overflow-y: auto;
	opacity: 0;
	pointer-events: none;
	transition: opacity .45s ease;
}
.menu.open { opacity: 1; pointer-events: auto; }
body.menu-open .nav { opacity: 0; pointer-events: none; }
.nav { transition: background .5s ease, padding .5s ease, opacity .3s ease; }

/* the sprig, oversized and barely there */
.menu:before {
	content: "";
	position: absolute;
	right: -6%;
	bottom: -14%;
	width: min(620px, 60vw);
	aspect-ratio: 1 / 1.01;
	background: var(--menu-mark) center / contain no-repeat;
	opacity: .05;
	pointer-events: none;
}

.menu-bar {
	position: relative;
	z-index: 2;
	flex: 0 0 auto;
	width: min(1280px, 88vw);
	margin: 0 auto;
	padding: 26px 0;
	display: flex;
	align-items: center;
	justify-content: space-between;
	border-bottom: 1px solid rgba(169, 133, 83, .22);
}
.menu-mark { width: 52px; }

.menu .close {
	width: 54px;
	height: 54px;
	border-radius: 50%;
	border: 1px solid rgba(243, 241, 235, .4);
	background: transparent;
	color: var(--limestone);
	font-size: 24px;
	line-height: 1;
	cursor: pointer;
	display: grid;
	place-items: center;
	transition: background .35s ease, color .35s ease, border-color .35s ease;
}
.menu .close:hover { background: var(--limestone); color: var(--forest-deep); border-color: var(--limestone); }

.menu-inner {
	position: relative;
	z-index: 2;
	flex: 1 1 auto;
	width: min(1280px, 88vw);
	margin: 0 auto;
	padding: 64px 0;
	display: grid;
	grid-template-columns: 1.15fr .85fr;
	gap: 70px;
	align-content: center;
}

.menu ul { list-style: none; padding: 0; margin: 0; }

.m-primary { display: grid; gap: 6px; }
.m-primary a {
	font-family: var(--font-display);
	font-size: clamp(30px, 3.9vw, 52px);
	line-height: 1.25;
	color: var(--limestone);
	display: inline-block;
	padding: 4px 0;
	position: relative;
	transition: color .35s ease;
}
/* a rule that draws in from the left, so the target is the word itself */
.m-primary a:after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 2px;
	height: 1px;
	background: var(--brand-accent);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform .45s cubic-bezier(.22, .61, .36, 1);
}
.m-primary a:hover { color: var(--sandstone); }
.m-primary a:hover:after { transform: scaleX(1); }

.m-side { display: grid; gap: 40px; align-content: center; padding-top: 8px; }
.m-group ul { display: grid; gap: 11px; margin-top: 16px; }
.m-group a,
.m-contact address {
	font-size: 16px;
	color: var(--limestone);
	opacity: .78;
	line-height: 1.6;
	transition: opacity .3s ease, color .3s ease;
}
.m-group a:hover { opacity: 1; color: var(--sandstone); }
.m-contact address { font-style: normal; margin-top: 12px; display: block; }
.m-phone {
	display: inline-block;
	margin-top: 16px;
	font-family: var(--font-display);
	font-size: 25px;
	color: var(--brand-accent);
	transition: color .3s ease;
}
.m-phone:hover { color: var(--sandstone); }

.menu-foot {
	position: relative;
	z-index: 2;
	flex: 0 0 auto;
	width: min(1280px, 88vw);
	margin: 0 auto;
	padding: 24px 0 30px;
	border-top: 1px solid rgba(169, 133, 83, .22);
	display: flex;
	justify-content: space-between;
	gap: 20px;
	flex-wrap: wrap;
	font-size: 12.5px;
	color: var(--limestone);
	opacity: .55;
}
.menu-foot a:hover { opacity: 1; color: var(--sandstone); }

/* items arrive in sequence once the panel is up */
.menu .m-primary li,
.menu .m-group,
.menu .m-contact {
	opacity: 0;
	transform: translateY(14px);
}
.menu.open .m-primary li,
.menu.open .m-group,
.menu.open .m-contact {
	opacity: 1;
	transform: none;
	transition: opacity .6s ease, transform .6s cubic-bezier(.22, .61, .36, 1);
}
.menu.open .m-primary li:nth-child(1) { transition-delay: .10s; }
.menu.open .m-primary li:nth-child(2) { transition-delay: .16s; }
.menu.open .m-primary li:nth-child(3) { transition-delay: .22s; }
.menu.open .m-primary li:nth-child(4) { transition-delay: .28s; }
.menu.open .m-primary li:nth-child(5) { transition-delay: .34s; }
.menu.open .m-primary li:nth-child(6) { transition-delay: .40s; }
.menu.open .m-primary li:nth-child(7) { transition-delay: .46s; }
.menu.open .m-group:nth-of-type(1) { transition-delay: .30s; }
.menu.open .m-group:nth-of-type(2) { transition-delay: .38s; }
.menu.open .m-contact { transition-delay: .46s; }

/* ── Inline prose links ───────────────────────────────────────────
   Anything inside body copy, on a light ground or a dark one. Bronze
   rule underneath, filling on hover, so a link reads as a link without
   needing a colour of its own.
   ─────────────────────────────────────────────────────────────── */
.g-light p a, .g-tint p a, .g-light li a, .g-tint li a,
.g-light address a, .g-tint address a {
	position: relative;
	color: var(--forest);
	border-bottom: 1px solid rgba(169, 133, 83, .55);
	padding-bottom: 1px;
	transition: color .3s ease, border-color .3s ease;
}
.g-light p a:hover, .g-tint p a:hover, .g-light li a:hover, .g-tint li a:hover,
.g-light address a:hover, .g-tint address a:hover {
	color: var(--sage);
	border-color: var(--sage);
}

/* ── Closing sections ─────────────────────────────────────────────
   Each page sets its finale copy on the left over a full-bleed photo. The
   scrim is dark behind the copy and fades to clear across the rest, so the
   photo reads while the type stays legible. Once the columns narrow, the
   copy spans the width, so the scrim has to as well.
   ─────────────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
	body .finale:before, body .finale-img:before {
		background: linear-gradient(90deg, rgba(10,22,16,.88) 0%, rgba(10,22,16,.78) 50%,
		            rgba(10,22,16,.35) 80%, rgba(10,22,16,.15) 100%);
	}
}
@media (max-width: 768px) {
	body .finale:before, body .finale-img:before { background: rgba(10,22,16,.72); }
}

/* ── Reveal animations ────────────────────────────────────────────
   One IntersectionObserver adds .is-visible as each element enters the
   viewport.

   The hiding rules are scoped to .sage-js, a class written onto <html>
   by an inline script before any CSS is parsed. No JS means nothing is
   ever hidden. There is deliberately no timed failsafe here: a timer
   forces everything to full opacity a fixed number of seconds after
   load, which on a long page means every section below the fold is
   already revealed before it is scrolled to.
   ─────────────────────────────────────────────────────────────── */

/* The default. Sets a transform, so never use it on an element whose
   position depends on its own transform. */
.sage-js .reveal { opacity: 0; transform: translateY(34px); }
.sage-js .reveal.is-visible {
	opacity: 1;
	transform: none;
	transition: opacity 1s ease, transform 1s cubic-bezier(.22, .61, .36, 1);
}

/* Opacity only. For anything centered, pinned, or absolutely positioned,
   where .reveal's transform would overwrite the one holding it in place. */
.sage-js .fade { opacity: 0; }
.sage-js .fade.is-visible { opacity: 1; transition: opacity 1.2s ease; }

/* Photographs. Settles down from a slight scale, which reads as the image
   coming to rest rather than sliding in. Scale is safe on absolutely
   positioned images; the translate in .reveal is not. */
.sage-js .fade-img { opacity: 0; transform: scale(1.045); }
.sage-js .fade-img.is-visible {
	opacity: 1;
	transform: none;
	transition: opacity 1.25s ease, transform 1.55s cubic-bezier(.22, .61, .36, 1);
}

/* Long, slow travel for large blocks that deserve the extra beat. */
.sage-js .rise { opacity: 0; transform: translateY(64px); }
.sage-js .rise.is-visible {
	opacity: 1;
	transform: none;
	transition: opacity 1.35s ease, transform 1.35s cubic-bezier(.22, .61, .36, 1);
}

/* Stagger steps. Wide enough apart to read as a sequence. */
.d1 { transition-delay: .14s; }
.d2 { transition-delay: .28s; }
.d3 { transition-delay: .42s; }
.d4 { transition-delay: .56s; }
.d5 { transition-delay: .70s; }
.d6 { transition-delay: .84s; }
.d7 { transition-delay: .98s; }
.d8 { transition-delay: 1.12s; }

/* ── Opening curtain ──────────────────────────────────────────────
   The panel and the lockup leave separately, so the logo is left over
   the live site for a beat before it goes.

   0.2s  lockup begins fading up and starts growing
   1.8s  lockup fully opaque, still growing
   2.5s  lockup reaches 110% and stops growing, begins fading over 1.2s
   2.8s  panel background begins fading over 0.9s
   3.7s  panel and lockup both gone, curtain element leaves the layer

   Three animations run on the lockup. Opacity and scale are separated so
   the fade can finish early while the growth keeps going, which one
   keyframe set could not do. introLogoOut sits last in the list, so it
   takes over opacity from introFadeUp the moment its delay elapses.
   ─────────────────────────────────────────────────────────────── */
.sage-curtain {
	position: fixed;
	inset: 0;
	z-index: 200;
	background: var(--forest-deep);
	display: grid;
	place-items: center;
	pointer-events: none; /* nothing here is clickable, so never trap a click */
	animation: introBgOut 0.9s ease 2.8s forwards,
	           introEnd 1ms linear 3.7s forwards;
}
.sage-curtain img {
	width: min(520px, 68vw);
	opacity: 0;
	transform: scale(.94);
	animation: introFadeUp 1.6s cubic-bezier(.33, .0, .2, 1) .2s forwards,
	           introGrow 2.3s linear .2s forwards,
	           introLogoOut 1.2s ease 2.5s forwards;
}
@keyframes introFadeUp  { to { opacity: 1; } }
@keyframes introGrow    { from { transform: scale(.94); } to { transform: scale(1.10); } }
@keyframes introLogoOut { to { opacity: 0; } }
@keyframes introBgOut   { to { background-color: rgba(10, 22, 16, 0); } }
@keyframes introEnd     { to { visibility: hidden; } }

/* Hero animates on paint, never on scroll, so it is up before any interaction.
   These are the interior page timings: immediate, with a short stagger. The
   homepage overrides them in home.css to wait out its opening curtain. */
.paint-in { opacity: 1; animation: paintIn 1300ms cubic-bezier(.22, .61, .36, 1) 0ms both; }
.pi2 { animation-delay: 220ms; }
.pi3 { animation-delay: 440ms; }
.pi4 { animation-delay: 660ms; }
@keyframes paintIn { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

/* ── Footer ───────────────────────────────────────────────────── */
.foot { background: var(--forest-deep); padding: 110px 0 40px; overflow: hidden; position: relative; }
.foot .watermark { position: absolute; right: -70px; bottom: -90px; width: 400px; opacity: .30; pointer-events: none; }
.foot .wrap { position: relative; z-index: 2; }
.foot-top { display: grid; grid-template-columns: 1.3fr .8fr .8fr .9fr; gap: 48px; padding-bottom: 66px; }
.foot-logo { width: 230px; margin-bottom: 24px; }
.foot h2 {
	font-family: var(--font-body);
	font-size: 11.5px;
	letter-spacing: .24em;
	text-transform: uppercase;
	font-weight: 500;
	color: var(--brand-accent);
	margin-bottom: 20px;
}
.foot ul { list-style: none; display: grid; gap: 12px; padding: 0; margin: 0; }
.foot li a, .foot address {
	font-size: 15px;
	color: var(--limestone);
	opacity: .75;
	font-style: normal;
	line-height: 1.8;
}

/* Footer links: limestone, with a bronze rule that wipes in from the left.
   Same gesture as the phone number in the nav, so the site has one hover
   behaviour instead of several. */
.foot li a, .foot address a, .foot-bot a {
	position: relative;
	display: inline-block;
	color: var(--limestone);
	transition: opacity .3s ease, color .3s ease;
}
.foot li a::after, .foot address a::after, .foot-bot a::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -2px;
	height: 1px;
	background: var(--brand-accent);
	transform: scaleX(0);
	transform-origin: right;
	transition: transform .4s cubic-bezier(.22, .61, .36, 1);
}
.foot li a:hover, .foot address a:hover, .foot-bot a:hover {
	opacity: 1;
	color: var(--sandstone);
}
.foot li a:hover::after, .foot address a:hover::after, .foot-bot a:hover::after {
	transform: scaleX(1);
	transform-origin: left;
}

.foot-bot {
	border-top: 1px solid rgba(169, 133, 83, .25);
	padding-top: 26px;
	display: flex;
	justify-content: space-between;
	gap: 24px;
	flex-wrap: wrap;
	font-size: 12px;
	opacity: .55;
}

/* ── 404 ─────────────────────────────────────────────────────────── */
.e404 { padding: 260px 0 150px; }
.e404 h1 { font-size: clamp(32px, 4vw, 54px); margin: 20px 0 24px; max-width: 16ch; }
.e404 .rule { margin-bottom: 28px; }
.e404-lede { max-width: 50ch; color: var(--sandstone); margin-bottom: 34px; }
.e404-links { list-style: none; padding: 0; margin: 0 0 40px; display: grid; gap: 16px; }

@media (max-width: 768px) {
	.e404 { padding: 190px 0 92px; }
}

/* ── Location modal ───────────────────────────────────────────── */
.lmodal {
	position: fixed;
	inset: 0;
	z-index: 90;
	display: grid;
	place-items: center;
	padding: 24px;
	opacity: 0;
	pointer-events: none;
	transition: opacity .45s ease;
}
.lmodal.open { opacity: 1; pointer-events: auto; }
.lmodal-scrim { position: absolute; inset: 0; background: rgba(10, 22, 16, .88); cursor: pointer; }
.lmodal-box {
	position: relative;
	z-index: 2;
	width: min(560px, 100%);
	max-height: 88vh;
	overflow: auto;
	background: var(--limestone);
	color: var(--forest);
	transform: translateY(18px);
	transition: transform .55s cubic-bezier(.22, .61, .36, 1);
}
.lmodal.open .lmodal-box { transform: none; }
.lmodal-box .ph { aspect-ratio: 16 / 10; }
.lmodal-close {
	position: absolute;
	top: 16px;
	right: 16px;
	z-index: 3;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid rgba(243, 241, 235, .55);
	background: rgba(10, 22, 16, .55);
	color: var(--limestone);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	display: grid;
	place-items: center;
	transition: background .35s ease, color .35s ease;
}
.lmodal-close:hover { background: var(--limestone); color: var(--forest-deep); }
.lmodal-body { padding: 36px; }
.lmodal-body h2 { font-size: clamp(26px, 3vw, 36px); margin: 16px 0; }
.lmodal-body .rule { margin-bottom: 20px; }
.lmodal-body p { font-size: 16px; margin-bottom: 26px; max-width: 44ch; }

/* ── Responsive ───────────────────────────────────────────────── */
@media (max-width: 1024px) {
	.foot-top { grid-template-columns: 1fr 1fr; gap: 40px; }
}

@media (max-width: 768px) {
	body { font-size: 16px; }
	.menu-inner { grid-template-columns: 1fr; gap: 44px; padding: 40px 0; align-content: start; }
	.m-primary a { font-size: 30px; }
	.m-side { grid-template-columns: 1fr 1fr; gap: 32px; align-content: start; }
	.m-contact { grid-column: 1 / -1; }
	.menu-foot { font-size: 11.5px; }
	.lmodal-body { padding: 26px; }
	.foot-top { grid-template-columns: 1fr; }
	.foot { padding: 80px 0 34px; }
}

/* ── Reduced motion ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
	.sage-js .reveal, .sage-js .fade, .sage-js .fade-img, .sage-js .rise,
	.paint-in { opacity: 1; transform: none; animation: none; transition: none; }
	.menu .m-primary li, .menu .m-group, .menu .m-contact { opacity: 1; transform: none; }
	.sage-curtain { display: none; }
	*, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
	html { scroll-behavior: auto; }
}
