/**
 * Earnest Built — Components.
 *
 * M2 scope only: the one real component this stage needs (the global
 * primary button). No secondary/ghost/inverse variants, no page-specific
 * components — those are later milestones, per the approved M2 proposal
 * (Part D).
 */

/* ---------- Global form fields ----------
   Field/label/focus-state appearance only, per Part D's original M2
   scope — this was approved but missed in the first pass; added here as
   part of bringing the foundation to full completion, not a new
   feature. Generic element selectors (not the reference site's bespoke
   .eb-field__control classes) since the only real front-end form right
   now is the default WP search widget — no real contact form exists
   yet (M4). Underline style matches the reference exactly. */
label {
	font-family: var(--font-body);
	font-size: var(--type-eyebrow);
	font-weight: 600;
	letter-spacing: var(--eyebrow-tracking);
	text-transform: uppercase;
	color: var(--text-secondary);
	display: block;
	margin-bottom: 6px;
}
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="search"],
input[type="password"],
input[type="number"],
textarea,
select,
/* WP core's block-library CSS styles Gutenberg block inputs (e.g. the
   Search block powering the sidebar widget) by class at a specificity
   the plain attribute selectors above can't beat — confirmed via
   computed styles on the live page, not assumed. Same class of
   third-party-chrome override as the Divi fixes above. */
.wp-block-search__input {
	font-family: var(--font-body);
	font-size: 17px !important;
	color: var(--text-primary) !important;
	background: transparent !important;
	border: none !important;
	border-bottom: 1px solid var(--border-strong) !important;
	border-radius: 0 !important;
	padding: 12px 0 !important;
	width: 100%;
	transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="search"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
textarea:focus,
select:focus,
.wp-block-search__input:focus {
	border-bottom-color: var(--accent) !important;
	box-shadow: 0 1px 0 var(--accent);
}
input::placeholder,
textarea::placeholder {
	color: var(--text-tertiary);
}
select {
	appearance: none;
	background-image:
		linear-gradient(45deg, transparent 50%, var(--eb-ink) 50%),
		linear-gradient(135deg, var(--eb-ink) 50%, transparent 50%);
	background-position: calc(100% - 12px) 55%, calc(100% - 7px) 55%;
	background-size: 5px 5px;
	background-repeat: no-repeat;
	cursor: pointer;
}
textarea {
	resize: vertical;
}

/* ---------- Button ----------
   Sharp corners, one primary variant only (per Part D). Background sits
   on --accent (real orange) with --accent-ink text — this pairing is
   its own contrast check (dark ink on bright orange), independent of
   whatever section background the button itself sits on, so it isn't
   affected by the orange-on-light-background contrast issue flagged for
   text/borders/focus rings in the M1 audit. */
.eb-btn {
	font-family: var(--font-body);
	font-size: var(--type-button);
	font-weight: 600;
	letter-spacing: var(--button-tracking);
	text-transform: uppercase;
	line-height: 1;
	border: 1px solid transparent;
	border-radius: 0;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 13px 26px;
	text-decoration: none;
	transition:
		background-color var(--dur-fast) var(--ease-standard),
		color var(--dur-fast) var(--ease-standard),
		border-color var(--dur-fast) var(--ease-standard),
		transform var(--dur-fast) var(--ease-standard);
}
.eb-btn:active {
	transform: translateY(1px);
}
.eb-btn:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}

.eb-btn--primary {
	background: var(--accent);
	color: var(--accent-ink);
}
.eb-btn--primary:hover {
	background: var(--accent-hover);
	color: var(--accent-ink);
}

/* ---------- Wordmark + accent utility ----------
   Shared by the Divi Theme Builder Global Header and Global Footer (M2).
   Real markup targeted directly against Divi's own generated classes
   (.et-l--header / .et-l--footer wrap the whole template; .et_pb_row /
   .et_pb_menu carry the eb-* classes assigned in the Theme Builder) —
   confirmed against the live rendered HTML, not assumed. */
.accent {
	color: var(--accent);
}
.eb-wordmark {
	font-family: var(--font-display);
	letter-spacing: .04em;
	text-transform: uppercase;
	font-size: 26px;
	line-height: 1;
}
/* Logo mark + wordmark pairing — matches the reference site's real
   Header/Footer markup exactly (logo-mark-white.svg + wordmark, flex
   row, gap 11px). Real, approved brand asset (not FPO).
   .eb-footer__brand is a plain div with the img/span as real direct
   children, so flex applies to it directly. .eb-header-brand is a Divi
   TEXT module, though — confirmed via live DOM that Divi always wraps a
   Text module's rich content in its own .et_pb_text_inner > p, so the
   img/span actually live two levels deeper than .eb-header-brand itself.
   Putting flex on .eb-header-brand did nothing for their layout (it has
   only one child, .et_pb_text_inner); the real flex container has to be
   that inner <p>. This was masked at wider viewports by a Divi default
   that happened to lay the <p> out correctly there, and only broke
   visibly once Divi's own phone-width responsive CSS reverted it. */
.eb-footer__brand {
	display: flex;
	align-items: center;
	gap: 11px;
}
.eb-header-brand .et_pb_text_inner p {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 11px;
	margin: 0;
}
.eb-header-brand img {
	height: 46px;
}
.eb-footer__brand img {
	height: 44px;
}

/* ---------- Global Header ----------
   Static single state only (M2) — the reference site's scroll-triggered
   transparent-to-solid nav swap is explicitly deferred to M6. Confirmed
   safe orange-on-black context (see M1 audit) for both the nav-link hover
   color and the CTA button. */
.et-l--header {
	background: var(--eb-black);
	color: var(--text-inverse);
	/* Reference (app/globals.css) sticks .eb-header at position:sticky;top:0;
	   z-index:50 — this wrapper is the real rendered equivalent (confirmed via
	   getBoundingClientRect/getComputedStyle on the live page: this is the
	   element whose height must equal the reference's 76px, and no ancestor
	   in the chain carried any sticky/fixed positioning before this). Divi's
	   Theme Builder header template has no separate "fixed nav" toggle to
	   conflict with here — this is the only mechanism producing sticky
	   behavior, so there's no duplicate-sticky risk between Divi JS and CSS. */
	position: sticky;
	top: 0;
	z-index: 50;
}
/* Divi's own section wrapper ships a default opaque white background
   that paints over the dark surface set above it, on both header and
   footer — confirmed via computed styles on the live page, not assumed.
   Neutralizing it here is the only way the real background is visible;
   nothing else in this cascade can reach a Divi-generated section. */
.et-l--header .et_pb_section,
.et-l--footer .et_pb_section {
	background-color: transparent;
}
/* Divi's own section wrapper also ships a default ~50-54px top/bottom
   padding (confirmed via computed styles: 50px 0px measured live), stacked
   on top of the .eb-header row's own 22px vertical padding below — removing
   only this section padding takes the header from ~216-224px down to
   ~116px (the row's own height), still short of the reference's exact
   76px. Scoped to the header section only — the footer section carries the
   same Divi default but was not part of this approved patch's scope, so it
   is left untouched here. */
.et-l--header .et_pb_section {
	padding: 0;
}
.eb-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	/* Reference (.eb-nav, app/globals.css) is a fixed height:76px with no
	   vertical padding — content is centered via align-items, not padded
	   into place. The row's own 22px top/bottom padding (measured live)
	   was the second contributor to the height gap, on top of the Divi
	   section padding removed above: 22+22 plus content still landed at
	   116.3px total, not 76px. Matching the reference's own mechanism
	   (fixed height, horizontal-only padding) instead of guessing at a
	   smaller padding value. */
	height: 76px;
	padding: 0 var(--gutter);
	gap: var(--space-5);
	/* Divi's own responsive column system marks both of this row's
	   columns et_flex_column_24_24_phone (100% width each at phone
	   sizes) — its own default assumption is that they stack (wrap) at
	   that breakpoint. !important is deliberate and confirmed necessary:
	   a plain (non-important) nowrap here still computed as "wrap" live
	   at ~560-960px widths — Divi's own phone/tablet column-stacking rule
	   wins the cascade at this specificity without it, which let the
	   second column (hamburger toggle) drop below the header's fixed
	   76px height entirely. nowrap keeps both columns on one line,
	   matching the reference's single-row nav at every width. */
	flex-wrap: nowrap !important;
}
/* Header: transparent over the hero/page top, solid page color once scrolled.
   header.js toggles .scrolled on .eb-header at scrollY > 40; the fill goes on the
   full-width header SECTION (selected via :has) so it spans edge-to-edge while the
   row stays transparent. Footer is untouched. */
/* Make the whole header stack transparent by default — the Theme Builder header
   WRAPPER (.et-l--header), the section, and the row — so no Divi-set dark fill
   shows through before scroll. The .scrolled paper fill is more specific, so it
   wins once the JS adds the class. */
body #page-container .et-l--header,
body #page-container .et-l--header .et_pb_section,
body #page-container .et-l--header .et_pb_row,
body #page-container .et_pb_section:has(.eb-header),
body #page-container .eb-header {
	background-color: transparent !important;
	background-image: none !important;
	box-shadow: none;
}
body #page-container .et_pb_section:has(.eb-header) {
	transition: background-color .3s var(--ease-standard), box-shadow .3s var(--ease-standard);
}
body #page-container .et_pb_section:has(.eb-header.scrolled) {
	/* Translucent paper + backdrop blur (glassy, like JDG) rather than a flat
	   opaque fill, so the content faintly shows through as it scrolls under. */
	background-color: rgba(250, 247, 241, 0.82) !important;
	backdrop-filter: blur(18px);
	-webkit-backdrop-filter: blur(18px);
	box-shadow: 0 8px 24px -16px rgba(23, 21, 20, 0.30);
}
/* Pin the header so it floats OVER the hero (JDG pattern) instead of sitting as a
   solid bar above it — that overlap is what makes the transparent state reveal the
   hero rather than the cream page background behind a static header. Divi's own
   Fixed Position toggle can silently reset, so guarantee it in CSS. Public
   visitors get top:0; the logged-in WordPress admin bar offsets it. */
body #page-container .et-l--header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 500;
	margin: 0 !important;
}
body.admin-bar #page-container .et-l--header { top: 32px; }
@media (max-width: 782px) {
	body.admin-bar #page-container .et-l--header { top: 46px; }
	/* WP's mobile admin bar is absolute and scrolls away, so once the header is
	   solid/scrolled, drop the offset to close the gap above it (logged-in only). */
	body.admin-bar:has(.eb-header.scrolled) #page-container .et-l--header { top: 0; }
}

/* AZ ROC credential — sits below the sub-heading and above the CTA, in the hero
   content column. Cream with a soft shadow for guaranteed contrast; meets the AZ
   Registrar of Contractors "home page, clearly visible, appropriately sized, not
   the footer" rule. */
.eb-hero3__roc {
	margin: -18px 0 40px; /* pulled up close to the sub-heading; larger gap before the CTA */
	font-family: var(--font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--text-inverse);
	text-shadow: 0 1px 14px rgba(0, 0, 0, .45);
}
/* Homepage (dark hero) before scroll: the transparent header sits over a dark
   image, so flip the wordmark, nav links, and the mark to light. Once .scrolled
   (solid paper) the base ink treatment applies again. Light-hero pages keep the
   base ink treatment throughout. */
body.eb-hero-dark .eb-header:not(.scrolled) .eb-header-brand .eb-wordmark,
body.eb-hero-dark .eb-header:not(.scrolled) .eb-nav-menu .et-menu > li > a {
	color: var(--eb-paper);
}
body.eb-hero-dark .et-l--header .eb-header:not(.scrolled) img[src*="logo-mark"] {
	content: url(../logo/logo-mark-eb.svg);
}
/* Scroll progress bar — pinned to the header's bottom edge, created by header.js.
   .eb-header is static (the fixed behavior lives on Divi's header wrapper), so
   position:relative here is safe and gives the bar its anchor. */
.eb-header { position: relative; }
.eb-scroll-bar {
	position: absolute;
	left: 0;
	bottom: 0;
	height: 3px;
	width: 0;
	background: var(--accent);
	opacity: 0;
	pointer-events: none;
	transition: width .1s linear, opacity .2s var(--ease-standard);
	z-index: 2;
}
.eb-header-brand .eb-wordmark {
	color: var(--eb-ink);
}
/* !important is deliberate and scoped to exactly one property: Divi's
   own et_pb_bg_layout_light utility class ships an opaque white
   background at higher specificity (two Divi classes) than a single
   custom class can reach — confirmed via computed styles on the live
   page, not assumed. This is overriding third-party framework chrome,
   not fighting our own cascade. */
.eb-nav-menu {
	background-color: transparent !important;
}
/* Divi's own .et-menu ships flex-wrap:wrap and align-items:stretch at a
   specificity this single class can't beat (confirmed via computed
   styles: both properties kept resolving to Divi's values even after
   the column-width fix removed the *reason* items would wrap). The
   30/70 column split (Theme Builder) gives the row enough real width;
   these two !importants are what actually let it use that width as one
   line — without them the CTA silently wraps to its own row even
   though there's visibly enough space. */
.eb-nav-menu .et-menu {
	display: flex;
	align-items: center !important;
	flex-wrap: nowrap !important;
	gap: var(--space-6);
	list-style: none;
	margin: 0;
	padding: 0;
}
.eb-nav-menu .et-menu > li > a {
	display: inline-block;
	color: var(--eb-ink);
	font-family: var(--font-body);
	font-size: var(--type-body-sm);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	border-bottom: 2px solid transparent;
	transition: color var(--dur-fast) var(--ease-standard);
}
.eb-nav-menu .et-menu > li:hover > a {
	color: var(--accent);
}
/* WordPress's own current-menu-item class (applied automatically by
   wp_nav_menu, including for Custom Link items whose URL matches the
   current request) — no page-specific work needed for this to activate
   once real pages exist. Scoped to .et-menu (desktop) specifically —
   confirmed via live DOM that Divi's mobile dropdown (.et_mobile_menu)
   shares the same .eb-nav-menu module ancestor, so the unscoped version
   of this selector was also painting an orange border-bottom onto the
   current item inside the mobile menu, which has its own distinct
   treatment below. */
