/*
 * JL Tyner Group — Nashville.
 *
 * Adam's brief was red, black and white. That is also 1st Cavalry's brief, and
 * this theme is copied from that build, so the work here was making sure they
 * do not come out looking like the same site.
 *
 * They do not, because the reds are doing different jobs. Cavalry's red is
 * #FF0004 sampled straight off a military-adjacent logo — loud on purpose.
 * The Tyners have no logo to sample and sell in Brentwood and Williamson
 * County, so this is a deep carmine (#B21E35): the same family, a completely
 * different register. It reads closer to a wine label than a warning sign.
 *
 * It is also one red doing both jobs. At 6.8:1 on white it carries body-weight
 * text, and white on it is 6.8:1 the other way, so it fills a button too — no
 * second darker variant invented for accessibility.
 *
 * Type is Instrument Serif over Instrument Sans, self-hosted. Their old site
 * was a RealGeeks template and is now a 404; there is no house style to honour
 * and every reason to look like the more expensive option.
 *
 * Rationing: red carries the logo, the primary button, the eyebrows and the
 * rules. A warm near-black carries structure. Everything else is white and one
 * barely-there warm grey band.
 */

/* ---------------------------------------------------------------- tokens -- */

:root {
	/*
	 * Dark luxury. Black ground, warm off-white type, gold used sparingly.
	 *
	 * The discipline here is the gold. At full strength across headings, rules,
	 * buttons and borders it stops reading as luxury and starts reading as a
	 * casino — the failure mode of every gold-on-black real estate site. So gold
	 * is an accent with a job: the rule under a heading, the active nav state,
	 * one button, the small caps. Everything else is black, near-black, and a
	 * warm white that carries all the body copy.
	 *
	 * #C6A968 is 6.4:1 on #0B0B0C, so it is legible at small sizes on the dark
	 * ground — which is where it is actually used. It is never put on white.
	 */
	--tyn-gold:       #C6A968;
	--tyn-gold-lt:    #E0CB9A;
	--tyn-gold-dk:    #967E44;
	--tyn-gold-pale:  #F3ECDC;

	--tyn-brand:      #C6A968;
	--tyn-brand-mid:  #E0CB9A;
	--tyn-brand-lt:   #E0CB9A;
	--tyn-brand-pale: #F3ECDC;

	--tyn-accent:       #C6A968;
	--tyn-accent-mid:   #E0CB9A;
	--tyn-accent-lt:    #E0CB9A;
	--tyn-accent-metal: linear-gradient(135deg, #967E44 0%, #E0CB9A 52%, #C6A968 100%);

	/* Structure. True black at the deep end — this is the ground the whole site
	   sits on now, not just the footer. */
	--tyn-deep:       #0B0B0C;
	--tyn-deep-dk:    #000000;
	--tyn-deep-lt:    #17171A;
	--tyn-stone:      #8A8A90;

	/* Text ON the dark ground. Warm off-white, never pure #fff at body size —
	   pure white on true black vibrates and is genuinely harder to read. */
	--tyn-ink:        #F4F2EE;
	--tyn-body:       #C9C6C0;
	--tyn-muted:      #9A968F;
	--tyn-faint:      #6E6A65;

	/* Ground. Inverted: 'white' is now the near-black the page is built on, and
	   the tints step UP into charcoal rather than down into grey. Every rule in
	   the stylesheet that fills with --tyn-white keeps working; it just fills
	   with black instead, which is what makes this a re-theme and not a rebuild. */
	--tyn-white:      #0B0B0C;
	--tyn-tint:       #101012;
	--tyn-tint-2:     #17171A;
	--tyn-sky:        #141416;
	--tyn-line:       #26262B;
	--tyn-line-soft:  #1B1B1F;

	--tyn-display:    'Instrument Serif', ui-serif, Georgia, 'Times New Roman', serif;
	--tyn-body-font:  'Instrument Sans', ui-sans-serif, -apple-system, 'Segoe UI', sans-serif;

	--tyn-wrap:       1280px;
	--tyn-gutter:     clamp(1.25rem, 4vw, 3rem);
	--tyn-band:       clamp(4rem, 8vw, 7rem);

	/* Header interpolates between these as --tyn-shrink runs 0 → 1. */
	--tyn-header-h:   104px;
	--tyn-bar-max:    104px;
	--tyn-bar-min:    70px;
	/*
	 * Smaller than the build this was copied from, deliberately.
	 *
	 * That one carries a wide horizontal lockup; this one is stacked — name
	 * over a rule over GROUP — so the same height makes the top line roughly
	 * twice as tall and the mark swallows the masthead before you scroll.
	 * Height is the wrong axis to share between a stacked mark and a
	 * horizontal one.
	 */
	--tyn-logo-max:   52px;
	--tyn-logo-min:   38px;
	--tyn-shrink:     0;

	--tyn-ease:       cubic-bezier(.22, .61, .36, 1);
	--tyn-shadow:     0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px -12px rgba(0, 0, 0, .5);
	--tyn-shadow-lg:  0 2px 4px rgba(0, 0, 0, .35), 0 20px 48px -20px rgba(0, 0, 0, .6);
}

@media (max-width: 1040px) {
	:root {
		--tyn-header-h: 88px;
		--tyn-bar-max:  88px;
		--tyn-bar-min:  62px;
		--tyn-logo-max: 40px;
		--tyn-logo-min: 30px;
	}
}

/* ------------------------------------------------------------------ base -- */

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

html {
	scroll-behavior: smooth;
	scroll-padding-top: 6rem;
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	background: var(--tyn-white);
	color: var(--tyn-body);
	font-family: var(--tyn-body-font);
	font-size: clamp(1rem, .97rem + .16vw, 1.0625rem);
	line-height: 1.72;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

body.tyn-locked { overflow: hidden; }

img, svg { max-width: 100%; display: block; }

a { color: var(--tyn-deep-lt); text-decoration: none; transition: color .2s var(--tyn-ease); }
a:hover { color: var(--tyn-deep); }

h1, h2, h3, h4 {
	margin: 0;
	font-family: var(--tyn-display);
	font-weight: 400;
	line-height: 1.16;
	letter-spacing: -.018em;
	color: var(--tyn-ink);
	text-wrap: balance;
}

h1 { font-size: clamp(2.1rem, 1.4rem + 3vw, 3.6rem); }
h2 { font-size: clamp(1.6rem, 1.2rem + 1.9vw, 2.5rem); }
h3 { font-size: clamp(1.1rem, 1.03rem + .4vw, 1.3rem); }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

:focus-visible { outline: 2px solid var(--tyn-deep-lt); outline-offset: 3px; border-radius: 3px; }
::selection { background: var(--tyn-accent-lt); color: var(--tyn-ink); }

.tyn-sr {
	position: absolute; width: 1px; height: 1px;
	padding: 0; margin: -1px; overflow: hidden;
	clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.tyn-skip {
	position: absolute; top: -100px; left: 1rem; z-index: 200;
	padding: .75rem 1.25rem;
	background: var(--tyn-deep); color: #fff; font-weight: 600;
	transition: top .2s var(--tyn-ease);
}
.tyn-skip:focus { top: 1rem; color: #fff; }

/* --------------------------------------------------------------- layout -- */

.tyn-wrap {
	width: 100%;
	max-width: var(--tyn-wrap);
	margin-inline: auto;
	padding-inline: var(--tyn-gutter);
}

.tyn-wrap--narrow { max-width: 60rem; }

.tyn-section { position: relative; padding-block: var(--tyn-band); }

.tyn-section--tint { background: var(--tyn-tint); }

/* The two navy bands. Full-bleed colour is the only thing on a light site that
   gives the eye a place to rest, so there are exactly two per page and they are
   always separated by white. */
.tyn-section--dark {
	background: var(--tyn-deep);
	color: rgba(255, 255, 255, .82);
}

.tyn-section--dark h1,
.tyn-section--dark h2,
.tyn-section--dark h3 { color: #fff; }

/* ------------------------------------------------------------- typography -- */

.tyn-eyebrow {
	display: inline-block;
	margin-bottom: .9rem;
	font-family: var(--tyn-display);
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}

.tyn-eyebrow--light { color: var(--tyn-accent-lt); }

/*
 * The page-banner eyebrow.
 *
 * parts/banner.php has always emitted `tyn-eyebrow--accent`, and this rule did
 * not exist — so it fell through to the base .tyn-eyebrow colour, --tyn-accent,
 * which is a 6.5:1-on-white dark red. Every banner on the site is a photograph
 * under a dark scrim, or --tyn-deep where there is no photograph, so the eyebrow
 * was dark red on near-black on every interior page: Buy, Sell, Rent, Listings,
 * About, Blog, Contact, Team and 404.
 *
 * It survived because a class that matches no rule renders perfectly happily.
 * Same family as the missing-fallback traps in themes/CLAUDE.md.
 */
.tyn-eyebrow--accent { color: var(--tyn-accent-lt); }

.tyn-banner .tyn-eyebrow--accent {
	color: rgba(255, 255, 255, .92);
	text-shadow: 0 1px 12px rgba(13, 10, 11, .6);
}

/* On the hero specifically the eyebrow sits on a photograph rather than a flat
   dark band, and the brand light blue disappears into the water. Near-white with
   a slight shadow holds it without turning it into a second headline. */
.tyn-hero .tyn-eyebrow--light {
	color: rgba(255, 255, 255, .92);
	text-shadow: 0 1px 12px rgba(8, 8, 9, .6);
}

.tyn-hero__title { text-shadow: 0 2px 28px rgba(8, 8, 9, .45); }

.tyn-rule {
	display: block;
	width: 56px; height: 3px;
	margin: 1.1rem 0 1.4rem;
	background: var(--tyn-accent-metal);
	border-radius: 3px;
}

.tyn-head--center .tyn-rule,
.tyn-closer .tyn-rule,
.tyn-modal__head .tyn-rule { margin-inline: auto; }

.tyn-lede {
	font-size: clamp(1.02rem, 1rem + .3vw, 1.2rem);
	line-height: 1.65;
	color: var(--tyn-muted);
	max-width: 56ch;
}

.tyn-head { max-width: 46rem; margin-bottom: clamp(2.25rem, 4vw, 3.25rem); }
.tyn-head--center { margin-inline: auto; text-align: center; }
.tyn-head--center .tyn-lede { margin-inline: auto; }
.tyn-head--light .tyn-lede { color: rgba(255, 255, 255, .8); }

.tyn-head--split {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.5rem;
	max-width: none;
}
@media (max-width: 720px) {
	.tyn-head--split { flex-direction: column; align-items: flex-start; }
}

.tyn-prose { color: var(--tyn-body); }
.tyn-prose p { margin-bottom: 1.1em; }

.tyn-prose--editor h2,
.tyn-prose--editor h3 { margin: 2rem 0 .75rem; }
.tyn-prose--editor ul,
.tyn-prose--editor ol { margin: 0 0 1.2em 1.25rem; list-style: disc; }
.tyn-prose--editor ol { list-style: decimal; }
.tyn-prose--editor li { margin-bottom: .4em; }
.tyn-prose--article { font-size: 1.05rem; }
.tyn-prose--article p { margin-bottom: 1.3em; }

.tyn-pull {
	margin: 1.75rem 0 0;
	padding: 1.1rem 1.4rem;
	border-left: 3px solid var(--tyn-accent);
	background: var(--tyn-tint);
	border-radius: 0 4px 4px 0;
	font-family: var(--tyn-display);
	font-size: clamp(1rem, .97rem + .3vw, 1.15rem);
	font-weight: 400;
	line-height: 1.45;
	color: var(--tyn-ink);
}

/* --------------------------------------------------------------- buttons -- */

.tyn-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	padding: .9rem 1.6rem;
	border: 1px solid var(--tyn-deep);
	border-radius: 4px;
	background: var(--tyn-deep);
	color: #fff;
	font-family: var(--tyn-display);
	font-size: .82rem;
	font-weight: 400;
	letter-spacing: .05em;
	text-transform: uppercase;
	line-height: 1;
	cursor: pointer;
	transition: transform .2s var(--tyn-ease), box-shadow .2s var(--tyn-ease), background .2s var(--tyn-ease);
	-webkit-appearance: none;
	appearance: none;
}

.tyn-btn:hover {
	background: var(--tyn-deep-dk);
	border-color: var(--tyn-deep-dk);
	color: #fff;
	transform: translateY(-2px);
	box-shadow: 0 12px 24px -12px rgba(0, 0, 0, .6);
}
.tyn-btn:active { transform: translateY(0); }

/* Gold is the primary call to action. Dark ink on gold rather than white —
   white on this gold fails contrast badly. */
/* White, not the inherited #0B3346. That navy was legible on the blue-metal
   gradient this theme was copied from and is dark maroon-on-red here — the
   primary CTA on the dark band was effectively unreadable. The shadow was
   still gold from a build two clients ago. */
.tyn-btn--accent {
	background: var(--tyn-accent-metal);
	border-color: transparent;
	color: #FFFFFF;
}
.tyn-btn--accent:hover {
	background: var(--tyn-accent-metal);
	filter: brightness(1.06);
	color: #FFFFFF;
	box-shadow: 0 12px 26px -12px rgba(198, 169, 104, .55);
}

.tyn-btn--ghost {
	background: transparent;
	border-color: var(--tyn-line);
	color: var(--tyn-deep);
}
.tyn-btn--ghost:hover {
	background: var(--tyn-tint);
	border-color: var(--tyn-deep);
	color: var(--tyn-deep);
	box-shadow: none;
}

.tyn-btn--ghost-light {
	background: transparent;
	border-color: rgba(255, 255, 255, .5);
	color: #fff;
}
.tyn-btn--ghost-light:hover {
	background: rgba(255, 255, 255, .12);
	border-color: #fff;
	color: #fff;
	box-shadow: none;
}

.tyn-btn--sm { padding: .68rem 1.1rem; font-size: .74rem; }
.tyn-btn--lg { padding: 1.05rem 2rem; font-size: .88rem; }
.tyn-btn--block { display: flex; width: 100%; }

/* -------------------------------------------------------------- utility -- */

.tyn-utility {
	position: relative;
	z-index: 60;
	background: var(--tyn-deep);
	color: rgba(255, 255, 255, .72);
	font-size: .78rem;
}

.tyn-utility__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	min-height: 40px;
	padding-block: .35rem;
}

.tyn-utility__tagline {
	margin: 0;
	font-family: var(--tyn-display);
	font-size: .7rem;
	font-weight: 400;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--tyn-accent-lt);
	white-space: nowrap;
}

.tyn-utility__list { display: flex; align-items: center; gap: 1.4rem; }

.tyn-utility__list a {
	display: inline-flex;
	align-items: center;
	gap: .4rem;
	color: rgba(255, 255, 255, .82);
}
.tyn-utility__list a:hover { color: #fff; }

.tyn-icon { flex-shrink: 0; color: var(--tyn-accent-lt); transition: color .2s var(--tyn-ease); }
.tyn-utility__list a:hover .tyn-icon { color: #fff; }

@media (max-width: 1040px) {
	/* Gone entirely on mobile. It was a strip of navy holding a phone number and
	   an email in 12px type — the phone is now a proper button in the masthead,
	   which is a real target and does not cost a band of colour above the logo. */
	.tyn-utility { display: none; }
}

/* ------------------------------------------------------------- language -- */

/*
 * EN / ES.
 *
 * A segmented pair rather than a dropdown: with exactly two languages a select
 * costs a tap to discover what it even contains, and both labels visible is its
 * own advertisement — a Spanish speaker sees "ES" without hunting for it, which
 * is the whole point of the feature.
 *
 * The inactive side is a link and the active side is not, so keyboard order
 * carries no dead stop and screen readers get aria-current on the live one.
 */



/*
 * In the drawer the bar is on white, not on the deep band, so the whole thing
 * inverts. It also spells the languages out — there is room for "Español" on a
 * phone and it reads as a promise rather than a two-letter code.
 */




/* --------------------------------------------------------------- header -- */

/* Constant-height shell; only the bar inside it moves. Collapsing the header
   itself would shorten the document mid-scroll and drag the page up under the
   reader — see themes/CLAUDE.md. */
.tyn-header {
	position: sticky;
	top: 0;
	z-index: 100;
	height: var(--tyn-header-h);
	pointer-events: none;
}

/*
 * Frosted glass rather than flat white.
 *
 * The blur is what makes it read as glass — translucent white on its own just
 * looks like a washed-out bar. saturate() ahead of the blur keeps colour
 * passing underneath from going grey, which is the thing that separates this
 * from a cheap opacity trick.
 *
 * .72 is deliberate. Below about .65 the nav text starts fighting whatever
 * scrolls under it; above .8 the effect stops being visible at all.
 */
.tyn-header__bar {
	pointer-events: auto;
	/* Near-black glass, not white. This was 72% white — on a dark site that is
	   a pale bar with white nav type on it, which is exactly what it looked
	   like. Same recipe, inverted ground. */
	background: rgba(11, 11, 12, .78);
	/* Same recipe as .tyn-search--hero, the panel in the hero — that is the
	   surface this was asked to match. Alpha is the one number that differs:
	   the hero panel can afford .52 because it sits on a scrimmed photograph,
	   whereas the masthead passes over whatever the page happens to contain,
	   and below about .65 the nav starts fighting it. */
	-webkit-backdrop-filter: blur(22px) saturate(1.5);
	backdrop-filter: blur(22px) saturate(1.5);
	border-bottom: 1px solid var(--tyn-line);
	box-shadow:
		0 8px 24px -18px rgba(0, 0, 0, calc(1.6 * var(--tyn-shrink))),
		inset 0 1px 0 rgba(255, 255, 255, .55);
}

/* Anything that cannot blur gets the opaque bar back, or the nav ends up
   sitting unreadable on top of the page content. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.tyn-header__bar { background: var(--tyn-white); }
}

.tyn-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	min-height: calc(var(--tyn-bar-max) + (var(--tyn-bar-min) - var(--tyn-bar-max)) * var(--tyn-shrink));
}

.tyn-brand { display: inline-flex; flex-shrink: 0; }
.tyn-logo { display: inline-flex; align-items: center; gap: .65rem; }

.tyn-logo__img {
	height: calc(var(--tyn-logo-max) + (var(--tyn-logo-min) - var(--tyn-logo-max)) * var(--tyn-shrink));
	width: auto;
}

.tyn-logo__mark { display: inline-flex; }
.tyn-logo__mark svg { width: 40px; height: 40px; }
.tyn-logo--footer .tyn-logo__mark svg { width: 46px; height: 46px; }

.tyn-logo__text { display: flex; flex-direction: column; line-height: 1.05; }

.tyn-logo__name {
	font-family: var(--tyn-display);
	font-size: 1.32rem;
	font-weight: 400;
	letter-spacing: -.01em;
	color: var(--tyn-deep);
}

.tyn-logo__sub {
	margin-top: .18rem;
	font-family: var(--tyn-display);
	font-size: .62rem;
	font-weight: 400;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}

.tyn-logo--footer .tyn-logo__name { color: #fff; }
.tyn-logo--footer .tyn-logo__img { height: 74px; }

/* ------------------------------------------------------------------ nav -- */

.tyn-nav { margin-inline: auto; }
.tyn-nav__list { display: flex; align-items: center; gap: clamp(.9rem, 1.8vw, 1.9rem); }

.tyn-nav__list a {
	position: relative;
	display: inline-block;
	padding-block: .35rem;
	font-family: var(--tyn-display);
	font-size: .8rem;
	font-weight: 400;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--tyn-ink);
}

.tyn-nav__list a::after {
	content: '';
	position: absolute;
	left: 0; bottom: 0;
	width: 0; height: 2px;
	background: var(--tyn-accent-metal);
	transition: width .25s var(--tyn-ease);
}

.tyn-nav__list a:hover { color: var(--tyn-deep); }
.tyn-nav__list a:hover::after,
.tyn-nav__list .is-current > a::after,
.tyn-nav__list .current-menu-item > a::after { width: 100%; }
.tyn-nav__list .is-current > a,
.tyn-nav__list .current-menu-item > a { color: var(--tyn-gold); }

.tyn-header__actions { display: flex; align-items: center; gap: .7rem; flex-shrink: 0; }

.tyn-burger {
	display: none;
	padding: .55rem;
	background: none;
	border: 1px solid var(--tyn-line);
	border-radius: 4px;
	cursor: pointer;
}
.tyn-burger__box { display: block; width: 20px; }
.tyn-burger__box i {
	display: block; height: 2px; background: var(--tyn-deep);
	transition: transform .25s var(--tyn-ease), opacity .2s var(--tyn-ease);
}
.tyn-burger__box i + i { margin-top: 4px; }
.tyn-burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.tyn-burger[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.tyn-burger[aria-expanded="true"] i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 1040px) {
	.tyn-nav { display: none; }
	.tyn-burger { display: block; }
}
@media (max-width: 620px) {
	/* The "Talk to an agent" button goes; the call button stays. Excluded by
	   name rather than by raising specificity elsewhere — this rule is more
	   specific than .tyn-callnow and would otherwise win silently. */
	.tyn-header__actions .tyn-btn:not(.tyn-callnow) { display: none; }
}

/* --------------------------------------------------------------- drawer -- */

.tyn-drawer {
	position: fixed;
	inset: 0;
	z-index: 90;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	gap: 1.5rem;
	padding: calc(var(--tyn-header-h) + 1.75rem) var(--tyn-gutter) 2.5rem;
	background: var(--tyn-white);
	overflow-y: auto;
	opacity: 0;
	visibility: hidden;
	transition: opacity .28s var(--tyn-ease), visibility .28s var(--tyn-ease);
}

.tyn-drawer[hidden] { display: flex; }
.tyn-drawer.is-open { opacity: 1; visibility: visible; }

.tyn-drawer__nav .tyn-nav__list { flex-direction: column; align-items: flex-start; gap: .25rem; }
.tyn-drawer__nav .tyn-nav__list a { padding-block: .7rem; font-size: 1.3rem; letter-spacing: .04em; }

.tyn-drawer__foot { display: flex; flex-direction: column; gap: 1rem; }
.tyn-drawer__call {
	font-family: var(--tyn-display);
	font-size: 1.05rem;
	font-weight: 400;
	text-align: center;
	color: var(--tyn-deep);
}

/* --------------------------------------------------------------- figures -- */

.tyn-figure {
	position: relative;
	margin: 0;
	overflow: hidden;
	border-radius: 6px;
	background: var(--tyn-tint-2);
}

.tyn-figure img { width: 100%; height: 100%; object-fit: cover; }

.tyn-figure--cover { position: absolute; inset: 0; border-radius: 0; }
.tyn-figure--tall { aspect-ratio: 4 / 5; }
.tyn-figure--portrait { aspect-ratio: 3 / 4; }
.tyn-figure--wide { aspect-ratio: 16 / 10; }
.tyn-figure--hero { aspect-ratio: 16 / 9; border-radius: 8px; }
.tyn-figure--lead { margin-bottom: 2rem; }

.tyn-figure--empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .75rem;
	min-height: 12rem;
	background:
		repeating-linear-gradient(135deg, transparent 0 12px, rgba(198, 169, 104, .04) 12px 24px),
		var(--tyn-tint-2);
}

.tyn-figure__mark { opacity: .5; }
.tyn-figure__note {
	font-family: var(--tyn-display);
	font-size: .66rem;
	font-weight: 400;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--tyn-faint);
}

/* ------------------------------------------------------------------ hero -- */

.tyn-hero {
	position: relative;
	display: flex;
	align-items: center;
	min-height: clamp(30rem, 74vh, 42rem);
	padding-block: clamp(5rem, 10vh, 7rem);
	overflow: hidden;
	background: var(--tyn-deep-dk);
}

.tyn-hero__media { position: absolute; inset: 0; z-index: 0; }

/* Warm, not navy.
 *
 * The hero is a house at golden hour, and a navy scrim was arguing with it —
 * the sky went slate, the lit windows went grey, and the one genuinely
 * attractive thing about the photograph was suppressed to make room for a brand
 * colour it did not need. The scrim is now a deep warm brown, which darkens
 * exactly as much for the text but reads as dusk rather than as a blue filter.
 *
 * The amber wash on the right is doing the opposite job: it sits over the part
 * of the frame with no text on it and lifts the water, so the colour is
 * strongest where the eye is free to enjoy it.
 *
 * Temperature matters here. The copied theme scrimmed in warm brown, which over
 * a blue-green aerial reads as dirt on the lens. This one is a deep ocean blue
 * drawn from --tyn-deep, so the photograph stays in the same family as the logo.
 * The photograph is also a top-down aerial and therefore busy edge to edge —
 * there is no empty sky to drop type onto — so the left side is scrimmed harder
 * than a normal hero would need. */
.tyn-hero__scrim {
	position: absolute;
	inset: 0;
	/*
	 * Black, not navy. This was rgba(8, 32, 48) throughout — a deep blue, left
	 * over from the build this theme was copied from, and it was tinting the
	 * whole hero cold on a site whose entire palette is black and champagne.
	 * The warm lift at top-right is gold now rather than pale blue, so the one
	 * bright note in the hero belongs to the brand.
	 */
	background:
		radial-gradient(108% 84% at 80% 24%, rgba(198, 169, 104, .12) 0%, transparent 58%),
		linear-gradient(to right, rgba(8, 8, 9, .90) 0%, rgba(8, 8, 9, .76) 42%, rgba(8, 8, 9, .30) 76%, rgba(8, 8, 9, .50) 100%),
		linear-gradient(to bottom, rgba(8, 8, 9, .50) 0%, rgba(8, 8, 9, .10) 40%, rgba(8, 8, 9, .72) 100%);
}

.tyn-hero__inner { position: relative; z-index: 2; max-width: 54rem; }
.tyn-hero__title { color: #fff; }
.tyn-hero__lede { color: rgba(255, 255, 255, .88); max-width: 46ch; margin-top: 1.25rem; }

.tyn-hero__actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 2rem; }

.tyn-hero__note {
	margin-top: 1.35rem;
	font-size: .84rem;
	color: rgba(255, 255, 255, .62);
}

/* ---------------------------------------------------------------- banner -- */

.tyn-banner {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: clamp(16rem, 38vh, 22rem);
	padding-block: clamp(4rem, 9vh, 6rem) clamp(2rem, 5vh, 3rem);
	overflow: hidden;
	background: var(--tyn-deep-dk);
}

.tyn-banner__media { position: absolute; inset: 0; z-index: 0; }
.tyn-banner__scrim {
	position: absolute;
	inset: 0;
	background:
		linear-gradient(to right, rgba(11, 11, 12, .92) 0%, rgba(11, 11, 12, .74) 55%, rgba(11, 11, 12, .54) 100%),
		linear-gradient(to bottom, rgba(11, 11, 12, .48) 0%, rgba(11, 11, 12, .32) 50%, rgba(11, 11, 12, .68) 100%);
}

.tyn-banner__inner { position: relative; z-index: 2; max-width: 56rem; }
.tyn-banner__title { color: #fff; }
.tyn-banner__lede { color: rgba(255, 255, 255, .85); }

/* Banners with no photograph still need to be navy, not a white void. */
.tyn-banner:not(:has(.tyn-banner__media)) { background: var(--tyn-deep); }

/* ----------------------------------------------------------------- split -- */

.tyn-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
	align-items: center;
	gap: clamp(2rem, 5vw, 4rem);
}

.tyn-split--reverse .tyn-split__media { order: 2; }
.tyn-split--reverse .tyn-split__body { order: 1; }
.tyn-split__body .tyn-lede { margin-bottom: 1.25rem; }
.tyn-split__body .tyn-btn { margin-top: 1.5rem; }

@media (max-width: 900px) {
	.tyn-split { grid-template-columns: 1fr; }
	.tyn-split--reverse .tyn-split__media,
	.tyn-split--reverse .tyn-split__body { order: initial; }
	.tyn-figure--tall, .tyn-figure--portrait { aspect-ratio: 16 / 11; }
}

/* ----------------------------------------------------------- cards, grid -- */

.tyn-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
	gap: 1.5rem;
}

