/* ==========================================================================
   AVENIR — sanctioned deviations from the prototype

   The fourth and last stylesheet in the chain (avenir-fonts → avenir-style → avenir-wp →
   avenir-deviations). It exists to hold the small number of rules whose purpose is to beat
   assets/css/styles.css, which assets/css/wp-adaptations.css may never do: that file's
   binding rule is "no selector may out-specify styles.css", and a deviation is the exact
   opposite of an adaptation. Two files, two invariants, each checkable on its own terms
   (TECH-019).

   ADMISSION RULE (binding, TECH-019, rule 4 as amended by CN-04). Every rule in this file:
     1. traces to a numbered Change note *and* a TECH-xxx;
     2. comments the Change note, the REQ/AC served, and the styles.css selector and line it
        overrides;
     3. out-specifies styles.css only for the declarations that Change note names;
     4. never changes a resting visual state pinned by an acceptance criterion, unless a
        later Change note explicitly re-pins that state — in which case the rule's comment
        names the earlier AC it supersedes and the Change note that authorises it;
     5. uses the lowest specificity that works. Never !important, never an ID.

   THE THREE CATEGORIES IN THIS FILE
     1. Point deviations (TECH-019). Rules whose purpose is to beat a named styles.css rule.
        Each one cites the Change note, the REQ/AC it serves and the styles.css line it
        overrides. The admission rule above binds them in full.
     2. The mobile layer (TECH-024), below the MOBILE LAYER banner. Its own invariant replaces
        the per-rule citation: every selector below that banner is inside a
        @media (max-width: …) block.
     3. Additive rules (TECH-043). Rules whose selector does not appear in styles.css at all,
        so there is nothing to out-specify and rule 3 of the admission rule cannot apply.
        Greppable admission test: the selector must return 0 from
        `grep -c '<selector>' assets/css/styles.css`. Such a rule must not out-specify
        anything — if it needs to, it is a category 1 deviation and belongs above.
        Rules 1, 2 (Change note/TECH and REQ/AC citation) and 5 (lowest specificity, never
        !important, never an ID) still bind.

   Nothing that is merely a WordPress adaptation belongs here; that is wp-adaptations.css.
   Nothing here may be moved into styles.css, which stays a verbatim prototype copy so the
   re-sync path is a file copy (TECH-003).
   ========================================================================== */

/* CN-04 / REQ-022 / AC-032, AC-033. Overrides styles.css:1429 (:root).
   The demo topbar is removed from the markup, so the height it reserved must go with it.
   Setting the token to 0 cascades to all nine consumers — .header top, .hero padding,
   .hero__content min-height, .nav inset, the .admin-bar offsets and .avenir-inner — each of
   which then computes its correct post-removal value with no further change.
   Supersedes AC-029 as to the header's vertical position only, per CN-04; both of its
   resting appearances are otherwise unchanged. */
:root {
	--topbar-h: 0px;
}

/* CN-08 / REQ-041, REQ-043 / AC-065, AC-066. Category 1 (TECH-037).
   Overrides styles.css:561  .footer__col a:hover { color: var(--green-900) }   (0,2,1)
   and       styles.css:131  .btn--gold:hover { box-shadow: 0 8px 20px rgba(224,178,58,.35) }.

   The footer CTA is marked up `btn btn--gold btn--sm` but styles.css:564 repaints it dark
   green, so on hover it was green-900 text on green-700 — 1.58:1 — wearing the gold button's
   glow. The rule that painted the label is styles.css:561, written for the footer's *text*
   links and matching this button only because the button is an <a> inside .footer__col; it is
   not one of the .btn rules anyone expects to find in this cascade. At (0,2,1) it beats
   .footer__col .btn (0,2,0), so this selector is (0,3,0) — deliberately, because anything
   weaker wins the box-shadow and loses the colour, leaving the defect in place.
   color: #fff on the existing hovered green-700 measures 7.68:1.
   --shadow-sm is what .btn--dark:hover (styles.css:134) already uses, so the button hovers
   like the dark button it is painted to look like (REQ-043's single deliberate state).
   Resting and focus are untouched: both already compute white on green-900 at 12.16:1 with
   the global gold focus ring (AC-067, AC-068). The translateY(-1px) lift is untouched too —
   every other solid button on the site lifts. Local to this button by design: closing the
   collision generally would raise .btn--gold site-wide, which AC-070 forbids. */
.footer__col .btn--gold:hover {
	color: #fff;
	box-shadow: var(--shadow-sm);
}

/* CN-08 / REQ-044 / AC-069, E-18. Category 1 (TECH-037), companion to the rule above.
   On a touch device the hover state is what a tap leaves behind, so here it collapses to the
   resting state — green-900, white, no shadow, no lift — and the tap leaves nothing stuck.
   Overrides styles.css:565 (.footer__col .btn:hover background) and styles.css:131
   (.btn--gold:hover transform + box-shadow) for pointers that cannot hover. */
@media (hover: none) {
	.footer__col .btn--gold:hover {
		background: var(--green-900);
		color: #fff;
		box-shadow: none;
		transform: none;
	}
}

/* CN-14 / REQ-086 / AC-107. Category 1 (TECH-019), raised from WP-05's ISSUE-WP05-01.
   Completes styles.css:1134  @media (prefers-reduced-motion: reduce) { .chip, .pill-shape
   { animation: none } }  — `.bubble` was never in that selector list, so it overrides the
   `animation: chipFloat …` shorthands at styles.css:1102 (.bubble--gold) and :1104
   (.bubble--green) for a visitor who has asked for no motion. Measured on the shipped build,
   under the preference: both hero bubbles compute animation-name: chipFloat with
   animation-play-state: running, at every width from 900px up.

   THE ONLY RULE IN THIS FILE FROM THE HERO WORK THAT MATCHES AT 1280px, and deliberately so:
   the user was asked (OQ-14) and chose the site-wide fix. REQ-034's freeze reads as "unchanged
   for a visitor who has not asked for animation to stop"; this visitor has. Because it is
   category 1, above the MOBILE LAYER banner, TECH-024's invariant — every selector BELOW the
   banner is inside a max-width query — is untouched; css-invariant.mjs still reports equal
   counts.

   WIDENED to every decorative bubble on the page by PM ruling on WP-05's ISSUE-WP05-05, which
   found the identical defect two sections down: styles.css:1249-1250 give .bubble--brandgold
   and .bubble--brandgreen — the "how it works" scene — the same `animation: chipFloat …`, and
   they are not in styles.css:1134's list either. Measured with the hero-only version of this
   rule in place: hero bubbles static, .value__scene's two still running at 375, 768, 1280 and
   1440. REQ-086 and AC-107 are widened from "the hero scene" to any decorative bubble.

   ONE rule at `.bubble`, not two scoped ones. The page has exactly four elements with this
   class (section-hero.php:90-91, section-value.php:81-82) and every one of them is decoration
   inside an aria-hidden scene, so there is nothing to exclude; (0,1,0) is the lowest
   specificity that works — it ties with .bubble--gold / --brandgold and wins on order, this
   file being last in the chain — and a bubble added later is covered without a third edit.
   Verified by measurement, not by cascade arithmetic. */
@media (prefers-reduced-motion: reduce) {
	.bubble {
		animation: none;
	}
}

/* How it works, compact steps (2026-09-29). Category 1 — REQ: user request to keep the
   four-step list (patterns/section-value.php) no taller than the scene beside it; the
   prototype sized these cards for three steps.
   Overrides styles.css:344  .value__steps { gap: 1rem; margin-top: 2rem }
             styles.css:345  .value__steps li { grid-template-columns: 56px 1fr; gap: 1.25rem;
                                                align-items: start; padding: 1.25rem }
             styles.css:347  .value__num { width: 56px; height: 56px }
   Equal specificity, wins on source order. */
.value__steps {
	gap: .75rem;
	margin-top: 1.5rem;
}

.value__steps li {
	grid-template-columns: 46px 1fr;
	gap: 1rem;
	align-items: center;
	padding: .9rem 1.1rem;
}

.value__num {
	width: 46px;
	height: 46px;
	border-radius: 12px;
	font-size: 1rem;
}

/* ==========================================================================
   ===== ADDITIVE RULES — TECH-043 =====

   Category 3 of this file: rules whose selector does not appear in styles.css at all. They
   out-specify nothing, because there is nothing to out-specify — which is why they carry no
   "overrides styles.css:NNN" citation and why they cannot damage a prototype rule.

   ADMISSION TEST (greppable, TECH-043): `grep -c '::selection' assets/css/styles.css` → 0.
   Everything here still traces to a REQ/AC and a TECH-xxx, and still uses the lowest
   specificity that works — never !important, never an ID.

   If this category ever grows beyond a handful of rules, the file should be renamed
   (after-prototype.css) rather than split — a rename plus a one-line change in inc/assets.php.
   ========================================================================== */

/* REQ-063, REQ-064, REQ-067 / AC-088, AC-089 / TECH-044. Category 3 — styles.css declares no
   ::selection rule, so this adds the brand selection colour rather than overriding anything.
   gold-500 on green-950 measures 7.76:1. One pair serves every section: ::selection replaces
   *both* the background and the text colour of the selected run, so the ratio is a property
   of the pair alone and does not vary with what is behind it — which is why there are no
   per-section variants and no .hl exception (A-23's premise does not hold; TECH-044).
   No @media (forced-colors) block: the forced palette already overrides author selection
   colours (E-35, measured). Reaches the editor canvas for free — functions.php already passes
   this file to add_editor_style().
   The two spellings are separate rule blocks on purpose (REQ-067, AC-091): an unrecognised
   pseudo-element invalidates the whole selector list, so combining them would drop both. */
::selection {
	background: var(--gold-500);
	color: var(--green-950);
}

::-moz-selection {
	background: var(--gold-500);
	color: var(--green-950);
}

/* Header navigation (2026-09-29) / TECH-043. Category 3 — `.nav__badge` appears nowhere in
   styles.css. The "Hiring" superscript after the Careers label in patterns/header.php.
   #E8703F is the hero scene's orange family (styles.css:1199). Raised with position/top
   rather than vertical-align: below 900px `.nav__list a` is a flex container, where
   vertical-align has no effect. The pill keeps its own colours in every header state. */
.nav__badge {
	position: relative;
	top: -.7em;
	display: inline-block;
	margin-left: .2rem;
	padding: .1em .5em;
	border-radius: 999px;
	background: #E8703F;
	color: var(--white);
	font-size: .625rem;
	font-weight: 700;
	line-height: 1.3;
}

/* Tools strip (2026-09-29) / TECH-043. Category 3 — no `.tools` selector exists in
   styles.css; the section replaces the prototype's .features strip (patterns/section-features.php).
   A white full-bleed band: uppercase label left, tool names scrolling right. The track holds
   the list twice and moves by exactly one copy (-50%), so the loop has no seam. Edge fades
   use a mask so they work on any background. */
.tools {
	background: var(--white);
	border-block: 1px solid var(--border);
	padding-block: 1.5rem;
}

.tools__inner {
	display: flex;
	align-items: center;
	gap: 2.5rem;
}

.tools__label {
	flex: none;
	margin: 0;
	font-size: .8125rem;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--charcoal-400);
}

.tools__marquee {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.tools__track {
	display: flex;
	width: max-content;
	animation: tools-marquee 40s linear infinite;
}

.tools__marquee:hover .tools__track {
	animation-play-state: paused;
}

.tools__list {
	display: flex;
	flex: none;
	gap: 3rem;
	margin: 0;
	padding: 0 3rem 0 0;
	list-style: none;
}

.tools__list li {
	font-size: 1.25rem;
	font-weight: 600;
	white-space: nowrap;
	color: var(--charcoal-400);
}

@keyframes tools-marquee {
	to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
	.tools__marquee {
		-webkit-mask-image: none;
		mask-image: none;
	}

	.tools__track {
		width: auto;
		animation: none;
	}

	.tools__list {
		flex-wrap: wrap;
		gap: .5rem 2rem;
		padding: 0;
	}

	.tools__list[aria-hidden] {
		display: none;
	}
}

/* FAQ section (2026-09-29) / TECH-043. Category 3 — no `.faq` selector exists in styles.css;
   the section is new (patterns/section-faq.php). White rounded cards on the page background,
   green-900 questions, charcoal-600 answers, a gold +/− drawn from two bars so no icon is
   needed. The vertical bar scales to 0 when the item is open, turning + into −. */
.faq__grid {
	display: grid;
	grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
	gap: clamp(2.5rem, 6vw, 6rem);
	align-items: start;
}

.faq__head {
	position: sticky;
	top: 7rem;
}

.faq__cta {
	margin-top: 2rem;
}

.faq__list {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.faq__item {
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	transition: box-shadow var(--dur);
}

.faq__item:hover,
.faq__item[open] {
	box-shadow: var(--shadow-sm);
}

.faq__q {
	position: relative;
	display: block;
	padding: 1.6rem 4rem 1.6rem 1.75rem;
	font-size: 1.125rem;
	font-weight: 700;
	line-height: 1.35;
	color: var(--green-900);
	cursor: pointer;
	list-style: none;
}

.faq__q::-webkit-details-marker {
	display: none;
}

.faq__q::before,
.faq__q::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 1.75rem;
	width: 14px;
	height: 3px;
	margin-top: -1.5px;
	border-radius: 2px;
	background: var(--gold-600);
	transition: transform var(--dur) var(--ease);
}

.faq__q::after {
	transform: rotate(90deg);
}

.faq__item[open] .faq__q::after {
	transform: rotate(90deg) scaleX(0);
}

.faq__q:focus-visible {
	outline: 2px solid var(--gold-500);
	outline-offset: -2px;
	border-radius: var(--radius-lg);
}

.faq__a {
	margin: -.5rem 0 0;
	padding: 0 1.75rem 1.6rem;
	max-width: 68ch;
	font-size: 1.0625rem;
	line-height: 1.7;
	color: var(--charcoal-600);
}

/* How it works durations (2026-09-29) / TECH-043. Category 3 — neither `.value__time` nor
   `.value__steps li > div` appears in styles.css. The duration pill sits on the title's line
   (flex order) rather than under the text, which saves a row per step. */
.value__steps li > div {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	column-gap: .6rem;
}

.value__steps li > div > p {
	flex-basis: 100%;
	order: 3;
}

.value__time {
	display: inline-block;
	margin-bottom: .25rem;
	padding: .15rem .6rem;
	border-radius: 999px;
	background: var(--green-100);
	color: var(--green-900);
	font-size: .75rem;
	font-weight: 700;
	line-height: 1.4;
}

/* Talk with our team (2026-09-29) / TECH-043. Category 3 — neither `.talk` nor `.chat`
   appears in styles.css; the section replaces the team arc (patterns/section-team.php).
   White, like the .team section it replaced (styles.css:925), which is also the about band's
   bottom-wave fill. padding-top mirrors .team's value, tuned to sit under that wave. */
.talk {
	background: var(--white);
	padding-top: clamp(1.5rem, 3vw, 3rem);
}

.talk__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: clamp(2.5rem, 6vw, 6rem);
	align-items: center;
}