.eb-nav-menu .et-menu > .current-menu-item > a,
.eb-nav-menu .et-menu > .current_page_item > a {
	border-bottom-color: var(--accent);
}
/* Desktop "About Us" dropdown — Divi ships this submenu as a white panel with a
   3px blue top border (its own default chrome). Restyle it to match the scrolled
   nav-bar: the same translucent paper fill + backdrop blur as the header section
   (.eb-header.scrolled, rgba(250,247,241,.82) / blur 18px), a --border-subtle
   hairline edge, --shadow-overlay, and dark 600 links so the panel reads as one
   surface with the bar it hangs from. !important is required to beat Divi core's
   submenu chrome — same pattern as the header/footer overrides. */
.eb-nav-menu .et-menu .sub-menu {
	background: rgba(250, 247, 241, 0.82) !important;
	backdrop-filter: blur(18px);
	-webkit-backdrop-filter: blur(18px);
	border: 1px solid var(--border-subtle) !important;
	box-shadow: var(--shadow-overlay) !important;
	padding: 8px !important;
}
.eb-nav-menu .et-menu .sub-menu li {
	border: 0 !important;
	background: transparent !important;
}
.eb-nav-menu .sub-menu a {
	color: var(--text-primary) !important;
	white-space: nowrap;
	padding: 9px 12px !important;
	border-radius: 4px;
	font-weight: 600;
	transition: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.eb-nav-menu .et-menu .sub-menu a:hover {
	background: rgba(23, 21, 20, .06) !important;
	color: var(--accent) !important;
}
/* "Start a Conversation" — always the last item, per the approved nav
   structure — rendered as a real button, not a plain link. Reference
   (components/NavBar.tsx) never renders this CTA as an orange-filled
   .eb-btn--primary — it is always .eb-btn--secondary (light/non-scrolled
   state) or .eb-btn--inverse (the solid-black state, which is the only
   state this static M2 build ever renders — see the M6 deferral note
   above). This now matches .eb-btn--inverse exactly (app/globals.css):
   transparent background, --border-inverse border, --text-inverse text. */
.eb-nav-menu .et-menu > li:last-child > a {
	background: var(--accent);
	color: var(--accent-ink);
	border: 1px solid var(--accent);
	padding: 13px 26px;
	text-transform: uppercase;
	letter-spacing: var(--button-tracking);
	transition: background-color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.eb-nav-menu .et-menu > li:last-child:hover > a {
	border-color: var(--eb-ink);
	background: var(--eb-ink);
	color: var(--eb-paper);
}

/* ---------- Mobile nav dropdown ----------
   All of the dark-theme styling above only ever targeted .eb-nav-menu
   .et-menu — the DESKTOP horizontal menu's own markup. Divi's real
   hamburger/mobile dropdown is a structurally separate module
   (.et_mobile_nav_menu > .mobile_nav > .et_mobile_menu, confirmed via the
   live DOM) that this theme had never targeted at all: it rendered with
   Divi's untouched default white background and unstyled links. Only
   cosmetic properties are set here (background, color, spacing,
   borders) — Divi's own JS still owns the open/close toggle
   (.mobile_nav.opened / .closed) and the fixed/absolute positioning of
   .et_mobile_nav_menu, so there is no duplicate positioning logic here. */
.et_mobile_menu {
	background: var(--eb-black);
	border-bottom: 1px solid var(--border-inverse);
	/* Divi's own default for this panel includes a 3px top border in its
	   stock accent blue (rgb(46,163,242), confirmed via computed style)
	   — never part of this project's palette. The reference has no top
	   border on its mobile menu at all. */
	border-top: none;
	padding: 8px var(--gutter) 24px;
}
.et_mobile_menu li {
	border-bottom: 1px solid var(--border-inverse);
	list-style: none;
}
/* Divi's hamburger toggle is an icon-font glyph rendered via ::before,
   with its own hardcoded color (rgb(46,163,242), the same stock accent
   blue as the border above) completely independent of the element's own
   `color`, which is already correct (--text-inverse) — confirmed via
   computed style that only the pseudo-element's own color property was
   wrong. !important matches this element's own icon-font specificity. */
/* iOS Safari only synthesizes a click from a tap on a non-interactive
   element (this is a <span> with a jQuery-bound handler, not a link/button)
   when it — or an ancestor — carries cursor: pointer. Without it the
   hamburger is dead to touch on iPhone while still working with a desktop
   mouse. Divi's own default pointer rule isn't winning here, so set it
   explicitly on the tap target. */
.mobile_menu_bar,
.mobile_menu_bar::before {
	cursor: pointer;
}
.mobile_menu_bar::before {
	color: var(--eb-white) !important;
}
/* !important is deliberate, scoped to exactly one property: confirmed via
   computed styles on a real deployment (not the earlier verification
   pass, which used !important defensively and masked this) that Divi's
   own core menu-module CSS still wins the top-level link color at this
   specificity — text rendered at rgba(0,0,0,.6) instead of white despite
   this rule. Same class of third-party-chrome override as the other
   documented !importants in this file, not a fight with our own cascade. */
.et_mobile_menu li > a {
	display: block;
	font-family: var(--font-body);
	font-size: 17px;
	font-weight: 600;
	color: var(--eb-white) !important;
	text-decoration: none;
	padding: 14px 0;
}
.et_mobile_menu li > a:hover {
	color: var(--eb-sandstone) !important;
}
/* "About Ernie" sub-item under "About Us" — same indentation/size-step
   treatment as the reference's .eb-nav__menu-sublink, on Divi's own
   .sub-menu markup instead of a custom class. */
.et_mobile_menu .sub-menu {
	background: transparent;
}
.et_mobile_menu .sub-menu li {
	border-bottom: none;
}
.et_mobile_menu .sub-menu a {
	padding-left: 20px;
	font-size: 15px;
	font-weight: 500;
	color: var(--eb-sandstone);
}
/* "Start a Conversation" — same last-child CTA pattern as the desktop
   menu (.eb-nav-menu .et-menu > li:last-child above), matching
   .eb-btn--inverse rather than a filled orange button. */
.et_mobile_menu > li:last-child {
	border-bottom: none;
	margin-top: 20px;
}
.et_mobile_menu > li:last-child > a {
	background: transparent;
	border: 1px solid var(--border-inverse);
	color: var(--text-inverse);
	text-align: center;
	text-transform: uppercase;
	letter-spacing: var(--button-tracking);
	padding: 13px 26px;
}
.et_mobile_menu > li:last-child:hover > a {
	border-color: var(--eb-paper);
	background: rgba(250, 247, 241, .08);
}

/* ---------- Header: continuous mobile/tablet brand+menu layout ----------
   SUPERSEDES an earlier fixed 78/22 percentage split scoped to ≤639px
   only. That approach caused two confirmed regressions, found by
   sweeping every ~20px from 900px down to 480px and measuring the real
   gap between the wordmark's right edge and the hamburger's left edge:

   1. A genuine overlap ABOVE 639px, not just at/below it. Divi's own
      unmodified column split (et_flex_column_12_24, ~25/75) shrinks
      proportionally with the viewport while the brand's real content
      (46px logo + 11px gap + ~121px wordmark ≈ 178px) does not. The gap
      crossed from positive to negative between 700px (+1.3px) and
      680px (-3.0px), reaching -7.4px at 660px — a real, live bleed of
      the hamburger into the wordmark's "BUILT" text that the ≤639px
      fix never covered.
   2. A hard, discontinuous jump exactly at the 639/640 boundary: at
      660px (just above, old default active) the gap measured -7.4px;
      at 625px (just below, old 78/22 fix active) it jumped to
      +245.3px. Any two fixed percentages meeting at a breakpoint
      necessarily does this — it's inherent to the approach, not a bug
      in either rule individually.

   Fix: stop assigning either column a percentage at all in this range.
   The brand column grows/shrinks to exactly what its content needs
   (flex: 1 1 auto — flex-basis:auto defers to width, so width:auto is
   required alongside it, confirmed live: without it Divi's own
   percentage width class still wins on flex-basis alone). The menu
   column never takes more than its own content needs (flex: 0 0 auto)
   and is pushed to the row's far right by .eb-header's own existing
   justify-content:space-between — confirmed via live measurement at
   500/660/780px that col1 stays pinned at ~38-79px (just the toggle
   button + its own small padding) at every width, so the gap is always
   large and positive, with no discontinuity anywhere in the range.

   Scoped ≤959px (this project's established "mobile nav visible"
   breakpoint elsewhere in this file) rather than the old ≤639px, since
   col1 is now deliberately narrow (content-sized) at every width in
   this range, including 640-959px where Divi's own default previously
   happened to leave enough width for the dropdown panel by accident.
   No !important anywhere below — confirmed via live testing (styles
   injected as the last stylesheet in <head>, matching how WordPress
   already enqueues this child theme's CSS after Divi's own core CSS)
   that plain declarations win on specificity/source-order alone; no
   competing Divi rule was found for these specific properties. No
   Theme Builder change — CSS-only, same two column elements and menu
   module already targeted elsewhere in this file. */
@media (max-width: 959px) {
	.eb-header .et_pb_column:first-child {
		flex: 1 1 auto;
		width: auto;
		margin-bottom: 0;
	}
	.eb-header .et_pb_column:last-child {
		flex: 0 0 auto;
		width: auto;
		margin-bottom: 0;
	}
	/* .et_pb_menu_inner_container and .et_pb_menu__wrap are Divi's own
	   wrappers around the toggle button — both shrink-to-content by
	   default, so without this the flex-end alignment below has nothing
	   to push against and the hamburger sits left of the column's real
	   right edge with unexplained dead space beside it. Stretching both
	   to 100% of the (now content-sized) column gives flex-end a real
	   boundary — confirmed the hamburger's own right edge lands exactly
	   on the column's right edge, flush with the header row's content
	   area, not the absolute viewport edge. */
	.eb-header .et_pb_menu_inner_container,
	.eb-header .et_pb_menu__wrap {
		width: 100%;
	}
	.eb-header .et_mobile_nav_menu {
		width: 100%;
		justify-content: flex-end;
		margin-right: 0;
	}
	/* Divi's real mobile dropdown panel (.et_mobile_menu) is
	   position:absolute; width:100% against its nearest positioned
	   ancestor (.et_pb_menu_inner_container). That ancestor is now
	   deliberately narrow (content-sized) at every width in this range,
	   so without this the dropdown panel would narrow to just the
	   toggle button's own width and every link would wrap word-by-word.
	   Fixed positioning escapes that ancestor's width entirely and
	   sizes against the viewport instead. top:76px matches the header's
	   own fixed height (.eb-header) exactly for a logged-out visitor
	   (no admin bar). */
	.et_mobile_menu {
		position: fixed;
		top: 76px;
		left: 0;
		right: 0;
		width: auto;
	}
	/* Logged-in only: WordPress's own admin bar becomes 46px tall below
	   782px (its own responsive breakpoint, separate from ours) and
	   pushes the whole page down via `html { margin-top }` — confirmed
	   live. .eb-header itself follows that push correctly (it's just
	   flowed, not fixed), but the hardcoded top:76px above assumes the
	   header starts at viewport y:0, so at this width it started 46px
	   too early and covered the header's own lower portion — including
	   the hamburger — with the black panel. --wp-admin--admin-bar--height
	   is WordPress's own custom property for this and was confirmed
	   live to compute correctly at this breakpoint (46px, matching the
	   real rendered #wpadminbar height exactly), so it's used directly
	   rather than a hardcoded value. Scoped to .admin-bar (WordPress
	   only adds this body class when logged in) so logged-out visitors
	   never see this offset at all. */
	body.admin-bar .et_mobile_menu {
		top: calc(76px + var(--wp-admin--admin-bar--height, 0px));
	}
}

/* ---------- Global Footer ----------
   Both rows (column grid + legal line) sit inside one .et-l--footer
   wrapper, so the dark surface is set once there rather than repeated
   per row. */
.et-l--footer {
	background: var(--surface-pine);
	color: var(--text-inverse);
}
/* The 2fr:1fr:1fr:1fr ratio below already matches the reference site's
   own --eb-footer__grid exactly — the brand column was always meant to
   be wider. What actually broke the layout: Divi's own .et_flex_column
   ships a content-based width that fights CSS Grid's default item
   stretch, so every column rendered far narrower than its track
   (confirmed via computed styles: track 336px, rendered box 70px). The
   width/min-width override below is the real fix — not a ratio change. */
.eb-footer {
	display: grid;
	grid-template-columns: 2fr 1fr 1fr 1fr;
	gap: var(--space-7);
	padding: 72px var(--gutter) 40px;
}
.eb-footer > .et_pb_column {
	width: 100% !important;
	min-width: 0 !important;
}
.eb-footer__brand {
	margin-bottom: var(--space-4);
}
.eb-footer__brand .eb-wordmark {
	color: var(--text-inverse);
}
.eb-footer__mission {
	color: var(--text-inverse-secondary);
	font-size: 16px;
	max-width: 300px;
}
.et-l--footer .et_pb_text_inner p {
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.et-l--footer .et_pb_text_inner p > a {
	color: var(--text-inverse);
	text-decoration: none;
	font-size: var(--type-body-sm);
}
.et-l--footer .et_pb_text_inner p > a:hover {
	color: var(--eb-sandstone);
}
.eb-footer__col-title {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--text-inverse-secondary);
}
.eb-footer__phone {
	font-family: var(--font-display);
	font-size: 24px;
	letter-spacing: .02em;
}
.eb-footer__muted {
	color: var(--text-inverse-secondary);
	font-size: var(--type-caption);
}
.eb-footer__legal {
	margin: 0 var(--gutter);
	padding-top: 24px;
	border-top: 1px solid var(--border-inverse);
	font-size: var(--type-caption);
	color: var(--text-inverse-secondary);
	text-align: center;
}

/* Social icons (Font Awesome brand glyphs, delivered inline as SVG). */
.eb-social { display: flex; align-items: center; gap: 12px; margin-top: var(--space-5); }
.eb-social__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border: 1px solid var(--border-inverse);
	border-radius: 50%;
	color: var(--text-inverse-secondary);
	transition: color .2s var(--ease-standard, ease), background-color .2s var(--ease-standard, ease), border-color .2s var(--ease-standard, ease);
}
.eb-social__link:hover,
.eb-social__link:focus-visible { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.eb-social__link svg { width: 17px; height: 17px; fill: currentColor; display: block; }

/* Responsive footer grid — these two breakpoints exist in the reference
   (app/globals.css: @media max-width:959px and max-width:639px) but were
   never ported here, so the 2fr:1fr:1fr:1fr ratio held at every width down
   to real mobile viewports, confirmed via live measurement to wrap text
   mid-word at 767px and 500px. Desktop ratio (.eb-footer above) is
   untouched by these — they only apply below 959px. */
@media (max-width: 959px) {
	.eb-footer {
		grid-template-columns: 1fr 1fr;
	}
}
@media (max-width: 639px) {
	.eb-footer {
		grid-template-columns: 1fr;
		gap: 36px;
	}
}

/* Styles the one example shortcode partial (partials/starter/example-section.php)
   renders — proves tokens defined upstream are actually consumed here.
   Remove once real components replace it. */
.deadstop-example-section {
	padding: var(--space-7) var(--gutter);
	max-width: var(--container);
	margin: 0 auto;
}
.deadstop-example-section h2 {
	font-family: var(--font-display);
	font-size: var(--type-display-sm);
	color: var(--text-primary);
	margin: 0;
}

/* ============================================================
   HOMEPAGE — Section 1 (Hero) only. Per
   clients/earnest-built/HOMEPAGE_IMPLEMENTATION_PLAN.md: one section at
   a time, approved before the next. Sections 2+ do not exist yet.
   ============================================================ */

/* .eb-container is the reference's own content-width primitive
   (app/globals.css; the Section component in components/ui.tsx wraps
   every section's children in it). Confirmed absent from this theme:
   the framework's .deadstop-container (utilities.css) bakes gutter
   padding into the container, whereas the reference's .eb-container has
   NO padding of its own — the hero relies on that (its content column
   centers inside a padding-less 1280px container, gutter handled by the
   content block's own padding). The reference's .eb-section primitive
   is deliberately NOT ported here: its only job is section-level
   padding (var(--section-y) var(--gutter)), which the hero overrides
   entirely and does not need, and porting it would require adding the
   --section-y token that no Hero rule consumes. Later sections that do
   need .eb-section will add it (and the token) then, per the
   one-section-at-a-time build. */
.eb-container {
	max-width: var(--container);
	margin: 0 auto;
}
/* .eb-display — the shared display-type utility the Hero's <h1> uses
   (app/globals.css). Also confirmed absent from this theme entirely;
   without it the H1 would render in the body font, not Bebas. */
.eb-display {
	font-family: var(--font-display);
	font-weight: 400;
	line-height: var(--display-line);
	letter-spacing: var(--display-tracking);
	text-transform: uppercase;
	margin: 0;
}

/* Divi wrapper neutralization for the Hero — scoped to ONLY the Divi
   section that actually contains .eb-hero3 (via :has), so no other
   page-body section, and nothing in the Theme Builder header/footer, is
   touched. Confirmed via live DOM on dev.earnest-built.com: Divi wraps
   the Code module in .et_pb_section (ships 54px top/bottom padding that
   would inset the hero from the header and footer) inside a .et_pb_row
   (ships max-width:1080px + width:80%, which was capping the full-bleed
   photo at 1080px centered instead of spanning the viewport). Zeroing
   the section padding and letting the row fill its full width is what
   makes the hero's own full-bleed CSS actually reach the edges. No
   !important needed — the :has-scoped selectors out-specify Divi's own
   single-class rules (verified live). */
.et_pb_section:has(.eb-hero3) {
	padding: 0;
}
.et_pb_section:has(.eb-hero3) .et_pb_row {
	width: 100%;
	max-width: 100%;
}

/* ---------- 1 · Hero (app/globals.css, components/HeroParallax.tsx) ----------
   The reference pulls the section up by the header's own height
   (margin-top: -76px; padding-top: 76px) so the full-bleed image can sit
   behind a TRANSPARENT-on-load nav. That transparent-nav state is M6
   (deferred, explicitly out of scope): WP's header is permanently solid
   black, and the approved build direction is that the hero must begin
   BELOW the solid header, not underneath it. So the reference's
   negative-margin slide is deliberately NOT ported — the hero starts
   flush below the header instead. min-height is the reference's own
   value minus that 76px header-overlap allowance (reference:
   calc(78svh + 76px) with 76px hidden under the nav → 78svh visible;
   here: 78svh visible, no overlap), preserving the same visible hero
   proportion. Verified live that the sticky header renders fully above
   the hero with zero overlap at every tested width. */
.eb-hero3 {
	position: relative;
	min-height: 100svh;
	box-sizing: border-box;
	/* Reserve space for the fixed, transparent header so the bottom-anchored
	   statement never tucks under the nav on short viewports. */
	padding-top: clamp(108px, 13vh, 148px);
	padding-bottom: 56px;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	overflow: hidden;
}
.eb-hero3 > .eb-container {
	width: 100%;
}
.eb-hero3__media {
	position: absolute;
	inset: 0;
	overflow: hidden;
}
.eb-hero3__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 44% 38%;
	display: block;
	transform: scale(1);
	transform-origin: center;
	will-change: transform;
}
.eb-hero3__wash {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(19, 30, 23, .1), rgba(19, 30, 23, .04) 40%, rgba(19, 30, 23, .55));
	mix-blend-mode: multiply;
}
.eb-hero3__fade {
	position: absolute;
	inset: 0;
	background: radial-gradient(ellipse 140% 120% at 0% 0%, var(--eb-forest-shadow) 0%, var(--eb-forest-shadow) 35%, transparent 90%);
}
.eb-hero3__scrim {
	position: absolute;
	inset: auto 0 0 0;
	height: 62%;
	background: linear-gradient(180deg, transparent, var(--eb-forest-shadow) 90%);
}
.eb-hero3__content {
	position: relative;
	max-width: 700px;
	/* Top spacing is handled by .eb-hero3 padding-top (header clearance). */
	padding: 0 var(--gutter) 56px;
}
.eb-hero3__place {
	font-family: var(--font-body);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--text-inverse-secondary);
	margin: 0 0 22px;
}
.eb-hero3__statement {
	font-size: clamp(42px, 5.6vw, 86px);
	color: var(--text-inverse);
	margin: 0 0 28px;
}
.eb-hero3__bridge {
	font-family: var(--font-body);
	font-style: italic;
	font-size: var(--type-lead);
	line-height: 1.5;
	color: var(--text-inverse);
	max-width: 440px;
	margin: 0 0 34px;
}
.eb-hero3__actions {
	display: flex;
	align-items: center;
	gap: 20px;
	flex-wrap: wrap;
}
@media (max-width: 959px) {
	.eb-hero3__img {
		object-position: 40% 34%;
	}
}
@media (max-width: 767px) {
	.eb-hero3__img {
		object-position: 37% 30%;
	}
	.eb-hero3__statement {
		font-size: clamp(36px, 9.5vw, 58px);
	}
	.eb-hero3__content {
		padding: 0 var(--gutter) 48px;
	}
}
/* Hide the hero CTA wherever the sticky mobile conversion bar shows (<=959px),
   so the two "Start a conversation" buttons aren't redundant on mobile/tablet. */