.tyn-card {
	display: flex;
	flex-direction: column;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	overflow: hidden;
	transition: transform .28s var(--tyn-ease), box-shadow .28s var(--tyn-ease), border-color .28s var(--tyn-ease);
}

.tyn-card:hover {
	transform: translateY(-4px);
	border-color: transparent;
	box-shadow: var(--tyn-shadow-lg);
}

.tyn-card__media { position: relative; display: block; }
.tyn-card__media .tyn-figure { border-radius: 0; }
.tyn-card__media img { transition: transform .5s var(--tyn-ease); }
.tyn-card:hover .tyn-card__media img { transform: scale(1.035); }

.tyn-card__status {
	position: absolute;
	top: .75rem; left: .75rem;
	padding: .35rem .7rem;
	border-radius: 3px;
	background: var(--tyn-deep);
	color: #fff;
	font-family: var(--tyn-display);
	font-size: .66rem;
	font-weight: 400;
	letter-spacing: .1em;
	text-transform: uppercase;
}

/* A sold listing should not look like an available one. */
.tyn-status--sold,
.tyn-status--closed { background: var(--tyn-ink); }
.tyn-status--pending,
.tyn-status--under-contract { background: var(--tyn-accent); color: #FFFFFF; }
.tyn-status--coming-soon { background: var(--tyn-deep-lt); }

.tyn-card__body { display: flex; flex-direction: column; padding: 1.35rem 1.35rem 1.5rem; }

.tyn-card__price {
	margin-bottom: .35rem;
	font-family: var(--tyn-display);
	font-size: 1.3rem;
	font-weight: 400;
	color: var(--tyn-deep);
}

.tyn-card__title { font-size: 1.05rem; margin-bottom: .5rem; }
.tyn-card__title a { color: var(--tyn-ink); }
.tyn-card__title a:hover { color: var(--tyn-deep); }

.tyn-card__addr {
	display: flex;
	align-items: center;
	gap: .4rem;
	margin-bottom: .9rem;
	font-size: .88rem;
	color: var(--tyn-muted);
}
.tyn-card__addr .tyn-icon { color: var(--tyn-accent); }

.tyn-card__specs {
	display: flex;
	flex-wrap: wrap;
	gap: .35rem 1.1rem;
	margin-top: auto;
	padding-top: .9rem;
	border-top: 1px solid var(--tyn-line-soft);
	font-size: .84rem;
	color: var(--tyn-body);
}
.tyn-card__specs li { display: inline-flex; align-items: center; gap: .35rem; }
.tyn-card__specs .tyn-icon { color: var(--tyn-deep-lt); }

.tyn-card__date {
	margin-bottom: .4rem;
	font-family: var(--tyn-display);
	font-size: .7rem;
	font-weight: 400;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-card__text { font-size: .93rem; color: var(--tyn-muted); margin-bottom: 1rem; }

.tyn-count {
	margin-bottom: 1.75rem;
	font-size: .88rem;
	color: var(--tyn-muted);
}

/* --------------------------------------------------------------- services -- */

.tyn-services {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
	gap: 1.25rem;
}

.tyn-service {
	display: flex;
	flex-direction: column;
	padding: 2rem 1.6rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	color: inherit;
	transition: transform .28s var(--tyn-ease), box-shadow .28s var(--tyn-ease), border-color .28s var(--tyn-ease);
}
.tyn-service:hover {
	transform: translateY(-4px);
	border-color: transparent;
	box-shadow: var(--tyn-shadow-lg);
	color: inherit;
}

.tyn-service__num {
	margin-bottom: .9rem;
	font-family: var(--tyn-display);
	font-size: 1.6rem;
	font-weight: 400;
	line-height: 1;
	color: var(--tyn-accent);
}
.tyn-service__title { margin-bottom: .5rem; }
.tyn-service__text { font-size: .93rem; color: var(--tyn-muted); margin-bottom: 1.25rem; }

.tyn-service__link {
	margin-top: auto;
	font-family: var(--tyn-display);
	font-size: .74rem;
	font-weight: 400;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-service__link::after {
	content: ' \2192';
	display: inline-block;
	transition: transform .25s var(--tyn-ease);
}
.tyn-service:hover .tyn-service__link::after,
.tyn-card:hover .tyn-service__link::after { transform: translateX(4px); }

/* A post without a photo drops the media panel entirely rather than showing a
   placeholder — ten empty frames in a row read as broken, not as restraint. */
.tyn-card--post.tyn-card--text .tyn-card__body { padding-top: 1.9rem; }
.tyn-card--post .tyn-card__text { min-height: 0; }

/*
 * The whole card is the link.
 *
 * The photo panel used to be an anchor, so most of the card was clickable and
 * nobody noticed that "Read more" is a span rather than a link. Dropping the
 * empty panel took the click target with it and left only the title text live,
 * which reads as a card that does nothing — you press the obvious affordance
 * and the page sits there. The title anchor is stretched over the card instead,
 * so there is still exactly one link per card for a screen reader to announce.
 */
.tyn-card--post { position: relative; }
.tyn-card--post .tyn-card__title a::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
}
.tyn-card--post:hover { border-color: var(--tyn-gold-dk); }
.tyn-card--post:hover .tyn-service__link { color: var(--tyn-gold-lt); }

/* --------------------------------------------------------------- pillars -- */

.tyn-pillars {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
	gap: 1.25rem;
}

.tyn-pillar {
	padding: 1.75rem 1.5rem;
	background: rgba(255, 255, 255, .06);
	border: 1px solid rgba(255, 255, 255, .14);
	border-radius: 8px;
}
.tyn-pillar__title { margin-bottom: .6rem; font-size: 1.05rem; }
.tyn-pillar__body { font-size: .92rem; color: rgba(255, 255, 255, .78); margin: 0; }

/* ----------------------------------------------------------------- steps -- */

.tyn-steps {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
	gap: 1.5rem;
}
.tyn-step { padding-top: 1.5rem; border-top: 2px solid var(--tyn-line); }
.tyn-step__num {
	display: block;
	margin-bottom: .7rem;
	font-family: var(--tyn-display);
	font-size: 1.7rem;
	font-weight: 400;
	line-height: 1;
	color: var(--tyn-accent);
}
.tyn-step__title { margin-bottom: .4rem; }
.tyn-step__text { font-size: .92rem; color: var(--tyn-muted); margin: 0; }

/* ---------------------------------------------------------------- quotes -- */

.tyn-quotes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
	gap: 1.5rem;
}

.tyn-quote {
	margin: 0;
	padding: 1.9rem 1.6rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
}
.tyn-quote__stars { color: var(--tyn-accent); letter-spacing: .12em; margin-bottom: .9rem; }
.tyn-quote blockquote { margin: 0 0 1.1rem; color: var(--tyn-body); }
.tyn-quote figcaption { display: flex; flex-direction: column; gap: .15rem; }
.tyn-quote__name { font-family: var(--tyn-display); font-weight: 400; color: var(--tyn-ink); font-size: .92rem; }
.tyn-quote__via { font-size: .8rem; color: var(--tyn-faint); }

/* ------------------------------------------------------------------ team -- */

.tyn-team { display: grid; gap: 2rem; }

.tyn-member {
	display: grid;
	grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
	padding: clamp(1.5rem, 3vw, 2.25rem);
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
}

@media (max-width: 760px) {
	.tyn-member { grid-template-columns: 1fr; }
}

.tyn-member__photo { position: relative; }

.tyn-member__initials {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 3 / 4;
	border-radius: 6px;
	background: var(--tyn-deep);
	color: var(--tyn-accent-lt);
	font-family: var(--tyn-display);
	font-size: 3.5rem;
	font-weight: 400;
	letter-spacing: .04em;
}

.tyn-member__name { margin-bottom: .2rem; }
.tyn-member__role {
	font-family: var(--tyn-display);
	font-size: .78rem;
	font-weight: 400;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-member__bio { color: var(--tyn-body); margin-bottom: 1.1rem; }
.tyn-member__contact { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; }
.tyn-member__contact a { display: inline-flex; align-items: center; gap: .4rem; font-size: .9rem; }
.tyn-member__contact .tyn-icon { color: var(--tyn-accent); }

.tyn-joinus {
	margin-top: 2rem;
	padding: clamp(1.75rem, 4vw, 2.5rem);
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	text-align: center;
}
.tyn-joinus h2 { font-size: 1.3rem; margin-bottom: .6rem; }
.tyn-joinus p { max-width: 52ch; margin-inline: auto; margin-bottom: 1.4rem; color: var(--tyn-muted); }

/* -------------------------------------------------------------- listing -- */

.tyn-listing { padding-block: clamp(2rem, 5vw, 3rem) 0; }
.tyn-listing__head { margin-bottom: 1.75rem; }

.tyn-crumb { font-size: .82rem; color: var(--tyn-faint); margin-bottom: 1rem; }
.tyn-crumb span { margin-inline: .4rem; }

.tyn-listing__titles {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.5rem;
	flex-wrap: wrap;
}
.tyn-listing__addr {
	display: flex;
	align-items: center;
	gap: .4rem;
	margin-top: .6rem;
	color: var(--tyn-muted);
}
.tyn-listing__addr .tyn-icon { color: var(--tyn-accent); }
.tyn-listing__price { text-align: right; }
.tyn-listing__amount {
	font-family: var(--tyn-display);
	font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem);
	font-weight: 400;
	color: var(--tyn-deep);
	margin-bottom: .4rem;
}
.tyn-listing__price .tyn-card__status { position: static; display: inline-block; }

.tyn-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(50%, 9rem), 1fr));
	gap: 1px;
	margin-top: 1.75rem;
	background: var(--tyn-line);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	overflow: hidden;
}
.tyn-facts li { padding: 1.1rem 1.25rem; background: var(--tyn-white); text-align: center; }
.tyn-facts__value {
	display: block;
	font-family: var(--tyn-display);
	font-size: 1.35rem;
	font-weight: 400;
	color: var(--tyn-ink);
}
.tyn-facts__label {
	display: block;
	margin-top: .2rem;
	font-size: .78rem;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--tyn-faint);
}