.talk__options {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

.talk__option {
	display: flex;
	align-items: center;
	gap: 1.1rem;
	padding: 1.1rem 1.4rem 1.1rem 1.1rem;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
}

.talk__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 48px;
	height: 48px;
	border-radius: 12px;
	background: var(--gold-500);
	color: var(--green-900);
}

.talk__icon svg {
	width: 22px;
	height: 22px;
}

.talk__text {
	display: flex;
	flex: 1;
	flex-direction: column;
	min-width: 0;
	line-height: 1.4;
}

.talk__text strong {
	font-size: 1.0625rem;
	color: var(--green-900);
}

.talk__text span {
	font-size: .9375rem;
	color: var(--charcoal-600);
}

.talk__action {
	flex: none;
	font-weight: 700;
	color: var(--green-900);
	white-space: nowrap;
}

.talk__action span {
	display: inline-block;
	transition: transform var(--dur) var(--ease);
}

.talk__action:hover span {
	transform: translateX(3px);
}

.talk__media {
	position: relative;
	padding-top: 3rem;
}

.talk__note {
	position: absolute;
	top: -.5rem;
	right: 0;
	display: flex;
	align-items: flex-start;
	gap: .5rem;
	margin: 0;
	font-family: var(--font-hand);
	font-size: 1.6rem;
	line-height: 1;
	color: #E8703F;
	transform: rotate(-3deg);
}

.talk__note svg {
	width: 22px;
	height: 34px;
	margin-top: -.25rem;
}

.chat {
	overflow: hidden;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: 22px;
	box-shadow: var(--shadow-md);
}

.chat__head {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 1.1rem 1.5rem;
	background: var(--green-900);
	color: var(--white);
}

.chat__avatars {
	display: flex;
	flex: none;
}

.chat__avatars span {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	margin-left: -10px;
	border: 2px solid var(--white);
	border-radius: 50%;
	background: var(--gold-500);
	color: var(--green-950);
	font-weight: 700;
	font-size: .9375rem;
}

.chat__avatars span:first-child {
	margin-left: 0;
}

.chat__avatars span:nth-child(2) {
	background: var(--white);
	border-color: var(--gold-300);
}

.chat__avatars span:nth-child(3) {
	background: #E8703F;
	color: var(--white);
}

.chat__who {
	display: flex;
	flex-direction: column;
	line-height: 1.35;
}

.chat__who strong {
	font-size: 1.0625rem;
}

.chat__who span {
	display: flex;
	align-items: center;
	gap: .4rem;
	font-size: .8125rem;
	color: rgba(255, 255, 255, .8);
}

.chat__who span::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--green-500);
}

.chat__body {
	display: flex;
	flex-direction: column;
	padding: 1.4rem 1.5rem .5rem;
}

.chat__meta {
	margin: 0 0 .4rem;
	font-size: .75rem;
	color: var(--charcoal-400);
}

.chat__msg {
	max-width: 82%;
	margin: 0 0 1.1rem;
	padding: .8rem 1.1rem;
	border-radius: 16px;
	font-size: .9375rem;
	line-height: 1.55;
}

.chat__msg--you {
	align-self: flex-end;
	background: var(--green-900);
	color: var(--white);
}

.chat__msg--team {
	align-self: flex-start;
	background: var(--green-50);
	border: 1px solid var(--green-200);
	color: var(--charcoal);
}

.chat__composer {
	display: flex;
	align-items: center;
	gap: .75rem;
	padding: 0 1.5rem 1.5rem;
}

.chat__input {
	flex: 1;
	padding: .8rem 1.1rem;
	border: 1px solid var(--border-strong);
	border-radius: 12px;
	font-size: .9375rem;
	color: var(--charcoal-400);
}

.chat__send {
	flex: none;
	padding: .8rem 1.4rem;
	border-radius: 999px;
	background: var(--green-900);
	color: var(--white);
	font-weight: 700;
	transition: background var(--dur);
}

.chat__composer:hover .chat__send {
	background: var(--green-700);
}

/* Careers (2026-09-29) / TECH-043. Category 3 — neither `.careers` nor `.growth` appears in
   styles.css; they are the new parts of the applicants section (patterns/section-applicants.php).
   The section keeps its styles.css background and grid. The growth card leaves room at its
   top-right and bottom-right for the two tilted notes that hang off it. An explicit width
   is needed because an auto margin on a grid item otherwise shrinks it to its content; the
   3rem it subtracts is the right margin the notes hang into. */
.careers__psst {
	margin: 0 0 .35rem;
	font-family: var(--font-hand);
	font-size: 1.75rem;
	line-height: 1;
	color: #E8703F;
	transform: rotate(-4deg);
	transform-origin: left bottom;
}

.careers__tags {
	display: flex;
	flex-wrap: wrap;
	gap: .6rem;
	margin: 1.75rem 0 0;
	padding: 0;
	list-style: none;
}

.careers__tags li {
	padding: .55rem 1.1rem;
	border-radius: 999px;
	background: var(--white);
	color: var(--green-900);
	font-size: .9375rem;
	font-weight: 600;
}

.growth {
	position: relative;
	width: calc(100% - 3rem);
	max-width: 540px;
	margin: 2.5rem 3rem 2rem auto;
	padding: 2.25rem 2.5rem 1.75rem;
	background: var(--white);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-md);
}

.growth__label {
	margin: 0 0 .75rem;
	font-size: var(--text-xs);
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--green-500);
}

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

.growth__steps li {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: .9rem 0;
	border-bottom: 1px dashed var(--border-strong);
}

.growth__steps li:last-child {
	border-bottom: 0;
}

.growth__num {
	display: grid;
	flex: none;
	place-items: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--green-50);
	color: var(--green-900);
	font-weight: 700;
}

.growth__steps li:nth-child(3) .growth__num {
	background: var(--green-200);
}

.growth__steps li:last-child .growth__num {
	background: var(--green-900);
	color: var(--gold-500);
}

.growth__text {
	display: flex;
	flex-direction: column;
	line-height: 1.35;
}

.growth__text strong {
	font-size: 1.0625rem;
	color: var(--green-900);
}

.growth__text span {
	font-size: .875rem;
	color: var(--charcoal-600);
}

.growth__note {
	position: absolute;
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: .8rem 1.1rem;
	border-radius: var(--radius);
	box-shadow: var(--shadow-md);
	line-height: 1.35;
}

.growth__note strong {
	font-size: 1rem;
}

.growth__note span {
	font-size: .8125rem;
}

.growth__note--tracks {
	top: -2rem;
	right: -3rem;
	background: var(--white);
	color: var(--green-900);
	transform: rotate(4deg);
}

.growth__note--tracks span {
	color: var(--charcoal-600);
}

.growth__note--review {
	bottom: -1.5rem;
	right: -3rem;
	background: var(--gold-500);
	color: var(--green-950);
	transform: rotate(-3deg);
}

/* Contact page body (2026-09-29) / TECH-043. Category 3 — neither `.contact-intro` nor
   `.contact-form` appears in styles.css (patterns/page-contact.php). Details on the left, a
   white form card on the right. Fields are the prototype's `.field` (styles.css:283); the
   textarea rule is additive — styles.css styles `.field input` and `.field select` only. */
.contact-intro__grid {
	display: grid;
	grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
	gap: clamp(2.5rem, 6vw, 5.5rem);
	align-items: start;
}

.contact-intro__heading {
	margin: 0;
	font-size: 1.625rem;
	line-height: 1.2;
	color: var(--green-900);
}

.contact-intro__text {
	margin: .75rem 0 0;
	max-width: 42ch;
	color: var(--charcoal-600);
	line-height: 1.65;
}

.contact-intro__list {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

.contact-intro__list li {
	display: flex;
	align-items: flex-start;
	gap: 1rem;
}

.contact-intro__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 48px;
	height: 48px;
	border-radius: 12px;
	background: var(--gold-500);
	color: var(--green-900);
}

.contact-intro__icon svg {
	width: 22px;
	height: 22px;
}

.contact-intro__detail {
	display: flex;
	flex-direction: column;
	gap: .15rem;
	min-width: 0;
	color: var(--charcoal-600);
	line-height: 1.5;
	overflow-wrap: anywhere;
}

.contact-intro__detail strong {
	color: var(--green-900);
}

.contact-intro__detail a {
	font-weight: 600;
	color: var(--green-900);
}

.contact-intro__detail a:hover {
	color: var(--green-500);
}

.contact-form {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-md);
	scroll-margin-top: 120px;
}

.contact-form__row {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
}

.field textarea {
	width: 100%;
	padding: 0;
	border: 0;
	background: transparent;
	font: inherit;
	font-size: .9375rem;
	font-weight: 500;
	color: var(--charcoal);
	resize: vertical;
	outline: none;
}

.field textarea::placeholder {
	color: var(--charcoal-400);
}

.contact-form__notice {
	margin: 0;
	padding: .85rem 1rem;
	border-radius: var(--radius-sm);
	font-size: .9375rem;
	font-weight: 600;
}

.contact-form__notice.is-success {
	background: var(--green-100);
	color: var(--green-900);
}

.contact-form__notice.is-error {
	background: #FDECE6;
	color: #9A3412;
}

.contact-form__submit {
	align-self: flex-start;
	margin-top: .25rem;
}

/* Book a Consultation notice (2026-09-29) / TECH-043. Category 3 — `.cta__notice` appears
   nowhere in styles.css. The result line under the CTA form (patterns/section-cta.php), on the
   dark band, so light text on translucent tints. */
.cta__notice {
	max-width: 560px;
	margin: .9rem 0 0;
	padding: .75rem 1.1rem;
	border-radius: 14px;
	font-size: .9375rem;
	font-weight: 600;
}

.cta__notice.is-success {
	background: rgba(224, 178, 58, .16);
	color: var(--gold-300);
}

.cta__notice.is-error {
	background: rgba(242, 103, 58, .16);
	color: #FDBA9F;
}

/* Form toasts (2026-09-29) / TECH-043. Category 3 — `.avenir-toast` appears nowhere in
   styles.css. Created by the Avenir Site plugin's forms.js after a background submission.
   Light bottom-right card: white, soft shadow and a badge — green/gold for success, coral
   for errors; slides up in, auto-dismisses. Sits above the fixed header. */
.avenir-toasts {
	position: fixed;
	right: 1.5rem;
	bottom: 1.5rem;
	z-index: 10000;
	display: flex;
	flex-direction: column;
	gap: .75rem;
	width: min(420px, calc(100vw - 2rem));
	pointer-events: none;
}

.avenir-toast {
	display: flex;
	align-items: flex-start;
	gap: .85rem;
	padding: 1rem 1rem 1rem 1.1rem;
	border: 1px solid var(--border);
	border-radius: 16px;
	background: var(--white);
	box-shadow: var(--shadow-lg);
	color: var(--charcoal);
	opacity: 0;
	transform: translateY(16px);
	transition: opacity var(--dur), transform var(--dur) var(--ease);
	pointer-events: auto;
}

.avenir-toast.is-in {
	opacity: 1;
	transform: none;
}

.avenir-toast__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--green-900);
	color: var(--gold-300);
	font-weight: 800;
	font-size: .875rem;
}

.avenir-toast.is-success .avenir-toast__icon::before {
	content: "✓";
}

.avenir-toast.is-error .avenir-toast__icon {
	background: #FDECE6;
	color: #C2410C;
}

.avenir-toast.is-error .avenir-toast__icon::before {
	content: "!";
}

.avenir-toast__text {
	flex: 1;
	margin: .2rem 0 0;
	font-size: .9375rem;
	font-weight: 500;
	line-height: 1.5;
}

.avenir-toast__close {
	flex: none;
	width: 28px;
	height: 28px;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--charcoal-400);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.avenir-toast__close:hover {
	background: var(--bg);
	color: var(--charcoal);
}

form.is-sending [type="submit"] {
	opacity: .7;
	cursor: progress;
}

@media (prefers-reduced-motion: reduce) {
	.avenir-toast {
		transform: none;
		transition: opacity var(--dur);
	}
}

/* Footer social area (2026-10-06) / TECH-043. `.footer__social` appears nowhere in styles.css.
   The icons live in the bottom bar between the copyright and the legal links, with a short
   label. `.footer__social .social` (0,2,0) overrides styles.css:554's `.social { margin-top }`
   and :555's 38px circles, which were sized for the brand column; here the row is 34px to sit
   on the bottom bar's baseline. Deliberate override, lowest specificity that works. */
.footer__social {
	display: flex;
	align-items: center;
	gap: .75rem;
}

.footer__social-label {
	font-weight: 600;
	color: var(--green-900);
}

.footer__social .social {
	margin-top: 0;
	gap: .5rem;
}

/* Desktop only: below 900px the mobile layer's 44px touch target (TECH-032) must keep the
   last word, so the smaller circle is scoped to widths where a pointer is the norm. */
@media (min-width: 900px) {
	.footer__social .social a {
		width: 34px;
		height: 34px;
	}
}

/* Services catalog (2026-09-29, relaid 2026-10-06) / TECH-043. Category 3 — none of
   `.svc-line`, `.svc-row` or their elements appear in styles.css (patterns/services-catalog.php,
   the Services page body).

   Layout pass, 2026-10-06. The first build set each line as an intro column beside a grid of
   two or three cards. Measured at 1512px the three-across cards were ~200px wide and their
   descriptions wrapped to six or seven lines of 25–30 characters; the intro column ended in
   white space beside them. Now each line is a spread: a portrait photograph (5 of 12 columns)
   that carries the line's letter badge and stays in view while the list scrolls (sticky), and
   a text column (7 of 12) whose services are rows — number, title, description, link — on a
   single measure of 60–65 characters. Lines alternate the photo's side so the page has a
   rhythm instead of a repeated template. One bold element per line (the photo); everything
   else is quiet type on rules. Tokens all come from styles.css :root. */
.svc-line {
	padding-block: clamp(3.5rem, 2.5rem + 3vw, 5.5rem);
	scroll-margin-top: 80px;
}

.svc-line:nth-child(even) {
	background: var(--bg);
}

.svc-line__grid {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	gap: clamp(2.5rem, 6vw, 5.5rem);
	align-items: start;
}

.svc-line:nth-child(even) .svc-line__grid {
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); /* text first, photo in the narrow track */
}

.svc-line:nth-child(even) .svc-line__media {
	order: 2;
}