@media (max-width: 959px) {
	.eb-hero3__actions {
		display: none;
	}
}
@media (prefers-reduced-motion: reduce) {
	.eb-hero3__img {
		transition: none;
	}
}

/* Bebas Neue 400 (self-hosted; matches the reference's next/font/google
   Bebas_Neue weight 400 — the display face for .eb-display and all
   .eb-hero3/.eb-philosophy display type). */
@font-face {
	font-family: "Bebas Neue";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("../fonts/bebas-neue-400.woff2") format("woff2");
}

/* HOMEPAGE — Section 3 (What We Do / Capabilities). Static build; idle
   card-pulse and Reveal entrance are M6 motion, omitted — cards at rest.
   Hover states kept (pure CSS). */
.et_pb_section:has(.eb-capabilities) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-capabilities) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-capabilities { background: var(--eb-white); padding: 80px var(--gutter); }
.eb-capabilities__head { max-width: 640px; margin: 0 auto var(--space-8); text-align: center; }
.eb-close__rule { display: block; width: 32px; height: 2px; background: var(--accent); margin: 0 auto 20px; }
.eb-close__label { font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--text-tertiary); margin: 0 0 12px; }
.eb-capabilities__title { font-family: var(--font-body); font-weight: 800; font-size: clamp(32px, 4vw, 48px); line-height: 1.1; color: var(--text-primary); margin: 0 0 16px; }
.eb-capabilities__intro { font-family: var(--font-body); font-size: var(--type-lead); color: var(--text-secondary); margin: 0; }
.eb-capabilities__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.eb-capability {
	display: block;
	background: var(--surface-tint);
	border: 1px solid var(--border-subtle);
	border-radius: 18px;
	padding: 44px 28px;
	height: 100%;
	text-align: center;
	text-decoration: none;
	color: inherit;
	transition: transform 400ms var(--ease-standard), border-color 400ms var(--ease-standard), box-shadow 400ms var(--ease-standard);
}
.eb-capability:hover {
	transform: translateY(-6px) scale(1.015) skewY(-1.5deg);
	border-color: var(--accent);
	box-shadow: 0 20px 40px rgba(23, 21, 20, .1);
}
.eb-capability__icon { display: block; width: 40px; height: 40px; color: var(--text-secondary); margin: 0 auto 24px; transition: transform 400ms var(--ease-standard); }
.eb-capability__icon svg { width: 100%; height: 100%; display: block; }
.eb-capability:hover .eb-capability__icon { transform: scale(1.2); }
.eb-capability__title { font-family: var(--font-body); font-weight: 800; font-size: clamp(21px, 2.2vw, 25px); line-height: 1.2; min-height: 2.4em; display: flex; align-items: center; justify-content: center; color: var(--text-primary); margin: 0 0 16px; }
.eb-capability__desc { font-family: var(--font-body); font-size: 16.5px; line-height: 1.65; color: var(--text-secondary); margin: 0; }
@media (max-width: 959px) { .eb-capabilities__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 767px) { .eb-capabilities__grid { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) {
	.eb-capability:hover { transform: none; }
	.eb-capability:hover .eb-capability__icon { transform: none; }
}

/* HOMEPAGE — Section 2 (Stats + Philosophy). Motion (reveal/rule-grow/
   value-scale) is M6-deferred; rendered in final settled state. */
.et_pb_section:has(.eb-philosophy) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-philosophy) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-philosophy { position: relative; overflow: hidden; background: var(--surface-pine); padding: 72px var(--gutter); text-align: center; min-height: 68svh; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.eb-philosophy__stats { display: flex; flex-wrap: wrap; justify-content: center; gap: 72px; row-gap: 32px; margin: 0 0 56px; }
.eb-stat__value { font-family: var(--font-display); font-size: 56px; line-height: 1; color: var(--text-primary); }
.eb-stat__rule { width: 24px; max-width: 24px; height: 2px; background: var(--accent); margin: 10px 0; }
.eb-stat__label { font-family: var(--font-body); font-size: 14px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--text-secondary); }
.eb-stat--inverse .eb-stat__value { color: var(--text-inverse); }
.eb-stat--inverse .eb-stat__label { color: var(--text-inverse-secondary); }
.eb-philosophy__stats .eb-stat { text-align: center; }
.eb-philosophy__stats .eb-stat__value { display: inline-block; }
.eb-philosophy__stats .eb-stat__rule { margin-left: auto; margin-right: auto; width: 32px; max-width: 32px; }
.eb-philosophy__statement { font-size: clamp(30px, 4.1vw, 68px); line-height: 1.2; letter-spacing: .012em; max-width: 920px; margin: 0 auto; color: var(--text-inverse); }
/* Oversized serif quotation marks in accent orange at 50%. The opening mark is a
   decorative wrap pseudo-element at the top-left; the closing mark flows inline
   right after the final period (.eb-philosophy__qmark) so it always sits just
   after the last word at any viewport. The mark takes zero width so it never
   shifts the centered statement. */
.eb-philosophy__quotewrap { position: relative; max-width: 920px; margin: 0 auto; }
.eb-philosophy__statement { position: relative; z-index: 1; }
.eb-philosophy__quotewrap::before {
  content: "\201C";
  position: absolute;
  z-index: 0;
  top: -0.15em;
  left: -0.04em;
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(6rem, 12vw, 11rem);
  line-height: 1;
  color: var(--accent);
  opacity: .5;
  pointer-events: none;
}
.eb-philosophy__qmark { display: inline-block; width: 0; }
.eb-philosophy__qmark::after {
  content: "\201D";
  position: relative;
  top: 0.30em;
  margin-left: 0.05em;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.6em;
  line-height: 0;
  color: var(--accent);
  opacity: .5;
  white-space: nowrap;
  pointer-events: none;
}
.eb-philosophy__rule { display: block; width: 32px; height: 2px; background: var(--accent); margin: 34px auto 0; }
.eb-philosophy__sig { font-family: var(--font-body); font-size: 15px; letter-spacing: .08em; color: var(--text-inverse-secondary); margin: 18px 0 0; }
@media (max-width: 639px) { .eb-philosophy__stats { gap: 40px; row-gap: 24px; margin-bottom: 40px; } }