.tyn-listing__body {
	display: grid;
	grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
	gap: clamp(2rem, 4vw, 3.5rem);
	align-items: start;
	padding-block: clamp(2.5rem, 5vw, 4rem);
}
@media (max-width: 900px) { .tyn-listing__body { grid-template-columns: 1fr; } }

.tyn-listing__galleryhead { margin-top: 2.5rem; }
.tyn-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
	gap: 1rem;
}

.tyn-askbox {
	position: sticky;
	top: calc(var(--tyn-header-h) + 1.5rem);
	padding: 1.75rem 1.6rem;
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
}
.tyn-askbox h2 { font-size: 1.2rem; margin-bottom: .5rem; }
.tyn-askbox p { font-size: .92rem; color: var(--tyn-muted); margin-bottom: 1.25rem; }
.tyn-askbox__call {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: .45rem;
	margin-top: .9rem;
	font-family: var(--tyn-display);
	font-weight: 400;
	color: var(--tyn-deep);
}

/* ----------------------------------------------------------------- empty -- */

.tyn-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1rem;
	max-width: 34rem;
	margin-inline: auto;
	padding: clamp(2.5rem, 5vw, 3.5rem);
	text-align: center;
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
}
.tyn-empty__mark { opacity: .7; }
.tyn-empty h2 { font-size: 1.3rem; }
.tyn-empty p { color: var(--tyn-muted); margin-bottom: .5rem; }

/* ------------------------------------------------------------------ faqs -- */

.tyn-faqs { display: grid; gap: .75rem; }

.tyn-faq {
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 6px;
}
.tyn-faq[open] { border-color: var(--tyn-deep-lt); }

.tyn-faq__q {
	position: relative;
	padding: 1.15rem 3rem 1.15rem 1.35rem;
	font-family: var(--tyn-display);
	font-size: 1rem;
	font-weight: 400;
	color: var(--tyn-ink);
	cursor: pointer;
	list-style: none;
}
.tyn-faq__q::-webkit-details-marker { display: none; }
.tyn-faq__q:hover { color: var(--tyn-deep); }

.tyn-faq__q::after,
.tyn-faq__q::before {
	content: '';
	position: absolute;
	right: 1.35rem; top: 50%;
	width: 12px; height: 2px;
	background: var(--tyn-accent);
	transition: transform .25s var(--tyn-ease);
}
.tyn-faq__q::before { transform: translateY(-50%) rotate(90deg); }
.tyn-faq__q::after { transform: translateY(-50%); }
.tyn-faq[open] .tyn-faq__q::before { transform: translateY(-50%) rotate(0deg); }

.tyn-faq__a { margin: 0; padding: 0 3rem 1.35rem 1.35rem; color: var(--tyn-muted); }

/* ---------------------------------------------------------------- contact -- */

.tyn-contact {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 3.5rem);
	align-items: start;
}
@media (max-width: 900px) { .tyn-contact { grid-template-columns: 1fr; } }

.tyn-contact__form .tyn-form { margin-top: 1.75rem; }

.tyn-contact__aside {
	display: grid;
	gap: 1px;
	background: var(--tyn-line);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	overflow: hidden;
}
.tyn-contact__block { padding: 1.4rem 1.5rem; background: var(--tyn-white); }
.tyn-contact__heading {
	margin-bottom: .4rem;
	font-family: var(--tyn-display);
	font-size: .68rem;
	font-weight: 400;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-contact__big {
	display: inline-block;
	font-family: var(--tyn-display);
	font-size: 1.1rem;
	font-weight: 400;
	color: var(--tyn-ink);
	word-break: break-word;
}
.tyn-contact__big:hover { color: var(--tyn-deep); }
.tyn-contact__note, .tyn-contact__text { margin: .3rem 0 0; font-size: .9rem; color: var(--tyn-muted); }
.tyn-contact__text { color: var(--tyn-body); }

.tyn-contact__seal {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: .6rem;
	padding: 1.75rem 1.5rem;
	text-align: center;
	background: var(--tyn-deep);
}
.tyn-contact__seal p {
	margin: 0;
	font-family: var(--tyn-display);
	font-size: .78rem;
	font-weight: 400;
	color: rgba(255, 255, 255, .82);
}
.tyn-contact__seal .tyn-mark { filter: brightness(1.6); }

/* ------------------------------------------------------------------ form -- */

.tyn-form { display: grid; gap: 1rem; }
.tyn-field { display: grid; gap: .4rem; min-width: 0; }
.tyn-field__row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
	gap: 1rem;
}

.tyn-field label {
	font-family: var(--tyn-display);
	font-size: .74rem;
	font-weight: 400;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--tyn-muted);
}
.tyn-field label span { color: var(--tyn-accent); }

.tyn-field input,
.tyn-field select,
.tyn-field textarea {
	width: 100%;
	padding: .8rem .95rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 5px;
	color: var(--tyn-ink);
	font-family: var(--tyn-body-font);
	font-size: 1rem;
	line-height: 1.5;
	transition: border-color .2s var(--tyn-ease), box-shadow .2s var(--tyn-ease);
	-webkit-appearance: none;
	appearance: none;
}

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

.tyn-field select {
	background-image:
		linear-gradient(45deg, transparent 50%, var(--tyn-deep) 50%),
		linear-gradient(135deg, var(--tyn-deep) 50%, transparent 50%);
	background-position: calc(100% - 20px) calc(50% + 2px), calc(100% - 14px) calc(50% + 2px);
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
	padding-right: 2.75rem;
	cursor: pointer;
}

.tyn-field input:focus,
.tyn-field select:focus,
.tyn-field textarea:focus {
	border-color: var(--tyn-deep-lt);
	box-shadow: 0 0 0 3px rgba(198, 169, 104, .22);
	outline: none;
}

.tyn-field input::placeholder, .tyn-field textarea::placeholder { color: var(--tyn-faint); }

/* Off-screen rather than display:none — some bots skip explicitly hidden
   fields, and this one is meant to be filled in. */
.tyn-trap {
	position: absolute !important;
	left: -9999px !important;
	width: 1px; height: 1px; overflow: hidden;
}