.svc-line__media {
	position: sticky;
	top: 104px; /* fixed header (84px at desktop) + breathing room */
	margin: 0;
	overflow: hidden;
	border-radius: var(--radius-lg);
	background: var(--green-50);
	box-shadow: var(--shadow-md);
	aspect-ratio: 4 / 5;
	max-height: 580px;
}

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

.svc-line__letter {
	position: absolute;
	top: 1.1rem;
	left: 1.1rem;
	display: grid;
	place-items: center;
	width: 56px;
	height: 56px;
	border-radius: 14px;
	background: var(--green-900);
	color: var(--gold-500);
	font-size: 1.5rem;
	font-weight: 800;
	box-shadow: var(--shadow-sm);
}

.svc-line__letter--inline {
	position: static;
	margin-bottom: 1.25rem;
}

.svc-line__body {
	min-width: 0;
}

.svc-line__title {
	margin: 0;
	font-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem);
	line-height: 1.08;
	letter-spacing: -.02em;
	color: var(--green-900);
}

.svc-line__lede {
	margin: 1rem 0 0;
	max-width: 46ch;
	font-size: 1.1875rem;
	line-height: 1.55;
	color: var(--charcoal-600);
}

.svc-line__best {
	display: inline-block;
	margin: 1.5rem 0 0;
	padding: .8rem 1.1rem;
	border-radius: var(--radius);
	background: var(--green-50);
	font-size: .9375rem;
	line-height: 1.5;
	color: var(--charcoal-600);
}

.svc-line__best strong {
	color: var(--green-900);
}

.svc-line__list {
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--border);
}

/* Two tracks, not three: measured with "Learn more" as a third column the description track
   was 363px (~45 characters) in a 585px body. The link now sits under the description in the
   text track, which gives the copy ~475px, 58–62 characters at 16px. */
.svc-row {
	display: grid;
	grid-template-columns: 5.75rem minmax(0, 1fr);
	column-gap: 1.25rem;
	align-items: start;
	padding: 1.4rem 0;
	border-bottom: 1px solid var(--border);
}

.svc-row__num {
	padding-top: .25rem;
	font-size: .8125rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--gold-600);
}

.svc-row__text {
	min-width: 0;
}

.svc-row__title {
	margin: 0;
	font-size: 1.1875rem;
	line-height: 1.3;
	color: var(--green-900);
}

.svc-row__desc {
	margin: .45rem 0 0;
	max-width: 62ch;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--charcoal-600);
}

.svc-row__more {
	grid-column: 2;
	justify-self: start;
	margin-top: .7rem;
	font-size: .9375rem;
	font-weight: 700;
	white-space: nowrap;
	color: var(--green-900);
	text-decoration: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 2px;
	text-underline-offset: .3em;
	transition: text-decoration-color var(--dur);
}

.svc-row__more span {
	display: inline-block;
	transition: transform var(--dur) var(--ease);
}

.svc-row__more:hover {
	text-decoration-color: var(--gold-500);
}

.svc-row__more:hover span {
	transform: translateX(3px);
}

.svc-line__guide {
	display: block;
	margin-top: 1.5rem;
	font-size: .9375rem;
	font-weight: 600;
	line-height: 1.45;
	color: var(--green-900);
}

.svc-line__guide span:first-child {
	display: block;
	margin-bottom: .15rem;
	font-size: .8125rem;
	font-weight: 700;
	color: var(--gold-600);
}

.svc-line__guide:hover {
	color: var(--green-700);
}

@media (prefers-reduced-motion: reduce) {
	.svc-row__more:hover span {
		transform: none;
	}
}

/* About page (2026-09-29, relaid 2026-10-06) / TECH-043. Category 3 — `.about-intro`,
   `.promise`, `.owners`, `.owner`, `.operate` appear nowhere in styles.css (patterns/page-about.php).

   Final layout, 2026-10-06. The two earlier passes that day reached for cards, a dark band, a
   bento and oversized initials; this one removes everything that does not carry information.
   System: the site's 12-column container; text left-aligned at 52–60 characters; one photo
   treatment (radius-lg, no overlays, no chips); 1px rules from --border as the only structure;
   type from the existing scale; spacing in 1 / 1.5 / 2 / 3rem steps; no motion. Icons remain
   in "How we operate" because each one names its item (check, calendar, shield, file); they
   are set small and inline rather than in tiles. Tokens all from styles.css :root. */
.about-intro {
	padding: calc(150px + var(--topbar-h)) 0 clamp(3.5rem, 2.5rem + 3vw, 5.5rem);
	background-color: var(--bg);
	background-image: radial-gradient(rgba(35, 39, 43, .09) 1px, transparent 1.5px);
	background-size: 22px 22px;
}

.about-intro__grid {
	display: grid;
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
	gap: clamp(2.5rem, 5vw, 5rem);
	align-items: center;
}

.about-intro__title {
	margin: 1.5rem 0 1.25rem;
	font-size: clamp(2.5rem, 1.6rem + 2.6vw, 3.75rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -.02em;
	color: var(--green-900);
}

.about-intro__copy > p:not(.page-hero__badge) {
	margin: 0 0 1rem;
	max-width: 56ch;
	font-size: 1.125rem;
	line-height: 1.7;
	color: var(--charcoal-600);
}

.about-intro__photo,
.operate__banner-photo {
	position: relative;
	margin: 0;
	overflow: hidden;
	border-radius: var(--radius-lg);
	background: var(--green-50);
}

.about-intro__photo {
	aspect-ratio: 4 / 5;
	max-height: 520px;
}

.about-intro__photo img,
.operate__banner-photo img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.promise {
	padding: clamp(2rem, 1.5rem + 1.5vw, 3rem) 0;
	border-top: 1px solid var(--border);
	border-bottom: 1px solid var(--border);
	background: var(--white);
}

.promise__grid {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 6fr) minmax(0, 4fr);
	gap: 1.5rem clamp(2rem, 4vw, 4rem);
	align-items: start;
}

.promise__label {
	margin: .2rem 0 0;
	font-family: var(--font-hand);
	font-size: 1.6rem;
	line-height: 1;
	color: var(--gold-600);
}

.promise__lines {
	margin: 0;
	font-size: clamp(1.375rem, 1.1rem + .9vw, 1.875rem);
	font-weight: 800;
	line-height: 1.2;
	letter-spacing: -.01em;
	color: var(--green-900);
}

.promise__stats {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, auto));
	gap: 1rem 2rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.promise__stats li {
	display: flex;
	flex-direction: column;
	gap: .3rem;
}

.promise__stats strong {
	font-size: 1.75rem;
	font-weight: 800;
	line-height: 1;
	color: var(--green-900);
}

.promise__stats span {
	font-size: .8125rem;
	line-height: 1.4;
	color: var(--charcoal-600);
}

.owners {
	background: var(--white);
	scroll-margin-top: 80px;
}

.owners__head,
.operate__head {
	margin-bottom: 2.5rem;
}

.owners__list {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0 clamp(2rem, 4vw, 4rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.owner {
	padding: 1.5rem 0 2rem;
	border-top: 1px solid var(--green-900);
}

.owner__name {
	margin: 0;
	font-size: 1.5rem;
	line-height: 1.2;
	color: var(--green-900);
}

.owner__role {
	margin: .35rem 0 0;
	font-size: .9375rem;
	font-weight: 600;
	color: var(--green-500);
}

.owner__bio {
	margin: 1rem 0 0;
	max-width: 36ch;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--charcoal-600);
}

.owners__note {
	margin: 1.5rem 0 0;
	max-width: 70ch;
	font-size: .9375rem;
	line-height: 1.55;
	color: var(--charcoal-600);
}

.operate {
	background: var(--bg);
}

.operate__list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0 clamp(2rem, 5vw, 5rem);
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--border);
}

.operate__item {
	display: grid;
	grid-template-columns: 24px minmax(0, 1fr);
	column-gap: 1rem;
	align-items: start;
	padding: 1.5rem 0;
	border-bottom: 1px solid var(--border);
}

.operate__icon {
	display: grid;
	place-items: center;
	width: 24px;
	height: 24px;
	margin-top: .1rem;
	color: var(--green-700);
}

.operate__icon svg {
	width: 22px;
	height: 22px;
}

.operate__item h3 {
	margin: 0;
	font-size: 1.125rem;
	line-height: 1.35;
	color: var(--green-900);
}

.operate__item p {
	margin: .35rem 0 0;
	max-width: 46ch;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--charcoal-600);
}

.operate__banner {
	display: grid;
	grid-template-columns: 200px minmax(0, 1fr) auto;
	align-items: center;
	gap: 1.5rem 2rem;
	margin-top: 3rem;
}

.operate__banner-photo {
	aspect-ratio: 3 / 2;
}

.operate__banner-text {
	display: flex;
	flex-direction: column;
	gap: .35rem;
}

.operate__banner-text strong {
	font-size: 1.125rem;
	line-height: 1.35;
	color: var(--green-900);
}

.operate__banner-text span {
	max-width: 52ch;
	font-size: .9375rem;
	line-height: 1.55;
	color: var(--charcoal-600);
}

/* Careers open roles (2026-09-29) / TECH-043. Category 3 — `.roles-list`, `.job-card` and
   `.apply-dialog` appear nowhere in styles.css (patterns/careers-roles.php). A stack of white
   role cards (gold icon tile, title + summary, tag pills, Apply) with department filter pills,
   a pale-green talent-pool banner, and the modal application form. */
.roles-list {
	background: var(--white);
	scroll-margin-top: 80px;
}

.roles-list__head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.25rem 2rem;
	margin-bottom: 2rem;
}

.roles-list__filters {
	display: flex;
	flex-wrap: wrap;
	gap: .4rem;
	padding: .35rem;
	border-radius: 999px;
	background: var(--green-50);
}

.roles-list__filters button {
	padding: .5rem 1.1rem;
	border: 0;
	border-radius: 999px;
	background: transparent;
	color: var(--charcoal-600);
	font: inherit;
	font-size: .875rem;
	font-weight: 600;
	cursor: pointer;
	transition: background var(--dur), color var(--dur);
}

.roles-list__filters button[aria-pressed="true"] {
	background: var(--green-900);
	color: var(--white);
}

.roles-list__items {
	display: flex;
	flex-direction: column;
	gap: .9rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.job-card {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	padding: 1.25rem 1.5rem;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
	transition: box-shadow var(--dur), border-color var(--dur);
}

.job-card:hover {
	border-color: var(--green-200);
	box-shadow: var(--shadow-md);
}

.job-card[hidden] {
	display: none;
}

.job-card__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 48px;
	height: 48px;
	border-radius: 12px;
	background: var(--gold-500);
	color: var(--green-900);
}

.job-card__icon svg {
	width: 22px;
	height: 22px;
}

.job-card__body {
	flex: 1;
	min-width: 0;
}

.job-card__title {
	margin: 0;
	font-size: 1.0625rem;
	color: var(--green-900);
}

.job-card__summary {
	margin: .25rem 0 0;
	font-size: .9375rem;
	color: var(--charcoal-600);
}

.job-card__tags {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: .4rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.job-card__tags li {
	padding: .3rem .7rem;
	border-radius: 999px;
	background: var(--green-50);
	color: var(--green-900);
	font-size: .75rem;
	font-weight: 600;
	white-space: nowrap;
}

.job-card__apply {
	flex: none;
}

.roles-list__empty {
	padding: 1.5rem;
	border-radius: var(--radius-lg);
	background: var(--bg);
	color: var(--charcoal-600);
}

.roles-list__pool {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem 2rem;
	margin-top: 1.5rem;
	padding: 1.5rem 1.75rem;
	border: 1px solid var(--green-200);
	border-radius: var(--radius-lg);
	background: var(--green-50);
	scroll-margin-top: 100px;
}

.roles-list__pool div {
	display: flex;
	flex-direction: column;
	gap: .3rem;
}

.roles-list__pool strong {
	color: var(--green-900);
}

.roles-list__pool span {
	font-size: .9375rem;
	color: var(--charcoal-600);
}

.apply-dialog {
	width: min(560px, calc(100vw - 2rem));
	max-height: calc(100vh - 2rem);
	padding: 0;
	border: 0;
	border-radius: 12px;
	box-shadow: 0 20px 50px rgba(10, 42, 32, .25);
	color: var(--charcoal);
}

.apply-dialog::backdrop {
	background: rgba(10, 42, 32, .5);
}

.apply-form {
	display: flex;
	flex-direction: column;
	max-height: calc(100vh - 2rem);
}

.apply-form__header,
.apply-form__footer {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 1.1rem 1.5rem;
}

.apply-form__header {
	justify-content: space-between;
	align-items: flex-start;
	border-bottom: 1px solid var(--border);
}

.apply-form__header h2 {
	margin: 0;
	font-size: 1.25rem;
	line-height: 1.3;
	color: var(--green-900);
}

.apply-form__header p {
	margin: .2rem 0 0;
	font-size: .875rem;
	color: var(--charcoal-600);
}

.apply-form__close {
	flex: none;
	width: 32px;
	height: 32px;
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var(--charcoal-600);
	font-size: 1.4rem;
	line-height: 1;
	cursor: pointer;
}

.apply-form__close:hover {
	background: var(--bg);
	color: var(--charcoal);
}

.apply-form__body {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding: 1.25rem 1.5rem;
	overflow-y: auto;
}

.apply-form__row {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
}

.apply-form__field {
	display: flex;
	flex-direction: column;
	gap: .35rem;
}

.apply-form__field label {
	font-size: .875rem;
	font-weight: 600;
	color: var(--charcoal);
}

.apply-form__field label span {
	color: #C2410C;
}

.apply-form__field small {
	font-size: .8125rem;
	color: var(--charcoal-400);
}

.apply-form__field input,
.apply-form__field select,
.apply-form__field textarea {
	width: 100%;
	padding: .6rem .75rem;
	border: 1px solid var(--border-strong);
	border-radius: 8px;
	background: var(--white);
	font: inherit;
	font-size: .9375rem;
	color: var(--charcoal);
	outline: none;
	transition: border-color var(--dur), box-shadow var(--dur);
}

.apply-form__field select {
	padding-right: 2.5rem;
	-webkit-appearance: none;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234A5057' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right .75rem center;
	background-size: 16px;
}

.apply-form__field textarea {
	min-height: 110px;
	resize: vertical;
}

.apply-form__field input:focus,
.apply-form__field select:focus,
.apply-form__field textarea:focus {
	border-color: var(--green-700);
	box-shadow: 0 0 0 3px rgba(27, 94, 69, .15);
}

.apply-form__field input[type="file"] {
	padding: .45rem;
	font-size: .875rem;
	color: var(--charcoal-600);
}

.apply-form__field input[type="file"]::file-selector-button {
	margin-right: .75rem;
	padding: .4rem .8rem;
	border: 1px solid var(--border-strong);
	border-radius: 6px;
	background: var(--bg);
	color: var(--charcoal);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

.apply-form__footer {
	justify-content: flex-end;
	border-top: 1px solid var(--border);
	background: var(--bg);
	border-radius: 0 0 12px 12px;
}

.apply-form__cancel,
.apply-form__submit {
	padding: .6rem 1.1rem;
	border-radius: 8px;
	font: inherit;
	font-size: .9375rem;
	font-weight: 600;
	cursor: pointer;
	transition: background var(--dur), border-color var(--dur);
}

.apply-form__cancel {
	border: 1px solid var(--border-strong);
	background: var(--white);
	color: var(--charcoal);
}

.apply-form__cancel:hover {
	border-color: rgba(35, 39, 43, .35);
}

.apply-form__submit {
	border: 1px solid var(--green-900);
	background: var(--green-900);
	color: var(--white);
}

.apply-form__submit:hover {
	background: var(--green-700);
}

.apply-form__submit:disabled {
	opacity: .65;
	cursor: progress;
}

/* Consultation booking (2026-09-29) / TECH-043. Category 3 — `.booking` appears nowhere in
   styles.css (patterns/page-consultation.php; the plugin's booking.js builds the day buttons
   and slot buttons). Two white cards on --bg: a calendar + slot picker, and the details form
   with topic chips. Open days are tinted and bold, the chosen day and slot go dark green. */
.booking-section {
	background: var(--bg);
}

.booking {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 1.5rem;
	align-items: start;
}

.booking__card {
	padding: clamp(1.5rem, 1rem + 1.5vw, 2.25rem);
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
}

.booking__card h2 {
	margin: 0;
	font-size: 1.375rem;
	color: var(--green-900);
}

.booking__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: .75rem;
}

.booking__tz {
	padding: .3rem .75rem;
	border-radius: 999px;
	background: var(--green-50);
	color: var(--green-900);
	font-size: .75rem;
	font-weight: 700;
}

.booking__sub {
	margin: .35rem 0 0;
	font-size: .9375rem;
	color: var(--charcoal-600);
}

.booking__picker {
	display: grid;
	grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
	gap: 1.5rem;
	margin-top: 1.5rem;
}

.booking__month {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: .75rem;
	color: var(--green-900);
}

.booking__month button {
	width: 28px;
	height: 28px;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--green-900);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.booking__month button:disabled {
	color: var(--charcoal-400);
	opacity: .4;
	cursor: default;
}

.booking__weekdays,
.booking__grid {
	display: grid;
	grid-template-columns: repeat(7, minmax(0, 1fr));
	gap: .3rem;
	text-align: center;
}

.booking__weekdays span {
	font-size: .75rem;
	font-weight: 700;
	color: var(--charcoal-400);
}

.booking__date {
	aspect-ratio: 1;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: var(--charcoal-400);
	font: inherit;
	font-size: .875rem;
}

.booking__date.is-open {
	background: var(--green-50);
	color: var(--green-900);
	font-weight: 700;
	cursor: pointer;
}

.booking__date.is-open:hover {
	background: var(--green-100);
}

.booking__date.is-selected {
	background: var(--green-900);
	color: var(--white);
}

.booking__day {
	margin: 0 0 .75rem;
	font-weight: 700;
	color: var(--green-900);
}

.booking__slots {
	display: flex;
	flex-direction: column;
	gap: .55rem;
}

.booking__slot {
	padding: .8rem 1rem;
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-sm);
	background: var(--white);
	color: var(--green-900);
	font: inherit;
	font-weight: 700;
	cursor: pointer;
	transition: border-color var(--dur), background var(--dur), color var(--dur);
}