/* HOMEPAGE — Section 4 (Meet Ernie). Full-bleed 2-col: grayscale
   portrait bleeds to the left edge, text centered on the right. No
   deferred motion in this section. */
.et_pb_section:has(.eb-record) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-record) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-record { background: var(--eb-charcoal); color: var(--text-inverse); padding: clamp(72px, 10vw, 128px) 0 0; }
.eb-record > .eb-container { max-width: none; }
.eb-record__grid { display: grid; grid-template-columns: minmax(340px, 42%) 1fr; min-height: 700px; }
.eb-record__media { position: relative; height: 100%; overflow: hidden; }
.eb-record__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; display: block; filter: grayscale(1); }
/* Portrait plate: an editorial caption anchored to the photo (accent rule +
   label + name), over a bottom gradient scrim so it stays legible on the image. */
.eb-record__media::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(to top, rgba(18, 20, 19, .82), rgba(18, 20, 19, 0) 44%); }
.eb-record__plate { position: absolute; z-index: 2; left: clamp(24px, 3vw, 44px); bottom: clamp(24px, 3vw, 44px); }
.eb-record__plate-rule { display: block; width: 40px; height: 2px; background: var(--accent); margin: 0 0 14px; }
.eb-record__plate-label { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--eb-paper); margin: 0; }
.eb-record__plate-name { font-family: var(--font-display); font-size: clamp(30px, 3.4vw, 48px); line-height: 1; letter-spacing: .01em; text-transform: uppercase; color: #fff; margin: 8px 0 0; }
.eb-record__text { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; text-align: left; padding: 64px var(--gutter) 64px clamp(48px, 6vw, 96px); }
.eb-record__anecdote { font-family: var(--font-body); font-size: clamp(24px, 2.8vw, 36px); line-height: 1.45; color: var(--text-inverse); margin: 0 0 var(--space-6); max-width: 27ch; }
.eb-record__caption { font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; line-height: 1.9; color: var(--text-inverse-secondary); margin: 0 0 var(--space-5); max-width: 520px; }
.eb-record__more { font-size: 15px; color: var(--text-inverse); text-decoration-color: var(--border-inverse); }
.eb-record__more:hover { color: var(--eb-sandstone); }
@media (max-width: 767px) {
	.eb-record { padding: clamp(72px, 10vw, 128px) var(--gutter); }
	.eb-record__grid { grid-template-columns: 1fr; min-height: 0; gap: var(--space-6); }
	.eb-record__media { height: 420px; }
	.eb-record__text { padding: 0; }
}

/* HOMEPAGE — Section 5 (The Decisions, In Order). Static; hover
   dim/underline/color are pure CSS, kept. No deferred motion. */
.et_pb_section:has(.eb-decisions) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-decisions) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-decisions { padding: clamp(72px, 10vw, 128px) var(--gutter); }
.eb-stages__label { font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--text-tertiary); margin: 0 0 24px; }
/* Section header — matches the "Our Services -> What We Do." pattern: centered
   accent rule + eyebrow (.eb-close__rule / .eb-close__label) over a title styled
   like .eb-capabilities__title. */
.eb-decisions__head { max-width: 640px; margin: 0 auto clamp(32px, 5vw, 56px); text-align: center; }
.eb-decisions__title { font-family: var(--font-body); font-weight: 800; font-size: clamp(32px, 4vw, 48px); line-height: 1.1; color: var(--text-primary); margin: 0; }
.eb-decisions__list { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-8); }
.eb-service-row { display: grid; grid-template-columns: 64px 1fr auto; gap: 24px; align-items: baseline; padding: 26px 0; border-top: 1px solid var(--border-subtle); text-decoration: none; }
.eb-service-row__index { font-family: var(--font-display); font-size: 22px; color: var(--text-tertiary); transition: color var(--dur-fast); }
.eb-service-row:hover .eb-service-row__index { color: var(--accent); }
.eb-service-row__title { font-family: var(--font-display); font-size: 34px; line-height: .95; text-transform: uppercase; color: var(--text-primary); transition: color var(--dur-fast); display: block; }
.eb-service-row:hover .eb-service-row__title { color: var(--eb-cedar); }
.eb-service-row__desc { font-family: var(--font-body); font-size: 16px; color: var(--text-secondary); display: block; margin-top: 8px; max-width: 520px; }
.eb-service-row__arrow { font-family: var(--font-body); font-size: 20px; color: var(--text-secondary); transition: transform var(--dur-med) var(--ease-standard), color var(--dur-fast); }
.eb-service-row:hover .eb-service-row__arrow { color: var(--accent); transform: translateX(6px); }
.eb-decisions__list .eb-service-row { position: relative; transition: opacity var(--dur-med) var(--ease-standard); }
.eb-decisions__list .eb-service-row::after { content: ""; position: absolute; left: 0; top: -1px; height: 1px; width: 0; background: var(--accent); transition: width var(--dur-med) var(--ease-standard); }
.eb-decisions__list:hover .eb-service-row { opacity: .4; }
.eb-decisions__list .eb-service-row:hover { opacity: 1; }
.eb-decisions__list .eb-service-row:hover::after { width: 100%; }
@media (max-width: 767px) { .eb-decisions__list { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) {
	.eb-decisions__list .eb-service-row { transition: none; }
	.eb-decisions__list:hover .eb-service-row { opacity: 1; }
}

/* HOMEPAGE — Section 6 (What We Look For On A Lot). Full-bleed two-zone:
   photo strip + charcoal ground. Reveal stagger/turn-rule-grow and the
   parallax scroll-zoom are M6 motion — rendered in final settled state
   (notes as direct grid children, turn-rule at 40px, image at scale 1). */
.et_pb_section:has(.eb-realities) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-realities) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-realities { position: relative; padding: 0; }
.eb-realities > .eb-container { max-width: none; }
.eb-realities__photo { position: relative; overflow: hidden; min-height: 380px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 44px var(--gutter); }
.eb-realities-photo__media { position: absolute; inset: 0; overflow: hidden; }
/* Scroll-zoom: JS (realities-zoom.js) sets scale() on scroll; static at scale 1
   with no JS / reduced motion. transform-origin center keeps the crop steady. */
.eb-realities-photo__img { width: 100%; height: 100%; object-fit: cover; object-position: 62% 55%; display: block; transform: scale(1); transform-origin: center; will-change: transform; }
.eb-realities-photo__scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(19,21,20,.62) 0%, rgba(19,21,20,.12) 42%, rgba(19,21,20,.12) 60%, rgba(19,21,20,.8) 100%); }
.eb-realities__title { position: relative; font-family: var(--font-display); font-size: clamp(40px, 6vw, 84px); line-height: .96; margin: 0 auto var(--space-5); color: var(--text-inverse); }
.eb-realities__intro { position: relative; font-family: var(--font-body); font-size: var(--type-lead); color: var(--text-inverse-secondary); margin: 0 auto; max-width: 420px; }
.eb-realities__ground { background: var(--eb-charcoal); text-align: center; padding: clamp(40px, 5vw, 60px) var(--gutter) clamp(48px, 6vw, 72px); }
.eb-realities__content { max-width: 1040px; margin: 0 auto; }
.eb-realities__grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--space-8); row-gap: var(--space-5); }
.eb-realities__grid > .eb-realities__note:nth-child(2n) { margin-top: clamp(12px, 2vw, 24px); }
.eb-realities__line { font-family: var(--font-body); font-weight: 400; font-size: clamp(17px, 1.6vw, 20px); line-height: 1.5; color: var(--text-inverse); max-width: 34ch; margin: 0 auto; }
.eb-realities__caption { display: block; margin-top: 14px; font-family: var(--font-body); font-size: 12px; letter-spacing: .1em; color: var(--text-inverse-secondary); opacity: .65; }
.eb-realities__turn { max-width: 840px; margin: clamp(20px, 3vw, 36px) auto 0; }
.eb-realities__turn-rule { display: block; width: 40px; height: 2px; background: var(--accent); margin: 0 auto 20px; }
.eb-realities__line--turn { font-size: clamp(21px, 2.3vw, 27px); line-height: 1.4; max-width: 40ch; }
.eb-realities__payoff { font-family: var(--font-body); font-weight: 400; font-size: clamp(22px, 2.6vw, 31px); line-height: 1.35; color: var(--text-inverse); max-width: 42ch; margin: clamp(24px, 3.5vw, 44px) auto 0; }
@media (max-width: 767px) { .eb-realities__title { font-size: clamp(34px, 11vw, 48px); } }
@media (max-width: 639px) {
	.eb-realities__grid { grid-template-columns: 1fr; row-gap: var(--space-6); }
	.eb-realities__grid > .eb-realities__note:nth-child(2n) { margin-top: 0; }
}

/* HOMEPAGE — Section 7 (Questions clients actually ask). The reference
   FAQ toggle is React state + a grid-rows open animation (M6/JS). To keep
   it fully usable with NO JavaScript, it's built on native <details
   name> — real single-open accordion, keyboard-accessible; the open
   animation is dropped (deferred). Hover states kept (pure CSS). */
.et_pb_section:has(.eb-close) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-close) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-close { padding: clamp(72px, 10vw, 128px) var(--gutter); }
.eb-close__head { text-align: center; max-width: 560px; margin: 0 auto; }
.eb-close__head .eb-close__label { margin: 0 0 12px; }
.eb-close__sub { font-family: var(--font-body); font-size: var(--type-lead); color: var(--text-secondary); margin: 0 auto var(--space-6); max-width: 480px; }
.eb-close__faq { max-width: 900px; margin: 0 auto; }
.th-faq { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-7); align-items: start; }
.th-faq__col { display: flex; flex-direction: column; gap: 14px; }
.th-faq__item { border: 1px solid var(--border-subtle); border-radius: 12px; background: var(--eb-white); transition: border-color 340ms var(--ease-standard), transform 340ms var(--ease-standard), box-shadow 340ms var(--ease-standard); }
.th-faq__item:hover { border-color: rgba(247, 146, 30, .4); transform: translateY(-2px); }
.th-faq__item[open] { border-color: var(--accent); }
.th-faq__q { list-style: none; width: 100%; display: flex; align-items: center; gap: 18px; cursor: pointer; text-align: left; padding: 20px 22px; font-family: var(--font-body); min-height: 86px; box-sizing: border-box; }
.th-faq__q::-webkit-details-marker { display: none; }
.th-faq__num { flex: none; font-family: var(--font-display); font-size: 15px; letter-spacing: .04em; color: var(--text-tertiary); }
.th-faq__qtext { flex: 1; font-family: var(--font-body); font-size: 17px; font-weight: 600; line-height: 1.35; color: var(--text-primary); transition: color 340ms var(--ease-standard), transform 340ms var(--ease-standard); }
.th-faq__item:hover .th-faq__qtext { color: var(--eb-cedar); transform: translateX(2px); }
.th-faq__icon { flex: none; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border-subtle); border-radius: 50%; color: var(--text-primary); transition: transform 360ms var(--ease-standard), border-color 340ms var(--ease-standard), background-color 340ms var(--ease-standard), color 340ms var(--ease-standard); }
.th-faq__item:hover .th-faq__icon { border-color: rgba(247, 146, 30, .5); }
.th-faq__item[open] .th-faq__icon { transform: rotate(45deg); border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.th-faq__a > p { margin: 0; padding: 0 22px 22px; font-size: 15.5px; line-height: 1.65; color: var(--text-secondary); }
@media (max-width: 767px) { .th-faq { grid-template-columns: 1fr; } }

/* HOMEPAGE — Section 8 (The Close). Full-width pine band, centered. No
   deferred motion. Bottom padding trimmed (shares --surface-pine with
   the footer). */
.et_pb_section:has(.eb-final) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-final) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-final { background: var(--surface-pine); text-align: center; padding: clamp(72px, 10vw, 128px) var(--gutter) var(--space-7); }
.eb-cta__title { font-size: var(--type-display-md); line-height: 1.1; color: var(--text-inverse); max-width: 46ch; margin: 0 auto 22px; }
.eb-final__lead { color: var(--text-inverse-secondary); font-size: var(--type-lead); margin: 0 auto 36px; max-width: 460px; }
.eb-final__phone { display: block; font-family: var(--font-body); font-size: 15px; color: var(--text-inverse-secondary); text-decoration: underline; text-underline-offset: 3px; margin-top: 24px; }
.eb-final__phone:hover { color: var(--text-inverse); }
/* Credential line hidden site-wide per client request (was: "Licensed & insured
   · AZ ROC #362997 · Licensed AZ Realtor · NAU Construction Management"). The
   markup lives in a Divi Code module reused across pages; hiding the class here
   removes it everywhere at once. Restore by reverting to the styled rule. */
.eb-final__creds { display: none; }

/* HOMEPAGE — Section 4B (Bridge). Full-width pine band, single row:
   line, grown rule, button. Reveal is deferred; row rendered directly. */
.et_pb_section:has(.eb-bridge) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-bridge) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-bridge { background: var(--surface-pine); padding: 64px var(--gutter); }
.eb-bridge__row { display: flex; align-items: center; gap: var(--space-6); }
.eb-bridge__line { font-family: var(--font-body); font-size: clamp(21px, 2.4vw, 28px); line-height: 1.3; color: var(--text-inverse); margin: 0; flex: none; max-width: 20ch; }
.eb-bridge__rule { flex: 1 1 auto; height: 1px; min-width: 40px; background: var(--border-inverse); }
.eb-bridge .eb-btn { flex: none; }
@media (max-width: 767px) {
	.eb-bridge__row { flex-direction: column; align-items: flex-start; gap: var(--space-5); }
	.eb-bridge__rule { display: none; }
}

/* ============================================================
   /services (What We Do) — 3 sections + JS-driven QuestionList
   artifacts. Reveal, artifact scale, and scroll parallax are real
   (recreated in an inline <script> on the page). Scoped to this page's
   own classes; nothing here matches homepage or header/footer markup.
   ============================================================ */