.tyn-form__note { margin: 0; font-size: .9rem; min-height: 1.4em; }
.tyn-form__note.is-ok { color: #1E7A4C; }
.tyn-form__note.is-bad { color: #C0392B; }
.tyn-form.is-sending { opacity: .6; pointer-events: none; }

.tyn-alert {
	padding: .9rem 1.15rem;
	margin-bottom: 1.5rem;
	border-left: 3px solid var(--tyn-deep);
	background: var(--tyn-tint);
	border-radius: 0 4px 4px 0;
	font-size: .94rem;
}
.tyn-alert--ok { border-left-color: #1E7A4C; color: #1E7A4C; }
.tyn-alert--bad { border-left-color: #C0392B; color: #C0392B; }

/* ----------------------------------------------------------------- modal -- */

.tyn-modal {
	position: fixed;
	inset: 0;
	z-index: 120;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--tyn-gutter);
	opacity: 0;
	visibility: hidden;
	transition: opacity .25s var(--tyn-ease), visibility .25s var(--tyn-ease);
}
.tyn-modal[hidden] { display: flex; }
.tyn-modal.is-open { opacity: 1; visibility: visible; }

.tyn-modal__veil {
	position: absolute;
	inset: 0;
	background: rgba(11, 11, 12, .72);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
}

.tyn-modal__panel {
	position: relative;
	width: 100%;
	max-width: 38rem;
	max-height: min(90vh, 52rem);
	overflow-y: auto;
	padding: clamp(1.75rem, 4vw, 2.5rem);
	background: var(--tyn-white);
	border-radius: 10px;
	box-shadow: var(--tyn-shadow-lg);
	transform: translateY(14px) scale(.99);
	transition: transform .3s var(--tyn-ease);
}
.tyn-modal.is-open .tyn-modal__panel { transform: translateY(0) scale(1); }

.tyn-modal__panel::before {
	content: '';
	position: absolute;
	top: 0; left: 0; right: 0;
	height: 4px;
	background: var(--tyn-accent-metal);
	border-radius: 10px 10px 0 0;
}

.tyn-modal__close {
	position: absolute;
	top: .8rem; right: .8rem;
	width: 2.25rem; height: 2.25rem;
	display: flex; align-items: center; justify-content: center;
	background: none;
	border: 1px solid transparent;
	border-radius: 4px;
	color: var(--tyn-muted);
	font-size: 1.55rem;
	line-height: 1;
	cursor: pointer;
	transition: color .2s var(--tyn-ease), border-color .2s var(--tyn-ease);
}
.tyn-modal__close:hover { color: var(--tyn-deep); border-color: var(--tyn-line); }

.tyn-modal__head { margin-bottom: 1.6rem; text-align: center; }
.tyn-modal__head h2 { font-size: clamp(1.3rem, 1.15rem + .9vw, 1.7rem); }
.tyn-modal__lede { margin: 0; font-size: .94rem; color: var(--tyn-muted); }

/* ---------------------------------------------------------------- closer -- */

.tyn-closer {
	position: relative;
	padding-block: clamp(3.5rem, 7vw, 5.5rem);
	background: var(--tyn-deep);
	color: rgba(255, 255, 255, .82);
	text-align: center;
	overflow: hidden;
}

.tyn-closer::before {
	content: '';
	position: absolute;
	top: -45%; left: 50%;
	width: 44rem; height: 44rem;
	transform: translateX(-50%);
	background: radial-gradient(circle, rgba(198, 169, 104, .10) 0%, transparent 62%);
	pointer-events: none;
}

.tyn-closer__inner { position: relative; max-width: 44rem; margin-inline: auto; }
.tyn-closer__title { color: #fff; }
.tyn-closer__lede { color: rgba(255, 255, 255, .82); margin-inline: auto; margin-top: 1rem; }
.tyn-closer__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .8rem; margin-top: 2rem; }

/* ----------------------------------------------------------------- posts -- */

.tyn-posts { display: grid; gap: 2.25rem; }
.tyn-post { padding-bottom: 2.25rem; border-bottom: 1px solid var(--tyn-line); }
.tyn-post__date {
	font-family: var(--tyn-display);
	font-size: .7rem;
	font-weight: 400;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-post__title { margin: .4rem 0 .6rem; }
.tyn-post__excerpt { color: var(--tyn-muted); margin: 0; }

.tyn-backlink { margin-top: 2.5rem; font-family: var(--tyn-display); font-weight: 400; }

.tyn-pagination { margin-top: 2.75rem; }
.tyn-pagination .nav-links { display: flex; gap: .5rem; flex-wrap: wrap; }
.tyn-pagination .page-numbers {
	padding: .5rem .9rem;
	border: 1px solid var(--tyn-line);
	border-radius: 4px;
	color: var(--tyn-body);
	font-size: .88rem;
}
.tyn-pagination .page-numbers.current,
.tyn-pagination .page-numbers:hover {
	border-color: var(--tyn-deep);
	background: var(--tyn-deep);
	color: #fff;
}

/* --------------------------------------------- syndicated legal documents -- */

/* Light site, so the plugin's inline color:#000000 is survivable here — but it
   is still forced to the body colour so legal pages match everything else. */
.bb-legal-container,
.bb-legal-container * { color: var(--tyn-body) !important; }
.bb-legal-container { max-width: 70ch; }
.bb-legal-container h1,
.bb-legal-container h2,
.bb-legal-container h3,
.bb-legal-container strong,
.bb-legal-container b { color: var(--tyn-ink) !important; }
.bb-legal-container h2,
.bb-legal-container h3 { margin: 2.25rem 0 .75rem; line-height: 1.25; font-family: var(--tyn-display); }
.bb-legal-container p, .bb-legal-container li { margin-bottom: 1em; }
.bb-legal-container ul, .bb-legal-container ol { margin: 0 0 1.25em 1.25rem; list-style: disc; }
.bb-legal-container ol { list-style: decimal; }
.bb-legal-container a { color: var(--tyn-deep-lt) !important; text-decoration: underline; }
.bb-legal-container hr { border: 0; border-top: 1px solid var(--tyn-line); margin: 2rem 0; }

/* ---------------------------------------------------------------- reveal -- */

@media (prefers-reduced-motion: no-preference) {
	html.js [data-tyn-reveal] {
		opacity: 0;
		transform: translateY(16px);
		transition: opacity .7s var(--tyn-ease), transform .7s var(--tyn-ease);
	}
	html.js [data-tyn-reveal].is-in { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}
}

/* ------------------------------------------------------------------ misc -- */

@media (max-width: 620px) {
	.tyn-section { padding-block: clamp(3rem, 10vw, 4rem); }
	.tyn-card__body { padding: 1.15rem; }
	.tyn-service { padding: 1.6rem 1.3rem; }
	.tyn-listing__titles { flex-direction: column; align-items: flex-start; }
	.tyn-listing__price { text-align: left; }
}

body.admin-bar .tyn-header { top: 32px; }
@media (max-width: 782px) { body.admin-bar .tyn-header { top: 46px; } }

/* -------------------------------------------------------- nav dropdowns -- */

.tyn-nav__item { position: relative; display: flex; align-items: center; gap: .2rem; }

/* The chevron is a button, not decoration: on a touch screen there is no hover,
   so the parent link has to stay a link and something else has to open the
   submenu. */
.tyn-nav__toggle {
	display: inline-flex;
	align-items: center;
	padding: .25rem;
	background: none;
	border: 0;
	color: var(--tyn-ink);
	cursor: pointer;
	transition: transform .2s var(--tyn-ease);
}
.tyn-nav__item.is-open > .tyn-nav__toggle { transform: rotate(180deg); }

.tyn-nav__sub {
	position: absolute;
	top: 100%;
	left: -1rem;
	min-width: 15rem;
	padding: .5rem 0;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 6px;
	box-shadow: var(--tyn-shadow-lg);
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	transition: opacity .2s var(--tyn-ease), transform .2s var(--tyn-ease), visibility .2s var(--tyn-ease);
	z-index: 20;
}

.tyn-nav__item:hover > .tyn-nav__sub,
.tyn-nav__item:focus-within > .tyn-nav__sub,
.tyn-nav__item.is-open > .tyn-nav__sub {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.tyn-nav__sub a {
	display: block;
	padding: .55rem 1.1rem;
	font-size: .78rem;
	text-transform: none;
	letter-spacing: .01em;
	color: var(--tyn-body);
}
.tyn-nav__sub a::after { display: none; }
.tyn-nav__sub a:hover { background: var(--tyn-tint); color: var(--tyn-deep); }

/* In the drawer every submenu is an accordion, collapsed by default.
 *
 * They used to be forced open, which turned six top-level items into fourteen
 * rows and pushed the bottom of the menu off a phone screen entirely. Collapsed,
 * the whole menu fits without scrolling and each section opens on a tap. */
.tyn-drawer__nav .tyn-nav__list { width: 100%; gap: 0; }

.tyn-drawer__nav .tyn-nav__item {
	display: grid;
	/* A centred row with the chevron pinned right: three columns where the outer
	   two are equal, so the label lands on the true centre rather than being
	   pushed left by the arrow's width. */
	grid-template-columns: 3rem 1fr 3rem;
	align-items: center;
	width: 100%;
	border-bottom: 1px solid var(--tyn-line);
}

.tyn-drawer__nav .tyn-nav__item > a {
	grid-column: 2;
	padding-block: 1rem;
	font-size: 1.06rem;
	text-align: center;
}
.tyn-drawer__nav .tyn-nav__item > a::after { display: none; }

/* The row is the control, so it should look like one under the finger. */
.tyn-drawer__nav .tyn-nav__item.has-children { cursor: pointer; }
.tyn-drawer__nav .tyn-nav__item.has-children:active { background: var(--tyn-tint); }

/* A proper hit target — the chevron is the control that opens the section, and
   on a phone it has to be thumb-sized rather than icon-sized. */
.tyn-drawer__nav .tyn-nav__toggle {
	grid-column: 3;
	display: inline-flex;
	justify-content: center;
	width: 3rem;
	height: 3rem;
	color: var(--tyn-deep);
}

.tyn-drawer__nav .tyn-nav__sub {
	grid-column: 1 / -1;
	background: var(--tyn-tint);
	position: static;
	min-width: 0;
	border: 0;
	box-shadow: none;
	background: none;
	transform: none;
	visibility: visible;
	opacity: 1;
	/* Collapsed by default.
	 *
	 * NOT the grid-template-rows: 0fr trick — that declares a single track, so
	 * only the first child collapses and every item after it lands in an
	 * implicit auto row and stays visible. It looked like the accordion worked
	 * until a submenu had more than one entry. max-height is unfashionable and
	 * correct. */
	display: block;
	max-height: 0;
	overflow: hidden;
	padding: 0;
	opacity: 0;
	transition: max-height .3s var(--tyn-ease), opacity .2s var(--tyn-ease), padding .3s var(--tyn-ease);
}

.tyn-drawer__nav .tyn-nav__item.is-open > .tyn-nav__sub {
	/* Comfortably past the tallest submenu (three items); the transition eases
	   on the real height because the content is shorter than the cap. */
	max-height: 22rem;
	opacity: 1;
	padding-bottom: .6rem;
}

.tyn-drawer__nav .tyn-nav__sub a {
	padding: .55rem 0;
	font-size: .95rem;
	font-weight: 500;
	text-align: center;
	text-transform: none;
	letter-spacing: 0;
	color: var(--tyn-body);
}

/* ----------------------------------------------------------- credentials -- */

/* White, not navy. It sat directly beneath a navy-scrimmed hero and the two ran
   together as one undifferentiated slab of blue. */
.tyn-creds { background: var(--tyn-white); border-bottom: 1px solid var(--tyn-line); }

.tyn-creds__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(50%, 13rem), 1fr));
	gap: 1px;
	background: var(--tyn-line);
}

.tyn-creds__list li {
	padding: 1.5rem 1.25rem;
	background: var(--tyn-white);
	text-align: center;
}

.tyn-creds__label {
	display: block;
	font-family: var(--tyn-display);
	font-size: 1.02rem;
	font-weight: 400;
	color: var(--tyn-ink);
}
.tyn-creds__note {
	display: block;
	margin-top: .3rem;
	font-size: .82rem;
	color: var(--tyn-muted);
}

/* ----------------------------------------------------------------- paths -- */

.tyn-paths {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
	gap: clamp(1.5rem, 3vw, 2.5rem);
}

.tyn-path {
	display: flex;
	flex-direction: column;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	overflow: hidden;
	transition: transform .28s var(--tyn-ease), box-shadow .28s var(--tyn-ease);
}
.tyn-path:hover { transform: translateY(-4px); box-shadow: var(--tyn-shadow-lg); }

.tyn-path__media .tyn-figure { border-radius: 0; }
.tyn-path__body { padding: clamp(1.5rem, 3vw, 2.25rem); }
.tyn-path__title { font-size: clamp(1.35rem, 1.1rem + 1vw, 1.8rem); }
.tyn-path__text { color: var(--tyn-muted); margin-bottom: 1.5rem; }

/* ----------------------------------------------------------------- creed -- */

.tyn-creed__inner { max-width: 52rem; margin-inline: auto; text-align: center; }

.tyn-creed__quote { margin: 0; }

.tyn-creed__goal {
	font-family: var(--tyn-display);
	font-size: clamp(1.3rem, 1.1rem + 1.2vw, 1.95rem);
	font-weight: 400;
	line-height: 1.3;
	color: #fff;
	margin-bottom: 1.5rem;
}

.tyn-creed__close {
	font-size: clamp(1rem, .97rem + .3vw, 1.12rem);
	color: var(--tyn-accent-lt);
	font-weight: 500;
}

.tyn-creed__attrib {
	margin-top: 1.25rem;
	font-family: var(--tyn-display);
	font-size: .76rem;
	font-weight: 400;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .6);
}

.tyn-creed__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: .8rem;
	margin-top: 2rem;
}

/* ------------------------------------------------------- valuation call -- */

.tyn-valuecta {
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
	align-items: center;
	gap: clamp(1.5rem, 4vw, 3rem);
	padding: clamp(1.75rem, 4vw, 2.75rem);
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-left: 4px solid var(--tyn-accent-mid);
	border-radius: 8px;
}
@media (max-width: 820px) { .tyn-valuecta { grid-template-columns: 1fr; } }

.tyn-valuecta h2 { margin-bottom: .6rem; }
.tyn-valuecta p { color: var(--tyn-muted); margin: 0; }
.tyn-valuecta__act { display: flex; flex-direction: column; align-items: flex-start; gap: .9rem; }

.tyn-valuecta__call {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	font-family: var(--tyn-display);
	font-weight: 400;
	color: var(--tyn-deep);
}
.tyn-valuecta__call .tyn-icon { color: var(--tyn-accent-mid); }

/* Both step lists are four items. auto-fit put three on one row and left the
   fourth stranded beside a hole, so the count is pinned instead: four across,
   then two, then one. Two never orphans a four-item list. */