.booking__slot:hover {
	border-color: var(--green-700);
}

.booking__slot[aria-pressed="true"] {
	border-color: var(--green-900);
	background: var(--green-900);
	color: var(--white);
}

.booking__card--details {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.booking__card--details .booking__sub {
	margin-top: -.65rem;
}

.booking__row {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
}

.booking__field {
	display: flex;
	flex-direction: column;
	gap: .4rem;
}

.booking__field > span,
.booking__topics legend {
	font-size: .8125rem;
	font-weight: 700;
	color: var(--green-900);
}

.booking__field input,
.booking__field select {
	width: 100%;
	padding: .75rem .9rem;
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-sm);
	background: var(--white);
	font: inherit;
	font-size: .9375rem;
	color: var(--charcoal);
	outline: none;
	transition: border-color var(--dur), box-shadow var(--dur);
}

.booking__field select {
	padding-right: 2.75rem;
	-webkit-appearance: none;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230F3D2E' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 1rem center;
	background-size: 16px;
	cursor: pointer;
}

.booking__field input:focus,
.booking__field select:focus {
	border-color: var(--green-700);
	box-shadow: 0 0 0 4px rgba(224, 178, 58, .22);
}

.booking__topics {
	display: flex;
	flex-wrap: wrap;
	gap: .45rem;
	margin: 0;
	padding: 0;
	border: 0;
}

.booking__topics legend {
	margin-bottom: .55rem;
	padding: 0;
}

.booking__chip {
	position: relative;
	cursor: pointer;
}

.booking__chip input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}

.booking__chip span {
	display: inline-block;
	padding: .45rem .9rem;
	border-radius: 999px;
	background: var(--green-50);
	color: var(--green-900);
	font-size: .8125rem;
	font-weight: 600;
	transition: background var(--dur), color var(--dur);
}

.booking__chip input:checked + span {
	background: var(--green-900);
	color: var(--white);
}

.booking__chip input:focus-visible + span {
	box-shadow: 0 0 0 3px rgba(224, 178, 58, .45);
}

.booking__submit {
	justify-content: center;
	width: 100%;
	margin-top: .5rem;
}

.booking__submit:disabled {
	opacity: .55;
	cursor: not-allowed;
	transform: none;
	box-shadow: none;
}

.booking__privacy {
	margin: 0;
	text-align: center;
	font-size: .8125rem;
	color: var(--charcoal-600);
}

.booking__privacy a {
	color: var(--green-900);
	text-decoration: underline;
}

/* Single job page (2026-09-29) / TECH-043. Category 3 — `.job-detail` appears nowhere in
   styles.css (patterns/job-detail.php). Readable description column beside a sticky apply
   card. Also: role titles on the Careers list are now links. */
.job-card__title a {
	color: inherit;
}

.job-card__title a:hover {
	color: var(--green-500);
}

.job-detail__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

.job-detail__content {
	max-width: 68ch;
	font-size: 1.0625rem;
	line-height: 1.75;
	color: var(--charcoal-600);
}

.job-detail__content > * + * {
	margin-top: 1rem;
}

.job-detail__content h2,
.job-detail__content h3 {
	margin-top: 2rem;
	font-size: 1.375rem;
	line-height: 1.3;
	color: var(--green-900);
}

.job-detail__content ul {
	padding-left: 1.25rem;
	list-style: disc;
}

.job-detail__content li + li {
	margin-top: .4rem;
}

.job-detail__content li::marker {
	color: var(--gold-600);
}

.job-detail__apply {
	position: sticky;
	top: 110px;
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding: 1.75rem;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
}

.job-detail__apply h2 {
	margin: 0;
	font-size: 1.25rem;
	line-height: 1.3;
	color: var(--green-900);
}

.job-detail__apply dl {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: .4rem 1rem;
	margin: 0;
	font-size: .9375rem;
}

.job-detail__apply dt {
	font-weight: 700;
	color: var(--green-900);
}

.job-detail__apply dd {
	margin: 0;
	color: var(--charcoal-600);
}

.job-detail__cta {
	justify-content: center;
}

.job-detail__back {
	text-align: center;
	font-size: .9375rem;
	font-weight: 600;
	color: var(--green-900);
}

/* Standard page content (2026-09-29) / TECH-043. Category 3 — `.wp-block-post-content`
   inside `.avenir-inner` appears nowhere in styles.css. Readable prose for editor-written
   pages (Privacy Policy, Terms of Use, Accessibility, posts): a comfortable measure, spaced
   headings, real list bullets and underlined links — styles.css resets all of these. */
.avenir-inner .wp-block-post-content {
	max-width: 72ch;
	margin-inline: auto;
	font-size: 1.0625rem;
	line-height: 1.75;
	color: var(--charcoal-600);
}

.avenir-inner .wp-block-post-content > * + * {
	margin-top: 1.1rem;
}

.avenir-inner .wp-block-post-content h2 {
	margin-top: 2.5rem;
	font-size: 1.5rem;
	line-height: 1.3;
	color: var(--green-900);
}

.avenir-inner .wp-block-post-content h3 {
	margin-top: 2rem;
	font-size: 1.25rem;
	color: var(--green-900);
}

.avenir-inner .wp-block-post-content ul,
.avenir-inner .wp-block-post-content ol {
	padding-left: 1.4rem;
}

.avenir-inner .wp-block-post-content ul {
	list-style: disc;
}

.avenir-inner .wp-block-post-content ol {
	list-style: decimal;
}

.avenir-inner .wp-block-post-content li + li {
	margin-top: .45rem;
}

.avenir-inner .wp-block-post-content li::marker {
	color: var(--gold-600);
}

.avenir-inner .wp-block-post-content a {
	color: var(--green-700);
	text-decoration: underline;
	text-underline-offset: .15em;
}

.avenir-inner .wp-block-post-content a:hover {
	color: var(--green-900);
}

.avenir-inner .wp-block-post-content strong {
	color: var(--charcoal);
}

/* Blog: index grid, article cards, byline, related posts (2026-09-29) / TECH-043. Category 3 —
   `.post-byline`, `.post-article`, `.related-posts`, `.post-pagination` and `.blog-index`
   appear nowhere in styles.css (templates/home.html, templates/single.html, patterns/post-meta.php,
   patterns/related-posts.php). The article cards themselves are the home page's `.card--post`
   (styles.css), shared through avenir_insight_cards_html(). */
.blog-index__empty {
	text-align: center;
	color: var(--charcoal-600);
}

.post-pagination {
	gap: .5rem;
	margin-top: 2.5rem;
	font-weight: 600;
}

.post-pagination a,
.post-pagination .page-numbers {
	padding: .45rem .8rem;
	border-radius: 8px;
	color: var(--green-900);
}

.post-pagination .current {
	background: var(--green-900);
	color: var(--white);
}

.post-byline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .4rem .6rem;
	max-width: 72ch;
	margin: 0 auto 1.75rem;
	font-size: .9375rem;
	color: var(--charcoal-600);
}

.post-byline strong {
	color: var(--green-900);
}

.post-byline a {
	font-weight: 600;
	color: var(--gold-600);
}

.post-byline__avatar {
	display: grid;
	place-items: center;
	width: 32px;
	height: 32px;
	border: 2px solid var(--gold-500);
	border-radius: 50%;
	background: var(--green-900);
	color: var(--gold-500);
	font-size: .8125rem;
	font-weight: 800;
}

.post-article__image {
	max-width: 900px;
	margin: 0 auto 2.5rem;
	overflow: hidden;
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
}

.post-article__image img {
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.related-posts {
	background: var(--bg);
}

.related-posts__title {
	margin: 0 0 1.75rem;
	font-size: clamp(1.625rem, 1.3rem + 1vw, 2.125rem);
	color: var(--green-900);
}


/* 404 page (2026-09-29) / TECH-043. Category 3 — `.not-found` appears nowhere in styles.css
   (patterns/not-found.php). A large rounded search bar, two actions, a row of page cards with
   gold icon tiles, then the latest articles as home-page cards. */
.not-found__search {
	position: relative;
	display: flex;
	align-items: center;
	gap: .5rem;
	max-width: 720px;
	margin: 0 auto;
	padding: .45rem .45rem .45rem 1.25rem;
	background: var(--white);
	border: 1px solid var(--border-strong);
	border-radius: 999px;
	box-shadow: var(--shadow-sm);
	transition: border-color var(--dur), box-shadow var(--dur);
}

.not-found__search:focus-within {
	border-color: var(--green-700);
	box-shadow: 0 0 0 4px rgba(224, 178, 58, .22);
}

.not-found__search-icon {
	flex: none;
	width: 18px;
	height: 18px;
	color: var(--charcoal-400);
}

.not-found__search input {
	flex: 1;
	min-width: 0;
	padding: .7rem .25rem;
	border: 0;
	background: transparent;
	font: inherit;
	font-size: 1rem;
	color: var(--charcoal);
	outline: none;
}

.not-found__search .btn {
	flex: none;
}

.not-found__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: .75rem;
	margin-top: 1.5rem;
}

.not-found__heading {
	margin: clamp(3rem, 2rem + 3vw, 4.5rem) 0 1.5rem;
	text-align: center;
	font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
	color: var(--green-900);
}

.not-found__pages {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.not-found__pages a {
	display: flex;
	flex-direction: column;
	gap: .4rem;
	height: 100%;
	padding: 1.4rem;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
	color: var(--charcoal-600);
	font-size: .875rem;
	line-height: 1.5;
	transition: transform var(--dur) var(--ease), box-shadow var(--dur), border-color var(--dur);
}

.not-found__pages a:hover {
	transform: translateY(-3px);
	border-color: var(--gold-500);
	box-shadow: var(--shadow-md);
}

.not-found__pages strong {
	margin-top: .5rem;
	font-size: 1.0625rem;
	color: var(--green-900);
}

.not-found__icon {
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	border-radius: 12px;
	background: var(--gold-500);
	color: var(--green-900);
}

.not-found__icon svg {
	width: 20px;
	height: 20px;
}

@media (prefers-reduced-motion: reduce) {
	.not-found__pages a:hover {
		transform: none;
	}
}

/* Inner-page hero (2026-09-29) / TECH-043. Category 3 — `.page-hero` appears nowhere in
   styles.css (patterns/page-hero.php, on every template but the front page). Dotted paper
   background, centred badge / title / lede / chips. The top padding clears the fixed header
   like the hero (styles.css:1441). `.page-hero + .avenir-inner` replaces the fallback
   chrome's header clearance (wp-adaptations.css `.avenir-inner`) once the hero has done it. */
.page-hero {
	padding: calc(150px + var(--topbar-h)) 0 clamp(3.5rem, 2.5rem + 3vw, 5.5rem);
	background-color: var(--bg);
	background-image: radial-gradient(rgba(35, 39, 43, .09) 1px, transparent 1.5px);
	background-size: 22px 22px;
	border-bottom: 1px solid var(--border);
	text-align: center;
}

.page-hero__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.page-hero__badge {
	display: inline-flex;
	align-items: center;
	gap: .55rem;
	margin: 0;
	padding: .45rem 1.1rem;
	border: 1.5px solid var(--gold-500);
	border-radius: 999px;
	background: rgba(255, 255, 255, .6);
	color: var(--green-900);
	font-size: .9375rem;
	font-weight: 600;
}

.page-hero__badge::before {
	content: "";
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--gold-500);
}