/* Reveal (real, JS-driven via the page's inline script). Literal values
   used in place of the reference --reveal-rise/--dur-reveal tokens. */
.eb-reveal { opacity: 0; transform: translateY(28px); transition: opacity 700ms var(--ease-standard) var(--reveal-delay, 0ms), transform 700ms var(--ease-standard) var(--reveal-delay, 0ms); }
.eb-reveal.on { opacity: 1; transform: none; }

.eb-eyebrow { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-accent); margin: 0; }
.eb-contact__lead { font-size: var(--type-lead); line-height: 1.55; color: var(--text-secondary); margin: 24px 0 36px; max-width: 380px; }

/* Section wrappers */
.et_pb_section:has(.eb-svc-intro) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-svc-intro) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-svc-intro { padding: 72px var(--gutter); }
.et_pb_section:has(.eb-svc-questions) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-svc-questions) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-svc-questions { padding: 0 var(--gutter) clamp(72px, 10vw, 128px); }

/* QuestionList */
.eb-question-list { display: flex; flex-direction: column; }
.eb-question { position: relative; max-width: 720px; padding: var(--space-9) 0; border-top: var(--rule); }
.eb-question:first-child { border-top: none; padding-top: 0; }
.eb-question:last-child { padding-bottom: 0; }
/* Questions 2–4 are each wrapped in their own .eb-reveal, so every one is the
   only child of its wrapper — which makes the naive :first-child/:last-child rules
   above wrongly strip its divider rule and vertical padding, collapsing them into
   one crammed block while Q1 (a direct list child) keeps its spacing. Restore the
   intended even rhythm by targeting the real list structure through the wrapper. */
.eb-question-list > .eb-reveal > .eb-question { border-top: var(--rule); padding-top: var(--space-9); padding-bottom: var(--space-9); }
.eb-question-list > .eb-reveal:last-child > .eb-question { padding-bottom: 0; }
.eb-question__sheet { position: absolute; z-index: 1; font-family: var(--font-body); font-size: 12px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--text-tertiary); white-space: nowrap; }
.eb-question__q { position: relative; z-index: 1; font-family: var(--font-body); font-weight: 500; font-size: clamp(24px, 2.8vw, 34px); line-height: 1.35; color: var(--text-primary); margin: 0 0 var(--space-5); max-width: 26ch; }
.eb-question__a { position: relative; z-index: 2; background: var(--surface-page); font-size: 17px; line-height: 1.7; color: var(--text-primary); margin: 0 0 var(--space-4); max-width: 640px; }
/* Service tag → an emphasized link to the matching service page. */
.eb-question__tag { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-body); font-size: 15px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); text-decoration: none; transition: color .2s var(--ease-standard, ease); }
.eb-question__tag::after { content: "\2192"; font-weight: 400; transition: transform .25s var(--ease-standard, ease); }
.eb-question__tag:hover, .eb-question__tag:focus-visible { color: var(--accent-hover); }
.eb-question__tag:hover::after, .eb-question__tag:focus-visible::after { transform: translateX(5px); }
.eb-question__tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px; }
@media (prefers-reduced-motion: reduce) { .eb-question__tag::after { transition: none; } }
.eb-question__artifact { position: absolute; z-index: 0; pointer-events: none; opacity: var(--art-opacity, .4); transition: opacity 400ms var(--ease-standard); transform: rotate(var(--art-rotate, 0deg)) translateY(var(--art-parallax, 0px)); will-change: transform; }
.eb-question__artifact svg { width: 100%; height: auto; display: block; overflow: visible; }
.eb-question:hover .eb-question__artifact { opacity: calc(var(--art-opacity, .4) + .22); }
.eb-artifact__draw { stroke-dasharray: 520; stroke-dashoffset: 520; transition: stroke-dashoffset 1100ms var(--ease-standard) 250ms; }
.eb-reveal.on .eb-artifact__draw { stroke-dashoffset: 0; }
.eb-artifact__fade { opacity: 0; transition: opacity 900ms var(--ease-standard) 600ms; }
.eb-reveal.on .eb-artifact__fade { opacity: 1; }
.eb-artifact__label { position: absolute; font-family: var(--font-body); font-style: italic; font-size: 11px; letter-spacing: .03em; color: var(--text-tertiary); opacity: 0; transition: opacity 700ms var(--ease-standard) 850ms; white-space: nowrap; }
.eb-reveal.on .eb-artifact__label { opacity: 1; }
@media (max-width: 959px) { .eb-question__sheet, .eb-question__artifact { display: none; } }

/* CTA (reuses .eb-cta__title from the homepage close) */
.et_pb_section:has(.eb-cta) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-cta) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-cta { background: var(--surface-pine); padding: clamp(72px, 10vw, 128px) var(--gutter); text-align: center; }
.eb-cta__lead { color: var(--text-inverse-secondary); font-size: var(--type-lead); margin: 20px auto 28px; max-width: 40rem; }
.eb-cta__actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) {
	.eb-reveal { transform: none; }
	.eb-artifact__draw { stroke-dashoffset: 0; transition: none; }
	.eb-artifact__fade, .eb-artifact__label { opacity: 1; transition: none; }
}
.eb-btn--inverse { background: transparent; color: var(--text-inverse); border-color: var(--border-inverse); }
.eb-btn--inverse:hover { border-color: var(--eb-paper); background: rgba(250, 247, 241, .08); color: var(--text-inverse); }

/* ============================================================
   /where-we-build — Journey (scroll "drive" map)
   Behavior in assets/js/journey.js. --ease-craft → --ease-standard.
   ============================================================ */

/* Divi full-bleed neutralization for the Journey section. */
.et_pb_section:has(.eb-journey) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-journey) .et_pb_row { width: 100%; max-width: 100%; padding: 0; margin: 0; }
.et_pb_section:has(.eb-journey) .et_pb_row .et_pb_column { width: 100%; margin: 0; }

.eb-journey { display: grid; }

.eb-journey__stage {
  grid-area: 1 / 1;
  position: sticky;
  top: 0;
  height: 100svh;
  align-self: start;
  overflow: hidden;
  background: var(--surface-page);
  z-index: 0;
}
.eb-journey__map { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.eb-journey__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(247, 245, 240, .74), rgba(247, 245, 240, .58) 45%, rgba(247, 245, 240, .74));
  pointer-events: none;
}

.eb-journey__content { grid-area: 1 / 1; position: relative; z-index: 1; }

.eb-journey__scene {
  min-height: 90vh;
  display: flex;
  align-items: center;
  padding: var(--space-7) var(--gutter);
  will-change: transform;
}
.eb-journey__scene--short { min-height: 82vh; }
.eb-journey__scene--medium { min-height: 100vh; }
.eb-journey__scene--long { min-height: 132vh; }
.eb-journey__scene--right { justify-content: flex-end; }
.eb-journey__scene-inner { max-width: 640px; }
.eb-journey__scene--intro .eb-journey__scene-inner { max-width: 860px; }

/* Town plates: a big photograph, then the town masthead, a headline (the site
   note), and a brief description. Centered so the ghost map + lit dot read in
   the margins; the alternating float is neutralized for stops. */
.eb-journey__scene--stop { justify-content: center; }
.eb-journey__scene--stop .eb-journey__scene-inner { max-width: 1120px; width: 100%; }

/* Caption below the photo: town + headline on the left, description on the
   right, baselines aligned like a printed plate. */
.eb-journey__plate-caption {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(24px, 4vw, 72px);
  align-items: end;
  margin-top: clamp(26px, 3.2vw, 44px);
}
.eb-journey__plate-tag {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-accent);
  margin: 0;
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 1.4), 1);
}
.eb-journey__plate-tag::before { content: ""; width: 22px; height: 2px; background: var(--accent); }
.eb-journey__scene--stop .eb-journey__stop-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(56px, 8.5vw, 128px);
  line-height: .9;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--text-primary);
  margin: 14px 0 0;
}
.eb-journey__scene--stop .eb-journey__observation {
  font-size: clamp(19px, 1.9vw, 26px);
  font-weight: 600;
  color: var(--text-primary);
  max-width: 24ch;
  margin: 18px 0 0;
}
.eb-journey__scene--stop .eb-journey__context { max-width: 48ch; margin: 0; }

@media (max-width: 820px) {
  .eb-journey__plate-caption { grid-template-columns: 1fr; gap: 18px; align-items: start; margin-top: 22px; }
  .eb-journey__scene--stop .eb-journey__observation { max-width: none; }
  .eb-journey__scene--stop .eb-journey__context { max-width: 60ch; }
}

.eb-journey__scene--intro .eb-eyebrow,
.eb-journey__intro-title,
.eb-journey__intro-lead {
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 1.4), 1);
}
.eb-journey__intro-title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(30px, 4.2vw, 60px);
  line-height: 1.1;
  color: var(--text-primary);
  margin: 14px 0 0;
}
.eb-journey__intro-lead {
  font-size: var(--type-lead);
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 480px;
  margin: 22px 0 0;
}
.eb-journey__intro-cue {
  display: block;
  width: 1px;
  height: 44px;
  margin-top: var(--space-7);
  background: var(--accent);
  opacity: clamp(0, calc((1 - var(--scene-fade-dist, 0) * 1.4) * .5), 1);
}

.eb-journey__stop-name {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(40px, 5.5vw, 72px);
  letter-spacing: -0.01em;
  line-height: 1.05;
  color: var(--text-accent);
  margin: 0 0 var(--space-6);
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 1), 1);
}
.eb-journey__observation {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(20px, 2.2vw, 26px);
  line-height: 1.45;
  color: var(--text-primary);
  margin: 0 0 var(--space-5);
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 1.4), 1);
}
.eb-journey__context {
  font-size: var(--type-body);
  line-height: 1.7;
  color: var(--text-secondary);
  max-width: 480px;
  margin: 0;
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 2), 1);
}

/* ---------- The map itself — atmosphere, not UI ---------- */
.eb-journey__outline { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; opacity: .9; }

.eb-journey__forest { fill: var(--eb-pine); opacity: .06; transition: opacity var(--dur-slow) var(--ease-standard); }
.eb-journey__forest.on { opacity: .16; }

.eb-journey__contours ellipse { fill: none; stroke: var(--eb-steel); stroke-width: 1; opacity: .28; }

/* Static road layer — the real I-40 + US-89A geography, laid down once, never redrawn. */
.eb-journey__road {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .38;
}

/* Town markers: quiet by default, lit (accent + halo) while their scene is active. */
.eb-journey__tick { fill: var(--eb-warm-gray); stroke: none; opacity: .4; transition: fill var(--dur-med) var(--ease-standard), opacity var(--dur-med) var(--ease-standard); }
.eb-journey__tick.on { fill: var(--accent); opacity: 1; }
.eb-journey__tick-glow { fill: var(--accent); opacity: 0; transition: opacity var(--dur-med) var(--ease-standard); }
.eb-journey__tick-glow.on { opacity: .18; }

@media (prefers-reduced-motion: reduce) {
  .eb-journey__stage { position: static; height: auto; }
  .eb-journey__scene { transform: none !important; }
  .eb-journey__scene--intro .eb-eyebrow,
  .eb-journey__intro-title,
  .eb-journey__intro-lead,
  .eb-journey__intro-cue,
  .eb-journey__stop-name,
  .eb-journey__observation,
  .eb-journey__context,
  .eb-journey__plate-tag,
  .eb-journey__photo { opacity: 1 !important; }
  .eb-journey__tick { opacity: .6 !important; }
  .eb-journey__forest { transition: none; }
}
/* Town photograph — the plate's hero. Real photo drops in as a child <img>;
   until then the figure shows a drafting-tinted empty state. */
.eb-journey__photo {
  position: relative;
  width: 100%;
  margin: 0;
  aspect-ratio: 3 / 2;
  max-height: 74vh; /* stay big, but keep the masthead close on tall viewports */
  overflow: hidden;
  background: var(--surface-tint);
  border: 1px solid var(--border-subtle);
  opacity: clamp(0, calc(1 - var(--scene-fade-dist, 0) * 1.6), 1);
}
.eb-journey__photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 1.2s cubic-bezier(.2, .7, .2, 1);
}
.eb-journey__photo:hover .eb-journey__photo-img { transform: scale(1.03); }
/* Empty state: dashed inner frame + centered utility label. */
.eb-journey__photo--empty { display: flex; align-items: center; justify-content: center; }
.eb-journey__photo--empty::before {
  content: "";
  position: absolute;
  inset: 16px;
  border: 1px dashed var(--border-strong);
  pointer-events: none;
}
.eb-journey__photo span {
  position: relative;
  font-family: var(--font-body);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--text-tertiary);
}

/* ============================================================
   Where We Build — immersive full-bleed town sections (redesign).
   Each town is an always-visible edge-to-edge photo with its info over a
   bottom scrim; .eb-town__img carries the shared Ken Burns scroll-zoom.
   ============================================================ */
.et_pb_section:has(.eb-wwb) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-wwb) .et_pb_row { width: 100%; max-width: 100%; padding: 0; margin: 0; }
.et_pb_section:has(.eb-wwb) .et_pb_row .et_pb_column { width: 100%; margin: 0; }

.eb-wwb__intro { background: var(--surface-page); padding: clamp(76px, 10vh, 132px) var(--gutter) clamp(56px, 7vh, 96px); }
.eb-wwb__intro .eb-container { max-width: var(--container); margin: 0 auto; }
.eb-wwb__intro .eb-eyebrow { margin: 0 0 18px; }
.eb-wwb__intro-title { font-size: clamp(38px, 6vw, 88px); line-height: 1; letter-spacing: .01em; text-transform: uppercase; color: var(--text-primary); margin: 0; }
.eb-wwb__intro-lead { font-size: var(--type-lead); line-height: 1.6; color: var(--text-secondary); max-width: 48ch; margin: 26px 0 0; }