.tyn-steps--wide { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 1120px) { .tyn-steps--wide { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px)  { .tyn-steps--wide { grid-template-columns: 1fr; } }

.tyn-quotes__more { margin-top: 2rem; text-align: center; }

/* Pillars sit on navy by default; this is the variant for a light band. */
.tyn-pillars--light .tyn-pillar {
	background: var(--tyn-white);
	border-color: var(--tyn-line);
}
.tyn-pillars--light .tyn-pillar__title { color: var(--tyn-ink); }
.tyn-pillars--light .tyn-pillar__body { color: var(--tyn-muted); }

/* ---------------------------------------------------------------- footer -- */

/* Same structure as themes/brokerboost-flagship, but white.
 *
 * The flagship paints it with --bbt-primary. Here the closing band above it is
 * already navy, so a navy footer made the bottom fifth of every page one
 * continuous blue block with a hairline through it. White separates the two and
 * lets the logo sit on its own background without a plate. */

/*
 * The footer, continuous with the closer above it.
 *
 * It used to be white with a cream legal strip, which meant the bottom of every
 * page was three surfaces in a row: a glowing navy band, a hard edge, white, and
 * then cream. The glow Adam liked was doing its work and then hitting a wall an
 * inch below.
 *
 * Now the closer and the footer share one ground, with no border between them,
 * and a second much wider glow sits at the top of the footer continuing the same
 * light. Read together they are one object: light falls from the closer's
 * headline and dies out somewhere around the legal line.
 *
 * Everything else is subtraction — the logo came down from 96px, the columns
 * tightened, and the legal strip is now a darker shelf rather than a different
 * material.
 */
.tyn-foot {
	position: relative;
	background: var(--tyn-deep);
	color: rgba(255, 255, 255, .70);
	overflow: hidden;
}

/* The continuation of the closer's light. Wider and fainter than the one above
   it, so it reads as the same source falling further rather than a second lamp. */
.tyn-foot::before {
	content: '';
	position: absolute;
	top: -70%; left: 50%;
	width: 74rem; height: 52rem;
	transform: translateX(-50%);
	background: radial-gradient(ellipse at center, rgba(198, 169, 104, .085) 0%, transparent 64%);
	pointer-events: none;
}

.tyn-foot__in {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	gap: clamp(28px, 4.5vw, 68px);
	padding-block: clamp(40px, 5vw, 60px);
}

.tyn-foot__brand { flex: 1 1 300px; }
.tyn-foot__col { flex: 0 1 190px; }

.tyn-foot__brand .tyn-logo { margin-bottom: .9rem; }
.tyn-foot__brand .tyn-logo__img { height: 64px; }

.tyn-foot__name { margin: 0; font-family: var(--tyn-display); font-size: 1.1rem; font-weight: 400; color: #fff; }
.tyn-foot__firm {
	margin: 2px 0 12px;
	font-size: .7rem;
	font-weight: 400;
	letter-spacing: .14em;
	text-transform: uppercase;
	/* --tyn-accent is a dark blue and vanishes here; the light tint is the only
	   member of the brand family that survives on this ground. */
	color: var(--tyn-brand-lt);
}
.tyn-foot__blurb { margin: 0; max-width: 40ch; color: rgba(255, 255, 255, .60); font-size: .9rem; }

.tyn-foot__h {
	margin: 0 0 12px;
	font-family: var(--tyn-display);
	font-size: .68rem;
	font-weight: 400;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .45);
}

.tyn-foot__menu { list-style: none; margin: 0; padding: 0; }
.tyn-foot__menu a,
.tyn-foot__link {
	display: block;
	padding: 4px 0;
	color: rgba(255, 255, 255, .72);
	text-decoration: none;
	font-size: .92rem;
	transition: color .18s var(--tyn-ease);
}
.tyn-foot__menu a:hover,
.tyn-foot__link:hover { color: #fff; text-decoration: none; }

.tyn-foot__addr { margin: 12px 0 0; color: rgba(255, 255, 255, .55); font-size: .88rem; }
.tyn-foot__social { margin: 14px 0 0; font-size: .88rem; }
.tyn-foot__social a { color: var(--tyn-brand-lt); }

/* A darker shelf rather than a different material. The hairline is white at low
   alpha so it reads as a fold in the same surface, not a seam between two. */
.tyn-foot__legal {
	position: relative;
	border-top: 1px solid rgba(255, 255, 255, .09);
	background: rgba(0, 0, 0, .18);
}
.tyn-foot__legal-in { padding-block: 20px; font-size: .76rem; color: rgba(255, 255, 255, .48); line-height: 1.65; }
.tyn-foot__legal-in p { margin: 0 0 6px; }
.tyn-foot__legal-in a { color: rgba(255, 255, 255, .68); }
.tyn-foot__legal-in a:hover { color: #fff; }

.tyn-foot__legalnav { display: flex; flex-wrap: wrap; gap: .35rem 1.25rem; margin: 10px 0; }
.tyn-foot__legalnav a { text-decoration: underline; text-underline-offset: 2px; }

.tyn-foot__eho { display: flex; align-items: center; gap: 8px; }

/* The Equal Housing mark is now real SVG geometry — see tyn_eho_mark(). */
.tyn-eho { flex: 0 0 auto; opacity: .85; }

/* --------------------------------------------------------- property search -- */

/* A mockup. It has to look like a working search or it undersells the site, and
   it has to be obviously a form or nobody will try it. */

.tyn-searchband {
	position: relative;
	z-index: 5;
	/* Rides up over the hero so it reads as part of it. */
	margin-top: -3.5rem;
	padding-bottom: 1rem;
}
@media (max-width: 900px) { .tyn-searchband { margin-top: -1.5rem; } }

.tyn-section--searchtop { padding-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.tyn-section--tight { padding-top: clamp(1.5rem, 3vw, 2.5rem); }

.tyn-search {
	padding: 1.1rem 1.25rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 10px;
	box-shadow: var(--tyn-shadow-lg);
}

.tyn-search--page { box-shadow: var(--tyn-shadow); }

.tyn-search__row {
	display: grid;
	grid-template-columns: 2fr 1fr 1fr 1fr auto;
	gap: .75rem;
	align-items: end;
}
@media (max-width: 900px) {
	.tyn-search__row { grid-template-columns: 1fr 1fr; }
	.tyn-search__field--wide { grid-column: 1 / -1; }
	.tyn-search__submit { grid-column: 1 / -1; }
}

.tyn-search__field { display: grid; gap: .3rem; min-width: 0; }

/*
 * The field headings.
 *
 * These were Instrument Serif at .68rem, uppercase, tracked .1em, in
 * --tyn-muted. Every one of those choices works against legibility at this
 * size: a high-contrast display serif puts its thin strokes below a pixel at
 * ~11px, uppercase removes the ascender/descender cues that let you read a
 * short word at a glance, and the muted grey is the palest text on the page
 * sitting on the busiest control.
 *
 * So: the body grotesque instead of the serif, a little larger, weighted up,
 * tracking eased off, and --tyn-body for roughly 8:1 instead of 4.7:1. Still
 * uppercase, because it keeps them reading as labels rather than as content —
 * but now with the weight to survive it.
 */
.tyn-search__field label {
	font-family: var(--tyn-body-font);
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--tyn-body);
}

.tyn-search__field input,
.tyn-search__field select {
	width: 100%;
	padding: .7rem .8rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 5px;
	color: var(--tyn-ink);
	font-family: var(--tyn-body-font);
	font-size: .95rem;
	line-height: 1.4;
	-webkit-appearance: none;
	appearance: none;
	transition: border-color .2s var(--tyn-ease), box-shadow .2s var(--tyn-ease);
}

.tyn-search__field select {
	background-image:
		linear-gradient(45deg, transparent 50%, var(--tyn-deep) 50%),
		linear-gradient(135deg, var(--tyn-deep) 50%, transparent 50%);
	background-position: calc(100% - 18px) calc(50% + 1px), calc(100% - 12px) calc(50% + 1px);
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
	padding-right: 2.4rem;
	cursor: pointer;
}

/* The focus ring was rgba(10,81,153) — a blue from the theme this was copied
   from, on a site with no blue in it. */
.tyn-search__field input:focus,
.tyn-search__field select:focus {
	border-color: var(--tyn-accent-mid);
	box-shadow: 0 0 0 3px rgba(198, 169, 104, .10);
	outline: none;
}

.tyn-search__submit .tyn-btn { width: 100%; padding-block: .78rem; }

.tyn-search__more { margin-top: .85rem; }
.tyn-search__more summary {
	display: inline-block;
	font-family: var(--tyn-display);
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: .08em;
	text-transform: uppercase;
	/* Accent, not --tyn-deep-lt. This is the only clickable thing in the panel
	   that is not a button, and at near-black it read as a caption. */
	color: var(--tyn-accent);
	cursor: pointer;
	list-style: none;
}
.tyn-search__more summary::-webkit-details-marker { display: none; }
.tyn-search__more summary::after { content: ' +'; }
.tyn-search__more[open] summary::after { content: ' \2013'; }

.tyn-search__row--more {
	grid-template-columns: repeat(auto-fit, minmax(min(50%, 11rem), 1fr));
	margin-top: .85rem;
	padding-top: .85rem;
	border-top: 1px solid var(--tyn-line-soft);
}

/* ------------------------------------------------------------------ creed -- */

.tyn-creed__call {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	color: rgba(255, 255, 255, .86);
	font-size: .98rem;
}
.tyn-creed__call strong { color: var(--tyn-accent-lt); }
.tyn-creed__call:hover { color: #fff; }
.tyn-creed__call .tyn-icon { color: var(--tyn-accent-lt); }

.tyn-glyph { color: var(--tyn-faint); }

/* ---------------------------------------------------------------- slider -- */

/* A real horizontal scroller with scroll-snap, not a JS carousel. Trackpad,
   swipe, keyboard and the arrow buttons all work without special-casing any of
   them — the buttons just call scrollBy(). */

.tyn-slider__controls { display: flex; align-items: center; gap: .5rem; }

.tyn-slider__btn {
	width: 2.5rem;
	height: 2.5rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 50%;
	color: var(--tyn-deep);
	cursor: pointer;
	transition: background .2s var(--tyn-ease), border-color .2s var(--tyn-ease), opacity .2s var(--tyn-ease);
}
.tyn-slider__btn:hover { background: var(--tyn-deep); border-color: var(--tyn-deep); color: #fff; }
.tyn-slider__btn[disabled] { opacity: .35; cursor: default; }
.tyn-slider__btn[disabled]:hover { background: var(--tyn-white); border-color: var(--tyn-line); color: var(--tyn-deep); }

.tyn-slider__track {
	display: grid;
	grid-auto-flow: column;
	/* Likewise a floor that is not zero, so the track overflows. */
	/* The cap used to be a flat 21rem, which is narrower than the container on
	   any phone above ~400px: a 336px card sat in a 390px track and left ~54px
	   of dead space on the right, so the carousel read as left-aligned rather
	   than centred. Falling back to 100% of the track means the card fills the
	   width on a phone and still peeks the next one on a tablet. */
	grid-auto-columns: min(84vw, 21rem, 100%);
	gap: 1.25rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	/* Room for the card hover lift and its shadow, which would otherwise be
	   clipped by the scroll container. */
	padding: .5rem .25rem 1.5rem;
	margin-inline: -.25rem;
	scrollbar-width: thin;
}

.tyn-slider__track::-webkit-scrollbar { height: 6px; }
.tyn-slider__track::-webkit-scrollbar-thumb { background: var(--tyn-line); border-radius: 6px; }
.tyn-slider__track::-webkit-scrollbar-track { background: transparent; }

.tyn-slider__slide { scroll-snap-align: start; min-width: 0; }

/*
 * On a phone the card is centred in the viewport with a symmetric peek either
 * side, rather than sitting flush against the left gutter with one card showing
 * on the right. Both are legitimate; this one reads as deliberate rather than
 * as a grid that happened to be cut off, which is the point on a site whose job
 * is to look more expensive than the client's current one.
 *
 * The negative margin lets the track escape the wrap's gutter so the peeking
 * cards run to the screen edge; the matching scroll-padding is what actually
 * centres the snap target, and without it the first and last cards cannot reach
 * the middle.
 */
@media (max-width: 899px) {
	.tyn-slider__track {
		grid-auto-columns: 78vw;
		margin-inline: calc(var(--tyn-gutter) * -1);
		padding-inline: 11vw;
		scroll-padding-inline: 11vw;
	}
	.tyn-slider__slide { scroll-snap-align: center; }
}
.tyn-slider__slide .tyn-card { height: 100%; }

@media (min-width: 900px) {
	/* A FIXED track width, not minmax(0, …).
	 *
	 * With a zero minimum every column is allowed to shrink, and a grid inside
	 * an overflow container will always take that offer — so twelve slides
	 * collapsed to 80px each and squeezed into the visible width instead of
	 * overflowing. scrollWidth equalled clientWidth, which is the tell: nothing
	 * to scroll, because nothing overflowed. A single length forces the track to
	 * that size and the container to scroll. */
	.tyn-slider__track { grid-auto-columns: calc((100% - 2.5rem) / 3); }
}

/* ------------------------------------------------- masthead over the hero -- */

/*
 * On the front page the masthead floats over the hero photograph and resolves
 * to the normal white bar as you scroll. Everywhere else it is opaque from the
 * first pixel, because only the front page has a dark image to float over.
 *
 * Two mechanisms, deliberately:
 *
 *   - the BACKGROUND interpolates continuously off --tyn-shrink, so the bar
 *     arrives smoothly rather than snapping;
 *   - the FOREGROUND (nav text, logo, CTA) swaps on the .is-solid class the
 *     scroll handler sets past 60%, with a transition doing the blending.
 *
 * The foreground is not interpolated through the same variable on purpose.
 * Doing so makes legibility depend on a value JS rewrites every frame, and the
 * failure mode is white text on a white bar. A class is either present or not,
 * so the worst case is "solid too early", never "invisible".
 *
 * The hero is pulled up under the masthead rather than the masthead being taken
 * out of flow — a fixed bar would force every other page to compensate for it.
 */
.tyn-home .tyn-hero { margin-top: calc(var(--tyn-header-h) * -1); }
.tyn-home .tyn-hero__inner { padding-top: var(--tyn-header-h); }

/*
 * On the home page the bar starts invisible over the hero and becomes glass as
 * it lands. The blur has to be genuinely OFF at scroll 0 — a backdrop-filter on
 * a fully transparent bar still frosts the top of the hero photograph, which
 * looks like a rendering fault rather than a design.
 */
.tyn-home .tyn-header__bar {
	/* Black, not white. The bar fades in as you scroll off the hero, and at 72%
	   white it arrived as a pale slab carrying white nav type. The whole site is
	   black; the masthead should be too. */
	background: rgba(11, 11, 12, calc(.88 * var(--tyn-shrink)));
	/* The line across the bottom was a near-white hairline, which is the single
	   brightest thing on the page once the bar lands. Gold, at the same opacity
	   ramp, so it reads as a finishing line rather than a seam. */
	border-bottom-color: rgba(198, 169, 104, calc(.55 * var(--tyn-shrink)));
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}

.tyn-home .tyn-header.is-solid .tyn-header__bar {
	-webkit-backdrop-filter: blur(22px) saturate(1.5);
	backdrop-filter: blur(22px) saturate(1.5);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.tyn-home .tyn-header__bar { background: rgba(11, 11, 12, var(--tyn-shrink)); }
}

/* The light state: only while over the photograph. */
.tyn-home .tyn-header:not(.is-solid) .tyn-nav__list > li > a,
.tyn-home .tyn-header:not(.is-solid) .tyn-nav__toggle,
.tyn-home .tyn-header:not(.is-solid) .tyn-callnow {
	color: #fff;
}

.tyn-home .tyn-header:not(.is-solid) .tyn-burger__box i { background: #fff; }

/* The hover underline is a gold-era gradient; on the photograph it reads as
   mud, so it becomes plain white until the bar arrives. */
.tyn-home .tyn-header:not(.is-solid) .tyn-nav__list > li > a::after { background: #fff; }

.tyn-header .tyn-nav__list > li > a,
.tyn-header .tyn-nav__toggle,
.tyn-header .tyn-callnow { transition: color .28s var(--tyn-ease); }

/* The submenu is its own dark panel and is never part of the swap. */
.tyn-home .tyn-nav__sub a { color: var(--tyn-body); }

/*
 * The masthead CTA. Solid navy on a navy photograph disappears, so over the
 * hero it is an outlined button and fills in once the bar is there.
 */
.tyn-header__actions .tyn-btn--sm { transition: background .28s var(--tyn-ease), border-color .28s var(--tyn-ease); }

.tyn-home .tyn-header:not(.is-solid) .tyn-header__actions .tyn-btn--sm {
	background: transparent;
	border: 1px solid rgba(255, 255, 255, .75);
	color: #fff;
}

/* The light lockup sits on top of the dark one and fades out as the bar lands. */
.tyn-logo { position: relative; }
.tyn-logo__img--light {
	position: absolute;
	inset-block-start: 0;
	left: 0;
	opacity: 0;
	pointer-events: none;
	transition: opacity .28s var(--tyn-ease);
}
/* The masthead is near-black on every page and at every scroll position, so the
   light lockup is simply the header's logo. It used to be switched on only over
   the home hero, which left the black logo.png sitting on the black bar
   everywhere else — and on the home page it turned black the moment you
   scrolled. The dark lockup stays in the markup for the white mobile drawer,
   which is the one light surface the header still passes over. */
.tyn-logo--header .tyn-logo__img--light { opacity: 1; }

/* No JS: .is-solid is never added and --tyn-shrink never moves, so the masthead
   would sit transparent forever over a hero that has been pulled up under it.
   The document only gains .js once the inline script in header.php runs. */
html:not(.js) .tyn-home .tyn-hero { margin-top: 0; }
html:not(.js) .tyn-home .tyn-hero__inner { padding-top: 0; }
html:not(.js) .tyn-home .tyn-header__bar { background: var(--tyn-white); }
html:not(.js) .tyn-logo__img--light { display: none; }

.tyn-rent__all { margin: 1.5rem 0 0; }

/* The Resident Benefits Package note under the rentals grid. Set smaller and
   quieter than body copy: it is terms, and it should read as terms rather than
   compete with the listings above it. */
.tyn-rent__note {
	margin: 2.25rem auto 0;
	max-width: 62ch;
	padding-top: 1.5rem;
	border-top: 1px solid var(--tyn-line);
	color: var(--tyn-muted);
	font-size: .875rem;
	line-height: 1.7;
	text-align: center;
}

/* ------------------------------------------------------ search notice -- */

/*
 * Reuses the enquiry modal's veil and panel wholesale — it is the same object,
 * just carrying a message instead of a form. Only the width and the button row
 * differ, so only those are declared.
 */
.tyn-modal__panel--sm { max-width: 34rem; }

.tyn-note__actions {
	display: flex;
	flex-wrap: wrap;
	gap: .75rem;
	margin-top: 1.6rem;
}

.tyn-note__actions .tyn-btn { flex: 1 1 auto; justify-content: center; }

/* ------------------------------------------------------- agent page -- */

/*
 * The facts block. This is what carries the eight agents who have neither a bio
 * nor a review: a direct line, an email and a state licence number, presented
 * as a proper specification rather than as leftovers. A definition list because
 * that is genuinely what it is, which also gives screen readers the pairing.
 */
.tyn-agentfacts {
	display: grid;
	gap: .85rem 2rem;
	margin: 1.75rem 0 0;
	padding: 1.25rem 0 0;
	border-top: 1px solid var(--tyn-line);
}

@media (min-width: 560px) {
	.tyn-agentfacts { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}

.tyn-agentfacts dt {
	font-size: .66rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tyn-muted);
}

.tyn-agentfacts dd {
	margin: .3rem 0 0;
	font-family: var(--tyn-display);
	font-size: 1.02rem;
	color: var(--tyn-ink);
	/* Licence numbers and long emails must not push the column open. */
	overflow-wrap: anywhere;
}

.tyn-agentfacts a { color: var(--tyn-accent); }
.tyn-agentfacts a:hover { text-decoration: underline; }

.tyn-agent__actions {
	display: flex;
	flex-wrap: wrap;
	gap: .8rem;
	margin-top: 1.9rem;
}

/* The monogram at portrait size, for an agent with no headshot yet. */
.tyn-agentcard__initials--lg {
	border-radius: 8px;
	font-size: clamp(3.5rem, 9vw, 6rem);
	letter-spacing: .04em;
}

/* ------------------------------------------------- review attribution -- */

.tyn-quote__via--google {
	display: inline-flex;
	align-items: center;
	gap: .32em;
}

/* Sized in em so the mark tracks the caption rather than being pinned to a
   pixel size that stops matching the moment the type scale changes. */
.tyn-gmark {
	width: 1em;
	height: 1em;
	flex-shrink: 0;
	/* The optical centre of the G sits slightly above the text baseline. */
	transform: translateY(.04em);
}

.tyn-quote__via--google > span { line-height: 1; }

/* ----------------------------------------------------------- agent cards -- */

/*
 * The team slider's card. Narrower than a property card on purpose — a
 * portrait, a name and a role is the whole job, and fitting more of them in
 * view is what makes fifteen people read as a roster rather than a queue.
 */
.tyn-slider--team .tyn-slider__track { grid-auto-columns: min(62vw, 15rem, 100%); }

@media (min-width: 900px) {
	.tyn-slider--team .tyn-slider__track { grid-auto-columns: calc((100% - 5rem) / 5); }
}

.tyn-agentcard {
	display: flex;
	flex-direction: column;
	height: 100%;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 8px;
	overflow: hidden;
	color: inherit;
	transition: transform .25s var(--tyn-ease), box-shadow .25s var(--tyn-ease), border-color .25s var(--tyn-ease);
}

.tyn-agentcard:hover {
	transform: translateY(-4px);
	border-color: var(--tyn-brand-lt);
	box-shadow: var(--tyn-shadow);
}

.tyn-agentcard__photo { position: relative; background: var(--tyn-sky); }

/* The monogram, for anyone whose headshot has not arrived. */
.tyn-agentcard__initials {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1 / 1;
	font-family: var(--tyn-display);
	font-size: 2.4rem;
	color: var(--tyn-brand);
	background: var(--tyn-sky);
}

.tyn-agentcard__body { padding: .95rem 1rem 1.15rem; }

.tyn-agentcard__name {
	display: block;
	font-family: var(--tyn-display);
	font-size: 1.12rem;
	line-height: 1.2;
	color: var(--tyn-ink);
}

.tyn-agentcard__role {
	display: block;
	margin-top: .3rem;
	font-size: .68rem;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--tyn-muted);
}

.tyn-agentcard:hover .tyn-agentcard__name { color: var(--tyn-accent); }

/* --------------------------------------------------------------- filters -- */

.tyn-filters {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: 2rem;
	padding-bottom: 1.5rem;
	border-bottom: 1px solid var(--tyn-line);
}

.tyn-filter {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	padding: .5rem .9rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 999px;
	color: var(--tyn-body);
	font-family: var(--tyn-display);
	font-size: .78rem;
	font-weight: 400;
	transition: background .2s var(--tyn-ease), border-color .2s var(--tyn-ease), color .2s var(--tyn-ease);
}
.tyn-filter:hover { border-color: var(--tyn-deep); color: var(--tyn-deep); }

.tyn-filter.is-on {
	background: var(--tyn-deep);
	border-color: var(--tyn-deep);
	color: #fff;
}

.tyn-filter__n {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.35rem;
	height: 1.35rem;
	padding-inline: .3rem;
	border-radius: 999px;
	background: var(--tyn-tint-2);
	color: var(--tyn-muted);
	font-size: .68rem;
}
.tyn-filter.is-on .tyn-filter__n { background: rgba(255, 255, 255, .18); color: #fff; }

/* --------------------------------------------------------------- headshot -- */

/* Her headshot is square, so it gets a square frame. It was being forced into a
   3/4 portrait, which cropped it and blew it up far larger than the section
   needed. Capped so it sits beside the text rather than dominating it. */
.tyn-figure--square { aspect-ratio: 1 / 1; }

.tyn-split__media--headshot { max-width: 26rem; margin-inline: auto; }

/* A placeholder that fills whatever frame it lands in — the card, the slider,
   the single-property hero — rather than collapsing to its min-height. */
.tyn-figure--empty.tyn-figure--wide,
.tyn-figure--empty.tyn-figure--hero,
.tyn-figure--empty.tyn-figure--square { min-height: 0; }

.tyn-listing__repd {
	margin: 0 0 .4rem;
	font-family: var(--tyn-display);
	font-size: .74rem;
	font-weight: 400;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}

/* ------------------------------------------------------- hero phone, card -- */

.tyn-hero__phone {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	margin-top: 1.35rem;
	font-family: var(--tyn-display);
	font-size: 1.15rem;
	font-weight: 400;
	color: #fff;
}
.tyn-hero__phone .tyn-icon { color: var(--tyn-accent-lt); }
.tyn-hero__phone:hover { color: var(--tyn-accent-lt); }
.tyn-hero__phone + .tyn-hero__note { margin-top: .5rem; }

/* The representation line is the reason a sold listing is worth showing. */
.tyn-card__repd {
	margin-bottom: .5rem;
	font-family: var(--tyn-display);
	font-size: .68rem;
	font-weight: 400;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}

/* ------------------------------------------------------- mobile call button -- */

/* Desktop already carries the number in the utility bar, so this is the phone's
   home only on the sizes where that bar is hidden. */
.tyn-callnow { display: none; }

@media (max-width: 1040px) {
	.tyn-callnow {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: .45rem;
		white-space: nowrap;
		/* Flat fill, not the metal gradient. That gradient runs dark at the
		   corners and bright through the middle, which is fine across a 200px
		   button and reads as a smudge across a small one. */
		background: var(--tyn-accent-mid);
		background-image: none;
		border-color: var(--tyn-accent-mid);
		/* White, not the inherited var(--tyn-deep). Near-black on red was a
		   leftover from the navy build — the comment under it still said "the
		   brand navy", on a brokerage whose brand has no navy in it. */
		color: #fff;

		/*
		 * Sized to match the "Talk to an agent" button beside it, exactly.
		 *
		 * These two sit side by side in the masthead actions and were visibly
		 * mismatched: .6rem/1rem padding and no set font-size here against
		 * .68rem/1.1rem at .74rem on .tyn-btn--sm. Both now share one padding,
		 * one type size and one min-height, so the pair reads as a pair.
		 * 44px is also the touch-target floor.
		 */
		min-height: 44px;
		min-width: 44px;
		padding: .68rem 1.1rem;
		font-size: .74rem;
		border-radius: 6px;
	}

	.tyn-callnow:hover {
		background: var(--tyn-accent);
		background-image: none;
		border-color: var(--tyn-accent);
		color: #fff;
		box-shadow: none;
	}

	/* Matched to the button beside it for the same reason. */
	.tyn-header__actions .tyn-btn--sm {
		min-height: 44px;
		padding: .68rem 1.1rem;
		font-size: .74rem;
		border-radius: 6px;
	}

	.tyn-callnow .tyn-icon { color: #fff; width: 17px; height: 17px; }
}

/* Below this the words go and the icon carries it — at 380px a labelled button
   plus a burger leaves the logo nowhere to sit. */
@media (max-width: 400px) {
	/* Icon only, and square — a squashed rectangle with a glyph floating in it
	   is what made this look broken. */
	.tyn-callnow span { display: none; }
	.tyn-callnow { padding: 0; width: 44px; height: 44px; }
}

.tyn-hero__phone strong { color: var(--tyn-accent-lt); font-weight: 700; white-space: nowrap; }

@media (max-width: 520px) {
	.tyn-hero__phone { font-size: 1.02rem; align-items: flex-start; }
	.tyn-hero__phone .tyn-icon { margin-top: .3rem; }
}

/* ------------------------------------------------------------ team roster -- */

/* Six members, so a grid rather than six full-width rows. The broker keeps the
   wide treatment because she is the reason to choose the brokerage. */
@media (min-width: 860px) {
	.tyn-team { grid-template-columns: 1fr 1fr; }
	.tyn-team .tyn-member:first-child { grid-column: 1 / -1; }
	.tyn-team .tyn-member:not(:first-child) { grid-template-columns: minmax(0, 12rem) minmax(0, 1fr); }

	/* A two-person brokerage. :nth-child(2):last-child matches only when the
	   second member is also the final one, so a roster of two gets two full
	   cards instead of one wide card and one stranded half beside a hole. Three
	   or more still pair up as before. */
	.tyn-team .tyn-member:nth-child(2):last-child {
		grid-column: 1 / -1;
		grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
	}
}

.tyn-member__license {
	margin: .75rem 0 0;
	font-family: var(--tyn-display);
	font-size: .7rem;
	font-weight: 400;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tyn-faint);
}

/* A card with no bio should sit tight rather than leave the gap the bio left. */
.tyn-member__bio:empty { display: none; }

/* A heading section immediately above another section doubles its vertical
   padding, which reads as a missing block rather than as breathing room. */
.tyn-section--flush { padding-bottom: 0; }
.tyn-head--tight { margin-bottom: 0; }

/* ------------------------------------------------------- listing address plate --
   Stands in for the listing photo. See tyn_listing_media() for why most synced
   listings arrive without one. It has to read as a designed panel, because on
   this site it is the common case. */
.tyn-plate {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .85rem;
	padding: 2rem 1.5rem;
	text-align: center;
	background:
		repeating-linear-gradient(135deg, transparent 0 14px, rgba(255, 255, 255, .022) 14px 28px),
		linear-gradient(160deg, var(--tyn-deep-lt) 0%, var(--tyn-deep) 55%, #403336 100%);
}

.tyn-plate__addr {
	font-family: var(--tyn-display);
	font-size: clamp(1.05rem, 1.9vw, 1.45rem);
	font-weight: 400;
	line-height: 1.25;
	color: #fff;
	text-wrap: balance;
}

.tyn-plate__rule {
	width: 42px;
	height: 2px;
	background: var(--tyn-accent);
}

.tyn-plate__city {
	font-family: var(--tyn-display);
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .62);
}

/* The hero on a single listing is far taller than a card, so it needs room. */
.tyn-figure--hero.tyn-plate { min-height: clamp(15rem, 34vw, 26rem); }

.tyn-foot__blurb--sm { font-size: .82rem; }

/* ------------------------------------------------------------ hero search --
   This brokerage is on the IDX plan, so the search sits inside the hero. It has
   to stay legible over a photograph, which the page variant never has to do:
   the panel is translucent-dark rather than white, and the labels invert. */
.tyn-hero__search { margin: 1.75rem 0 1.25rem; max-width: 62rem; }

/*
 * The hero search panel: light frosted glass over the photograph.
 *
 * It was a 62% warm-charcoal veil carried over from the previous client, which
 * on a blue-green aerial read as a dirty smudge. This is the opposite — a light
 * material that lifts the photograph rather than covering it.
 *
 * Two things make it read as glass rather than as a flat white box: a real blur
 * doing the work at low opacity, and `saturate()`, which keeps the water and
 * the greenery showing through in colour instead of going milky grey. The inner
 * hairline is the classic glass edge — a light top rim catching the light.
 *
 * The panel is light, so the labels flip to ink. That is the whole reason the
 * old rules cannot simply have their alpha lowered: white-on-light would fail.
 */
/*
 * The hero search panel.
 *
 * saturate(1.5) — inherited from the build this was copied from — amplifies
 * whatever the panel happens to be sitting over. On this hero that is roof on
 * the left and lawn on the right, so the panel ran grey-to-green across its
 * own width and read as a rendering fault rather than as glass.
 *
 * saturate(.55) does the opposite: it drains the colour out of the backdrop so
 * the panel stays one neutral surface whatever photograph ends up behind it,
 * which also means a photo swap can never reintroduce the problem. The higher
 * white opacity carries the rest.
 */
.tyn-search--hero {
	background: rgba(255, 255, 255, .74);
	border-color: rgba(255, 255, 255, .7);
	box-shadow:
		0 18px 44px rgba(16, 10, 12, .3),
		inset 0 1px 0 rgba(255, 255, 255, .6);
	backdrop-filter: blur(24px) saturate(.55);
	-webkit-backdrop-filter: blur(24px) saturate(.55);
}

.tyn-search--hero .tyn-search__field label { color: var(--tyn-ink); }

/*
 * The fields stay solidly white so they still read as things you type into —
 * on a translucent panel an equally translucent input disappears into it. The
 * hairline border is what separates white-on-light; without it the fields merge
 * into the glass.
 */
.tyn-search--hero .tyn-search__field input,
.tyn-search--hero .tyn-search__field select {
	background: var(--tyn-white);
	border-color: rgba(255, 255, 255, .14);
}

.tyn-search--hero .tyn-search__field input::placeholder { color: var(--tyn-faint); }

/* --tyn-body here was a mid grey on a 52%-white panel over a dark photograph,
   which left the only non-button control in the hero effectively invisible. */
.tyn-search--hero .tyn-search__more summary { color: var(--tyn-accent); }
.tyn-search--hero .tyn-search__more summary:hover { color: var(--tyn-accent); }

/*
 * Safari on iOS honours backdrop-filter; a browser that does not would render a
 * 52%-white box with no blur, which is legible but flat. Give those a more
 * opaque panel so the type never sits on a half-transparent ground.
 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.tyn-search--hero { background: rgba(255, 255, 255, .88); }
}

/* The disclosure and the result line. */
.tyn-search__more { margin-top: .8rem; }

.tyn-search__more summary {
	font-family: var(--tyn-display);
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--tyn-muted);
	cursor: pointer;
}

.tyn-search__row--more {
	grid-template-columns: repeat(3, 1fr);
	margin-top: .75rem;
}
@media (max-width: 900px) { .tyn-search__row--more { grid-template-columns: 1fr 1fr; } }

.tyn-search__result {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .75rem;
	margin: 1rem 0 0;
	font-size: .95rem;
	color: var(--tyn-body);
}

.tyn-search__clear {
	font-family: var(--tyn-display);
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--tyn-accent);
}

/* ============================================================= markets === */

/*
 * The market grid.
 *
 * Each card is an area's own boundary, drawn from OpenStreetMap geometry —
 * see TYN_Areas. The shape is the picture, so it gets the space a photograph
 * would and the caption sits under it rather than over it.
 *
 * Cards whose outline has not been cached yet carry .tyn-market--noshape and
 * simply centre their caption. That has to look deliberate, because on a cold
 * cache it is what every card looks like.
 */

.tyn-markets__grid {
	list-style: none;
	margin: 2.5rem 0 0;
	padding: 0;
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 1040px) { .tyn-markets__grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 780px)  { .tyn-markets__grid { grid-template-columns: repeat(2, 1fr); gap: .75rem; } }

.tyn-market__link {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: .3rem;
	height: 100%;
	padding: 1.5rem 1rem 1.25rem;
	background: var(--tyn-white);
	border: 1px solid var(--tyn-line);
	border-radius: 14px;
	text-align: center;
	text-decoration: none;
	transition: border-color .22s var(--tyn-ease), transform .22s var(--tyn-ease), box-shadow .22s var(--tyn-ease);
}

.tyn-market__link:hover {
	border-color: var(--tyn-accent);
	transform: translateY(-3px);
	box-shadow: 0 16px 34px -20px rgba(16, 10, 12, .4);
}

.tyn-market__shape {
	display: block;
	width: 96px; height: 96px;
	margin-bottom: .55rem;
}

/* The silhouette itself. Filled rather than stroked: at this size a 1px
   outline of a municipal boundary is a grey haze, and a solid shape reads as
   a place. */
.tyn-market__shape .tyn-shape { width: 100%; height: 100%; display: block; }
.tyn-market__shape .tyn-shape path {
	fill: var(--tyn-accent);
	opacity: .16;
	transition: opacity .22s var(--tyn-ease);
}
.tyn-market__link:hover .tyn-shape path { opacity: .34; }

.tyn-market__name {
	font-family: var(--tyn-display);
	font-size: 1.2rem;
	line-height: 1.15;
	color: var(--tyn-ink);
}

.tyn-market__note {
	color: var(--tyn-muted);
	font-size: .82rem;
	line-height: 1.45;
}

.tyn-market__cta {
	margin-top: .55rem;
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tyn-accent);
	opacity: 0;
	transform: translateY(3px);
	transition: opacity .22s var(--tyn-ease), transform .22s var(--tyn-ease);
}
.tyn-market__link:hover .tyn-market__cta,
.tyn-market__link:focus-visible .tyn-market__cta { opacity: 1; transform: none; }

/* Keep the caption vertically centred when there is no shape to sit under. */
.tyn-market--noshape .tyn-market__link { justify-content: center; padding-block: 2.25rem; }

/* ================================================================ pair === */

.tyn-pair__photo {
	margin: 2.5rem auto 0;
	max-width: 900px;
	border-radius: 16px;
	overflow: hidden;
	box-shadow: 0 26px 60px -34px rgba(16, 10, 12, .55);
}
.tyn-pair__photo img { display: block; width: 100%; height: auto; }

.tyn-pair__grid {
	margin-top: 2.25rem;
	display: grid;
	gap: 2rem;
	grid-template-columns: repeat(2, 1fr);
	max-width: 900px;
	margin-inline: auto;
}
@media (max-width: 780px) { .tyn-pair__grid { grid-template-columns: 1fr; gap: 1.75rem; } }

.tyn-pair__name { margin: 0 0 .15rem; font-family: var(--tyn-display); font-size: 1.5rem; color: var(--tyn-ink); }
.tyn-pair__role {
	margin: 0 0 .7rem;
	font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
	color: var(--tyn-accent);
}
.tyn-pair__bio  { margin: 0 0 .9rem; color: var(--tyn-body); font-size: .95rem; }
.tyn-pair__more {
	font-size: .82rem; font-weight: 600; color: var(--tyn-accent); text-decoration: none;
}
.tyn-pair__more:hover { text-decoration: underline; }

/* ================================================== mobile header controls ==
 *
 * The call button and the menu button sit next to each other and were built at
 * different times, which showed: 44px tall with a 6px radius and a flat red
 * fill against roughly 38px with a 4px radius and a hairline border. Two
 * controls a thumb-width apart have to look like one set of controls, or the
 * masthead reads as unfinished before a word of the site is read.
 *
 * So the burger is now the same 44px square with the same radius, and it takes
 * the hero omnibar's glass — blur plus a desaturating filter, which is what
 * keeps the surface neutral over whatever photograph is behind it rather than
 * picking up its colour. The call button stays solid: these should be the same
 * SIZE, not the same weight. Calling is the thing worth doing, and the button
 * that does it should be the one with the fill.
 */

.tyn-burger {
	width: 44px;
	height: 44px;
	padding: 0;
	display: none;
	place-items: center;
	border-radius: 6px;
	border: 1px solid rgba(255, 255, 255, .12);
	background: rgba(255, 255, 255, .55);
	-webkit-backdrop-filter: blur(18px) saturate(.6);
	backdrop-filter: blur(18px) saturate(.6);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7);
	transition: background .25s var(--tyn-ease), border-color .25s var(--tyn-ease),
	            transform .18s var(--tyn-ease);
}

@media (max-width: 1040px) { .tyn-burger { display: grid; } }

/* A press that answers. Nothing else in the masthead moves on tap. */
.tyn-burger:active { transform: scale(.94); }

.tyn-burger__box { width: 18px; }
.tyn-burger__box i { height: 1.5px; border-radius: 1px; }
.tyn-burger__box i + i { margin-top: 4.5px; }

/*
 * Over the home hero the header is transparent and the backdrop is a dark
 * photograph, so a white glass would be a bright chip on a dark scene and the
 * white bars inside it would disappear. Same material, inverted: a dark tint
 * with a white hairline, which reads as frosted rather than as a hole.
 */
.tyn-home .tyn-header:not(.is-solid) .tyn-burger {
	background: rgba(255, 255, 255, .14);
	border-color: rgba(255, 255, 255, .34);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);
}

/* Browsers without backdrop-filter get a solid chip instead of a see-through
   one — legible either way, which is the only requirement. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.tyn-burger { background: rgba(255, 255, 255, .92); }
	.tyn-home .tyn-header:not(.is-solid) .tyn-burger { background: rgba(255, 255, 255, .42); }
}

/* The X state fills in, so the control that closes the drawer is unmistakably
   the live one while the drawer is open. */
.tyn-burger[aria-expanded="true"],
.tyn-home .tyn-header:not(.is-solid) .tyn-burger[aria-expanded="true"] {
	background: var(--tyn-accent-mid);
	border-color: var(--tyn-accent-mid);
	box-shadow: none;
}
.tyn-burger[aria-expanded="true"] .tyn-burger__box i,
.tyn-home .tyn-header:not(.is-solid) .tyn-burger[aria-expanded="true"] .tyn-burger__box i {
	background: var(--tyn-white);
}

/* ============================================================ drawer entry ==
 *
 * The drawer was a flat white sheet cross-fading in — correct, and inert. On a
 * phone this panel IS the navigation, so it is worth the few frames it takes to
 * feel like something opened rather than something appeared.
 *
 * Three things happen at once. The panel is the same glass as the omnibar and
 * the menu button, so the three surfaces are visibly one material. It settles
 * down and up to its resting size instead of arriving there. And the links
 * arrive in sequence, which is what makes a list read as a list rather than as
 * a block of text that faded in.
 *
 * The stagger is nth-child rather than an inline --i, so this is a stylesheet
 * change with no markup behind it and nothing to keep in sync. Eight items is
 * more than these menus carry; past that the last ones share the final delay,
 * which is the right failure — a ninth link is late, never missing.
 */

.tyn-drawer {
	background: rgba(255, 255, 255, .82);
	-webkit-backdrop-filter: blur(30px) saturate(1.1);
	backdrop-filter: blur(30px) saturate(1.1);
	transform: translateY(-10px) scale(.985);
	transform-origin: 50% 0;
	transition:
		opacity .3s var(--tyn-ease),
		visibility .3s var(--tyn-ease),
		transform .42s cubic-bezier(.16, .84, .32, 1);
}

.tyn-drawer.is-open { transform: none; }

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.tyn-drawer { background: rgba(255, 255, 255, .97); }
}

/* Resting state of every row: down and out. */
.tyn-drawer__nav .tyn-nav__item,
.tyn-drawer__foot > * {
	opacity: 0;
	transform: translateY(14px);
	transition:
		opacity .34s var(--tyn-ease),
		transform .44s cubic-bezier(.16, .84, .32, 1);
}

.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item,
.tyn-drawer.is-open .tyn-drawer__foot > * {
	opacity: 1;
	transform: none;
}

/* 55ms apart. Fast enough that the whole menu is settled in about a third of a
   second, slow enough to read as a sequence rather than a flicker. */
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(1) { transition-delay: .06s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(2) { transition-delay: .115s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(3) { transition-delay: .17s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(4) { transition-delay: .225s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(5) { transition-delay: .28s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(6) { transition-delay: .335s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(7) { transition-delay: .39s; }
.tyn-drawer.is-open .tyn-drawer__nav .tyn-nav__item:nth-child(n+8) { transition-delay: .445s; }

.tyn-drawer.is-open .tyn-drawer__foot > *:nth-child(1) { transition-delay: .40s; }
.tyn-drawer.is-open .tyn-drawer__foot > *:nth-child(2) { transition-delay: .455s; }

/* Closing runs immediately and together. A staggered exit makes a menu feel
   slow to dismiss, which is the one thing a menu must never feel. */
.tyn-drawer:not(.is-open) .tyn-drawer__nav .tyn-nav__item,
.tyn-drawer:not(.is-open) .tyn-drawer__foot > * { transition-delay: 0s; }

/*
 * Honour the OS setting. Someone who has asked for less motion still needs the
 * menu, so the panel and the rows still change state — they just do it without
 * travelling or waiting their turn.
 */
@media (prefers-reduced-motion: reduce) {
	.tyn-drawer,
	.tyn-drawer.is-open,
	.tyn-drawer__nav .tyn-nav__item,
	.tyn-drawer__foot > * {
		transform: none;
		transition-duration: .01ms;
		transition-delay: 0s !important;
	}
	.tyn-burger { transition-duration: .01ms; }
}

/*
 * While the drawer is open the header still floats above it, and over the home
 * hero that header is in its light state -- so the white lockup was sitting on
 * the drawer's near-white glass and all but disappeared. The dark lockup is
 * always rendered underneath it, so fading the light one out is the whole fix.
 *
 * Driven by a body class rather than :has() so it works the same everywhere,
 * and kept separate from tyn-locked, which the enquiry modal also sets --
 * that one opens over a dark scrim where the light logo is correct.
 */
body.tyn-nav-open .tyn-logo__img--light,
body.tyn-nav-open.tyn-home .tyn-header:not(.is-solid) .tyn-logo__img--light { opacity: 0; }

/* ============================================== the portrait, sized down ==
 *
 * There were two copies of the same photograph of Jim and Lisa on the home
 * page — this one and another inside the pair section — and the second was the
 * largest object on the screen. The duplicate is gone; this one is also capped,
 * because at full column width a single portrait outweighed the eight market
 * outlines and their two bios put together.
 */
.tyn-section--split .tyn-split__media { max-width: 27rem; margin-inline: auto; }

@media (max-width: 900px) {
	.tyn-section--split .tyn-split__media { max-width: 22rem; }
}

/* ============================================ dark theme, structural fixes ==
 *
 * Inverting the tokens gets most of the way there, but a stylesheet written for
 * a light site has a handful of places where the colour was hard-coded or where
 * a light assumption is baked into a shadow or a border. These are those.
 */
html, body { background: var(--tyn-deep); color: var(--tyn-body); }

/* Anything that painted itself white now has to mean the dark ground. */
.tyn-header__bar,
.tyn-drawer,
.tyn-card,
.tyn-pair__person,
.tyn-market__link,
.tyn-quote,
.tyn-step { background: var(--tyn-tint); }

/* Shadows do nothing on black — a border is what separates surfaces here. */
.tyn-card,
.tyn-quote,
.tyn-market__link,
.tyn-pair__person {
	border: 1px solid var(--tyn-line);
	box-shadow: none;
}

.tyn-card:hover,
.tyn-market__link:hover {
	border-color: var(--tyn-gold-dk);
	box-shadow: 0 18px 40px -24px rgba(0, 0, 0, .9);
}

h1, h2, h3, h4, .tyn-card__title, .tyn-pair__name { color: var(--tyn-ink); }

a { color: var(--tyn-gold-lt); }
a:hover { color: var(--tyn-gold); }

/* Gold earns its four places and no more. */
.tyn-eyebrow { color: var(--tyn-gold); }
.tyn-rule { background: linear-gradient(90deg, var(--tyn-gold) 0%, var(--tyn-gold-dk) 100%); }
.tyn-nav__list > li > a::after { background: var(--tyn-gold); }

/* The primary button is the one solid gold object on the page. Dark type on
   gold, because gold behind white type is unreadable at button size. */
.tyn-btn--accent {
	background: var(--tyn-gold);
	border-color: var(--tyn-gold);
	color: #0B0B0C;
	background-image: none;
}

.tyn-btn--accent:hover {
	background: var(--tyn-gold-lt);
	border-color: var(--tyn-gold-lt);
	color: #0B0B0C;
}

/* The outline button reads as a hairline on black rather than a grey box. */
.tyn-btn:not(.tyn-btn--accent) {
	background: transparent;
	border: 1px solid var(--tyn-line);
	color: var(--tyn-ink);
}

.tyn-btn:not(.tyn-btn--accent):hover {
	border-color: var(--tyn-gold);
	color: var(--tyn-gold);
	background: transparent;
}

/* Form fields were white boxes on a white page; on black they need to be a
   shade lighter than the ground or they disappear into it. */
.tyn-field input,
.tyn-field select,
.tyn-field textarea {
	background: var(--tyn-tint-2);
	border-color: var(--tyn-line);
	color: var(--tyn-ink);
}

.tyn-field input::placeholder,
.tyn-field textarea::placeholder { color: var(--tyn-faint); }

/* The tinted band has to step UP on a dark site, not down. */
/* The tinted band is black, not charcoal. A grey section between two black
   ones is the thing that made the page look like two palettes; a hairline is
   enough to separate them. */
.tyn-section--tint {
	background: var(--tyn-deep);
}

/* The brokerage mark sits under their own lockup, deliberately smaller — it is
   a licence condition and a courtesy, not a second brand competing with the
   first. */
.tyn-foot__brokerage { margin: 1.5rem 0 0; }
.tyn-foot__brokerage-img { display: block; width: 150px; max-width: 100%; height: auto; opacity: .72; }
.tyn-foot__brokerage-img:hover { opacity: .9; }

/* The footer was the dark thing on a light page. Now the page is dark, so it
   needs a hairline to read as a separate region at all. */
.tyn-foot { border-top: 1px solid var(--tyn-line); background: var(--tyn-deep-dk); }

/* The brokerage mark is an SVG of white paths — it needs no treatment here,
   only room. */
.tyn-foot__firmmark { max-width: 190px; margin-top: 1.5rem; opacity: .9; }

/* ======================================================== the hero video ==
 *
 * The poster and the video occupy the same box. The poster paints immediately;
 * the video sits on top at zero opacity and fades in only once it can play,
 * so there is never a black rectangle waiting for bytes.
 *
 * If the video never loads — narrow screen, reduced motion, Save-Data, or
 * autoplay refused — nothing happens and the poster is simply the hero. That
 * is not a fallback so much as the default with an enhancement on top.
 */
.tyn-hero__poster,
.tyn-hero__video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 58%;
}

.tyn-hero__video {
	opacity: 0;
	transition: opacity .9s var(--tyn-ease);
	pointer-events: none;
}

.tyn-hero__video.is-ready { opacity: 1; }

/* The mark that was burned into the top-right of the footage is cropped out of
   the encode itself now, not nudged out of frame — nudging only moved the
   collision around and cost composition. Nothing left to dodge. */

/* ======================================== dark theme, second pass ==
 *
 * The first pass inverted the tokens. This is what the tokens could not reach:
 * places where a colour was written as a literal, and two components that were
 * designed around a white card and needed rethinking rather than recolouring.
 */

/* The buyer/seller cards were white panels — the token swap fixed the ground
   but their type was still set for a light card, so it was white on white. */
.tyn-path {
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	box-shadow: none;
}

.tyn-path:hover {
	transform: translateY(-4px);
	border-color: var(--tyn-gold-dk);
	box-shadow: 0 20px 44px -26px rgba(0, 0, 0, .9);
}

.tyn-path__title { color: var(--tyn-ink); }
.tyn-path__text  { color: var(--tyn-body); }

/*
 * The team cards. They were a hairline box round a name and a paragraph, which
 * on black reads as an empty frame rather than as a person — the user's words
 * were "only outline their names". They get a filled surface, a gold rule that
 * ties them to the rest of the site, and the name given the room it deserves.
 */
.tyn-pair__person {
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-top: 2px solid var(--tyn-gold);
	border-radius: 2px;
	padding: clamp(1.6rem, 2.4vw, 2.1rem);
}

.tyn-pair__person:hover { border-color: var(--tyn-line); border-top-color: var(--tyn-gold-lt); }

.tyn-pair__name {
	color: var(--tyn-ink);
	font-size: clamp(1.5rem, 1.2rem + 1vw, 1.95rem);
	margin-bottom: .35rem;
}

.tyn-pair__role {
	color: var(--tyn-gold);
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .16em;
	text-transform: uppercase;
}

.tyn-pair__bio  { color: var(--tyn-body); }
.tyn-pair__more { color: var(--tyn-gold); font-weight: 600; }
.tyn-pair__more:hover { color: var(--tyn-gold-lt); }

/* Anything still sitting on a pale surface from the light build. */
.tyn-facts li,
.tyn-contact__block,
.tyn-search,
.tyn-quote { background: var(--tyn-tint); border: 1px solid var(--tyn-line); }

.tyn-quote__text { color: var(--tyn-body); }
.tyn-quote__who  { color: var(--tyn-ink); }

/* ================================================ the floating call button ==
 *
 * Bottom-right, on both breakpoints. Ours rather than Follow Up Boss's: no
 * third-party script, his black and gold rather than their blue, and it does
 * not leave with them if he changes CRM.
 *
 * The two sizes are doing different jobs. On a phone the thumb is already down
 * there and the number is the point, so it is a pill with the number showing.
 * On desktop a phone number permanently floating over a luxury site reads as a
 * support widget, so it collapses to a gold disc and expands on hover.
 */
.tyn-callbar {
	position: fixed;
	right: clamp(1rem, 2.2vw, 1.75rem);
	bottom: clamp(1rem, 2.2vw, 1.75rem);
	z-index: 80;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: .6rem;
	padding-bottom: env(safe-area-inset-bottom, 0px);
}

.tyn-callbar a,
.tyn-callbar button {
	display: flex;
	align-items: center;
	gap: .6rem;
	margin: 0;
	padding: 0;
	border: 0;
	cursor: pointer;
	text-decoration: none;
	font-family: var(--tyn-body-font);
	border-radius: 999px;
	overflow: hidden;
	box-shadow: 0 14px 34px -12px rgba(0, 0, 0, .8);
	transition: background .25s var(--tyn-ease), transform .18s var(--tyn-ease);
}

.tyn-callbar__ico {
	display: grid;
	place-items: center;
	width: 56px;
	height: 56px;
	flex: none;
}

.tyn-callbar__ico .tyn-icon { width: 20px; height: 20px; }

.tyn-callbar__txt {
	display: flex;
	flex-direction: column;
	justify-content: center;
	line-height: 1.15;
	padding-right: 1.15rem;
	white-space: nowrap;
}

.tyn-callbar__txt strong { font-size: .8rem; font-weight: 700; letter-spacing: .05em; }
.tyn-callbar__txt em {
	font-style: normal;
	font-size: .74rem;
	opacity: .8;
	font-variant-numeric: tabular-nums;
}

.tyn-callbar__call { background: var(--tyn-gold); color: #0B0B0C; }
.tyn-callbar__call .tyn-icon { color: #0B0B0C; }
.tyn-callbar__call:hover { background: var(--tyn-gold-lt); }

.tyn-callbar__msg {
	background: var(--tyn-tint-2);
	color: var(--tyn-ink);
	border: 1px solid var(--tyn-line);
}
.tyn-callbar__msg .tyn-icon { color: var(--tyn-gold); }
.tyn-callbar__msg:hover { background: var(--tyn-deep-lt); border-color: var(--tyn-gold-dk); }

.tyn-callbar a:active,
.tyn-callbar button:active { transform: scale(.96); }

/*
 * Desktop: collapsed to a disc, label revealed on hover or keyboard focus.
 * grid-template-columns 0fr -> 1fr animates a width the browser can actually
 * interpolate, which max-width hacks only approximate.
 */
@media (min-width: 781px) {

	.tyn-callbar__txt {
		display: grid;
		grid-template-columns: 0fr;
		padding-right: 0;
		transition: grid-template-columns .28s var(--tyn-ease), padding-right .28s var(--tyn-ease);
	}

	.tyn-callbar__txt > * { overflow: hidden; min-width: 0; }

	.tyn-callbar a:hover .tyn-callbar__txt,
	.tyn-callbar a:focus-visible .tyn-callbar__txt,
	.tyn-callbar button:hover .tyn-callbar__txt,
	.tyn-callbar button:focus-visible .tyn-callbar__txt {
		grid-template-columns: 1fr;
		padding-right: 1.15rem;
	}
}

/* Phone: the number is worth the width, so it is always shown. */
@media (max-width: 780px) {
	.tyn-callbar__ico { width: 52px; height: 52px; }
	.tyn-callbar__msg .tyn-callbar__txt { display: none; }
	.tyn-callbar__msg .tyn-callbar__ico { width: 52px; }
}

/* It must not sit on top of the enquiry form while someone is filling it in. */
body.tyn-locked .tyn-callbar { display: none; }

@media (prefers-reduced-motion: reduce) {
	.tyn-callbar a, .tyn-callbar button, .tyn-callbar__txt { transition-duration: .01ms; }
}

/* ==================================================== community pages ==
 *
 * The banner puts the town's own outline behind the title rather than a stock
 * photograph of somewhere that might not be here. It is the same OSM boundary
 * the markets grid draws, at size, in gold at low opacity — the one piece of
 * artwork on the page that is factually about this specific place.
 */
.tyn-cbanner {
	position: relative;
	overflow: hidden;
	padding-block: clamp(4.5rem, 9vw, 7.5rem);
	background: var(--tyn-deep);
	border-bottom: 1px solid var(--tyn-line);
}

.tyn-cbanner__in { position: relative; z-index: 2; }
.tyn-cbanner__text { max-width: 46rem; }

.tyn-cbanner__title {
	font-size: clamp(2.1rem, 1.4rem + 2.8vw, 3.6rem);
	line-height: 1.06;
	color: var(--tyn-ink);
}

.tyn-cbanner__shape {
	position: absolute;
	right: -4%;
	top: 50%;
	transform: translateY(-50%);
	width: clamp(18rem, 34vw, 34rem);
	z-index: 1;
	pointer-events: none;
}

.tyn-cbanner__shape .tyn-shape { width: 100%; height: auto; display: block; }
.tyn-cbanner__shape .tyn-shape path { fill: var(--tyn-gold); opacity: .10; }

@media (max-width: 860px) {
	.tyn-cbanner__shape { right: -22%; width: 26rem; }
	.tyn-cbanner__shape .tyn-shape path { opacity: .07; }
}

/* Body and the facts panel. */
.tyn-csplit {
	display: grid;
	grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

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

.tyn-csplit__body p { margin-bottom: 1.15rem; }
.tyn-csplit__body .tyn-btn { margin-top: 1rem; }

.tyn-cfacts {
	padding: clamp(1.5rem, 2.6vw, 2rem);
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	border-top: 2px solid var(--tyn-gold);
}

.tyn-cfacts__h {
	font-family: var(--tyn-body-font);
	font-size: .72rem;
	font-weight: 600;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--tyn-gold);
	margin: 0 0 1.1rem;
}

.tyn-cfacts dl { margin: 0; }

.tyn-cfacts__row {
	padding: .85rem 0;
	border-bottom: 1px solid var(--tyn-line);
}
.tyn-cfacts__row:last-child { border-bottom: 0; padding-bottom: 0; }

.tyn-cfacts dt {
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--tyn-muted);
	margin-bottom: .3rem;
}

.tyn-cfacts dd { margin: 0; color: var(--tyn-ink); font-size: .95rem; line-height: 1.45; }

/* Nearby: three across, not the eight-up grid the home page uses. */
.tyn-markets__grid--near { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 860px) { .tyn-markets__grid--near { grid-template-columns: 1fr; } }

/* ========================================================= video wall ==
 *
 * Facades, not embeds. Each card is a thumbnail and a play button until it is
 * clicked; the iframe replaces the button in place, which is why the aspect
 * ratio lives on the card rather than on either child.
 */
.tyn-videos__grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1rem, 2vw, 1.6rem);
}

@media (max-width: 1000px) { .tyn-videos__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .tyn-videos__grid { grid-template-columns: 1fr; } }

.tyn-video {
	background: var(--tyn-tint);
	border: 1px solid var(--tyn-line);
	overflow: hidden;
}

.tyn-video:hover { border-color: var(--tyn-gold-dk); }

.tyn-video__btn,
.tyn-video__frame {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	border: 0;
	margin: 0;
	padding: 0;
	background: #000;
}

.tyn-video__btn { position: relative; cursor: pointer; overflow: hidden; }

.tyn-video__thumb {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	/* hqdefault is 4:3 with black bars baked in; a small scale crops them
	   without stretching the picture. */
	transform: scale(1.34);
	transition: opacity .25s var(--tyn-ease);
}

.tyn-video__btn:hover .tyn-video__thumb { opacity: .82; }

.tyn-video__play {
	position: absolute;
	left: 50%; top: 50%;
	transform: translate(-50%, -50%);
	display: grid;
	place-items: center;
	width: 60px; height: 60px;
	border-radius: 50%;
	background: var(--tyn-gold);
	color: #0B0B0C;
	box-shadow: 0 10px 28px -10px rgba(0, 0, 0, .9);
	transition: transform .2s var(--tyn-ease), background .2s var(--tyn-ease);
}

.tyn-video__btn:hover .tyn-video__play { transform: translate(-50%, -50%) scale(1.08); background: var(--tyn-gold-lt); }
.tyn-video__btn:focus-visible .tyn-video__play { outline: 2px solid var(--tyn-gold-lt); outline-offset: 3px; }
.tyn-video__play svg { width: 26px; height: 26px; margin-left: 3px; }

.tyn-video__meta { padding: .95rem 1.1rem 1.15rem; }

.tyn-video__title {
	display: block;
	font-family: var(--tyn-display);
	font-size: 1.12rem;
	color: var(--tyn-ink);
	line-height: 1.25;
}

.tyn-video__place {
	display: block;
	margin-top: .3rem;
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--tyn-gold);
}

.tyn-videos__more { margin: 2.25rem 0 0; text-align: center; }

/* ====================================================== the review ask ==
 *
 * Centred, quiet, and only on the video page — asking a stranger for a review
 * on the home page is the wrong request to the wrong person.
 */
.tyn-review { background: var(--tyn-tint); border-top: 1px solid var(--tyn-line); }
.tyn-review__in { text-align: center; }
.tyn-review__in .tyn-rule { margin-inline: auto; }
.tyn-review__title { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.3rem); color: var(--tyn-ink); }
.tyn-review__cta { margin-top: 1.75rem; }