.page-hero__title {
	max-width: 24ch;
	margin: 1.75rem 0 0;
	font-size: clamp(2.5rem, 1.5rem + 3.2vw, 4.5rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -.02em;
	color: var(--green-900);
	overflow-wrap: break-word;
}

.page-hero__lede {
	max-width: 62ch;
	margin: 1.5rem 0 0;
	font-size: 1.125rem;
	line-height: 1.7;
	color: var(--charcoal-600);
}

.page-hero__chips {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: .75rem;
	max-width: 960px;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

.page-hero__chips li {
	padding: .6rem 1.2rem;
	background: var(--white);
	border: 1px solid var(--border);
	border-radius: 999px;
	color: var(--green-900);
	font-size: .9375rem;
	font-weight: 600;
}

.page-hero__chips li:has(> a) {
	padding: 0;
	transition: border-color var(--dur), box-shadow var(--dur);
}

.page-hero__chips li > a {
	display: block;
	padding: .6rem 1.2rem;
	border-radius: 999px;
	color: inherit;
}

.page-hero__chips li:has(> a):hover {
	border-color: var(--gold-500);
	box-shadow: var(--shadow-sm);
}

.page-hero__chips b {
	margin-right: .3rem;
	color: var(--gold-600);
	font-weight: 700;
}

.page-hero + .avenir-inner {
	padding-top: var(--section-y);
}

/* Inner-page content on white (2026-09-29) / TECH-043. `.avenir-page` is the <main> of every
   template except the front page; the hero keeps its own dotted background above it.
   Overrides styles.css:847  html.has-fixed-footer main { background: var(--bg) } (0,1,2), which
   avenir.js turns on for every page; `.has-fixed-footer .avenir-page` (0,2,0) is the lowest
   selector that outranks it. The bare `.avenir-page` covers the no-JS case. */
.avenir-page,
.has-fixed-footer .avenir-page {
	background: var(--white);
}

/* Inner pages: no top wave on the closing .cta band (2026-09-29), on request — it meets the
   white content with a straight edge. The band's top padding drops the 70px it reserved for
   the wave. Overrides styles.css:530  .cta { padding-block: calc(var(--section-y) + 70px) … }. */
.avenir-page .cta .wave--top {
	display: none;
}

.avenir-page .cta {
	padding-top: var(--section-y);
}

/* ==========================================================================
   ===== MOBILE LAYER — CN-06 / TECH-024 =====

   Category 2 of this file. Everything below this banner belongs to the mobile experience
   pass (Change note CN-06, REQ-024..REQ-040 / AC-036..AC-064). Below 1024px the prototype's
   own responsive rendering is no longer a reference (CN-06 amends REQ-003), so these rules
   deviate from nothing — which is why they cannot carry Category 1's per-rule "overrides
   styles.css:NNN" citation. They carry a section reference to the blueprint instead.

   BINDING INVARIANT (TECH-024, replaces the per-rule citation for this category):
     >>> EVERY SELECTOR BELOW THIS BANNER IS INSIDE A @media (max-width: …) BLOCK. <<<
     Nothing here may apply at 1280px. No exceptions, ever. That single, greppable fact is
     what makes REQ-034 / AC-053 (desktop unchanged at >=1280px) structurally true rather
     than reviewed by eye. A rule that needs to apply at every width does not belong in this
     category; it belongs in Category 1 above, or in wp-adaptations.css.

   Rules 1 and 5 of the admission rule still bind: every rule traces to CN-06 and a TECH-xxx,
   and uses the lowest specificity that works — never !important, never an ID. If a rule here
   ever seems to need !important, the cause is an inline style written by assets/js/avenir.js
   and the fix belongs in that file's media gates (TECH-026 / TECH-028), not here.

   ------------------------------------------------------------------------------------
   THE DECLARED BREAKPOINT SET (REQ-035 / AC-054, TECH-023, blueprint §8.1)

   Five entries, four of them max-width. This is the whole set the theme uses, declared in one
   place. Desktop-first max-width queries, because that is what the 1462-line prototype
   stylesheet is, and mixing query directions is how the current set became hard to read.

   | token         | query                              | what it is for                      |
   |---------------|------------------------------------|-------------------------------------|
   | wide          | @media (max-width: 1100px)         | desktop density only: 4-up grids    |
   |               |                                    | become 2-up, footer columns halve.  |
   |               |                                    | No mobile semantics. NO NEW RULES.  |
   |---------------|------------------------------------|-------------------------------------|
   | nav-fit       | @media (min-width: 900px) and      | ADDED 2026-09-17 (ISSUE-W2-01,      |
   |               |        (max-width: 1100px)         | TECH-045), REVISED the same day.    |
   |               | @media (min-width: 900px) and      | The band where the desktop header   |
   |               |        (max-width: 1024px)         | does not fit and the burger has not |
   |               |                                    | appeared yet. TWO BLOCKS, §8.13:    |
   |               |                                    | relief + nowrap to 1100 because the |
   |               |                                    | wrap runs to ~1050; density + type  |
   |               |                                    | step to 1024 because that is where  |
   |               |                                    | the row runs out of room. BOTH ARE  |
   |               |                                    | BOUNDED BELOW AT 900px so neither   |
   |               |                                    | can reach the phone nav sheet.      |
   |---------------|------------------------------------|-------------------------------------|
   | mobile        | @media (max-width: 899px)          | THE SWITCH. Above it the page uses  |
   |               |                                    | desktop mechanics; at and below it  |
   |               |                                    | this layer governs: nav sheet,      |
   |               |                                    | single column, hero reorder, team   |
   |               |                                    | list, services stack.               |
   |---------------|------------------------------------|-------------------------------------|
   | phone         | @media (max-width: 600px)          | phone refinements inside the mobile |
   |               |                                    | layer: full-width buttons, tighter  |
   |               |                                    | padding, the admin-bar offset.      |
   |---------------|------------------------------------|-------------------------------------|
   | coarse        | @media (hover: none)               | affordances that depend on a        |
   | pointer /     | @media (prefers-reduced-motion:    | pointer or on motion permission,    |
   | reduced motion|        reduce)                     | at any width. Existing; no new      |
   |               |                                    | rules required by this layer.       |

   Why 899 and not 900: `max-width: 899px` is the exact complement of the
   `matchMedia('(min-width: 900px)')` that gates the industries block (avenir.js:483), the
   coverflow (avenir.js:296) and the hero tweens (avenir.js:810). Normalising it to 900 would
   open a 1px band where the CSS says mobile and the JavaScript says desktop. The two stay
   complementary by construction (TECH-023, finding M-13).

   The orphaned `max-width: 700px` query in styles.css is retired by attrition: the team fan
   is the only thing it styles and the fan is replaced below 899px. styles.css is not edited
   (TECH-003); the query simply stops applying to anything that is still visible.

   ------------------------------------------------------------------------------------
   ORDER OF THIS LAYER (blueprint §17 step 2; item 0 added 2026-09-17 by ISSUE-W2-01)
     0. nav-fit: relief 900-1100px + density 900-1024px               §8.13 TECH-045
     1. nav sheet + document scroll lock + anchor offset + safe areas   §8.7  TECH-030/036
     2. hero                                                            §8.3  TECH-025
     3. about / .polaroids                                              §8.9  TECH-031
     4. team member list                                                §8.4  TECH-027
     5. services stack                                                  §8.5  TECH-028
     6. industries retune                                               §8.6  TECH-029
     7. typography                                                      §8.9  TECH-031
     8. touch targets + carousel arrows                                 §8.10 TECH-032
     9. admin bar below 600px                                           §8.8  TECH-033
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. NAV-FIT — the band where the desktop header does not fit
   ISSUE-W2-01 / CN-06 / REQ-024 / AC-036 / TECH-045. Blueprint §8.13 as revised 2026-09-17.

   Tightens, in this band only:
     styles.css:170  .header__inner { gap: 2rem }
     styles.css:188  .nav          { gap: 2rem }
     styles.css:189  .nav__list    { gap: 2rem }
     styles.css:190  .nav__list a, .nav__link { font-size: .9375rem }
     styles.css:194  .nav__actions { gap: 1.5rem }
     styles.css:195  .nav__cta     { padding: .8rem 1.4rem }   (inline padding only)

   The burger does not appear until 900px (styles.css:586), so from 901px up the full desktop
   nav has to render in a row that cannot hold it. Measured before any of this, transparent
   state: the CTA's right edge sat 59.6 / 41.4 / 29.9 / 3.0px outside the VIEWPORT at
   901 / 920 / 932 / 960px, and "For Applicants" wrapped to two lines from 901 all the way to
   ~1040px (~1050px scrolled) — the wrap outlives the clipping by 25px of viewport width.
   Pre-existing and inside REQ-024's declared 320-1024 range, so CN-06 governs it.

   TWO BLOCKS, AND WHY THE SPLIT IS WHERE IT IS.
   The relief pair plus nowrap runs to 1100px because the wrap does; the stronger density and
   the type step stop at 1024px because that is where the row actually runs out of room. Between
   1051 and 1100px the only difference is a CTA ~13px narrower and one gap 10px tighter — a real
   but small cost in the band A-09 protects, taken so the same defect is closed on both sides of
   1024 rather than at a line drawn by a range limit.

   WHITE-SPACE: NOWRAP IS NOT SHIPPABLE WITHOUT THE TYPE STEP. On its own it stops the wrap and
   pushes the CTA 19px PAST .header__inner's right edge at 901px (18px scrolled). In the
   transparent state that box is invisible; in the scrolled state it is the frosted pill, so the
   gold button hangs outside the pill's rounded edge. Measured against the VIEWPORT the same
   state looks fine, with 17.2px of clearance — the wrong instrument hides it entirely
   (blueprint §18.3a). The .875rem type step buys back the room the nowrap costs.

   BOTH BLOCKS ARE BOUNDED BELOW AT 900px, and that bound is load-bearing, not tidiness: these
   selectors also exist inside the phone nav sheet. Unbounded, `.nav__list a { font-size:
   .875rem }` would drop the sheet's menu items from 16px to 14px, straight at AC-047 and
   AC-049, and `nowrap` would apply to a stacked full-width list. 900px is the complement of
   styles.css:586's mobile nav, so the two never overlap.

   A compound query whose upper bound is a max-width satisfies category 2's invariant: it still
   contains a max-width clause and it still cannot match at 1280px (TECH-024 as clarified).
   These blocks come first in the layer because their upper bounds are the widest — the 899px
   and 600px blocks below must keep the last word inside their own ranges.

   CN-19 / TECH-050 / REQ-106 / AC-124 (2026-10-06): `.nav__list { gap }` in the 1024 block
   steps 1rem → .75rem. The fifth link (Insights, patterns/header.php) spent the slack the
   four-link row had: measured at 901px the CTA's right edge sat 5px outside .header__inner
   (870 vs 865, scrollWidth − clientWidth = 6) while the row was already clean at 940px. Four
   gaps × 4px return 16px, so the row fits at 901 with ~10px to spare. Still overrides
   styles.css:189 only; nothing above 1024px changes and the 900px lower bound still keeps
   this out of the phone sheet. TECH-045 is not reopened; this is the same block, one value.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) and (max-width: 1100px) {
	.nav__actions { gap: .875rem; }
	.nav__cta     { padding-inline: 1rem; }
	.nav__list a,
	.nav__link { white-space: nowrap; }
}

@media (min-width: 900px) and (max-width: 1024px) {
	.header__inner { gap: 1rem; }
	.nav           { gap: 1rem; }
	.nav__list     { gap: .75rem; } /* was 1rem here until CN-19; see the note above */
	.nav__list a,
	.nav__link { font-size: .875rem; }
}

/* --------------------------------------------------------------------------
   1. NAVIGATION — opaque full-bleed sheet, scroll lock, anchor offset, safe areas
   REQ-026, REQ-038 / AC-040, AC-041, AC-042 / TECH-030, TECH-036. Blueprint §8.7.

   Measured before: the panel was rgba(255,255,255,.85) over backdrop-filter: blur(18px),
   inset by the gutter (41..372 of a 375px viewport) with the document still scrollable —
   so AC-040's "no page content visible through OR AROUND it" failed twice over and the
   testimonials headline read straight through it. Opaque alone does not satisfy "around";
   a full-bleed sheet does, and it drops the most expensive paint on the page while open.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	/* WHY THIS RULE COMES FIRST. `position: fixed` resolves against the viewport only while
	   no ancestor creates a containing block for it, and `backdrop-filter` does exactly that
	   (CSS Filter Effects 2, §containing block). `.header.is-scrolled .header__inner`
	   (styles.css:200) carries `backdrop-filter: blur(10px) saturate(140%)`, and the header
	   is ALWAYS solid while the menu is open, because `is-scrolled` is `scrolled || menuOpen`
	   (CN-02 / TECH-019). So the fixed `.nav` was being positioned against the 68px header
	   pill, not the viewport: measured, `inset: 0` produced a sheet at 21..354 x 13..131 of a
	   375px viewport instead of the full bleed AC-040 asks for. Dropping the blur below 899px
	   removes the containing block and the sheet fills the viewport.
	   Not scoped to `html.is-nav-open`, deliberately: a containing block that appears and
	   disappears with the panel would re-parent the sheet mid-transition, which is a visible
	   snap on close. The pill keeps `background: rgba(255,255,255,.92)`, its inner white rings
	   and its shadow, so the mobile header still reads as the same white pill; what it loses
	   below 899px is an 8%-visible blur that CN-02 already identified as the most expensive
	   paint on the page. Desktop is untouched: this rule cannot leave the query. */
	.header.is-scrolled .header__inner {
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
	}

	/* The sheet itself. `inset: 0` replaces the gutter inset; the opacity/transform
	   transition and the `.nav.is-open` state from styles.css are deliberately kept, so
	   the sheet still fades in and is still driven by the same single JS writer. */
	.nav {
		inset: 0;
		border-radius: 0;
		border-color: var(--border);
		background: var(--bg);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		/* clear of the header lockup, then safe-area insets on the other three sides
		   (TECH-036: env() degrades to 0 where it is unsupported, so max() is safe). */
		padding: calc(var(--topbar-h) + 84px)
		         max(var(--gutter), env(safe-area-inset-right))
		         max(2rem, env(safe-area-inset-bottom))
		         max(var(--gutter), env(safe-area-inset-left));
		overflow-y: auto;
		overscroll-behavior: contain;
		/* AC-049's separation clause across the sheet's two groups: without it the last
		   .nav__list item and .nav__link sit flush against each other. */
		gap: .75rem;
	}

	/* The sheet paints after .brand in source order, so the lockup has to be lifted above
	   it or the logo disappears under the sheet. `.header__inner > *` already gives both
	   elements `position: relative; z-index: 1` (styles.css:214); this only raises them. */
	.brand,
	.nav-toggle {
		z-index: 2;
	}

	/* styles.css:217 gives every nav label a mirrored reflection
	   (-webkit-box-reflect: below -.55em …) while the header is solid, and the header is
	   always solid while the sheet is open. It is a frosted-pill detail for a horizontal nav
	   over the hero; in a vertical sheet it lands in the space under each divider and reads
	   as a smudge of ghost text (visible in the 375px nav capture before this rule). */
	.header.is-scrolled .nav__list a,
	.header.is-scrolled .nav__link {
		/* `initial`, not `none`: Chrome parses the keyword `none` for this legacy property as
		   invalid and drops the declaration — verified by setting both inline and reading the
		   computed value back (`none` left the reflection in place, `initial` computes to
		   `none`). */
		-webkit-box-reflect: initial;
	}

	/* AC-040, "the page behind does not scroll". Same mechanism and same idiom as
	   `html.is-loading { overflow: hidden }` (styles.css:1451), so the theme has one way of
	   saying "the document is frozen", not two. The class is written by setMenu() (WP-01). */
	html.is-nav-open {
		overflow: hidden;
	}

	/* AC-042, "the section's heading visible clear of the header". There is no scroll-margin
	   anywhere in the theme today, so an anchor jump parks the target heading underneath the
	   fixed header. Scoped to the mobile layer: changing anchor behaviour at >=1280px would
	   be a REQ-034 change. The value is the sheet's own top padding, so a tapped menu item
	   and a tapped in-page link land identically. */
	section[id] {
		scroll-margin-top: calc(var(--topbar-h) + 84px);
	}
}