.eb-town { position: relative; min-height: clamp(560px, 82vh, 860px); display: flex; align-items: center; overflow: hidden; background: var(--surface-page); }
.eb-town__media { position: absolute; inset: 0; overflow: hidden; }
.eb-town__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 40%; transform: scale(1); transform-origin: center; will-change: transform; display: block; }
.eb-town__ph { position: absolute; inset: 0 0 0 auto; width: 60%; display: flex; align-items: center; justify-content: center; font-family: var(--font-body); font-size: 13px; letter-spacing: .2em; text-transform: uppercase; color: var(--text-tertiary); background: var(--surface-tint); }
/* Paper gradient runs left to right: opaque behind the copy, clearing to reveal the photo on the right. */
.eb-town__scrim { position: absolute; inset: 0; background: linear-gradient(to right, var(--surface-page) 0%, var(--surface-page) 26%, rgba(250, 247, 241, .86) 42%, rgba(250, 247, 241, 0) 66%); }

/* Staggered towns: every other section flips — image on the left, copy block
   pushed to the right, gradient reversed — so the page zigzags down. */
.eb-town--flip .eb-town__scrim { background: linear-gradient(to left, var(--surface-page) 0%, var(--surface-page) 26%, rgba(250, 247, 241, .86) 42%, rgba(250, 247, 241, 0) 66%); }
.eb-town--flip .eb-town__body { margin-left: auto; }
.eb-town--flip .eb-town__ph { inset: 0 auto 0 0; }

.eb-town__inner { position: relative; z-index: 1; width: 100%; max-width: var(--container); margin: 0 auto; padding: clamp(44px, 8vh, 104px) var(--gutter); }
.eb-town__body { max-width: 520px; }
.eb-town__index { font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: .2em; color: var(--text-tertiary); margin: 0 0 22px; }
.eb-town__tag { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-body); font-size: 13px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--accent); margin: 0; }
.eb-town__tag::before { content: ""; width: 24px; height: 2px; background: var(--accent); }
.eb-town__name { font-size: clamp(56px, 8vw, 120px); line-height: .9; letter-spacing: .01em; text-transform: uppercase; color: var(--text-primary); margin: 12px 0 0; }
.eb-town__note { font-size: clamp(19px, 2.1vw, 26px); font-weight: 600; line-height: 1.3; color: var(--text-primary); margin: 18px 0 0; max-width: 22ch; }
.eb-town__context { font-size: var(--type-body); line-height: 1.7; color: var(--text-secondary); margin: 18px 0 0; max-width: 46ch; }

/* Mobile: stack the photo on top of the copy (the side gradient does not work narrow). */
@media (max-width: 760px) {
  .eb-town { display: block; min-height: 0; }
  .eb-town__media { position: relative; height: 56vh; }
  .eb-town__ph { inset: 0; width: 100%; }
  .eb-town__scrim { display: none; }
  .eb-town__body { max-width: none; }
  .eb-town__context { max-width: 60ch; }
}

/* ============================================================
   /about (About Ernie) — hero split + story. CTA reuses .eb-cta.
   --section-y not in WP tokens → hardcoded clamp(72px,10vw,128px).
   ============================================================ */

/* Divi full-bleed neutralization for the two About sections. */
.et_pb_section:has(.eb-about-hero),
.et_pb_section:has(.eb-about-story-wrap) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-about-hero) .et_pb_row,
.et_pb_section:has(.eb-about-story-wrap) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.et_pb_section:has(.eb-about-hero) .et_pb_row .et_pb_column,
.et_pb_section:has(.eb-about-story-wrap) .et_pb_row .et_pb_column { width: 100%; margin: 0; }

/* Section shells (Section pad="72px" hero; default section-y story). */
.eb-about-hero { padding: 72px var(--gutter); }
.eb-about-section { padding: clamp(72px, 10vw, 128px) var(--gutter); }

/* Shared page grid */
.eb-split-5-7 { display: grid; grid-template-columns: 5fr 7fr; gap: var(--space-8); align-items: start; }
.eb-split-5-7--center { align-items: center; }

.eb-about-hero__portrait { width: 100%; max-width: 420px; display: block; }
.eb-about-name {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--text-tertiary);
  margin: 0;
}

.eb-about-story-wrap { display: grid; grid-template-columns: minmax(0, 760px) 1fr; gap: var(--space-8); }
.eb-about-story-wrap__mark {
  position: sticky;
  top: 160px;
  height: fit-content;
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.eb-about-story-wrap__rule { flex: none; width: 2px; height: 64px; background: var(--accent); }
.eb-about-story-wrap__label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--font-body);
  font-size: var(--type-eyebrow);
  font-weight: 600;
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
}
.eb-about-story { max-width: 720px; margin: 0 0 var(--space-8); }
.eb-about-story__lead {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(26px, 3.2vw, 40px);
  line-height: 1.4;
  color: var(--text-primary);
  margin: 0;
}
.eb-about-story__quiet {
  font-size: var(--type-lead);
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 46ch;
  margin: var(--space-5) 0 0;
}
.eb-about-bio { font-size: 17px; line-height: 1.7; color: var(--text-primary); max-width: 640px; }
/* Match the reference's default paragraph rhythm (UA 1em margins), overriding
   Divi's own p { padding-bottom:1em; margin:0 } default. */
.eb-about-bio p { margin: 1em 0; }
.eb-about-bio p:first-child { margin-top: 0; }
.eb-about-bio p:last-child { margin-bottom: 0; }
.eb-about-proof {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  max-width: 640px;
  margin: var(--space-7) 0 0;
  padding-top: var(--space-5);
  border-top: var(--rule);
}

@media (max-width: 959px) {
  .eb-split-5-7 { grid-template-columns: 1fr; }
  .eb-about-story-wrap { grid-template-columns: 1fr; }
  .eb-about-story-wrap__mark { display: none; }
}

/* ============================================================
   Homepage scroll reveals — reproduce the reference's <Reveal>
   entrances (app/page.tsx: staggered stats, capability cards, the
   bridge row, and the realities notes/turn/payoff) by targeting the
   same elements directly, so no page-content changes are needed.
   Engine: assets/js/reveal.js adds `.on` when an element scrolls into
   view. Gated by html.eb-anim (added pre-paint in inc/enqueue.php) and
   a no-preference media query, so no-JS and reduced-motion users get
   the final state with no animation and no flash.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {

	/* Shared entrance transition (opacity + rise), per-element stagger via
	   --reveal-delay set below. */
	html.eb-anim .eb-philosophy__stats > .eb-stat,
	html.eb-anim .eb-bridge__row,
	html.eb-anim .eb-realities__grid > .eb-realities__note,
	html.eb-anim .eb-realities__turn,
	html.eb-anim .eb-realities__payoff {
		transition:
			opacity 700ms var(--ease-standard) var(--reveal-delay, 0ms),
			transform 700ms var(--ease-standard) var(--reveal-delay, 0ms);
	}

	/* Pre-hide state — the :not(.on) pattern means the rule simply stops
	   matching once revealed, so an element with its own transform (the
	   capability cards' hover lift) is never fought by a revealed-state
	   transform override. */
	html.eb-anim .eb-philosophy__stats > .eb-stat:not(.on),
	html.eb-anim .eb-capabilities__grid > .eb-capability:not(.on),
	html.eb-anim .eb-bridge__row:not(.on),
	html.eb-anim .eb-realities__grid > .eb-realities__note:not(.on),
	html.eb-anim .eb-realities__turn:not(.on),
	html.eb-anim .eb-realities__payoff:not(.on) {
		opacity: 0;
		transform: translateY(28px);
	}

	/* Stats — larger rise (40px), slower (850ms), staggered 160ms; plus the
	   value scale-in and the accent rule growing 0 → 32px, matching the
	   reference's philosophy-stats treatment. */
	html.eb-anim .eb-philosophy__stats > .eb-stat { transition-duration: 850ms; }
	html.eb-anim .eb-philosophy__stats > .eb-stat:not(.on) { transform: translateY(40px); }
	html.eb-anim .eb-philosophy__stats > .eb-stat:nth-child(2) { --reveal-delay: 160ms; }
	html.eb-anim .eb-philosophy__stats > .eb-stat:nth-child(3) { --reveal-delay: 320ms; }
	html.eb-anim .eb-philosophy__stats > .eb-stat .eb-stat__value {
		display: inline-block;
		transform: scale(.86);
		transition: transform 850ms var(--ease-standard) 90ms;
	}
	html.eb-anim .eb-philosophy__stats > .eb-stat.on .eb-stat__value { transform: scale(1); }
	html.eb-anim .eb-philosophy__stats > .eb-stat .eb-stat__rule {
		width: 0;
		transition: width var(--dur-med) var(--ease-standard) 200ms;
	}
	html.eb-anim .eb-philosophy__stats > .eb-stat.on .eb-stat__rule { width: 32px; }

	/* Capabilities — staggered 100ms. Own transition keeps the hover
	   feedback (border/box-shadow at 400ms), and hover resets the reveal
	   delay so a card near the end of the stagger still lifts immediately. */
	html.eb-anim .eb-capabilities__grid > .eb-capability {
		transition:
			opacity 700ms var(--ease-standard) var(--reveal-delay, 0ms),
			transform 700ms var(--ease-standard) var(--reveal-delay, 0ms),
			border-color 400ms var(--ease-standard),
			box-shadow 400ms var(--ease-standard);
	}
	html.eb-anim .eb-capabilities__grid > .eb-capability:hover { transition-delay: 0s; }
	html.eb-anim .eb-capabilities__grid > .eb-capability:nth-child(2) { --reveal-delay: 100ms; }
	html.eb-anim .eb-capabilities__grid > .eb-capability:nth-child(3) { --reveal-delay: 200ms; }
	html.eb-anim .eb-capabilities__grid > .eb-capability:nth-child(4) { --reveal-delay: 300ms; }

	/* Realities — notes staggered 90ms, then the turn (360ms) and payoff
	   (480ms), plus the turn's accent rule growing 0 → 40px. */
	html.eb-anim .eb-realities__grid > .eb-realities__note:nth-child(2) { --reveal-delay: 90ms; }
	html.eb-anim .eb-realities__grid > .eb-realities__note:nth-child(3) { --reveal-delay: 180ms; }
	html.eb-anim .eb-realities__grid > .eb-realities__note:nth-child(4) { --reveal-delay: 270ms; }
	html.eb-anim .eb-realities__turn { --reveal-delay: 360ms; }
	html.eb-anim .eb-realities__payoff { --reveal-delay: 480ms; }
	html.eb-anim .eb-realities__turn .eb-realities__turn-rule {
		width: 0;
		transition: width var(--dur-med) var(--ease-standard) 200ms;
	}
	html.eb-anim .eb-realities__turn.on .eb-realities__turn-rule { width: 40px; }
}

/* ============================================================
   Sticky mobile conversion bar (.eb-mobile-bar) — ported from the
   reference Footer.tsx / globals.css. Shown ≤959px, output on every
   page via a wp_footer action in inc/enqueue.php.
   ============================================================ */
.eb-mobile-bar { display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 60; }
@media (max-width: 959px) {
	.eb-mobile-bar { display: grid; grid-template-columns: 1fr 1fr; }
	body { padding-bottom: 56px; }
	.eb-mobile-bar a {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 56px;
		font-family: var(--font-body);
		font-size: 15px;
		font-weight: 600;
		letter-spacing: var(--button-tracking);
		text-transform: uppercase;
		text-decoration: none;
	}
	.eb-mobile-bar__call { background: var(--eb-ink); color: var(--text-inverse); }
	.eb-mobile-bar__call:hover { color: var(--text-inverse); }
	.eb-mobile-bar__cta { background: var(--accent); color: var(--accent-ink); }
	.eb-mobile-bar__cta:hover { color: var(--accent-ink); }
}

/* ============================================================
   Self-owned mobile menu (.eb-mnav) — replaces Divi's native mobile
   hamburger, which is an untappable <span> on iOS. Our toggle is a real
   <button> (natively tappable), driving our own dark dropdown panel that
   mirrors the reference's .eb-nav__menu. Markup printed via wp_footer
   (inc/enqueue.php); behavior in assets/js/mobile-nav.js. Divi's own
   mobile menu is hidden at the same breakpoint so there's only one.
   ============================================================ */
.eb-mnav__toggle,
.eb-mnav,
.eb-mnav__backdrop { display: none; }