/* --------------------------------------------------------------------------
   2. HERO — scene above the badge, no viewport-height floor, no guillotine
   REQ-024, REQ-025 / AC-037, AC-038 / TECH-025. Blueprint §8.3.

   `.hero__content` is already a flex column below 900px (styles.css:1363) with exactly two
   children, so the reorder AC-038 asks for is one declaration. It is done visually rather
   than in the markup because moving the scene before the copy in section-hero.php would
   force a compensating `order` on the DESKTOP grid — a change at a frozen width (AC-039,
   AC-053). Nothing is lost by doing it in CSS: .hero__scene carries aria-hidden="true"
   (section-hero.php:74) so it is not in the accessibility tree, and it contains no focusable
   element, so there is no reading order and no tab order to disagree with.

   The bleed in the reported defect was the GSAP parallax, not this box; that is fixed in
   avenir.js by TECH-026 (WP-01). What is fixed here is the section that had nowhere to put
   the figure: `min-height: 100svh` plus `padding-bottom: 0` plus `overflow: hidden`.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.hero {
		/* no viewport-height floor: it is what trapped content below the fold in landscape
		   on a 390px-tall viewport (E-10, AC-061), and the section now sizes to its content */
		min-height: auto;

		/* CN-11 era rhythm — REQ-068 / AC-092 / TECH-046. GAP 1, header -> model.
		   84px is not a number picked to look right: it is the header's own measured height
		   (68px below 900) plus 1rem. styles.css:1445 sets calc(110px + var(--topbar-h)),
		   which put the scene box 42px below the header and the model's VISIBLE top 52px
		   below it — the PNG's first opaque row is 71 of 1100 (6.45%), so the figure starts
		   ~25px inside its own element box (M-26). Measured after: box 16px, visible model
		   26px, at 320/375/430, logged out and logged in.
		   --hero-top exists so the .admin-bar rule below derives from the same number instead
		   of repeating it (TECH-021's lesson: never a hard-coded sum). */
		--hero-top: 84px;
		padding-top: calc(var(--hero-top) + var(--topbar-h));

		/* GAP 3, "Apply as a professional" -> features — REQ-070 / AC-094 / TECH-047.
		   Was clamp(3rem, 8vw, 4.5rem) = 48px at 375px. Only 48px of the measured 138px gap
		   was ever the hero's: 56px is .features' own padding-block and ~34px its list's
		   internal placement, both out of scope by REQ-070. 1.5rem is the same step as
		   .hero__scene's margin-bottom below, so the hero has one spacing step instead of
		   three. Measured 138px -> 114px, against a page inter-section rhythm of 94px. */
		padding-bottom: 1.5rem;
	}

	/* E-36 / AC-096 / TECH-046 — MOVED UP from the max-width: 600px block (section 9).
	   It is not only a follow-on from the reduced padding above: scoped to 600px it left a
	   defect on the shipped build. Between 601 and 899px core makes #wpadminbar `fixed`, the
	   header moves down 46px (<=782) or 32px (<=899), and with no hero compensation the
	   header's lower edge sat at 114px against 110px of hero padding — 4px of overlap today
	   (M-29), which the reduced padding would have widened to 30px. One rule at <=899 covers
	   every case: core already sets the token to 46px below 782px and 32px above it. */
	.admin-bar .hero {
		padding-top: calc(var(--hero-top) + var(--topbar-h) + var(--wp-admin--admin-bar--height, 32px));
	}

	.hero__content {
		min-height: 0;
		/* GAP 2, scene -> badge — REQ-069 / AC-093 / TECH-047. styles.css:1047 and :1302 give
		   .hero__content a `gap` written as the HORIZONTAL gutter of the desktop two-column
		   grid (:1302 wins, clamp(2rem, 3vw, 4rem) = 32px at 375px); TECH-025's reorder turned
		   it into a vertical step between the scene and the copy. Removing it leaves
		   .hero__scene's own declared 1.5rem. Measured 72px -> 40px. The pre-reorder
		   margin-bottom: -64px named in the brief (styles.css:1126) is NOT part of this gap:
		   it is already overridden below (M-25). */
		gap: 0;
	}

	.hero__copy {
		/* the copy column stops being a shrink-to-fit centred block: full measure, left */
		align-self: stretch;
		flex: none;
		padding-bottom: 0;
	}

	/* AC-038: model image first, then badge, headline, lede, both calls to action. */
	.hero__scene {
		order: -1;
		/* styles.css:1368 pushes the scene to the bottom with margin-top: auto; with the
		   scene first that would push the copy down instead */
		margin-top: 0;
		margin-bottom: 1.5rem;
		margin-inline: auto;
		max-width: min(100%, 420px);
	}
}

/* --------------------------------------------------------------------------
   2c. HERO PRIMARY CTA — full width of the content column, capped at the lede's measure
   REQ-087 (amended), REQ-090, REQ-091, REQ-092 / AC-108 (corrected), AC-110, AC-111 /
   CN-15, CN-16 (OQ-15, OQ-16).
   Overrides nothing in styles.css; it extends styles.css:629 and :1130
   (`@media (max-width: 600px) { .hero__actions .btn { width: 100% } }`) across the whole
   mobile layer and adds the cap.

   THE RULE IN ONE LINE: the button is the LESSER of the hero's content column and 513px.

   `max-width: 513px` is not a taste value: it is `.hero__lede`'s own `max-width: 42ch`
   (styles.css:1066) computed, so the button's right edge lands on the paragraph's right edge
   instead of 314px past it. Measured without it (WP-05 ISSUE-WP05-06): the button's aspect
   ratio ran 6.7:1 at 375px to 18:1 at 899px, 83% of it empty pill, 284px wider than the
   longest line of text in its own column. The user was shown those numbers and chose the cap
   (OQ-15). A-31's "content column" definition is superseded by it.

   NO LOWER BOUND, and the seam is why. OQ-16 lifted the sub-600px exclusion, so this now
   governs the whole layer — but even taken narrowly it could not stay bounded at 601px: the
   content column already exceeds 513px from about a 558px viewport (measured 515.2 at 560,
   533.6 at 580, 552.0 at 600), so a cap scoped to >=601 would have left a 552px button at
   600px against a 513px button at 601px. One block, one behaviour, no seam.

   TWO declarations on two selectors, because `width: 100%` alone does not do it.
   `.hero__actions` is a shrink-to-fit flex item of `.hero__copy`, and its max-content width is
   set by its longest child — the "Looking for work? Apply as a professional" link — so it
   measures **307.5px at every viewport width from 320 to 1920**. That is why the prototype's
   own sub-600px rule produced a 307.5px button inside a 335px column at 375px, 27.5px short of
   the lede above it, which is the behaviour AC-108 used to describe as correct (ISSUE-WP05-07,
   corrected by CN-16). Stretching the wrapper is what makes 100% resolve against the column.

   The secondary link is untouched (REQ-088, AC-110): it is not a .btn, and `align-items:
   flex-start` on .hero__actions keeps it at its own 307.5px content width inside the stretched
   wrapper — measured unchanged at 375px and 768px, still 44px tall. Height, padding, radius and
   colours are untouched (REQ-091); width is the only property named. Nothing matches at 900px
   and above (REQ-089, AC-109) — 900px is the seam to test, not 1280px.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.hero__actions {
		align-self: stretch;
	}

	.hero__actions .btn {
		width: 100%;
		max-width: 513px;
	}
}

/* --------------------------------------------------------------------------
   2b. HERO FLOATING ELEMENTS — restored on phones, sequenced down the scene
   REQ-076..REQ-084 / AC-099..AC-105 / TECH-048. Blueprint §8.15. Change notes CN-11, CN-12.

   Supersedes the rule that used to sit here: `.hero__scene .chip, .hero__scene .bubble
   { display: none }` below 600px, which TECH-025 added on finding M-7. CN-11 reverses that
   REMEDY, not the finding — the user wants the proof points present on phones, so the
   overlap has to be solved by geometry (REQ-078). The rule is deleted rather than overridden:
   `display`'s two values (flex for .chip, inline-flex for .bubble) belong to styles.css and
   re-declaring them here would hard-code values that could drift (AC-099).

   Correction to the record, measured: M-7's "both over the model's face" was wrong. The head
   occupies y 119..183 at 320px and the topmost element starts at y 233 — they are over her
   torso. The COLLISION was real (89x36px at 320px) and is what these rules fix; the face was
   never covered (M-31).

   The scaling the user asked for already exists and was simply unreachable while the elements
   were hidden: styles.css:1337-1343 carries the phone variant (chip padding .45rem, avatar
   34px, bubble 36px tall). What this block adds is VERTICAL SEQUENCING (A-29): 34% / 52% /
   bottom 18% / bottom 2%, each element keeping its own side and its order, so no two can
   overlap on the vertical axis whatever their widths do. Scaling alone cannot work — at 320px
   the collision needs ~93px off .chip--br's 246px width, which no legible type size delivers.

   WHY <=899 AND NOT <=600 (CN-12, ISSUE-H1, OQ-12). The same chip--br x bubble--gold overlap
   is on the shipped build at EVERY width from 601 to 899px (11x40px, measured at 601, 667,
   700, 768, 782, 844, 899) — and every modern phone in landscape is in that band (iPhone SE
   667, iPhone 14 Pro Max 844), so AC-105 could not pass while AC-103 froze 768px. The user
   ruled: fix it and accept the 768px change. REQ-083 and AC-103 are amended accordingly;
   REQ-034 / AC-053 are untouched — nothing here matches at 1280px and above.

   Legibility floor: 11px (REQ-080 / AC-102), declared here so QA tests this number. These are
   decorative labels inside an aria-hidden scene, which blueprint §8.9 excludes from AC-047's
   16px body-copy floor. The floor is raised to 11px, never lowered: the .6875rem below applies
   only where styles.css:1341 would otherwise compute 10.88px. Measured minimum after: 11px.

   THE FACE BOX, as corrected (ISSUE-WP05-03, blueprint §8.15 revised, TECH-048 amended):
   **the scene box's top edge down to 34% of its height — the chin, not the eye line.** The
   first version of this block used an alpha-channel head box ending at 26.45% of the image,
   which renders at her EYES; it passed while AC-101 failed, and the user then found the chip
   on her jaw at a width in the 601-899px band. Derived: chin at 36.5% of the PNG, rendered at
   height: 104% anchored bottom: 0, so (0.365 x 1.04) - 0.04 = 0.3396 of the scene box. The
   invariant is tested in the LIFTED phase: with chipFloat frozen, every element's rect top
   minus the 8px float lift must sit below that line, and every adjacent gap minus 8px must
   stay positive.

   The 30-38% latitude the first version granted is withdrawn — measured, it contains no
   working value. Do not tune these percentages: at 320px the design has 5.7px of margin and
   that width decides it. The size reduction below 600px is what buys the clearance.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.hero__scene .chip--tl {
		top: 41%;
		left: 0;
	}

	.hero__scene .bubble--gold {
		top: 58%;
		left: 0;
	}

	.hero__scene .chip--br {
		bottom: 14%;
		right: 0;
	}

	.hero__scene .bubble--green {
		bottom: 0;
		right: 0;
	}
}

/* The reduced-motion rule that used to sit here — `@media (max-width: 899px) and
   (prefers-reduced-motion: reduce) { .hero__scene .bubble { animation: none } }` — is
   SUBSUMED by the unbounded category 1 rule above the MOBILE LAYER banner (CN-14, REQ-086,
   AC-107). The user authorised the site-wide fix, the new rule is identical apart from the
   width bound, and keeping both would be the same declaration written twice with one copy
   unreachable. Nothing is lost below 899px: the category 1 rule matches there too. */

@media (max-width: 600px) {
	/* THE SIZE REDUCTION (§8.15 revised) — this is the lever that buys the chin clearance,
	   not the positions. styles.css:1337-1343's phone variant (chip padding .45rem, avatar
	   34px, bubble 36px) leaves a budget of 189px between the chin and the scene's bottom
	   edge against 168px of elements — about 7px per gap, less than the 8px the float alone
	   consumes. Shrinking the three boxes is what makes all four fit below her chin at 320px,
	   so A-28's "report it rather than drop some" escalation is not triggered. */
	.hero__scene .chip {
		padding: .25rem .6rem .25rem .25rem;
	}

	.hero__scene .chip__avatar {
		width: 28px;
		height: 28px;
	}

	.hero__scene .bubble {
		height: 28px;
	}

	/* the 11px floor, true rather than aspirational: styles.css:1341 sets .68rem = 10.88px on
	   this node below 600px and it is the smallest type on the page. Bumped by 0.12px.
	   Above 600px the same node already computes 12px and is left alone — the floor is a
	   minimum, not a target (REQ-080), and CN-12 unfroze the 601-899px band for the overlap
	   only: "everything else in that band remains unchanged". */
	.hero__scene .chip__text span {
		font-size: .6875rem;
	}
}

/* --------------------------------------------------------------------------
   2d. HERO -> FEATURES SEAM — the other half of GAP 3
   Continues REQ-070 / AC-094 / TECH-047 from section 2. Same gap, the part of it that was
   never the hero's to give.

   THE GAP AT REST IS 80px, NOT THE 114px ON RECORD ABOVE. 114px was read before the strip's
   entrance animation had played. avenir.js:840 reveals the rows with
   `gsap.from(kids, { y: 34, autoAlpha: 0 })` on a ScrollTrigger at `top 85%`, so a rect taken
   while they are still parked at their start value is exactly 34px too tall — and that 34px
   is the whole of the "~34px of list placement" section 2 could not account for. The list
   contributes nothing of its own: measured at 375px, `.features__list` margin-top 0,
   padding-top 0, and the first li's layout top equals the ul's top to the pixel (1051.2).
   The transform settles to 0 the moment the strip enters the viewport, and under
   prefers-reduced-motion the reveal never runs at all (avenir.js:754 gates the whole block),
   so 80px is the resting number in every case, including a screenshot of a scrolled page.

   80px = 24px hero padding-bottom (section 2) + 56px from `.features { padding-block: 3.5rem }`
   (styles.css:292). There is no third term. Cutting the features half to 2rem takes the gap
   to 56px; measured 80 -> 56 at 375px and at 700px.

   TOP ONLY, and `padding-bottom` is deliberately NOT restated. The shorthand's bottom edge is
   the distance to the services section, which is not what was reported, and repeating 3.5rem
   here would copy a constant out of a frozen stylesheet for no behaviour. The result is a
   strip held closer to the hero above it (56px) than to the section below it (128px from the
   last row to the services head, unchanged). That asymmetry is intended: the strip has no
   heading of its own, it is the hero's trust line, and grouping it upward is what the
   spacing should say. 56px is also still more than twice the list's own 24px row gap
   (styles.css:293), so the first row reads as the head of a list rather than as one more
   line of the hero.

   Nothing matches at 900px and above — the desktop hero contributes 0 there and the strip
   keeps its full 56px. Measured unchanged at 900, 1280 and 1440.
   -------------------------------------------------------------------------- */
/* RETIRED 2026-09-29: the .features strip was replaced by the tools band (TECH-043 rules
   above the MOBILE LAYER banner), which sets its own padding. The rule that stood here —
   `.features { padding-top: 2rem }` below 900px — had nothing left to match. */

/* --------------------------------------------------------------------------
   3. ABOUT / POLAROIDS — restore the collapsed image column
   REQ-030 / AC-048, AC-050 / TECH-031. Blueprint §8.9.

   The one-word-per-line Caveat script line is not a font-size problem. styles.css:616 adds
   `margin-inline: auto` to .polaroids below 900px, which turns the grid item from stretch to
   shrink-to-fit; all four of its children are absolutely positioned, so its content width is
   0 and `aspect-ratio: 1/1` makes its height 0 too — measured at exactly w:0 h:0, rect
   188..188 at 375px. `.handwriting` (left: 6%) then shrink-to-fits inside a 0px containing
   block and wraps at every word. Restoring the box fixes the script line, both photographs
   and the doodle at once: the about section's entire image column was missing on mobile.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.polaroids {
		width: 100%;
	}

	/* A-11, new design work: at 62% the two photographs run under the script line in the
	   restored square. 54% keeps the overlap that the desktop composition has while leaving
	   the Caveat phrase clear, verified at 320 / 375 / 430. */
	.polaroid {
		width: 54%;
	}

	.polaroid--b {
		top: 24%;
	}

	/* the doodle is 130px fixed; in a 280px-wide square it crowds polaroid--b */
	.doodle {
		width: 92px;
	}
}

/* --------------------------------------------------------------------------
   4. TEAM — the arc becomes a list of member rows
   REQ-024, REQ-027, REQ-031 / AC-036, AC-043, AC-049, AC-056, AC-062, AC-064 / TECH-027.
   Blueprint §8.4.

   This is the feature's largest single defect and its blast radius was wider than reported.
   Measured: with `.fan.is-visible` the phone cards span -38px..413px at a 375px viewport, so
   `document.body.scrollWidth` becomes 413 — and every `position: fixed` element then resolves
   `right: 0` against that 413px box, which is why the header was 413px wide with its nav
   toggle off-screen and why the nav sheet landed at left: 41px clipped on the right. Removing
   the transforms removes all three symptoms at once (finding M-1).

   ALL SEVEN MEMBERS ARE SHOWN. styles.css:978 hides the `--a:3` pair below 700px purely so
   seven would fit the arc; the arc is gone, so the reason is gone. A-12 is void and AC-043 is
   amended to "all seven" (CN-07, PM ruling on ISSUE-M1). The hide rule is NOT re-applied.

   JavaScript-independent, not JavaScript-suppressed: `opacity: 1` is set on .fan__card
   unconditionally rather than on `.fan.is-visible`, so the section is correct with JS
   disabled (AC-062), under reduced motion (AC-056) and before the IntersectionObserver fires.
   The observer keeps running and keeps adding a class that has no effect here.
   Visual language reused from the existing `.role` list in the applicants section (A-11).
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.fan {
		position: static;
		display: flex;
		flex-direction: column;
		gap: .75rem;
		height: auto;
		max-width: none;
		margin: 1.5rem 0 0;
	}

	.fan__card {
		position: static;
		width: auto;
		height: auto;
		margin: 0;
		transform: none;
		opacity: 1;
		transition: none;
		transition-delay: 0s;
		z-index: auto;
	}

	/* styles.css:967 is `.fan:not(.is-visible) .fan__card` at (0,3,0) and would otherwise
	   keep the pre-reveal transform on a page where the observer has not fired yet */
	.fan:not(.is-visible) .fan__card {
		transform: none;
	}

	/* This is the rule that makes "all seven" true. styles.css:978 hides the outer pair below
	   700px — `@media (max-width: 700px) { .fan__card[style*="--a:3"] { display: none } }` —
	   purely because seven would not fit the arc. The mobile layer does not RE-APPLY that
	   rule, but it does have to UNDO it: the hide lives in styles.css, which TECH-003 keeps
	   verbatim, so without this the 320px and 375px viewports would still show five.
	   (0,2,0), the same weight as the rule it beats, winning on order. */
	.fan__card[style*="--a:3"] {
		display: list-item;
	}

	.fan__card a {
		display: grid;
		grid-template-columns: 88px 1fr;
		align-items: center;
		gap: 1rem;
		width: 100%;
		height: auto;
		padding: .75rem;
		border: 1px solid var(--border);
		border-radius: var(--radius);
		background: var(--white);
		box-shadow: var(--shadow-sm);
	}

	/* the desktop hover lift scales the card 1.04; on a full-width row that pushes the row
	   past both viewport edges, which REQ-024 forbids */
	.fan__card:hover a {
		transform: none;
		box-shadow: var(--shadow-sm);
	}

	.fan__card img {
		width: 88px;
		height: 88px;
		border-radius: 14px;
	}

	/* the only hover-only affordance on the page that carried information (name and role
	   revealed on hover) becomes permanently visible — REQ-031's last clause */
	.fan__label {
		position: static;
		padding: 0;
		background: none;
		color: var(--charcoal-600);
		font-size: 1rem;
		line-height: 1.35;
		opacity: 1;
		transform: none;
	}

	.fan__label strong {
		font-size: 1.0625rem;
		color: var(--green-900);
	}
}

/* --------------------------------------------------------------------------
   5. SERVICES — the 3D coverflow becomes a stack of six media cards
   REQ-024, REQ-028, REQ-030 / AC-044, AC-047, AC-050, AC-056, AC-062 / TECH-028.
   Blueprint §8.5.

   The JavaScript half of this is WP-01's: render() writes transform, opacity and zIndex as
   INLINE styles every frame, which no stylesheet can outrank without !important, so the
   renderer is gated off below 900px instead. What is left for CSS is a real layout for six
   cards that are no longer being positioned by script. The per-card description paragraph
   is real markup (patterns/section-services.php, WP-01) with a `display: none` default in
   wp-adaptations.css; this is the rule that turns it on.

   The card idiom is the prototype's own `.card` (image, then an icon overlapping its bottom
   edge, then a title and a paragraph) rather than a new one (A-11).
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	/* it currently breaks out of the container to 100vw for the 3D rack */
	.coverflow {
		width: auto;
		margin-left: 0;
	}

	.coverflow__stage {
		height: auto;
		perspective: none;
		overflow: visible;
		cursor: auto;
		touch-action: auto;
		user-select: auto;
		-webkit-user-select: auto;
	}

	.coverflow__rack {
		position: static;
		display: grid;
		gap: 1.25rem;
		width: auto;
		height: auto;
		transform-style: flat;
	}

	.cover {
		position: static;
		display: flex;
		flex-direction: column;
		width: auto;
		height: auto;
		aspect-ratio: auto;
		background: var(--white);
		border: 1px solid var(--border);
		box-shadow: var(--shadow-sm);
		will-change: auto;
	}

	.cover img {
		height: auto;
		aspect-ratio: 4 / 3;
	}

	/* the dark gradient exists to let white text sit over the art; the text is out of the
	   image now */
	.cover::after {
		display: none;
	}

	/* the JS-appended dimming layer. .cover is static here, so an absolutely positioned
	   child would resolve against .coverflow and stretch over the whole section. It is
	   already held at opacity 0 by render()'s disabled branch; this removes the box as well.
	   It stays the element's lastElementChild, which is what avenir.js reads (R-30). */
	.cover .shade {
		display: none;
	}

	.cover__icon {
		position: static;
		/* the .card__icon idiom: overlap the media's bottom edge with a white ring */
		margin: -22px 1.25rem .5rem;
		background: var(--green-100);
		border-color: transparent;
		box-shadow: 0 0 0 4px var(--white);
		color: var(--green-900);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
	}

	.cover__title {
		position: static;
		margin: 0 1.25rem;
		color: var(--green-900);
		font-size: 1.125rem;
	}

	/* AC-044: every card carries its own full description now */
	.cover__desc {
		display: block;
		margin: .4rem 1.25rem 1.25rem;
		color: var(--charcoal-600);
		font-size: 1rem;
		line-height: 1.55;
	}

	/* the caption describes "the active card", which has no meaning in a stack, and its
	   link reads "Request this role" for the same reason. The content is not lost: the same
	   title and description are now on every card (recorded as a deliberate substitution,
	   R-35). Hiding .coverflow__controls also removes its six 8x8px dots from the page,
	   which AC-049 would otherwise have to account for. */
	.coverflow__caption,
	.coverflow__controls {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   6. INDUSTRIES — readability and touch only; the layout already works
   REQ-029, REQ-030, REQ-031 / AC-045, AC-047, AC-049 / TECH-029. Blueprint §8.6.

   Measured at 320 and 375px: styles.css:823 already unsticks .spread, flattens
   .spread__sticky, restores the clamped paragraphs and drops to a 2-up grid, :832 gives one
   column below 600px, and render()'s existing disabled branch clears every inline transform
   and z-index (CN-03 / TECH-020). Eight legible cards, no overlap, no clipping. So this
   section needs the same readability and touch work as everywhere else and nothing more —
   and avenir.js's industries block, which CN-03 fixed, is not touched.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	/* 13.44px, the smallest running prose on the page */
	.spread-card p {
		font-size: 1rem;
		line-height: 1.5;
	}

	/* the disabled render branch parks the bar at 100%, so on mobile it is a full green rule
	   that tracks nothing */
	.spread__meta .ind-progress {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   7. TYPOGRAPHY — the body-copy floor
   REQ-030 / AC-047, AC-048 / TECH-031. Blueprint §8.9.

   AC-047 (as amended by CN-07) reads: body copy, as enumerated in blueprint §8.9, is at
   least 16px. That enumeration is the contract — QA tests the same list this builds to. The
   full IN list and where each selector is handled:

     .section__lede .............. 17px already, not touched (1rem is a floor, not a target)
     .hero__lede ................. 17px already, not touched
     .about__text ................ 16px already, not touched
     .cta__lede .................. 16px already, not touched
     .quote p .................... 17px already, not touched
     .spread-card p .............. 13.44px -> set in §6 above, with its line-height
     .cover__desc ................ set in §5 above, with the rest of the card
     .fan__label ................. 11.2px -> set in §4 above, with the rest of the row
     .card__body p ............... 14.4px  |
     .checks li .................. 14.4px  |
     .value__steps p ............. 14.4px  |
     .step p ..................... 14.4px  |- set here
     .coverflow__desc ............ 15px    |
     .features__list span ........ 13px    |
     .footer__col a / li ......... 14px    |
     .footer__blurb .............. 13px    |
     .role__body span ............ 13px    |

   OUT of the definition and deliberately left at their design sizes: .eyebrow, .pill,
   .badge, .quote__flag, .stat__label, .placeholder-note, .stars, .footer__bottom,
   .footer__legal, .btn, .nav__cta, .card__meta, .quote footer span, .coverflow__title,
   .cover__title, .value__num, .step__num, .chip__text, .bubble, .brand__word, .tile__label
   span, .skip-link. Forcing 16px onto a label does not make it more readable; it dismantles
   the type hierarchy the design is made of.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	.card__body p,
	.checks li,
	.value__steps p,
	.step p,
	.coverflow__desc,
	.footer__col a,
	.footer__col li,
	.role__body span {
		font-size: 1rem;
	}

	/* .footer__blurb measures 13px, not the .875rem its own rule sets: `.footer__brand > p`
	   (styles.css:565) is (0,1,1) and outweighs `.footer__blurb` (0,1,0). Matching that
	   weight with an element+class selector is the lowest specificity that works; it wins on
	   order. The !important on that rule's colour and font-weight is not touched. */
	p.footer__blurb {
		font-size: 1rem;
	}

	/* AC-048's other clause: no line may contain a single word because the container is too
	   narrow. `text-wrap: balance` is already on .hero__title (styles.css:1178); at element
	   specificity it reaches every heading in every section and every fallback template
	   without naming one of them. */
	h1,
	h2,
	h3 {
		text-wrap: balance;
	}
}

@media (max-width: 600px) {
	/* REQ-030, "headings scaled to their container so that no line breaks mid-phrase into
	   single words". Measured at 320px: the headline computes to 36.8px, where "Dedicated
	   Remote" is 299px against 280px of column, so it broke as
	   "Dedicated" / "Remote Talent." / "Built for Your" / "Growth." — a single word MID
	   phrase, which is the case REQ-030 names. At this scale it computes to 30.1px at 320px
	   and the same phrase sets as "Dedicated Remote" / "Talent.", so every break lands at the
	   end of a phrase rather than inside one. The two phrases are separated by a <br> in the
	   pattern, so `text-wrap: balance` can only balance within each of them. */
	.hero__title {
		font-size: clamp(1.875rem, 1.2rem + 3.4vw, 2.75rem);
	}
}

/* --------------------------------------------------------------------------
   8. TOUCH TARGETS — 44 x 44 with 8px of separation, and the carousel arrows back
   REQ-031, REQ-032 / AC-049, AC-051 / TECH-032. Blueprint §8.10.

   Measured before: 19 controls under 44 x 44 at 375px, and the nav toggle squeezed to
   34 x 44 at 320px because it has no `flex: none` in the header row. Three techniques, in
   order of preference: (1) grow the box where the element is already block-level;
   (2) inline-flex + min-height for links inside prose, which grows the hit box without
   touching the type; (3) an ::before hit-area overlay where the visual must not change.

   THE SEPARATION CLAUSE IS NOT FREE. 44px boxes with 8px of clearance need >=52px centre to
   centre. The carousel dots are 8px with a .5rem gap — 16px apart — so naive 44px hit areas
   would overlap and a tap between two dots would activate the wrong one. Below they become
   12px with a 2.5rem (40px) gap: inactive neighbours sit exactly 52px apart, and the 34px
   active pill leaves 19px. Three dots occupy 138px at a 320px viewport.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
	/* --- technique 1: grow the box --- */
	.btn {
		min-height: 44px;
	}

	/* without this the flex row squeezes the toggle to 34 x 44 at 320px (finding M-9) */
	.nav-toggle {
		flex: none;
	}

	/* ...but `flex: none` on its own only converts a squeezed toggle into a clipped one.
	   MEASURED at 320px, BEFORE this feature: the header row needs 317px (brand 241 + a 2rem
	   gap + the toggle) and has 280px, so the toggle rendered at x 294..337 — 17px of a 44px
	   control outside a 320px viewport, which REQ-024 ("no element clipped at a viewport
	   edge") and AC-064 forbid, and AC-049 needs the whole 44px to be reachable. Both parts
	   of the squeeze are fixed here rather than by shrinking the logo: the row's gap only
	   matters when space is tight (the two items are already pushed to the edges by
	   justify-content: space-between), and letting the brand shrink lets the wordmark take a
	   second line at the narrow end while staying on one line wherever it fits — at 375px the
	   row needs 300px of 335px and nothing wraps. */
	.header__inner {
		gap: .75rem;
	}

	.brand {
		flex: 0 1 auto;
		min-width: 0;
	}

	.brand__mark {
		flex: none;
	}

	.brand__word {
		white-space: normal;
		line-height: 1.05;
	}

	/* the nav sheet's rows. styles.css gives them padding: .9rem 0 and a divider; the gap is
	   what buys the 8px of separation AC-049 asks for between stacked targets. */
	.nav__list {
		gap: .75rem;
	}

	.nav__actions {
		gap: .75rem;
	}

	.nav__list a,
	.nav__link {
		display: flex;
		align-items: center;
		min-height: 44px;
	}

	.nav__cta {
		min-height: 44px;
	}

	/* --- technique 2: inline-flex hit box, type unchanged --- */
	.badge,
	.link-more,
	.ind-card__link,
	.hero__alt,
	.footer__col a,
	.footer__legal a,
	.cta__secondary,
	.skip-link {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		/* AC-049 is 44 x 44, not 44 tall: the three footer legal links measure 70-85px wide,
		   but a short one ("Terms") would not, and min-width costs nothing to the long ones */
		min-width: 44px;
	}

	/* the insights section head puts "View All Articles" directly above the first card's
	   image link; at 44px tall the two hit boxes end up 5px apart */
	.section__head--row .btn {
		margin-bottom: .5rem;
	}

	/* the insights card's title link is 23px tall wherever the title fits on one line
	   (measured 415 x 23 at 568x320 and 340 x 23 at 430) */
	.card--post h3 a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}

	/* the only <input> on the page: 42px tall, so it misses by 2 */
	.cta__form input {
		min-height: 44px;
	}

	.social a {
		width: 44px;
		height: 44px;
	}

	.social {
		gap: .75rem;
	}

	/* --- technique 3: ::before hit-area overlay, visual unchanged ---
	   ::after is already the timed fill on these buttons, so ::before is free. The visible
	   dot cannot simply be enlarged: its size is the design and its width is animated. */
	.carousel__dots {
		gap: 2.5rem;
	}

	.carousel__dots button {
		width: 12px;
		height: 12px;
		/* styles.css:625 sets overflow: hidden on these buttons, which CLIPS the ::before
		   hit-area below to the 12px dot — measured with elementFromPoint, a tap 20px above
		   the dot's centre missed it entirely. The overflow is not load-bearing: the timed
		   fill (::after) is inset: 0 with border-radius: inherit, so it never paints outside
		   the button in the first place. */
		overflow: visible;
	}

	.carousel__dots button.is-active {
		width: 34px;
	}

	.carousel__dots button::before {
		content: "";
		position: absolute;
		left: 50%;
		top: 50%;
		width: 44px;
		height: 44px;
		transform: translate(-50%, -50%);
	}

	/* --- AC-051: the arrows come back, on a control row under the track ---
	   styles.css:620 hides them below 900px, but AC-051 requires them to change the slide at
	   phone width and AC-049 requires them to be 44 x 44, so resizing them is not enough —
	   they have to exist. This reuses the grid .carousel already is. */
	.carousel {
		grid-template-columns: 1fr auto 1fr;
		gap: 1rem 0;
	}

	.carousel__track {
		grid-column: 1 / -1;
		grid-row: 1;
	}

	.carousel__btn {
		display: grid;
		grid-row: 2;
		width: 44px;
		height: 44px;
	}

	.carousel__btn--prev {
		grid-column: 1;
		justify-self: end;
		margin-right: 6px;
	}

	.carousel__btn--next {
		grid-column: 3;
		justify-self: start;
		margin-left: 6px;
	}
}