@media (max-width: 959px) {
	/* Remove Divi's native (untappable) mobile hamburger + menu. */
	.et_mobile_nav_menu,
	.et_pb_menu__mobile-bottom { display: none !important; }

	/* Our hamburger — a real button, vertically centered in the 76px header. */
	.eb-mnav__toggle {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		position: fixed;
		top: 14px;
		right: 16px;
		z-index: 1002;
		width: 48px;
		height: 48px;
		padding: 0;
		background: none;
		border: none;
		cursor: pointer;
		color: var(--eb-ink);
		-webkit-tap-highlight-color: transparent;
	}
	body.admin-bar .eb-mnav__toggle { top: calc(14px + 46px); }
	body.admin-bar:has(.eb-header.scrolled) .eb-mnav__toggle { top: 14px; }
	/* White over the dark hero (transparent header); ink otherwise. Always ink
	   while the menu is open, since the panel behind the X is light. */
	body.eb-hero-dark:has(.eb-header:not(.scrolled)) .eb-mnav__toggle { color: var(--eb-white); }
	.eb-mnav__toggle[aria-expanded="true"] { color: var(--eb-ink) !important; }

	.eb-mnav__bars { position: relative; width: 26px; height: 2px; background: currentColor; transition: background-color .15s linear; }
	.eb-mnav__bars::before,
	.eb-mnav__bars::after {
		content: '';
		position: absolute;
		left: 0;
		width: 26px;
		height: 2px;
		background: currentColor;
		transition: transform .3s var(--ease-standard);
	}
	.eb-mnav__bars::before { top: -8px; }
	.eb-mnav__bars::after { top: 8px; }
	.eb-mnav__toggle[aria-expanded="true"] .eb-mnav__bars { background: transparent; }
	.eb-mnav__toggle[aria-expanded="true"] .eb-mnav__bars::before { transform: translateY(8px) rotate(45deg); }
	.eb-mnav__toggle[aria-expanded="true"] .eb-mnav__bars::after { transform: translateY(-8px) rotate(-45deg); }

	/* Full-screen light panel covers everything; the WP admin bar (z-index 99999)
	   still renders above it for logged-in users, so no admin offset is needed. */
	.eb-mnav__backdrop { display: none; }
	.eb-mnav__backdrop[hidden] { display: none; }

	.eb-mnav {
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		text-align: center;
		gap: 6px;
		position: fixed;
		inset: 0;
		z-index: 1001;
		background: var(--eb-paper);
		padding: 72px var(--gutter) 40px;
	}
	.eb-mnav[hidden] { display: none; }

	.eb-mnav__link {
		display: block;
		font-family: var(--font-body);
		font-size: 22px;
		font-weight: 600;
		text-transform: uppercase;
		letter-spacing: .04em;
		text-decoration: none;
		color: var(--eb-ink);
		padding: 8px 0;
	}
	.eb-mnav__link:hover { color: var(--accent); }
	.eb-mnav__link--sub { font-size: 15px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--text-secondary); }
	.eb-mnav__cta { width: auto; margin-top: 18px; }

	/* About Us disclosure: tap to expand its sub-links; caret rotates. */
	.eb-mnav__group { display: flex; flex-direction: column; align-items: center; gap: 6px; }
	.eb-mnav__disclosure { display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; cursor: pointer; font: inherit; }
	.eb-mnav__caret { display: inline-block; width: 8px; height: 8px; margin: -3px 0 0 12px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); transition: transform .2s ease; }
	.eb-mnav__disclosure[aria-expanded="true"] .eb-mnav__caret { transform: rotate(-135deg); margin-top: 3px; }
	.eb-mnav__submenu { display: flex; flex-direction: column; align-items: center; gap: 6px; }
	.eb-mnav__submenu[hidden] { display: none; }

	/* Social row in the mobile menu: centered, dark-on-paper (the menu is light). */
	.eb-mnav__social { justify-content: center; margin-top: 26px; }
	.eb-mnav .eb-social__link { border-color: rgba(23, 21, 20, .18); color: var(--eb-ink); }
	.eb-mnav .eb-social__link:hover,
	.eb-mnav .eb-social__link:focus-visible { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
}

/* ============================================================
   Header + footer logo — EB mark in accent orange (swap the white SVG for
   the orange one via CSS, no Theme Builder edit) + tighten the logo's left
   margin on mobile (Divi's header row hardcodes 48px padding; use the
   responsive --gutter instead so it isn't pushed in on a phone).
   ============================================================ */
/* Footer sits on the dark charcoal ground, so it keeps the white-frame mark
   (orange monogram + paper-white house frame). */
.et-l--footer img[src*="logo-mark"] {
	content: url(../logo/logo-mark-eb.svg);
}
/* Header now sits on a light-tan ground, so it uses the dark-frame mark:
   orange monogram + ink house frame (black + orange), legible on tan. */
.et-l--header img[src*="logo-mark"] {
	content: url(../logo/logo-mark-eb-dark.svg);
}
@media (max-width: 959px) {
	/* Divi keeps the header row at its default width:80%; max-width:1080px;
	   margin:auto, so on a phone it's centered and ~10% narrower than the
	   viewport — that centering margin, on top of the gutter padding, is what
	   pushes the logo too far in. Make the row full-bleed so the logo sits one
	   tight gutter (16px) from the edge, balancing the mobile hamburger's own
	   right:16px. !important is needed here for the same reason as this row's
	   flex-wrap rule above — Divi's own responsive row/column CSS wins at this
	   specificity otherwise. */
	.eb-header {
		width: 100% !important;
		max-width: 100% !important;
		margin-left: 0 !important;
		margin-right: 0 !important;
		padding-left: 16px;
		padding-right: 16px;
	}
}

/* Header brand link — wraps the logo lockup (added in header.js), so the
   mark + wordmark link to the homepage without disturbing the inner flex. */
.eb-header-brand__link { display: inline-flex; align-items: center; text-decoration: none; color: inherit; }

/* Footer brand link — same treatment for the footer lockup (added in
   footer.js): inline-flex so the anchor hugs the mark + wordmark rather than
   spanning the column, keeping the click target tight. */
.eb-footer-brand__link { display: inline-flex; align-items: center; text-decoration: none; color: inherit; }

/* ============================================================
   HOMEPAGE — Letter frame ([eb_home_letter]). One real client letter as
   quiet evidence of continuity: photographed derivative + verbatim
   transcription. Deliberately shares the "Meet Ernie" section's charcoal
   ground and caption treatment (.eb-record) so it reads as that section's
   pair — the founder says who he is, a client confirms it. The dark ground
   also gives the bright letter real separation and presence (paper-on-paper
   read as pasted-in). Uses the theme's own devices: eyebrow label, the
   recurring accent rule, caption-style attribution. NOT in reveal.js's target
   list — it renders plainly, a peer of the sections around it (the approved
   "not a dramatic reveal" principle).
   ============================================================ */
.et_pb_section:has(.eb-letter) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-letter) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.eb-letter { position: relative; overflow: hidden; background: var(--eb-charcoal); color: var(--text-inverse); padding: clamp(72px, 10vw, 128px) var(--gutter); }
.eb-letter__inner { display: flex; align-items: center; gap: clamp(40px, 7vw, 110px); }
.eb-letter__figure { flex: 0 0 46%; margin: 0; }
/* Seat the letter as a real object resting in space — one soft, low, realistic
   shadow (a document on a desk), not a hard card. Sharp corners: it's a
   document, not a card (--radius-sm is 0). */
/* Card-style drop-shadow, matched to the JDG team-photo cards
   (--shadow-md: 0 10px 30px -12px). JDG's value is tuned for light grounds;
   on the charcoal letter bands the same geometry needs a darker tone to read,
   so the light-band override below uses JDG's exact warm-ink value. */
.eb-letter__img { display: block; width: 100%; height: auto; border-radius: 0; box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .5); }
.eb-letter__text { flex: 1 1 auto; max-width: 48ch; }
.eb-letter__eyebrow { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-inverse-secondary); margin: 0; }
.eb-letter__rule { display: block; width: 40px; height: 2px; background: var(--accent); margin: 18px 0 28px; }
/* Neutralize Divi's default blockquote chrome (stock-blue 5px left border +
   left padding + background) — same third-party-chrome override pattern as
   the header/footer fixes above. Two classes so it beats Divi's own
   `.et_pb_section blockquote` without !important. */
.eb-letter .eb-letter__transcript,
.eb-experiences .eb-letter__transcript { position: relative; margin: 0; border: 0; padding: 0; background: transparent; }
/* Keep the words above the oversized quotation marks. */
.eb-letter__transcript > * { position: relative; z-index: 1; }
/* Oversized quotation marks — an editorial flourish set BEHIND the copy so the
   words overlap them, not a corner sticker. Serif is deliberate (and the only
   serif on the site): the large curly quote is an ornamental glyph, never
   reading type. Accent orange at 50%. Purely decorative — the real quotation
   is the <blockquote>; the section clips (overflow:hidden) so the marks can
   bleed off-edge without adding scroll. */
.eb-letter__transcript::before,
.eb-letter__transcript::after {
	position: absolute;
	z-index: 0;
	font-family: Georgia, "Times New Roman", serif;
	font-size: clamp(6rem, 12vw, 11rem);
	line-height: 1;
	color: var(--accent);
	opacity: .5;
	pointer-events: none;
}
.eb-letter__transcript::before { content: "\201C"; top: -0.18em; left: -0.12em; }
.eb-letter__transcript::after { content: "\201D"; right: -0.02em; bottom: -0.42em; }
.eb-letter__date { font-family: var(--font-body); font-size: var(--type-caption); letter-spacing: .1em; text-transform: uppercase; color: var(--text-inverse-secondary); margin: 0 0 var(--space-4); }
.eb-letter__transcript p { font-family: var(--font-body); font-size: var(--type-body); line-height: var(--body-line); color: var(--text-inverse); margin: 0 0 var(--space-4); }
.eb-letter__attribution { margin: var(--space-5) 0 0; }
.eb-letter__attribution cite { font-family: var(--font-body); font-style: normal; font-size: var(--type-body-sm); letter-spacing: .06em; color: var(--text-inverse-secondary); }
@media (max-width: 959px) {
	.eb-letter__inner { flex-direction: column; align-items: stretch; gap: var(--space-7); }
	.eb-letter__figure { flex: 1 1 auto; width: 100%; max-width: 460px; align-self: center; }
	.eb-letter__text { max-width: none; }
}

/* Homepage letter — "Read all letters" link to the Client Experiences page.
   Inverse colors for the charcoal ground; the arrow nudges on hover, matching
   the theme's decisions-row arrow motif. */
.eb-letter__more { display: inline-flex; align-items: center; gap: 8px; margin-top: var(--space-6); font-family: var(--font-body); font-size: var(--type-body-sm); font-weight: 600; letter-spacing: .04em; color: var(--text-inverse); text-decoration: none; }
.eb-letter__more:hover { color: var(--eb-sandstone); }
.eb-letter__more-arrow { transition: transform var(--dur-med) var(--ease-standard); }
.eb-letter__more:hover .eb-letter__more-arrow { transform: translateX(6px); }
.eb-letter__more:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .eb-letter__more-arrow { transition: none; } }

/* ============================================================
   PAGE — Client Experiences ([eb_client_experiences]). The full collection of
   client letters. Reuses the homepage letter's inner treatment (.eb-letter__*)
   on the same charcoal ground, alternating the image side for rhythm; a light
   intro band above and the shared pine CTA (.eb-cta) below. One Divi Code
   module wraps the whole page, so the section is neutralized once here.
   ============================================================ */
.et_pb_section:has(.eb-experiences) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-experiences) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.et_pb_section:has(.eb-experiences) .et_pb_row .et_pb_column { width: 100%; margin: 0; }

.eb-experiences__intro { background: var(--eb-paper-2); color: var(--text-primary); padding: clamp(88px, 11vw, 150px) var(--gutter) clamp(48px, 6vw, 72px); }
.eb-experiences__eyebrow { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-secondary); margin: 0 0 18px; }
.eb-experiences__title { font-size: var(--type-display-lg); color: var(--text-primary); margin: 0; }
.eb-experiences__lead { font-family: var(--font-body); font-size: var(--type-lead); line-height: 1.5; color: var(--text-secondary); max-width: 46ch; margin: var(--space-5) 0 0; }

.eb-letter-entry { position: relative; overflow: hidden; background: var(--eb-charcoal); color: var(--text-inverse); padding: clamp(64px, 8vw, 104px) var(--gutter); }
/* Alternating grounds: default entries are charcoal (inverse text); --light
   entries flip to the warm paper tint with dark text and a softer shadow. The
   ground change itself separates consecutive entries, so no divider rule. */
.eb-letter-entry--light { background: var(--eb-paper-2); color: var(--text-primary); }
.eb-letter-entry--light .eb-letter__eyebrow,
.eb-letter-entry--light .eb-letter__date { color: var(--text-secondary); }
.eb-letter-entry--light .eb-letter__transcript p { color: var(--text-primary); }
.eb-letter-entry--light .eb-letter__attribution cite { color: var(--text-secondary); }
.eb-letter-entry--light .eb-letter__img { box-shadow: 0 10px 30px -12px rgba(30, 29, 23, .18); }
.eb-letter-entry__inner { display: flex; align-items: center; gap: clamp(40px, 7vw, 110px); max-width: var(--container); margin: 0 auto; }
.eb-letter-entry--flip .eb-letter-entry__inner { flex-direction: row-reverse; }
@media (max-width: 959px) {
	.eb-letter-entry__inner,
	.eb-letter-entry--flip .eb-letter-entry__inner { flex-direction: column; align-items: stretch; gap: var(--space-7); }
}

/* Client Experiences — reveal entrances, reusing the homepage engine
   (reveal.js adds `.on`; gated by html.eb-anim + no-preference so no-JS and
   reduced-motion users get the final, visible state with no flash). The intro
   group staggers in on load; as each letter scrolls into view its image
   settles first, then its words (140ms behind). Same opacity + 28px rise and
   --ease-standard as the homepage, so it's one motion language. */
@media (prefers-reduced-motion: no-preference) {
	html.eb-anim .eb-experiences__eyebrow,
	html.eb-anim .eb-experiences__title,
	html.eb-anim .eb-experiences__lead,
	html.eb-anim .eb-letter-entry .eb-letter__figure,
	html.eb-anim .eb-letter-entry .eb-letter__text {
		transition:
			opacity 700ms var(--ease-standard) var(--reveal-delay, 0ms),
			transform 700ms var(--ease-standard) var(--reveal-delay, 0ms);
	}
	html.eb-anim .eb-experiences__eyebrow:not(.on),
	html.eb-anim .eb-experiences__title:not(.on),
	html.eb-anim .eb-experiences__lead:not(.on),
	html.eb-anim .eb-letter-entry .eb-letter__figure:not(.on),
	html.eb-anim .eb-letter-entry .eb-letter__text:not(.on) {
		opacity: 0;
		transform: translateY(28px);
	}
	html.eb-anim .eb-experiences__title { --reveal-delay: 100ms; }
	html.eb-anim .eb-experiences__lead { --reveal-delay: 200ms; }
	html.eb-anim .eb-letter-entry .eb-letter__text { --reveal-delay: 140ms; }
}