/* --------------------------------------------------------------------------
   9. ADMIN BAR BELOW 600px — the header and the sheet clear it
   (the hero's compensation moved to section 2's max-width: 899px block — TECH-046, M-29)
   E-11 / AC-060 / TECH-033. Blueprint §8.8. Closes QA TEST-012.

   Core makes #wpadminbar `position: absolute` below 600px so it scrolls away with the page,
   and CN-04 correctly returned the header to `top: var(--topbar-h)` there. The consequence
   nobody measured at the time: at scroll 0 the 46px bar sits on top of the fixed header
   (z-index 100000 vs 100), covering the logo and the nav toggle — QA TEST-012, where
   elementFromPoint at the centre of the toggle returned the admin bar and the mobile menu
   could not be opened until the page was scrolled.

   The trigger is `is-top`, the scroll-derived state class that applyHeaderState() writes
   (WP-01, TECH-033). `is-scrolled` cannot be used: it is `scrolled || menuOpen`, so opening
   the menu at the top of the page would drop the offset. By the time `is-top` is removed
   (scrollY > 40) the bar has scrolled to within 6px of the top and the scrolled header's own
   12px padding clears it. Logged-out visitors never match .admin-bar; desktop never matches
   the query. Every offset is token-driven, never a hard-coded sum (TECH-021's lesson).
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
	.admin-bar .header.is-top {
		top: calc(var(--topbar-h) + var(--wp-admin--admin-bar--height, 46px));
	}

	/* AC-060 names three things, and the blueprint's §8.8 specifies only the first. The
	   other two follow from it: moving the header down moves its lower edge below the hero's
	   top padding, so the hero's first element would sit under the header that was just moved
	   to clear the bar. The sheet has the same problem for the same reason. Both are the same
	   token-driven offset.

	   The `.admin-bar .hero` rule that used to sit here MOVED to the max-width: 899px hero
	   block (section 2) under TECH-046: scoped to 600px it left 4px of header-over-hero
	   overlap at 601-899px logged in on the shipped build (M-29). It is the same offset,
	   derived from --hero-top, and it still covers everything this block covered. */
	.admin-bar .header.is-top .nav {
		padding-top: calc(var(--topbar-h) + 84px + var(--wp-admin--admin-bar--height, 46px));
	}
}

/* Tools strip, mobile (2026-09-29) / TECH-024, TECH-043. The label stacks above the
   marquee, which then spans the full container width. */
@media (max-width: 899px) {
	.tools__inner {
		flex-direction: column;
		gap: 1rem;
	}

	.tools__marquee {
		width: 100%;
	}

	.tools__list li {
		font-size: 1.125rem;
	}
}

/* FAQ, mobile (2026-09-29) / TECH-024, TECH-043. One column; the head stops being sticky
   so it scrolls away above the questions. */
@media (max-width: 899px) {
	.faq__grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.faq__head {
		position: static;
	}
}

/* FAQ, phone (2026-09-29) / TECH-024, TECH-043. Tighter card padding so the question keeps
   most of a 320px row. */
@media (max-width: 600px) {
	.faq__q {
		padding: 1.25rem 3.25rem 1.25rem 1.25rem;
		font-size: 1.0625rem;
	}

	.faq__q::before,
	.faq__q::after {
		right: 1.25rem;
	}

	.faq__a {
		padding: 0 1.25rem 1.25rem;
		font-size: 1rem;
	}
}

/* Talk with our team, mobile (2026-09-29) / TECH-024, TECH-043. One column; on phones each
   option's action drops under its text so the description keeps the row. */
@media (max-width: 899px) {
	.talk__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 600px) {
	.talk__option {
		flex-wrap: wrap;
	}

	.talk__action {
		margin-left: calc(48px + 1.1rem);
	}

	.talk__note {
		font-size: 1.35rem;
	}

	.chat__head,
	.chat__body,
	.chat__composer {
		padding-inline: 1.1rem;
	}

	.chat__msg {
		max-width: 90%;
	}
}

/* Careers, mobile (2026-09-29) / TECH-024, TECH-043. The growth card centres under the copy
   and its notes tuck inside the gutter instead of hanging off the right edge. */
@media (max-width: 899px) {
	.growth {
		margin: 2.5rem auto 1.5rem;
	}

	.growth__note--tracks,
	.growth__note--review {
		right: -.5rem;
	}
}

@media (max-width: 600px) {
	.growth {
		padding: 1.75rem 1.25rem 1.25rem;
	}

	.growth__note--tracks {
		top: -2.5rem;
	}
}

/* Contact page body, mobile (2026-09-29) / TECH-024, TECH-043. One column below 900px; the
   two-up field rows stack on phones. */
@media (max-width: 899px) {
	.contact-intro__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 600px) {
	.contact-form__row {
		grid-template-columns: minmax(0, 1fr);
	}

	.contact-form__submit {
		align-self: stretch;
		justify-content: center;
	}
}

/* Inner-page hero, mobile (2026-09-29) / TECH-024, TECH-043. The header is shorter below
   900px (see the hero rule above), so the hero clears less. */
@media (max-width: 899px) {
	.page-hero {
		padding-top: calc(120px + var(--topbar-h));
	}

	.page-hero__lede {
		font-size: 1.0625rem;
	}
}

/* Form toasts, phone (2026-09-29) / TECH-024, TECH-043. Centred along the bottom edge. */
@media (max-width: 600px) {
	.avenir-toasts {
		right: 1rem;
		bottom: 1rem;
		left: 1rem;
		width: auto;
	}
}

/* Services catalog, mobile (2026-09-29, relaid 2026-10-06) / TECH-024, TECH-043. Below 1100px
   the spread stacks: photo (now landscape, letter badge still on it) above the text, in document
   order on every line. Below 700px a service row stacks too — number, title, description, link —
   so nothing is squeezed beside the text. */
@media (max-width: 1099px) {
	.svc-line__grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 2rem;
	}

	.svc-line:nth-child(even) .svc-line__grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.svc-line:nth-child(even) .svc-line__media {
		order: 0;
	}

	/* `relative`, not `static`: the image and letter badge are absolutely positioned inside
	   the figure, so the figure must stay a containing block when it stops being sticky.
	   (Shipped as `static` for an hour on 2026-10-06, which emptied every photo box on phones.)
	   `top: auto` clears the sticky offset, which would otherwise shift a relative box down. */
	.svc-line__media {
		position: relative;
		top: auto;
		aspect-ratio: 16 / 9;
		max-height: 360px;
	}
}

@media (max-width: 699px) {
	.svc-row {
		grid-template-columns: minmax(0, 1fr);
		row-gap: .35rem;
		padding-block: 1.25rem;
	}

	.svc-row__num {
		padding-top: 0;
	}

	.svc-row__more {
		grid-column: 1;
		margin-top: .25rem;
	}
}

/* About page, mobile (2026-09-29, relaid 2026-10-06) / TECH-024, TECH-043. Everything goes to
   one column in document order. The promise row stacks label / statement / figures; the
   owners stack with their top rules; the banner stacks photo, text, button. */
@media (max-width: 899px) {
	.about-intro {
		padding-top: calc(120px + var(--topbar-h));
	}

	.about-intro__grid,
	.promise__grid,
	.owners__list,
	.operate__list,
	.operate__banner {
		grid-template-columns: minmax(0, 1fr);
	}

	.about-intro__photo {
		aspect-ratio: 16 / 10;
		max-height: 360px;
	}

	.promise__grid {
		gap: 1rem;
	}

	.promise__stats {
		margin-top: .5rem;
	}

	.owner {
		padding: 1.25rem 0 1.5rem;
	}

	.owner__bio {
		max-width: 56ch;
	}

	.operate__banner {
		gap: 1.25rem;
		justify-items: start;
	}

	.operate__banner-photo {
		width: 100%;
		aspect-ratio: 16 / 9;
	}
}

@media (max-width: 600px) {
	.promise__stats {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 1rem;
	}
}

/* Careers open roles, mobile (2026-09-29) / TECH-024, TECH-043. Role cards wrap: tags and
   Apply drop under the text; dialog fields stack on phones. */
@media (max-width: 899px) {
	.job-card {
		flex-wrap: wrap;
	}

	.job-card__body {
		flex-basis: calc(100% - 48px - 1.25rem);
	}

	.job-card__tags {
		flex: 1;
		justify-content: flex-start;
		margin-left: calc(48px + 1.25rem);
	}
}

@media (max-width: 600px) {
	.job-card__tags {
		margin-left: 0;
	}

	.apply-form__row {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Consultation booking, mobile (2026-09-29) / TECH-024, TECH-043. Cards stack below 1000px;
   calendar and slots stack, and field pairs go single on phones. */
@media (max-width: 999px) {
	.booking {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 600px) {
	.booking__picker,
	.booking__row {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Single job page, mobile (2026-09-29) / TECH-024, TECH-043. The apply card moves above the
   description and stops being sticky. */
@media (max-width: 899px) {
	.job-detail__grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.job-detail__apply {
		position: static;
		order: -1;
	}
}

/* 404 page, mobile (2026-09-29) / TECH-024, TECH-043. Page cards go three, then two, then one. */
@media (max-width: 1099px) {
	.not-found__pages {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 600px) {
	.not-found__pages {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.not-found__search .btn {
		padding-inline: 1rem;
	}
}

@media (max-width: 400px) {
	.not-found__pages {
		grid-template-columns: minmax(0, 1fr);
	}
}