/* ============================================================
   Letter lightbox. The letter image is a button (.eb-letter__zoom) that opens
   a full-size, scrollable overlay so the real artifact can be inspected up
   close. A quiet corner badge is the affordance (visible on touch, not just
   hover). Behavior in assets/js/letters-lightbox.js; overlay markup printed in
   inc/enqueue.php. Enhancement only — the transcription is the reading path.
   ============================================================ */
.eb-letter__zoom { display: block; width: 100%; margin: 0; padding: 0; border: 0; background: none; appearance: none; -webkit-appearance: none; position: relative; cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.eb-letter__zoom:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.eb-letter__zoom-badge { position: absolute; top: 14px; right: 14px; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(19, 21, 20, .6); color: var(--eb-paper); font-family: var(--font-body); font-size: 24px; line-height: 1; transition: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
.eb-letter__zoom:hover .eb-letter__zoom-badge,
.eb-letter__zoom:focus-visible .eb-letter__zoom-badge { background: var(--accent); color: var(--accent-ink); transform: scale(1.08); }

/* Overlay. z-index sits above the fixed mobile nav toggle (1002) so nothing
   floats over the open letter. */
html.eb-lightbox-open, html.eb-lightbox-open body { overflow: hidden; }
.eb-lightbox { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center; padding: clamp(16px, 4vw, 56px); }
.eb-lightbox[hidden] { display: none; }
.eb-lightbox__backdrop { position: absolute; inset: 0; background: rgba(19, 21, 20, .88); }
.eb-lightbox__close { position: absolute; top: clamp(12px, 3vw, 24px); right: clamp(12px, 3vw, 24px); z-index: 2; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; padding: 0; border: 1px solid var(--border-inverse); border-radius: 50%; background: transparent; color: var(--eb-paper); font-family: var(--font-body); font-size: 26px; line-height: 1; cursor: pointer; transition: background-color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard); }
.eb-lightbox__close:hover { border-color: var(--eb-paper); background: rgba(250, 247, 241, .08); }
.eb-lightbox__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.eb-lightbox__panel { position: relative; z-index: 1; max-width: min(680px, 92vw); max-height: 92vh; overflow: auto; -webkit-overflow-scrolling: touch; }
.eb-lightbox__img { display: block; width: 100%; height: auto; box-shadow: 0 40px 80px -30px rgba(0, 0, 0, .7); }
.eb-lightbox__caption { margin: 0; padding: 16px 4px 6px; font-family: var(--font-body); font-size: var(--type-body-sm); letter-spacing: .06em; color: var(--text-inverse-secondary); text-align: center; }
@media (prefers-reduced-motion: no-preference) {
	.eb-lightbox:not([hidden]) .eb-lightbox__backdrop { animation: eb-lightbox-fade 240ms var(--ease-standard) both; }
	.eb-lightbox:not([hidden]) .eb-lightbox__panel { animation: eb-lightbox-rise 320ms var(--ease-standard) both; }
}
@keyframes eb-lightbox-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes eb-lightbox-rise { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }

/* ============================================================
   PAGE — Start a Conversation ([eb_contact]). Ported from the Next.js contact
   reference. Reuses .eb-split-5-7 (intro), the M2 global field styles
   (underline inputs), and .eb-btn. One Divi Code module wraps the page, so the
   section is neutralized once here.
   ============================================================ */
.et_pb_section:has(.eb-contact) { padding: 0; background-color: transparent; }
.et_pb_section:has(.eb-contact) .et_pb_row { width: 100%; max-width: 100%; padding: 0; }
.et_pb_section:has(.eb-contact) .et_pb_row .et_pb_column { width: 100%; margin: 0; }
.eb-contact { background: var(--surface-page); color: var(--text-primary); padding: clamp(72px, 10vw, 120px) var(--gutter); }

.eb-contact__intro { margin-bottom: clamp(48px, 7vw, 84px); }
.eb-contact__title { font-size: var(--type-display-lg); color: var(--text-primary); margin: 18px 0 0; }
.eb-contact__lead { font-size: var(--type-lead); line-height: 1.55; color: var(--text-secondary); margin: 24px 0 0; max-width: 380px; }
.eb-contact__direct { margin-top: 28px; display: flex; flex-direction: column; gap: 10px; }
.eb-contact__email { font-family: var(--font-body); font-size: var(--type-lead); color: var(--text-primary); text-decoration: underline; text-underline-offset: 3px; }
.eb-contact__email:hover { color: var(--eb-cedar); }
.eb-contact__meta { font-family: var(--font-body); font-size: var(--type-caption); letter-spacing: .04em; line-height: 1.7; color: var(--text-tertiary); }
.eb-contact__bigphone { display: inline-flex; flex-direction: column; gap: 10px; font-family: var(--font-display); font-size: clamp(38px, 6vw, 68px); line-height: .95; letter-spacing: .01em; color: var(--text-primary); text-decoration: none; transition: color var(--dur-fast) var(--ease-standard); }
.eb-contact__bigphone:hover { color: var(--accent); }
.eb-contact__bigphone-label { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-tertiary); }

.eb-contact__grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: clamp(32px, 5vw, 64px); align-items: start; }
.eb-contact__form { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5) var(--space-6); margin: 0; }
.eb-field { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.eb-field--full { grid-column: 1 / -1; }
.eb-field__label { font-family: var(--font-body); font-size: var(--type-eyebrow); font-weight: 600; letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-secondary); margin: 0; }
.eb-field__control { width: 100%; }
.eb-btn--lg { padding: 16px 34px; }

/* Shared lead form (.eb-leadform) — the single form on /contact/ and
   /project-management-consulting/ (partials/global/lead-form.php). Two-column
   field grid; message + actions span full width. Identical on both pages. */
.eb-leadform-wrap { width: 100%; max-width: 860px; margin: 0 auto; }
.eb-contact__formmain { margin-top: clamp(32px, 5vw, 56px); }
.eb-leadform { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(20px, 3vw, 32px); }
.eb-leadform .eb-field--full { grid-column: 1 / -1; }
.eb-leadform__actions { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; gap: clamp(16px, 3vw, 28px); flex-wrap: wrap; margin-top: 12px; }
.eb-leadform__phone { font-family: var(--font-body); font-size: 15px; color: var(--text-tertiary); text-decoration: underline; text-underline-offset: 3px; }
.eb-leadform__phone:hover { color: var(--text-primary); }
/* Honeypot: visually and semantically hidden, still submitted if a bot fills it. */
.eb-leadform__hp { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.eb-leadform__notice { font-family: var(--font-body); font-size: var(--type-lead); line-height: 1.5; padding: 18px 22px; margin: 0 0 var(--space-5); border-left: 3px solid var(--accent); background: var(--surface-tint); }
.eb-leadform__notice--ok { color: var(--text-primary); }
.eb-leadform__notice--err { border-left-color: #b3452f; color: var(--text-primary); }
@media (max-width: 639px) { .eb-leadform { grid-template-columns: 1fr; } }

.eb-cal { border: 1px solid var(--border-subtle); background: var(--surface-tint); padding: clamp(24px, 3vw, 36px); }
.eb-cal__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.eb-cal__icon { width: 40px; height: 40px; color: var(--text-tertiary); margin: 20px 0 18px; }
.eb-cal__title { font-family: var(--font-body); font-weight: 600; font-size: var(--type-lead); color: var(--text-primary); margin: 0 0 8px; }
.eb-cal__desc { font-family: var(--font-body); font-size: var(--type-body-sm); line-height: 1.6; color: var(--text-secondary); margin: 0; max-width: 40ch; }
.eb-cal__frame { width: 100%; min-height: 580px; border: 0; display: block; }

.eb-badge { display: inline-flex; align-items: center; font-family: var(--font-body); font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; padding: 4px 10px; }
.eb-badge--orange { background: var(--accent); color: var(--accent-ink); }

.eb-contact__close { max-width: 640px; margin: clamp(56px, 8vw, 96px) auto 0; text-align: center; font-family: var(--font-body); font-size: var(--type-lead); line-height: 1.5; color: var(--text-secondary); }

/* Cal.com inline booking section. Only the Earnest Built container is styled;
   Cal's own iframe/widget is left untouched. Reuses the site's type/spacing
   tokens so it reads as native to the page. */
.eb-booking { margin-top: clamp(64px, 9vw, 112px); }
.eb-booking__head { text-align: center; max-width: 60ch; margin: 0 auto clamp(28px, 4vw, 44px); }
.eb-booking__head .eb-eyebrow { margin: 0 0 14px; }
.eb-booking__title { font-size: var(--type-display-md); line-height: 1.02; color: var(--text-primary); margin: 0; }
.eb-booking__lead { font-size: var(--type-lead); line-height: 1.55; color: var(--text-secondary); max-width: 56ch; margin: 16px auto 0; }
.eb-booking__cal { max-width: 980px; margin: 0 auto; }
/* Container sizing lives here, not inline (per requirements 2 & 5): a min-height
   floor that reserves space so the embed can't collapse before Cal loads, kept
   below the rendered widget height so Cal's auto-resize grows the box to fit
   with no dead space and no internal scrollbar. Never height:100%. */
.eb-booking__cal #my-cal-inline-consultation { width: 100%; min-height: 500px; overflow: auto; }

@media (max-width: 959px) {
	.eb-contact__grid { grid-template-columns: 1fr; }
	.eb-contact__bigphone { margin-top: var(--space-6); }
}
@media (max-width: 639px) {
	.eb-contact__form { grid-template-columns: 1fr; }
}

/* Fluent Forms (form #4) restyled to the site's hand-built field look:
   transparent underline inputs, uppercase eyebrow labels, sharp orange submit.
   Scoped under .eb-contact__formwrap; !important is used narrowly to beat
   Fluent's own .ffs_default plugin CSS (full-border/rounded/grey inputs + its
   own button) — the same third-party-chrome override pattern this file already
   uses for Divi. Selectors confirmed against the live rendered markup. */

/* Group rhythm */
.eb-contact__formwrap .frm-fluent-form .ff-el-group { margin: 0 0 var(--space-5); }
.eb-contact__formwrap .frm-fluent-form .ff-el-group:last-of-type { margin-bottom: 0; }

/* Labels -> eyebrow */
.eb-contact__formwrap .ff-el-input--label { margin: 0 0 8px; padding: 0; }
.eb-contact__formwrap .ff-el-input--label label {
	font-family: var(--font-body);
	font-size: var(--type-eyebrow);
	font-weight: 600;
	letter-spacing: var(--eyebrow-tracking);
	text-transform: uppercase;
	line-height: 1.3;
	color: var(--text-secondary);
	margin: 0;
}
.eb-contact__formwrap .ff-el-is-required label:after,
.eb-contact__formwrap .asterisk-right label:after { color: var(--accent); }

/* Controls -> transparent underline */
.eb-contact__formwrap .ff-el-form-control {
	width: 100% !important;
	font-family: var(--font-body) !important;
	font-size: 17px !important;
	line-height: 1.5 !important;
	color: var(--text-primary) !important;
	background: transparent !important;
	border: 0 !important;
	border-bottom: 1px solid var(--border-strong) !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	padding: 12px 0 !important;
	height: auto !important;
	transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.eb-contact__formwrap textarea.ff-el-form-control { min-height: 120px; resize: vertical; }
.eb-contact__formwrap .ff-el-form-control:focus {
	border-bottom-color: var(--accent) !important;
	box-shadow: 0 1px 0 var(--accent) !important;
	outline: none !important;
}
.eb-contact__formwrap .ff-el-form-control::placeholder { color: var(--text-tertiary); opacity: 1; }

/* Submit -> .eb-btn--primary (sharp orange) */
.eb-contact__formwrap .ff-btn-submit {
	font-family: var(--font-body) !important;
	font-size: var(--type-button) !important;
	font-weight: 600 !important;
	letter-spacing: var(--button-tracking) !important;
	text-transform: uppercase !important;
	line-height: 1 !important;
	color: var(--accent-ink) !important;
	background: var(--accent) !important;
	border: 1px solid transparent !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	padding: 16px 34px !important;
	transition: background-color var(--dur-fast) var(--ease-standard) !important;
}
.eb-contact__formwrap .ff-btn-submit:hover { background: var(--accent-hover) !important; color: var(--accent-ink) !important; }

.eb-contact__formnote { font-family: var(--font-body); font-size: var(--type-body-sm); line-height: 1.6; color: var(--text-tertiary); border: 1px dashed var(--border-subtle); padding: 20px; margin: 0; }
.eb-contact__formnote code { font-family: monospace; font-size: 12px; color: var(--text-primary); }

/* ============================================================
   Social icons — standard brand colors (NOT the site palette).
   Filled brand tiles with a white glyph so Instagram / LinkedIn
   read as themselves rather than the theme's mono treatment.
   Targeted by href so every instance picks it up (dark footer
   block + mobile-nav panel) with no markup change. Placed at
   EOF so it outranks the accent-hover and .eb-mnav overrides by
   source order without !important.
   ============================================================ */
.eb-social__link[href*="instagram.com"] {
	background: radial-gradient(circle at 28% 100%, #FEDA75 0%, #FA7E1E 20%, #D62976 48%, #962FBF 72%, #4F5BD5 100%);
	border-color: transparent;
	color: #fff;
}
.eb-social__link[href*="linkedin.com"] {
	background: #0A66C2;
	border-color: transparent;
	color: #fff;
}
.eb-social__link[href*="instagram.com"]:hover,
.eb-social__link[href*="instagram.com"]:focus-visible {
	background: radial-gradient(circle at 28% 100%, #FEDA75 0%, #FA7E1E 20%, #D62976 48%, #962FBF 72%, #4F5BD5 100%);
	border-color: transparent;
	color: #fff;
	filter: brightness(1.08);
}
.eb-social__link[href*="linkedin.com"]:hover,
.eb-social__link[href*="linkedin.com"]:focus-visible {
	background: #0A66C2;
	border-color: transparent;
	color: #fff;
	filter: brightness(1.08);
}
