/*
* Description: Custom CSS Additions Go Here
* Template: twentyseventeen
* Version: 1.0
* Author: VDS
*/

/* vars vars vars vars vars vars vars vars vars vars vars vars vars vars  */

:root {

/* These vars do not require values as they get set automatically in options-page-stylesheet.php
 * They are mainly here so they show up as autocomplete suggestions in code editors if desired.
*/

@property --accent1 { syntax: '*'; inherits: true; }
@property --accent2 { syntax: '*'; inherits: true; }
@property --accent3 { syntax: '*'; inherits: true; }
@property --dark1   { syntax: '*'; inherits: true; }
@property --dark2   { syntax: '*'; inherits: true; }
@property --dark3   { syntax: '*'; inherits: true; }
@property --light1  { syntax: '*'; inherits: true; }
@property --light2  { syntax: '*'; inherits: true; }
@property --light3  { syntax: '*'; inherits: true; }
@property --uihover { syntax: '*'; inherits: true; }
@property --white   { syntax: '*'; inherits: true; }
@property --black   { syntax: '*'; inherits: true; }

/* font family vars */
/*--bodyfont:;*/
/*--headingfont:;*/
/* 	--DunbarMed: 'DunbarTall-Medium', sans-serif; */
/* 	--MontReg: 'Montserrat-Regular', sans-serif; */
/* 	--MontB: 'Montserrat-Bold', sans-serif; */

}

/* /vars /vars /vars /vars /vars /vars /vars /vars /vars /vars /vars  */

/* General */

/*header#header {
	display: none !important;
    color: var(--);
}*/

/* Top Anchor + Recaptcha */

a.topbutton {
    background-color: var(--accent1);
    transition: all 0.3s ease-in-out;
    border: 2px solid var(--accent2);
    text-decoration: none;
    border-radius: 7px;
    bottom: 148px;
    right: 10px;
}
a.topbutton:hover {
	background-color: var(--accent2);
	border-color: var(--accent1);
}
a.topbutton i.icon-angle-up {
	justify-content: center;
	align-items: center;
	display: flex;
}
a.topbutton i.icon-angle-up:before {
	transition: all 0.3s ease-in-out;
    color: var(--accent2);
    margin: 0 !important;
    position: relative;
    font-size: 48px;
    line-height: 1;
    top: -4.5px;
}
a.topbutton:hover i:before {
	transition: all 0.3s ease-in-out;
	color: var(--accent1);
}
div.grecaptcha-badge {
    bottom: 70px !important;
}

/* END Top Anchor + Recaptcha */

.top-widget .widget a:link {
    color: var(--accent2);
}

/* === Page: component-library === 2026-10-07 === */
/* ============================================================================
   COMPONENT LIBRARY — Hype Man Entertainment
   BUILD-PLAN §7. Authored once, inherited by every page. Nothing below is
   page-specific; per-page padding and background images live in page blocks.

   Conventions (BUILD-PLAN Appendix):
     .bakery               layout, spacing, background
     body #content + !important   every text property and link colour
     16px image radius · 1280/90% container · 88/48px section rhythm
     breakpoints 979px (stack) and 480px (small mobile)

   NO BACKSLASH ESCAPES IN THIS FILE. The /custom-css PUT handler passes the
   payload to preg_replace() as the REPLACEMENT string when replace=true, so
   a hex glyph escape is read as a backreference and collapses. Draw marks with
   borders/transforms instead of glyph escapes. Verify with:
     grep -n 'content: "' on the SERVED custom.css, not the local file.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   0. VARIABLES THE OPTIONS COMPILER DOES NOT SET
   §14: --white and --black are hardcoded in the template (#FFF / #000) and
   --uihover does not exist as a field at all. Correct them here.
   --------------------------------------------------------------------------- */

:root {
	--black: #101012;
	--uihover: #C9981F;
	--hm-radius: 16px;
	--hm-gap: 24px;
	--hm-section-y: 60px;
	--hm-section-y-mobile: 32px;
	--hm-shadow: 0 2px 10px rgba(16, 16, 18, 0.06);
	--hm-shadow-lift: 0 10px 28px rgba(16, 16, 18, 0.14);
	--hm-border: 1px solid var(--light3);
	--hm-ease: 200ms cubic-bezier(0.2, 0.6, 0.3, 1);
	/* accent3 (#C9981F) is 2.63:1 on white — §3.1 says decorative only.
	   Anything that is TEXT, a glyph carrying meaning, or a UI indicator
	   uses this instead: 5.37:1 on white, 4.0:1 on light2. On dark1/dark2
	   accent3 is fine (7.2:1) and the rules below switch back to it. */
	--hm-gold-text: #8A6410;
}


/* ---------------------------------------------------------------------------
   1. CONTRAST CORRECTIONS — THESE ARE BUGS, NOT PREFERENCES
   color.css paints white text on every accent1/2/3 container, and the compiled
   options CSS paints buttons white-on-yellow and black-on-black. Three real
   failures, all site-wide:
     .accent1 surface  #FFF on #F7C659  = 1.9:1   unreadable
     a.btn-bt.default  #FFF on #F7C659  = 1.9:1   unreadable
     a.btn-bt.alternate #1C1C22 on #101012 = 1.1:1 invisible
   After these rules: #101012 on #F7C659 = 12.6:1 (AAA), #FFF on #101012 = 19:1.
   --------------------------------------------------------------------------- */

body #content .accent1,
body #content .accent1 h1, body #content .accent1 h2, body #content .accent1 h3,
body #content .accent1 h4, body #content .accent1 h5, body #content .accent1 h6,
body #content .accent1 p,  body #content .accent1 li,
body #content .accent1 a:not(.btn-bt),
body #content .accent1 strong, body #content .accent1 em {
	color: var(--black) !important;
}

body #content .accent1 a:not(.btn-bt) {
	text-decoration: underline;
	text-underline-offset: 3px;
}
body #content .accent1 a:not(.btn-bt):hover { color: var(--dark2) !important; }

/* Default (yellow) button — black label, deep-gold hover. */
body #content a.btn-bt.default,
body #content a.btn-bt.accent1,
.header-button a.btn-bt,
body .gform_wrapper .gform_footer input[type="submit"],
body .gform_wrapper .gform_footer button.gform_button,
body .gform_wrapper .gform-footer button.gform_button {
	background: var(--accent1) !important;
	color: var(--black) !important;
	font-family: var(--headingfont);
	letter-spacing: 0.5px;
}
body #content a.btn-bt.default:hover,
body #content a.btn-bt.default:focus-visible,
body #content a.btn-bt.accent1:hover,
.header-button a.btn-bt:hover,
body .gform_wrapper .gform_footer input[type="submit"]:hover,
body .gform_wrapper .gform_footer input[type="submit"]:focus-visible,
body .gform_wrapper .gform_footer button.gform_button:hover,
body .gform_wrapper .gform_footer button.gform_button:focus-visible,
body .gform_wrapper .gform-footer button.gform_button:hover,
body .gform_wrapper .gform-footer button.gform_button:focus-visible {
	background: var(--uihover) !important;
	color: var(--black) !important;
}

/* Alternate (ink) button — white label, yellow hover. */
body #content a.btn-bt.alternate,
body #content a.btn-bt.accent2,
footer a.btn-bt.alternate {
	background: var(--accent2) !important;
	color: var(--white) !important;
	font-family: var(--headingfont);
	letter-spacing: 0.5px;
}
body #content a.btn-bt.alternate:hover,
body #content a.btn-bt.alternate:focus-visible,
body #content a.btn-bt.accent2:hover,
footer a.btn-bt.alternate:hover {
	background: var(--accent1) !important;
	color: var(--black) !important;
}

/* SESSION 13 — an alternate button sitting ON the yellow mid-page band.
   The shared hover above flips the background to accent1, which IS that
   band's own ground, so the control dissolved into the band on hover. Hold
   the ink ground and move the LABEL to accent1 instead: 12.6:1, same pair of
   colours as the rest-state button, read in the other direction. */
body #content .accent1 a.btn-bt.alternate:hover,
body #content .accent1 a.btn-bt.alternate:focus-visible {
	background: var(--black) !important;
	color: var(--accent1) !important;
}

/* An alternate button sitting ON a dark band needs a visible edge. */
body #content .dark1 a.btn-bt.alternate,
body #content .dark2 a.btn-bt.alternate,
body #content .bottom-cta a.btn-bt.alternate {
	box-shadow: inset 0 0 0 2px var(--white);
}
body #content .dark1 a.btn-bt.alternate:hover,
body #content .dark2 a.btn-bt.alternate:hover,
body #content .bottom-cta a.btn-bt.alternate:hover { box-shadow: none; }

/* Deep gold is decorative only — never let it become body text (2.6:1 on white). */
body #content hr.line { border: 0; height: 3px; width: 64px; margin: 0 0 24px; }
body #content hr.line.accent3 { background: var(--accent3); }
body #content .text-center hr.line,
body #content hr.line.centered { margin-left: auto; margin-right: auto; }

/* Keyboard focus — the theme ships none. */
body #content a:focus-visible,
body .gform_wrapper input:focus-visible,
body .gform_wrapper select:focus-visible,
body .gform_wrapper textarea:focus-visible {
	outline: 3px solid var(--hm-gold-text);
	outline-offset: 2px;
}


/* ---------------------------------------------------------------------------
   2. LAYOUT & RHYTHM — §3.3
   --------------------------------------------------------------------------- */

/* custom.css is enqueued BEFORE style.css on this theme, so a tie on
   specificity loses. style.css ships `.bakery .vc_row:not(.vc_inner)` (0,3,0)
   at 480px and under, and `.bakery section.vc_section` (0,2,1) everywhere — both would
   beat a plain `.bakery .hm-section` (0,2,0). Carrying the element selector
   takes these to (0,3,1) and wins without !important. */
.bakery div.vc_row.hm-section,
.bakery section.vc_section.hm-section { padding: var(--hm-section-y) 0; }
.bakery div.vc_row.hm-section.hm-tight,
.bakery section.vc_section.hm-section.hm-tight { padding: 56px 0; }
.bakery div.vc_row.hm-section.hm-flush,
.bakery section.vc_section.hm-section.hm-flush { padding: 0; }

.bakery .hm-narrow { max-width: 820px; margin-left: auto; margin-right: auto; }
.bakery .hm-center { text-align: center; }

/* Vertical spacing between two rows that share one vc_section. */
.bakery .hm-mt-lg { margin-top: 40px; }
.bakery .hm-mt-sm { margin-top: 24px; }

/* Card grids. §3.3.
   The theme renders `.vc_row > .container > .wpb_column` — `.container` sits
   BETWEEN the row and the columns, so a child combinator off the row matches
   nothing. The gutter goes on the columns; the container widens by one gutter
   so the outer card edges stay flush with every other section. A negative
   margin is not available here — `.container` is centred with `margin: 0 auto`. */
.bakery div.vc_row.hm-cards > .container,
.bakery div.vc_row.hm-grid  > .container {
	max-width: calc(1280px + var(--hm-gap));
	width: calc(90% + var(--hm-gap));
	align-items: stretch;
	flex-wrap: wrap;
}
.bakery .hm-cards .vc_column_container,
.bakery .hm-grid  .vc_column_container { padding: 0 12px 24px !important; }

body #content .hm-eyebrow {
	color: var(--hm-gold-text) !important;
	text-transform: uppercase;
	letter-spacing: 2px;
	margin-bottom: 8px !important;
}
body #content .dark1 .hm-eyebrow,
body #content .dark2 .hm-eyebrow,
body #content .bottom-cta .hm-eyebrow { color: var(--accent1) !important; }
body #content .dark1 .hm-quote__stars,
body #content .dark2 .hm-quote__stars { color: var(--accent3) !important; }

/* Site-standard image radius. */
.bakery img,
.bakery .hm-media img { border-radius: var(--hm-radius); }
.bakery .hm-media { border-radius: var(--hm-radius); overflow: hidden; }

@media (max-width: 979px) {
	.bakery .hm-mt-lg { margin-top: 32px; }
	.bakery div.vc_row.hm-section,
	.bakery section.vc_section.hm-section { padding: var(--hm-section-y-mobile) 0; }
	.bakery div.vc_row.hm-section.hm-tight,
	.bakery section.vc_section.hm-section.hm-tight { padding: 32px 0; }
}


/* ---------------------------------------------------------------------------
   2b. RESPONSIVE TYPE SCALE
   The options compiler emits ONE size per heading level — §3.2's values are
   desktop-only and there is no mobile step anywhere in the theme. h1 at 56px on
   a 390px viewport is three lines of banner. Scale the display sizes down with
   clamp(); body copy stays at 17px because it is already tuned for mobile.
   --------------------------------------------------------------------------- */

body #content h1, body .default-header h1, body #content .hm-hero h1 {
	font-size: clamp(32px, 7.2vw, 56px) !important;
	line-height: 1.08 !important;
	letter-spacing: -0.5px !important;
}
body #content h2 {
	font-size: clamp(26px, 4.6vw, 38px) !important;
	line-height: 1.15 !important;
	letter-spacing: -0.25px !important;
}
body #content h3 {
	font-size: clamp(21px, 3.0vw, 26px) !important;
	line-height: 1.25 !important;
}
body #content h4 { font-size: clamp(18px, 2.2vw, 20px) !important; line-height: 1.3 !important; }

/* Long single words (venue names, URLs) must not force a horizontal scroll. */
body #content h1, body #content h2, body #content h3,
body .default-header h1 { overflow-wrap: break-word; }


/* ---------------------------------------------------------------------------
   3. §7.1 TOP BANNER — all 16 subpages + utility templates
   ACF header_background + top_banner_title. Scrim so white H1 holds over any
   photo, including a light one.
   --------------------------------------------------------------------------- */

.default-header {
	background-position: center center;
	background-color: var(--dark1);
	background-size: cover;
	position: relative;
}

.default-header::after {
	background: linear-gradient(180deg,
		rgba(16, 16, 18, 0.58) 0%,
		rgba(16, 16, 18, 0.70) 55%,
		rgba(16, 16, 18, 0.84) 100%);
	position: absolute;
	content: "";
	inset: 0;
	z-index: 1;
}
.default-header > * { position: relative; z-index: 2; }

body #content .default-header h1,
body .default-header h1 {
	color: var(--white) !important;
	text-shadow: 0 2px 18px rgba(16, 16, 18, 0.45);
	max-width: 18ch;
	/* .default-header .container is display:flex, so the h1 is a flex item with
	   min-width:auto and will not shrink below its longest word — at 390px it
	   overflowed the container by 10px a side. */
	min-width: 0;
}
.default-header.hm-center h1 { margin-left: auto; margin-right: auto; }

/* style.css forces `background-position: top left !important`, which crops faces
   off the top of a portrait-ish banner photo. Centre it. */
.default-header { background-position: center center !important; }

/* Utility templates have no ACF banner image — hardcode a fallback so the
   scrim never sits on an empty box. §7.1 */
body.error404 .default-header,
body.search .default-header,
body.single-post .default-header,
body.page-template-default .default-header.hm-fallback {
	/* !important is load-order, not laziness: search.css hardcodes a VDS grey
	   placeholder (/uploads/2021/05/d9d9d9.png) at the same specificity and is
	   enqueued AFTER custom.css, so it wins every tie. */
	background-image: url("/wp-content/uploads/2026/10/dance-floor-fog-magenta-lighting.webp") !important;
	background-position: center 60% !important;
	background-size: cover !important;
}


/* ---------------------------------------------------------------------------
   4. §7.2 HOME HERO — video desktop, poster image on mobile
   The video element is the only justified raw-html block on Home (§9.2).
   --------------------------------------------------------------------------- */

.bakery .hm-hero {
	background-image: url("/wp-content/uploads/2026/10/packed-dance-floor-crowd-hands-up.webp");
	background-position: center center;
	background-color: var(--dark1);
	background-size: cover;
	position: relative;
	overflow: hidden;
	/* The video gets its own compositing layer. Without a stacking context on
	   .hm-hero that layer paints over the ::after scrim even though the scrim
	   has the higher z-index — A/B measured: mean channel value identical with
	   the scrim present and with it display:none, i.e. it was not painting.
	   `isolation: isolate` makes .hm-hero the stacking context so the z-indexes
	   below actually resolve against each other. */
	isolation: isolate;
}

.bakery .hm-hero__video {
	object-fit: cover;
	position: absolute;
	display: none;
	height: 100%;
	width: 100%;
	inset: 0;
	z-index: 0;
}

.bakery div.vc_row.hm-hero::after,
.bakery .hm-hero::after {
	display: block;
	/* Mobile/tablet ramp. Session 6 reset style.css:66's
	   `background-blend-mode: overlay`, which had been multiplying this photo
	   against --dark1 and rendering it near-black; with the real image now
	   painting, the ramp had to come UP a step or the h1 clipped AA over the
	   bright clock face. Measured at 390px after: h1 min 4.66:1 (large text
	   needs 3.0), body min 4.90:1 (needs 4.5), 0.000% of either below. */
	background: linear-gradient(180deg,
		rgba(16, 16, 18, 0.52) 0%,
		rgba(16, 16, 18, 0.60) 45%,
		rgba(16, 16, 18, 0.82) 100%);
	position: absolute;
	content: "";
	inset: 0;
	z-index: 1;
}

/* The video element lives inside the column (WPBakery gives us nowhere else to put
   it), so every wrapper between .hm-hero and the video has to stay static or
   `inset: 0` resolves against the wrong box. The copy blocks are then lifted
   above the scrim individually. */
.bakery .hm-hero > .container,
.bakery .hm-hero .wpb_column,
.bakery .hm-hero .vc_column-inner,
.bakery .hm-hero .vc_column-inner > .wpb_wrapper,
.bakery .hm-hero .wpb_raw_code,
.bakery .hm-hero .wpb_raw_code > .wpb_wrapper { position: static; }

.bakery .hm-hero > .container { padding: 72px 0; }
.bakery .hm-hero .hm-hero__inner { position: relative; z-index: 2; }

body #content .hm-hero h1,
body #content .hm-hero h2,
body #content .hm-hero p { color: var(--white) !important; }
body #content .hm-hero h1 {
	text-shadow: 0 2px 20px rgba(16, 16, 18, 0.5);
	margin-bottom: 18px !important;
	max-width: 20ch;
}
body #content .hm-hero p  { max-width: 60ch; }

/* Video only above the tablet breakpoint — §9.2, protects CWV on the 70% of
   traffic that arrives on a phone. */
@media (min-width: 980px) {
	.bakery .hm-hero { min-height: 640px; display: flex; align-items: center; }
	.bakery .hm-hero__video { display: block; }
	.bakery .hm-hero > .container { padding: 96px 0; }

	/* The flat scrim is not enough once the video is playing — the clip's LED
	   floor goes to near-white and measured 1.0:1 against white copy. A
	   directional wash holds the copy side dark and leaves the right side of
	   the frame bright. Re-measured: worst case 7.9:1 over the copy box. */
	.bakery div.vc_row.hm-hero::after,
	.bakery .hm-hero::after {
		/* Session 6: the copy side measured 7.9:1 worst case, well past the
		   4.5 it needs, while the right half of the frame — the half that is
		   supposed to sell the room — was being washed to near-black by a
		   second gradient it never needed. Lifted on the RIGHT only, so the
		   copy box is untouched and re-measures identically. */
		background:
			linear-gradient(90deg,
				rgba(16, 16, 18, 0.90) 0%,
				rgba(16, 16, 18, 0.76) 40%,
				rgba(16, 16, 18, 0.18) 72%,
				rgba(16, 16, 18, 0.08) 100%),
			linear-gradient(180deg,
				rgba(16, 16, 18, 0.22) 0%,
				rgba(16, 16, 18, 0.26) 55%,
				rgba(16, 16, 18, 0.50) 100%);
	}
}

@media (prefers-reduced-motion: reduce) {
	.bakery .hm-hero__video { display: none !important; }
}


/* ---------------------------------------------------------------------------
   5. §7.3 TRUST BAR — 4 stats on the yellow band
   --------------------------------------------------------------------------- */

.bakery .hm-trust { padding: 40px 0; }

.bakery .hm-trust .hm-trust__grid {
	grid-template-columns: repeat(4, minmax(0, 1fr));
	align-items: start;
	display: grid;
	gap: 24px;
}

body #content .hm-trust__stat { text-align: center; }
body #content .hm-trust__num {
	font-family: var(--headingfont);
	color: var(--black) !important;
	letter-spacing: -0.5px;
	line-height: 1.05;
	font-size: 42px;
	display: block;
}
body #content .hm-trust__label {
	color: var(--black) !important;
	text-transform: uppercase;
	letter-spacing: 1.5px;
	margin: 6px 0 0 !important;
	font-size: 13px;
	opacity: 0.78;
}

@media (max-width: 979px) {
	.bakery .hm-trust .hm-trust__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 16px; }
	body #content .hm-trust__num { font-size: 34px; }
}
@media (max-width: 480px) {
	body #content .hm-trust__num { font-size: 30px; }
	body #content .hm-trust__label { font-size: 12px; letter-spacing: 1px; }
}


/* ---------------------------------------------------------------------------
   6. §7.4 SERVICE CARD — 4/5-up, equal height
   Five-layer cascade: column > wpb_wrapper > text element > wrapper > card.
   --------------------------------------------------------------------------- */

/* The column is stretched by the flex container — do NOT give it
   `height: 100%`. A percentage height against an auto-height flex container is
   indefinite, and declaring it overrides `align-self: stretch`, which is what
   was going to supply the height. Measured before this fix: 800/597/565/597px
   for four cards that should have matched. Children inherit from the stretched
   column, which IS definite after layout. */
.bakery .hm-cards .vc_column_container > .vc_column-inner,
.bakery .hm-cards .vc_column_container > .vc_column-inner > .wpb_wrapper,
.bakery .hm-cards .wpb_text_column,
.bakery .hm-cards .wpb_text_column > .wpb_wrapper { height: 100%; }

.bakery .hm-card {
	border-radius: var(--hm-radius);
	background: var(--light1);
	border: var(--hm-border);
	flex-direction: column;
	box-shadow: var(--hm-shadow);
	overflow: hidden;
	display: flex;
	height: 100%;
}

.bakery .hm-card__media {
	background: var(--light3);
	aspect-ratio: 4 / 3;
	position: relative;
	display: block;
}
/* §12-F: Bar & Mixology has no photography in the client library. A brand
   panel holds the grid rhythm until the client supplies a photo. */
.bakery .hm-card__media.is-placeholder {
	background: linear-gradient(135deg, var(--accent1) 0%, var(--accent3) 100%);
}

.bakery .hm-card__media img {
	/* Absolute, not static: a box with `aspect-ratio` still takes a
	   content-based automatic minimum height, so an in-flow portrait image
	   stretches the 4/3 frame instead of being cropped by it (measured at
	   300x400 on a 300x225 box). Out of flow, the ratio holds. */
	position: absolute;
	object-fit: cover;
	border-radius: 0;
	display: block;
	height: 100%;
	width: 100%;
	inset: 0;
}

.bakery .hm-card__body {
	flex-direction: column;
	padding: 24px 24px 28px;
	display: flex;
	flex: 1 1 auto;
}

body #content .hm-card__body h3 { margin: 0 0 10px !important; }
body #content .hm-card__body p  { margin: 0 0 16px !important; }
body #content .hm-card__price {
	font-family: var(--headingfont);
	color: var(--black) !important;
	margin: 0 0 16px !important;
	font-size: 18px;
}
body #content .hm-card__price .hm-card__from {
	text-transform: uppercase;
	font-family: inherit;
	letter-spacing: 1.5px;
	margin-right: 6px;
	font-size: 12px;
	opacity: 0.6;
}

/* Link sits at the bottom no matter how uneven the copy is. */
.bakery .hm-card__body .hm-card__link { margin-top: auto; }
body #content a.hm-card__link {
	font-family: var(--headingfont);
	color: var(--black) !important;
	text-decoration: none;
	letter-spacing: 0.5px;
	align-items: center;
	display: inline-flex;
	font-size: 15px;
	gap: 8px;
}
body #content a.hm-card__link::after {
	border-right: 2px solid currentColor;
	border-top: 2px solid currentColor;
	transition: transform var(--hm-ease);
	transform: rotate(45deg);
	display: inline-block;
	content: "";
	height: 7px;
	width: 7px;
}
body #content a.hm-card__link:hover { color: var(--uihover) !important; }
body #content a.hm-card__link:hover::after { transform: rotate(45deg) translate(3px, -3px); }

/* Whole-card link (one anchor wrapping the card — the justified raw-html case). */
.bakery a.hm-card { text-decoration: none; color: inherit; }

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-card { transition: transform var(--hm-ease), box-shadow var(--hm-ease); }
	.bakery .hm-card:hover,
	.bakery a.hm-card:hover { transform: translateY(-4px); box-shadow: var(--hm-shadow-lift); }
}


/* ---------------------------------------------------------------------------
   7. §7.5 PRICING / PACKAGE CARD — the hipstr pattern
   Replaces every [TABLE] of rates in the copy doc. Tables do not work at 390px.
   --------------------------------------------------------------------------- */

.bakery .hm-price {
	border-radius: var(--hm-radius);
	background: var(--light1);
	border: var(--hm-border);
	box-shadow: var(--hm-shadow);
	flex-direction: column;
	padding: 32px 28px;
	position: relative;
	display: flex;
	height: 100%;
}

body #content .hm-price h3 { margin: 0 0 4px !important; }
body #content .hm-price__sub {
	margin: 0 0 20px !important;
	color: var(--dark3) !important;
	font-size: 15px !important;
}

body #content .hm-price__amount {
	font-family: var(--headingfont) !important;
	color: var(--black) !important;
	margin: 0 0 4px !important;
	letter-spacing: -1px;
	line-height: 1;
	font-size: 44px !important;
}
body #content .hm-price__unit {
	color: var(--dark3) !important;
	text-transform: uppercase;
	margin: 0 0 22px !important;
	letter-spacing: 1.5px;
	font-size: 12px !important;
}

body #content ul.hm-price__list { margin: 0 0 26px !important; padding: 0 !important; list-style: none !important; }
body #content ul.hm-price__list li {
	border-bottom: 1px solid var(--light3);
	padding: 10px 0 10px 28px !important;
	position: relative;
	list-style: none !important;
	font-size: 15px !important;
	margin: 0 !important;
}
body #content ul.hm-price__list li:last-child { border-bottom: 0; }
body #content ul.hm-price__list li::before {
	border-right: 2px solid var(--hm-gold-text);
	border-bottom: 2px solid var(--hm-gold-text);
	transform: rotate(45deg);
	position: absolute;
	content: "";
	height: 10px;
	width: 6px;
	left: 6px;
	top: 14px;
}

.bakery .hm-price .hm-price__cta { margin-top: auto; }

/* The featured card — lifted, yellow ribbon. One per row. */
.bakery .hm-price.is-featured {
	box-shadow: 0 16px 40px rgba(16, 16, 18, 0.16);
	border: 3px solid var(--accent1);
	padding-top: 44px;
}
.bakery .hm-price.is-featured .hm-price__ribbon {
	font-family: var(--headingfont);
	border-radius: var(--hm-radius) var(--hm-radius) 0 0;
	padding: 11px 16px 5px 16px;
	background: var(--accent1);
	text-transform: uppercase;
	color: var(--black);
	letter-spacing: 2px;
	text-align: center;
	position: absolute;
	font-size: 12px;
	right: -3px;
	left: -3px;
	top: -3px;
}

/* SESSION 13 — THE DESKTOP LIFT IS GONE. `transform: translateY(-12px)` on
   the featured card did not change its height — both cards measured an equal
   572px — but it moved the whole box up 12px, so neither the tops nor the
   bottoms of the two cards lined up and the featured one read as the shorter
   of the pair. Cody asked for equal height; equal height was already true and
   the offset was what he was seeing. The ribbon, the 3px accent1 border and
   the heavier shadow carry the featured treatment on their own.
   Do not reinstate the lift without also giving the sibling card the same
   translate, or the pair goes right back to looking mismatched. */
@media (max-width: 979px) {
	body #content .hm-price__amount { font-size: 38px !important; }
	.bakery .hm-price { padding: 28px 22px; }
}


/* ---------------------------------------------------------------------------
   8. §7.6 INCLUSIONS LIST — 2-col icon list from the copy doc feature tables
   --------------------------------------------------------------------------- */

body #content ul.hm-inclusions {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
	display: grid;
	gap: 18px 32px;
}
body #content ul.hm-inclusions li {
	padding: 0 0 0 32px !important;
	list-style: none !important;
	position: relative;
	margin: 0 !important;
}
body #content ul.hm-inclusions li::before {
	background: var(--accent1);
	border-radius: 50%;
	position: absolute;
	content: "";
	height: 20px;
	width: 20px;
	left: 0;
	top: 4px;
}
body #content ul.hm-inclusions li::after {
	border-right: 2px solid var(--black);
	border-bottom: 2px solid var(--black);
	transform: rotate(45deg);
	position: absolute;
	content: "";
	height: 8px;
	width: 5px;
	left: 7px;
	top: 8px;
}
body #content ul.hm-inclusions li strong { display: block; }

@media (max-width: 767px) {
	body #content ul.hm-inclusions { grid-template-columns: minmax(0, 1fr); gap: 14px; }
}


/* ---------------------------------------------------------------------------
   9. §7.7 NUMBERED PROCESS — DJ 3-step, Officiant 10-question, Thank You
   --------------------------------------------------------------------------- */

.bakery .hm-steps { counter-reset: hmstep; }

.bakery .hm-step { padding: 0 0 0 76px; position: relative; margin: 0 0 32px; }
.bakery .hm-step:last-child { margin-bottom: 0; }

/* SESSION 14 — the numeral was `var(--accent1)`, which is 1.59:1 on light1
   and 1.47:1 on light2. Section 0's own rule settles it: accent1/accent3 are
   decorative, and "anything that is TEXT, a glyph carrying meaning, or a UI
   indicator" takes --hm-gold-text, which measures 5.37:1 and 4.97:1 on those
   two grounds. A step numeral is the clearest possible case of a glyph
   carrying meaning — and since 32.1 resets `list-style`, this counter is now
   the ONLY place the step number exists. Same base-plus-dark-override shape
   `.hm-eyebrow` has used since section 2.

   THE CONTRAST GATE CANNOT SEE THIS. contrast-s7.mjs scores text by walking
   DOM text nodes with a Range; generated content has no text node to select,
   so a ::before is invisible to it no matter which selectors are passed in.
   This would have shipped on all three §7.7 pages — DJ, Officiant and Thank
   You — with nothing in the gate set going red. Tracked as an open item. */
.bakery .hm-step::before {
	font-family: var(--headingfont);
	counter-increment: hmstep;
	content: counter(hmstep);
	color: var(--hm-gold-text);
	letter-spacing: -2px;
	position: absolute;
	line-height: 0.9;
	font-size: 56px;
	left: 0;
	top: -6px;
}
body #content .dark1 .hm-step::before,
body #content .dark2 .hm-step::before { color: var(--accent1); }
body #content .accent1 .hm-step::before { color: var(--black); }

body #content .hm-step h3,
body #content .hm-step h4 { margin: 0 0 8px !important; }
body #content .hm-step p  { margin: 0 !important; }

/* Compact variant for the 10-question list. */
.bakery .hm-steps.is-compact .hm-step { padding-left: 56px; margin-bottom: 20px; }
.bakery .hm-steps.is-compact .hm-step::before { font-size: 34px; top: -2px; }

@media (max-width: 480px) {
	.bakery .hm-step { padding-left: 56px; }
	.bakery .hm-step::before { font-size: 40px; }
}


/* ---------------------------------------------------------------------------
   10. §7.8 TIMELINE — Weddings. 3-col desktop, stacked cards on mobile.
   --------------------------------------------------------------------------- */

.bakery .hm-timeline { border-top: var(--hm-border); }

.bakery .hm-timeline__row {
	grid-template-columns: 160px 220px minmax(0, 1fr);
	border-bottom: var(--hm-border);
	align-items: start;
	padding: 20px 0;
	display: grid;
	gap: 24px;
}

body #content .hm-timeline__time {
	font-family: var(--headingfont);
	color: var(--black) !important;
	margin: 0 !important;
	font-size: 16px;
}
body #content .hm-timeline__milestone { margin: 0 !important; font-weight: 700; }
body #content .hm-timeline__detail { margin: 0 !important; color: var(--dark3) !important; }

@media (max-width: 979px) {
	.bakery .hm-timeline { border-top: 0; }
	.bakery .hm-timeline__row {
		border-radius: var(--hm-radius);
		grid-template-columns: minmax(0, 1fr);
		border: var(--hm-border);
		background: var(--light1);
		margin-bottom: 12px;
		padding: 18px 20px;
		gap: 6px;
	}
	body #content .hm-timeline__time { color: var(--hm-gold-text) !important; text-transform: uppercase; letter-spacing: 1.5px; font-size: 13px; }
}


/* ---------------------------------------------------------------------------
   11. §7.9 FAQ ACCORDION — [vc_tta_accordion], row needs el_class="accordion"
   --------------------------------------------------------------------------- */

.bakery .accordion .vc_tta-panel {
	border-radius: var(--hm-radius) !important;
	border: var(--hm-border) !important;
	background: var(--light1) !important;
	margin-bottom: 12px !important;
	transition: border-color 250ms ease;
	overflow: hidden;
}
.bakery .accordion .vc_tta-panel-heading { border: 0 !important; background: transparent !important; }

/* The theme renders this anchor as a CENTRED FLEX CONTAINER, so the
   question sits in the middle of the panel and the 56px right padding that
   was reserved for the chevron does nothing. Both have to be undone
   explicitly — this is 29.3 again, one component along. Measured session 12:
   textAlign "center", display "flex", the title span starting at x=585 in a
   panel running 81 to 1359. */
body #content .accordion .vc_tta-panel-title > a {
	font-family: var(--headingfont) !important;
	padding: 20px 56px 20px 24px !important;
	justify-content: flex-start !important;
	text-decoration: none !important;
	color: var(--black) !important;
	text-align: left !important;
	font-size: 18px !important;
	position: relative;
}
/* The title TEXT is a span inside the anchor and section 2's
   `body #content span` rule sizes it independently, so the anchor's 18px
   never reached it (measured 17px). Both are set.

   The active state was WHITE ON WHITE. The theme colours an open panel's
   title #FFF against our light1 panel ground — 1:1, the question simply
   disappears when you open it, which is what the first FAQ screenshot
   showed. The contrast gate did not catch it and structurally cannot:
   it captures the page as loaded, and every panel starts closed
   (active_section="" in hm_build.faq). A state the gate never enters is a
   state nothing measures — so look at the open one by hand.

   Hover is --hm-gold-text, not --uihover. --uihover is #C9981F at 2.63:1 on
   white, which §3.1 restricts to decoration; this is a text colour on an
   interactive control. */
body #content .accordion .vc_tta-panel-title > a .vc_tta-title-text,
body #content .accordion .vc_tta-panel.vc_active .vc_tta-panel-title > a,
body #content .accordion .vc_tta-panel.vc_active .vc_tta-panel-title > a .vc_tta-title-text {
	font-family: var(--headingfont) !important;
	color: var(--black) !important;
	font-size: 18px !important;
}
body #content .accordion .vc_tta-panel-title > a:hover,
body #content .accordion .vc_tta-panel-title > a:hover .vc_tta-title-text,
body #content .accordion .vc_tta-panel-title > a:focus-visible .vc_tta-title-text {
	color: var(--hm-gold-text) !important;
}

/* THE ICON BOX MUST BE SIZED HERE. WPBakery draws its chevron as a square
   whose ::before carries a right and bottom border and a 45deg rotation,
   and it sizes that square in js_composer's own stylesheet — which this
   build does not load for the accordion skin in use. Left unsized, the
   element is position:absolute with no width, so it stretches to the full
   panel and the "chevron" renders as a 1228px diagonal hairline drawn
   corner to corner across the question. Measured session 12: icon box
   1232x0, ::before 1228.28x2 at rotate(45deg).

   Packages is the first page in the build to carry a FAQ accordion, which
   is the only reason this surfaced now — the same way Contact surfaced the
   six section-29 defects by being the first page with a banner and a form.

   -7px margin-top, not -5px: the box is rotated 45 degrees about its own
   centre, so its VISUAL centre sits half a border-width below its layout
   centre. */
/* `left: auto` is load-bearing. WPBakery also sets `left` on this element;
   while the width was auto that was harmless, but a definite 10px width
   makes left+right+width over-constrained, and in LTR the spec says `right`
   is the one that gets dropped. The chevron then renders hard against the
   left edge of the question instead of at the far right — measured at x=103
   in a panel starting at x=81, with the computed `right` still reading the
   26px we asked for. A computed value is not proof a property was used. */
.bakery .accordion .vc_tta-controls-icon {
	margin-top: -7px !important;
	height: 10px !important;
	width: 10px !important;
	right: 26px !important;
	left: auto !important;
	top: 50% !important;
}
.bakery .accordion .vc_tta-controls-icon::before,
.bakery .accordion .vc_tta-controls-icon::after { border-color: var(--hm-gold-text) !important; }

/* SESSION 13 — THE PANEL BODY MUST CARRY NO PADDING OF ITS OWN.
   WPBakery opens a panel with jQuery slideDown, which animates the body's
   height AND its vertical padding up from zero by writing both inline, frame
   by frame. Our padding was declared important, and an important author
   declaration beats a normal inline one, so jQuery's padding animation was
   overruled while its height animation was not: the bottom padding appeared
   in full on the first frame and the height then crept up underneath it.
   Measured session 13 — the panel went 70 to 94.4px in one frame, then slid
   to 124.2px over 200ms. Forty-four percent of the travel was a snap, and on
   close the same band vanished at the end instead of sliding away. That is
   the glitch Cody saw, and no amount of easing would have smoothed it,
   because the snapping part was never being animated at all.

   Zero here; the visual padding moves to the body's only child, which jQuery
   never touches. The height animation then runs the full distance and the
   theme's own `transition: padding .2s` on the body becomes a no-op.
   `> *` rather than a class: WPBakery wraps section content in its own
   element and the wrapper it picks depends on what the section contains. */
.bakery .accordion .vc_tta-panel-body {
	background: transparent !important;
	padding: 0 !important;
}
.bakery .accordion .vc_tta-panel-body > * { padding: 0 24px 24px; }
body #content .accordion .vc_tta-panel-body p:last-child { margin-bottom: 0 !important; }

.bakery .accordion .vc_tta-panel.vc_active { border-color: var(--accent1) !important; }

@media (max-width: 480px) {
	body #content .accordion .vc_tta-panel-title > a { padding: 16px 48px 16px 18px !important; font-size: 16px; }
	.bakery .accordion .vc_tta-panel-body > * { padding: 0 18px 18px; }
}


/* ---------------------------------------------------------------------------
   12. §7.10 TESTIMONIALS — 3 client-approved pull quotes + the Google link
   --------------------------------------------------------------------------- */

.bakery .hm-quote {
	border-radius: var(--hm-radius);
	border-top: 4px solid var(--accent1);
	background: var(--light1);
	box-shadow: var(--hm-shadow);
	flex-direction: column;
	padding: 28px 26px;
	display: flex;
	height: 100%;
}

body #content .hm-quote__stars {
	letter-spacing: 3px;
	margin: 0 0 14px !important;
	color: var(--hm-gold-text) !important;
	font-size: 16px !important;
}
body #content .hm-quote blockquote,
body #content .hm-quote__text {
	border: 0 !important;
	padding: 0 !important;
	margin: 0 0 18px !important;
	font-style: normal;
}
body #content .hm-quote__text::before { content: open-quote; }
body #content .hm-quote__text::after  { content: close-quote; }

body #content .hm-quote__cite {
	font-family: var(--headingfont) !important;
	color: var(--black) !important;
	margin: auto 0 0 !important;
	font-style: normal;
	font-size: 15px !important;
}

body #content a.hm-google-link {
	font-family: var(--headingfont);
	text-underline-offset: 4px;
	color: var(--black) !important;
	align-items: center;
	display: inline-flex;
	gap: 8px;
}
body #content a.hm-google-link:hover { color: var(--uihover) !important; }
body #content .dark1 a.hm-google-link,
body #content .dark2 a.hm-google-link { color: var(--white) !important; }
body #content .dark1 a.hm-google-link:hover,
body #content .dark2 a.hm-google-link:hover { color: var(--accent1) !important; }


/* ---------------------------------------------------------------------------
   13. §7.11 GALLERY GRID — Media + Photo Booth, lazy-loaded
   --------------------------------------------------------------------------- */

.bakery .hm-gallery {
	grid-template-columns: repeat(4, minmax(0, 1fr));
	display: grid;
	gap: 16px;
}
.bakery .hm-gallery__item {
	border-radius: var(--hm-radius);
	background: var(--light3);
	aspect-ratio: 1 / 1;
	position: relative;
	overflow: hidden;
	display: block;
}
.bakery .hm-gallery__item img {
	/* Out of flow for the same reason as .hm-card__media img above. */
	position: absolute;
	object-fit: cover;
	border-radius: 0;
	display: block;
	height: 100%;
	width: 100%;
	inset: 0;
}
/* Portrait booth prints read better un-cropped. */
.bakery .hm-gallery__item.is-print { aspect-ratio: 2 / 3; }
.bakery .hm-gallery__item.is-wide  { grid-column: span 2; aspect-ratio: 2 / 1; }

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-gallery__item img { transition: transform 250ms cubic-bezier(0.2, 0.6, 0.3, 1); }
	.bakery .hm-gallery__item:hover img { transform: scale(1.04); }
}

/* Filter buttons. */
.bakery .hm-filters { flex-wrap: wrap; display: flex; gap: 10px; margin: 0 0 28px; }
body #content button.hm-filter,
body #content a.hm-filter {
	font-family: var(--headingfont);
	border: 1px solid var(--light3);
	color: var(--black) !important;
	background: var(--light1);
	text-decoration: none;
	border-radius: 50px;
	padding: 9px 18px;
	cursor: pointer;
	font-size: 14px;
}
body #content button.hm-filter.is-active,
body #content a.hm-filter.is-active {
	border-color: var(--accent1);
	background: var(--accent1);
	color: var(--black) !important;
}
body #content button.hm-filter:hover,
body #content a.hm-filter:hover { border-color: var(--hm-gold-text); }

@media (max-width: 979px) { .bakery .hm-gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; } }
@media (max-width: 480px) { .bakery .hm-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
	.bakery .hm-gallery__item.is-wide { grid-column: span 2; } }


/* ---------------------------------------------------------------------------
   14. §7.13 GRAVITY FORM 1 — legacy CSS is off, so this renders unstyled
   --------------------------------------------------------------------------- */

.bakery .gform_wrapper { margin: 0; }

/* Single column by default — form 1 currently sits in a 1/2-width vc_column,
   where two columns would be unreadable. Add .hm-form-2col on the row when the
   form runs full width (the §17 nine-field layout). */
body .gform_wrapper.gravity-theme .gform_fields {
	grid-template-columns: minmax(0, 1fr) !important;
	display: grid !important;
	gap: 20px 24px !important;
}
body .gform_wrapper.gravity-theme .gfield { grid-column: 1 / -1 !important; min-width: 0; }

body .hm-form-2col .gform_wrapper.gravity-theme .gform_fields {
	grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
}
body .hm-form-2col .gform_wrapper.gravity-theme .gfield { grid-column: span 1 !important; }
body .hm-form-2col .gform_wrapper.gravity-theme .gfield.hm-full,
body .hm-form-2col .gform_wrapper.gravity-theme .gfield--type-textarea,
body .hm-form-2col .gform_wrapper.gravity-theme .gfield--type-checkbox,
body .hm-form-2col .gform_wrapper.gravity-theme .gfield--type-html { grid-column: 1 / -1 !important; }

/* GF ships a honeypot field as a visible grid cell. Hide it. */
body .gform_wrapper.gravity-theme .gfield--type-honeypot,
body .gform_wrapper .gform_validation_container { display: none !important; }

body #content .gform_wrapper .gfield_label,
body .gform_wrapper .gfield_label {
	font-family: var(--headingfont);
	color: var(--black) !important;
	margin: 0 0 7px !important;
	letter-spacing: 0.2px;
	display: block;
	font-size: 14px;
}
body .gform_wrapper .gfield_required { color: var(--hm-gold-text) !important; margin-left: 3px; }

body .gform_wrapper.gravity-theme input[type="text"],
body .gform_wrapper.gravity-theme input[type="email"],
body .gform_wrapper.gravity-theme input[type="tel"],
body .gform_wrapper.gravity-theme input[type="number"],
body .gform_wrapper.gravity-theme input[type="date"],
body .gform_wrapper.gravity-theme select,
body .gform_wrapper.gravity-theme textarea {
	border: 1px solid var(--light3) !important;
	transition: border-color var(--hm-ease), box-shadow var(--hm-ease);
	background: var(--light1) !important;
	color: var(--black) !important;
	padding: 13px 15px !important;
	border-radius: 10px !important;
	/* NOT `inherit` — twentytwentyfive's inline global styles set
	   `body { font-family: Literata }`, so inheriting lands on a serif. */
	font-family: var(--bodyfont) !important;
	font-size: 16px !important;  /* 16px stops iOS zooming the viewport on focus */
	width: 100% !important;
	max-width: 100%;
	display: block;
}
body .gform_wrapper textarea { min-height: 150px; resize: vertical; }

body .gform_wrapper input:focus,
body .gform_wrapper select:focus,
body .gform_wrapper textarea:focus {
	box-shadow: 0 0 0 3px rgba(247, 198, 89, 0.35) !important;
	border-color: var(--accent1) !important;
	outline: none;
}
body .gform_wrapper ::placeholder {
	font-family: var(--bodyfont) !important;
	color: var(--dark3) !important;
	opacity: 0.75;
}

/* The options compiler sets the body font on `button` and `form label` but never
   on input / select / textarea, so every field on the site falls back to the
   browser's default serif. Site-wide gap, fixed once here. */
body input, body select, body textarea,
body .gform_wrapper.gravity-theme input,
body .gform_wrapper.gravity-theme select,
body .gform_wrapper.gravity-theme textarea {
	font-family: var(--bodyfont);
}

/* Checkbox / radio groups — Services desired is a checkbox set. */
body .gform_wrapper .gfield_checkbox,
body .gform_wrapper .gfield_radio { margin: 0 !important; padding: 0 !important; list-style: none !important; }
body .gform_wrapper .gfield_checkbox .gchoice,
body .gform_wrapper .gfield_radio .gchoice {
	align-items: flex-start;
	margin: 0 0 10px !important;
	display: flex;
	gap: 10px;
}
body .gform_wrapper .gfield_checkbox input,
body .gform_wrapper .gfield_radio input {
	accent-color: var(--accent1);
	flex: 0 0 auto;
	margin-top: 3px;
	height: 18px;
	width: 18px;
}
body .gform_wrapper .gfield_checkbox label,
body .gform_wrapper .gfield_radio label { margin: 0 !important; font-size: 15px; }

body .gform_wrapper .gfield_description,
body .gform_wrapper .gform_fileupload_rules {
	color: var(--dark3) !important;
	margin: 6px 0 0 !important;
	font-size: 13px;
}

/* Validation — GF's default red is too harsh against this palette. */
body .gform_wrapper .gfield_error input,
body .gform_wrapper .gfield_error select,
body .gform_wrapper .gfield_error textarea { border-color: #C0392B !important; }
body .gform_wrapper .gfield_validation_message,
body .gform_wrapper .validation_message {
	background: rgba(192, 57, 43, 0.07) !important;
	border-left: 3px solid #C0392B !important;
	color: #8E2A20 !important;
	margin: 8px 0 0 !important;
	border-radius: 0 8px 8px 0;
	padding: 8px 12px !important;
	font-size: 14px;
}
body .gform_wrapper .gform_validation_errors {
	background: rgba(192, 57, 43, 0.07) !important;
	border: 1px solid rgba(192, 57, 43, 0.3) !important;
	border-radius: var(--hm-radius) !important;
	margin: 0 0 24px !important;
	padding: 16px 20px !important;
}
body .gform_wrapper .gform_validation_errors h2,
body .gform_wrapper .gform_validation_errors > h2.gform_submission_error { color: #8E2A20 !important; font-size: 17px !important; }

.bakery .gform_wrapper .gform_footer,
.bakery .gform_wrapper .gform-footer { margin: 28px 0 0 !important; padding: 0 !important; }
body .gform_wrapper .gform_footer input[type="submit"],
body .gform_wrapper .gform_footer button.gform_button,
body .gform_wrapper .gform-footer button.gform_button {
	font-family: var(--headingfont);
	border-radius: 50px !important;
	padding: 15px 34px !important;
	text-transform: none;
	border: 0 !important;
	letter-spacing: 0.5px;
	cursor: pointer;
	font-size: 16px;
	width: auto;
}
body .gform_wrapper .gform_ajax_spinner { margin-left: 12px; }

/* Turnstile sits above the footer — give it room. */
.bakery .gform_wrapper .gfield--type-turnstile,
.bakery .gform_wrapper .cf-turnstile { margin-top: 4px; }

body .gform_confirmation_message {
	border-radius: var(--hm-radius);
	border-left: 4px solid var(--accent1);
	background: var(--light2);
	padding: 24px 26px;
}

@media (max-width: 767px) {
	.bakery .gform_wrapper .gform_fields { grid-template-columns: minmax(0, 1fr); gap: 16px; }
	.bakery .gform_wrapper .gfield { grid-column: 1 / -1; }
	body .gform_wrapper .gform_footer input[type="submit"],
	body .gform_wrapper .gform_footer button.gform_button,
	body .gform_wrapper .gform-footer button.gform_button { width: 100%; }
}


/* ---------------------------------------------------------------------------
   15. §7.14 BOTTOM CTA + §7.15 MID-PAGE CTA BAND
   bottom-cta is page-ending only; cta-section is mid-page. §Appendix.
   --------------------------------------------------------------------------- */

.bakery .bottom-cta { padding: 96px 0; }
.bakery div.vc_row.bottom-cta::before,
.bakery .bottom-cta::before {
	background: linear-gradient(180deg,
		rgba(16, 16, 18, 0.46) 0%,
		rgba(16, 16, 18, 0.58) 55%,
		rgba(16, 16, 18, 0.66) 100%);
	display: block;
	position: absolute;
	content: "";
	inset: 0;
	z-index: 1;
}
.bakery .bottom-cta > .vc_row,
.bakery .bottom-cta > * { position: relative; z-index: 2; }

/* Placeholder so the band is never a blank box if the image fails. §Appendix */
.bakery .bottom-cta {
	background-image: url("/wp-content/uploads/2026/10/couple-celebrating-signed-marriage-license.webp");
	background-position: center 35%;
	background-color: var(--dark1);
	background-size: cover;
	position: relative;
	/* NOT `fixed`, despite the add-parallax class on the row. Measured in
	   session 6: with background-attachment:fixed the positioning area is the
	   VIEWPORT, not the element, so `cover` fits the photo to 1440x900 and the
	   336px band only ever shows the ~37% slice that happens to line up with
	   its position on screen — and background-position stops having any
	   vertical effect, because there is no overflow left to position. On every
	   landscape frame in this library that slice lands on ceiling and dark air.
	   Captured band: mean luminance 0.0042, brightest pixel in 484k still only
	   17:1 against white. It was a black rectangle, not a photograph.
	   With `scroll` the whole image maps into the band and `center 45%` means
	   what it says. Parallax on a 336px band was imperceptible anyway; §3.4
	   permits it, it does not require it. */
	background-attachment: scroll;
}
/* THE reason this band looked like a black rectangle, found by A/B after the
   image swap and the scrim solve both failed to move it:

       style.css:66   .bakery .wpb_row, .bakery .vc_row
                      { background-blend-mode: overlay; }

   Every WPBakery row on this theme blends its background IMAGE against its
   background COLOR. Site Conductor requires a colour placeholder on any
   section carrying a photo, so every such row on this site is blending a
   photograph against --dark1. `overlay` with a backdrop below 50% luminance
   degenerates to multiply(2 x backdrop), and #101012 is 6% luminance, so the
   photo rendered at roughly an eighth of its real brightness. Measured: the
   crop the band shows is mean RGB 153 in the file and was painting at 29.

   Proven by A/B per §14 — with the scrim pseudo-element removed entirely the
   band only went from mean RGB 27.3 to 29.3. The scrim was never the cause.

   Reset globally, not just here: this is latent on every remaining page that
   gives a row a background image, which is most of them. Nothing on this build
   wants an overlay blend; if something ever does, it can opt back in. */
.bakery div.vc_row,
.bakery div.wpb_row { background-blend-mode: normal; }
.bakery div.vc_row.hm-blend-overlay { background-blend-mode: overlay; }

/* style.css:378 ships `@media (min-width:979px){ .add-parallax {
   background-attachment: fixed !important } }` and is enqueued AFTER
   custom.css, so the declaration above lost outright. !important against
   !important is decided on specificity: (0,4,1) beats (0,1,0). */
.bakery div.vc_row.bottom-cta.add-parallax,
.bakery div.vc_row.bottom-cta { background-attachment: scroll !important; }

body #content .bottom-cta h2,
body #content .bottom-cta h3,
body #content .bottom-cta p { color: var(--white) !important; }
body #content .bottom-cta h2 { margin-bottom: 14px !important; }

/* Button rows. `bottom-cta-row` is an el_class on the text block itself, so
   the element IS the .wpb_content_element — a descendant selector off it
   matched nothing. Each button is authored in its own paragraph so the flex
   gap has two items (wpautop would otherwise fold both into one). */
.bakery .bottom-cta-row > .wpb_wrapper,
.bakery .hm-btn-row > .wpb_wrapper {
	justify-content: center;
	align-items: center;
	column-gap: var(--hm-gap);
	flex-wrap: wrap;
	row-gap: 16px;
	display: flex;
}
.bakery .hm-btn-row.is-left > .wpb_wrapper { justify-content: flex-start; }
body #content .bottom-cta-row p,
body #content .hm-btn-row p { margin: 0 !important; }
.bakery .bottom-cta-row,
.bakery .hm-btn-row { margin-top: 10px; }
.bakery .cta-row .wpb_content_element .wpb_wrapper { margin-top: 10px; }

/* Mid-page band — solid accent1, black text (rule 1 handles the colour). */
.bakery .cta-section { padding: 56px 0; }
.bakery .cta-section.accent1 { background: var(--accent1); }

@media (max-width: 979px) {
	.bakery .bottom-cta { padding: 64px 0; }
	.bakery .cta-section { padding: 40px 0; }
	/* Parallax is a jank factory on touch. */
	.bakery .add-parallax { background-attachment: scroll !important; }
}


/* ---------------------------------------------------------------------------
   16. §7.16 SERVICE-AREA BLOCK — two tiers, no map iframe
   --------------------------------------------------------------------------- */

.bakery .hm-area {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	display: grid;
	gap: 24px;
}
.bakery .hm-area__tier {
	border-radius: var(--hm-radius);
	background: var(--light1);
	border: var(--hm-border);
	padding: 28px 26px;
}
.bakery .hm-area__tier.is-primary { border-left: 4px solid var(--accent1); }
.bakery .hm-area__tier.is-travel  { border-left: 4px solid var(--accent3); }

body #content .hm-area__tier h4 { margin: 0 0 6px !important; }
body #content .hm-area__scope {
	color: var(--dark3) !important;
	text-transform: uppercase;
	margin: 0 0 14px !important;
	letter-spacing: 1.5px;
	font-size: 12px;
}
body #content .hm-area__tier p:last-child { margin-bottom: 0 !important; }

@media (max-width: 767px) {
	.bakery .hm-area { grid-template-columns: minmax(0, 1fr); gap: 16px; }
}


/* ---------------------------------------------------------------------------
   17. §7.17 SOCIAL STRIP — [social_links] outputs ul.social
   --------------------------------------------------------------------------- */

body #content ul.social,
.bakery ul.social {
	list-style: none !important;
	flex-wrap: wrap;
	padding: 0 !important;
	margin: 0 !important;
	display: flex;
	gap: 12px;
}
body #content ul.social li { margin: 0 !important; list-style: none !important; }
.bakery ul.social li a {
	border: 1px solid rgba(255, 255, 255, 0.22);
	transition: all var(--hm-ease);
	justify-content: center;
	align-items: center;
	border-radius: 50%;
	display: flex;
	height: 42px;
	width: 42px;
}
.bakery ul.social li a:hover { background: var(--accent1); border-color: var(--accent1); }
.bakery ul.social li a:hover i { color: var(--black) !important; }

/* On a light surface the ring has to darken instead. */
.bakery .light1 ul.social li a,
.bakery .light2 ul.social li a { border-color: var(--light3); }


/* ---------------------------------------------------------------------------
   18. MEDIA + COPY SPLIT — the "inline-fifty" role §8.1 / §8.3 / §8.6 name.
   §14: `inline-fifty` and `fifty-section` do not exist anywhere on this stack.
   This is that pattern, authored against the real .vc_row > .container > column
   markup. Put the widths on the columns (5/12 + 7/12 etc) — never 1/2 // 1/2.
   --------------------------------------------------------------------------- */

.bakery div.vc_row.hm-split > .container {
	max-width: calc(1280px + 56px);
	width: calc(90% + 56px);
	align-items: center;
}
.bakery .hm-split .vc_column_container { padding: 0 28px !important; }

.bakery .hm-split__media img {
	box-shadow: 0 0px 24px rgba(0, 0, 0, 0.35);
	border-radius: var(--hm-radius);
	display: block;
	height: auto;
	width: 100%;
}

/* Opt-in crop for tall portrait sources. A 2:3 photo in a 5/12 column runs
   ~795px while the copy beside it is ~200px, which left the row mostly
   whitespace. 4:5 with the focal point high keeps both faces and halves the
   gap. Only applied where the source is actually portrait. */
.bakery .hm-split__media.is-portrait img {
	object-position: center 20%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
}
.bakery .hm-split p {
	margin-top: 15px;
}
.bakery .hm-split a.btn-bt {
	margin-top: 18px;
}

@media (max-width: 979px) {
	.bakery div.vc_row.hm-split > .container { max-width: 1280px; width: 90%; }
	.bakery .hm-split .vc_column_container { padding: 0 !important; }
	.bakery .hm-split > .container > .vc_column_container + .vc_column_container { margin-top: 28px; }
}


/* ---------------------------------------------------------------------------
   19. FEATURE BLOCK — text-only 3-up. Home "The Hype Man Difference",
   About "The Hype Man Way", the service-page intros.
   --------------------------------------------------------------------------- */

.bakery .hm-feature {
	border-top: 3px solid var(--accent1);
	padding: 18px 0 0;
	height: 100%;
}
body #content .hm-feature h3,
body #content .hm-feature h4 { margin: 0 0 8px !important; }
body #content .hm-feature p { margin: 0 !important; }
body #content .dark1 .hm-feature p,
body #content .dark2 .hm-feature p { color: var(--light3) !important; }


/* ---------------------------------------------------------------------------
   20. VIDEO EMBED — YouTube on Home (§8.1) and Media (§8.7).
   Embedded rather than self-hosted, per §9.2.
   --------------------------------------------------------------------------- */

.bakery .hm-video {
	box-shadow: 0px 0px 36px var(--accent1);
	border-radius: var(--hm-radius);
	background: var(--dark2);
	aspect-ratio: 16 / 9;
	position: relative;
	overflow: hidden;
	display: block;
}
.bakery .hm-video iframe {
	position: absolute;
	border: 0 !important;
	height: 100%;
	width: 100%;
	display: block;
	inset: 0;
}


/* ---------------------------------------------------------------------------
   21. MOTION — §3.4. Nothing beyond hover; no scroll-reveal, no AOS.
   --------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.bakery *,
	.bakery *::before,
	.bakery *::after {
		animation-duration: 0.001ms !important;
		transition-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
	}
	.bakery .add-parallax { background-attachment: scroll !important; }
}


/* ---------------------------------------------------------------------------
   22. FONT FACES THE OPTIONS COMPILER NEVER DECLARED
   Found in session 6 while chasing "the fonts seem too thin".

   option-page-styles.css emits exactly TWO @font-face blocks — Montserrat-Bold
   (nav) and Montserrat-Regular (body). Its "Call Heading Font Family" branch
   compiles to nothing, yet the very next rule says

       body h1 ... body h6 { font-family: Spartan-Bold, sans-serif; }

   So every heading on this site has been falling straight through to the UA's
   `sans-serif` — Helvetica on a Mac. The intended geometric face was never
   loaded. The file is on the server (fonts/spartan/Spartan-Bold.ttf -> 200), it
   was simply never declared. Declaring it here is the no-PHP fix.

   Montserrat-Medium is declared for the same reason: the compiler only knows
   Regular, and Regular at 17px under twentytwentyfive's inherited
   `font-weight: 300` is what read as thin. The .ttf is on the server already.
   --------------------------------------------------------------------------- */

@font-face {
	font-family: 'Spartan-Bold';
	src: url("/wp-content/themes/vds/fonts/spartan/Spartan-Bold.ttf") format("truetype");
	font-display: swap;
	font-variant: normal;
	font-weight: normal;
}

@font-face {
	font-family: 'Montserrat-Medium';
	src: url("/wp-content/themes/vds/fonts/montserrat/Montserrat-Medium.ttf") format("truetype");
	font-display: swap;
	font-variant: normal;
	font-weight: normal;
}

/* twentytwentyfive's global-styles block sets `body { font-weight: 300 }` and
   `body { color: var(--wp--preset--color--accent-2) }` (a pink, #DB9AB1) — both
   inherited by everything that does not restate them. 300 against a single-
   weight face does not synthesise, so the weight alone was not the whole story;
   the real lift is moving running copy onto the Medium cut. */
body,
body #content p,
body #content li,
body #content span:not([class*="icon-"]):not([class*="fa-"]) { font-weight: 400 !important; }

body #content p,
body #content li,
body #content .hm-card p,
body #content .hm-feature p,
body footer .textwidget,
body footer .menu li a {
	font-family: var(--bodyfont) !important;
	line-height: 1.68 !important;
	font-size: 18px !important;
}

/* Form fields stay on Regular — Medium in an input reads as a filled value
   rather than a placeholder. §14 also warns never to write `font-family:
   inherit` here, or twentytwentyfive's Literata gets pulled down. */
body .gform_wrapper.gravity-theme input,
body .gform_wrapper.gravity-theme select,
body .gform_wrapper.gravity-theme textarea {
	font-family: var(--bodyfont) !important;
	font-weight: 400 !important;
}


/* ---------------------------------------------------------------------------
   23. SITE CHROME — TOP WIDGET, FOOTER, COPYRIGHT BAR
   These live OUTSIDE #content, so neither `.bakery` nor `body #content` reaches
   them and every component rule above stopped at the footer's edge. That is why
   the footer rendered as unstyled browser defaults.

   A FOURTH shipped contrast failure, alongside the three in rule 1. The options
   compiler paints both chrome bands --dark2 and then paints their contents
   --accent2, which on this palette are #1C1C22 and #101012:

       .row.copyright, .top-widget      { background: var(--dark2); }   #1C1C22
       ul.social li a i, .top-widget p a { color: var(--accent2); }     #101012

   = 1.06:1. The header phone number and every social icon in both bars were
   invisible on every page of the site. option-page-styles.css is enqueued
   FIRST, so plain specificity is enough to win here — no !important needed for
   the cascade, only for the convention on text properties.
   --------------------------------------------------------------------------- */

:root {
	/* Muted text on an ink ground. --dark3 (#44444F) is only 2.2:1 on #101012
	   and cannot be used for the footer's secondary copy. This is 7.6:1. */
	--hm-ink-muted: #A3A3AE;
	--hm-ink-rule: rgba(255, 255, 255, 0.10);
}

/* --- Top widget bar ------------------------------------------------------ */

body .top-widget { border-bottom: 1px solid var(--hm-ink-rule); }

body .top-widget p,
body .top-widget p a,
body .top-widget .widget a:link,
body .top-widget .widget a:visited {
	font-family: var(--bodyfont) !important;
	color: var(--light2) !important;
	letter-spacing: 0.2px;
	font-size: 15px !important;
}
body .top-widget p a:hover,
body .top-widget .widget a:hover { color: var(--accent1) !important; }

body .top-widget ul.social li a i,
body .top-widget ul.social li a { color: var(--light2) !important; }
body .top-widget ul.social li a:hover i { color: var(--accent1) !important; }

/* The chip treatment in rule 17 is scoped to .bakery, which never reaches the
   header. The top bar is only 40px tall, so it gets the bare glyph with a
   hover colour rather than a 42px ring. */
body .top-widget ul.social { gap: 18px; }
body .top-widget ul.social li a { border: 0; height: auto; width: auto; }

/* --- Footer -------------------------------------------------------------- */

body footer#footer.site-footer {
	border-top: 4px solid var(--accent1);
	background: var(--dark1);
	padding: 72px 0 56px;
}
body footer#footer.site-footer .row .container { align-items: flex-start; }

body footer#footer .widget-title,
body footer#footer h2.widget-title,
body footer#footer h3.widget-title {
	font-family: var(--headingfont) !important;
	color: var(--accent1) !important;
	text-transform: uppercase;
	margin: 0 0 18px !important;
	letter-spacing: 1.6px;
	font-size: 14px !important;
	line-height: 1.3 !important;
}

/* The compiler sets footer links to --dark3 (#44444F) via
   `footer .widget a:link:not(.ab-item):not(.btn-bt)`. That is 2.2:1 on ink. */
body footer#footer .widget a:link:not(.ab-item):not(.btn-bt),
body footer#footer .widget a:visited:not(.ab-item):not(.btn-bt),
body footer#footer a:not(.ab-item):not(.btn-bt) {
	color: var(--light3) !important;
	text-decoration: none !important;
	box-shadow: none !important;
}
body footer#footer a:not(.ab-item):not(.btn-bt):hover {
	color: var(--accent1) !important;
	text-decoration: none !important;
}
body footer#footer .textwidget,
body footer#footer p,
body footer#footer li { color: var(--light3) !important; }

/* Column 1 — the NAP block. It shipped as a bulleted UL with the company name
   floating above it as a bare P, which is most of why this read as unstyled. */
body footer#footer p.footer-brand {
	font-family: var(--headingfont) !important;
	color: var(--white) !important;
	margin: 0 0 18px !important;
	letter-spacing: -0.2px;
	font-size: 20px !important;
	line-height: 1.25 !important;
}
/* SESSION 8 — Cody: "the border bottom on the li's are too close to touching
   column 2." Measured at 1440 the rules ran to x=540 and "QUICK LINKS" starts
   at x=560: a 20px gutter between a drawn line and the next column, which
   reads as a collision. The rule is drawn by the li, so the inset has to be on
   the list, not on the column — 72px of right padding puts the gutter at 92px,
   wider than the 28px of air above and below each rule, so the line now
   clearly belongs to column 1. Reset below 980px, where the columns stack and
   there is no neighbour to clear. */
body footer#footer ul.footer-nap {
	list-style: none !important;
	padding: 0 72px 0 0 !important;
	margin: 0 !important;
}
body footer#footer ul.footer-nap li {
	border-top: 1px solid var(--hm-ink-rule);
	padding: 10px 0 0 !important;
	margin: 0 0 10px !important;
	font-size: 15px !important;
	line-height: 1.55 !important;
}
body footer#footer ul.footer-nap li:first-child { border-top: 0; padding-top: 0 !important; }
body footer#footer .footer-label {
	color: var(--hm-ink-muted) !important;
	text-transform: uppercase;
	margin-right: 6px;
	letter-spacing: 1.2px;
	font-size: 11px !important;
	display: block;
}

/* Menu columns — the theme ships these as plain UL.menu with browser
   bullets and underlines. */
body footer#footer .menu {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
}
body footer#footer .menu li {
	margin: 0 0 11px !important;
	font-size: 15px !important;
	padding: 0 !important;
}
body footer#footer .menu li:last-child { margin-bottom: 0 !important; }

/* Column 4 — social chips. Rule 17's ring treatment, re-scoped past .bakery. */
body footer#footer ul.social {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
	flex-wrap: wrap;
	display: flex;
	gap: 12px;
}
body footer#footer ul.social li { margin: 0 !important; display: block; }
body footer#footer ul.social li a {
	border: 1px solid rgba(255, 255, 255, 0.22);
	transition: all 200ms cubic-bezier(0.2, 0.6, 0.3, 1);
	justify-content: center;
	align-items: center;
	border-radius: 50%;
	display: flex;
	height: 42px;
	width: 42px;
}
body footer#footer ul.social li a i { color: var(--light2) !important; font-size: 18px; }
body footer#footer ul.social li a:hover {
	border-color: var(--accent1);
	background: var(--accent1);
}
body footer#footer ul.social li a:hover i { color: var(--black) !important; }

/* The consultation button in column 4 renders but had no styling outside
   #content, so it sat as plain ink-on-ink text. */
body footer#footer p.footer-button { margin-top: 26px !important; }
body footer#footer a.btn-bt.default {
	font-family: var(--bodyfont) !important;
	background: var(--accent1) !important;
	color: var(--black) !important;
	transition: all 200ms cubic-bezier(0.2, 0.6, 0.3, 1);
	text-decoration: none !important;
	padding: 13px 26px !important;
	border-radius: 50px !important;
	display: inline-block;
	font-size: 15px !important;
	line-height: 1.2 !important;
}
body footer#footer a.btn-bt.default:hover {
	background: var(--uihover) !important;
	color: var(--black) !important;
}

/* --- Copyright bar ------------------------------------------------------- */

body .row.copyright {
	border-top: 1px solid var(--hm-ink-rule);
	padding: 18px 0 !important;
}
body .row.copyright .copyright-text p,
body .row.copyright .copyright-content p,
body .row.copyright p {
	color: var(--hm-ink-muted) !important;
	font-size: 14px !important;
	line-height: 1.6 !important;
}
body .row.copyright a:not(.btn-bt) {
	color: var(--light3) !important;
	text-decoration: none !important;
}
body .row.copyright a:not(.btn-bt):hover { color: var(--accent1) !important; }

/* Same 1.06:1 bug as the top bar: the A was white but the fontello I inside
   it still carried --accent2. The glyph is the only visible part. */
body .row.copyright ul.social li a,
body .row.copyright ul.social li a i { color: var(--light2) !important; }
body .row.copyright ul.social li a:hover i { color: var(--accent1) !important; }
body .row.copyright ul.social {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
	display: inline-flex;
	gap: 16px;
}
body .row.copyright ul.social li a { border: 0; height: auto; width: auto; }

@media (max-width: 979px) {
	body footer#footer.site-footer { padding: 48px 0 40px; }
	body footer#footer ul.footer-nap { padding-right: 0 !important; }
	body footer#footer .vc_col-sm-3 { margin-bottom: 36px; }
	body footer#footer .vc_col-sm-3:last-child { margin-bottom: 0; }
	body .row.copyright ul.social { justify-content: center; margin-top: 10px !important; }
	/* The theme floats .copyright-text p left and .copyright-links right, which
	   at 390px splits one sentence across two opposed alignments. */
	body .row.copyright .copyright-text,
	body .row.copyright .copyright-content { text-align: center !important; }
	body .row.copyright .copyright-text p,
	body .row.copyright .copyright-links {
		text-align: center !important;
		padding-left: 0 !important;
		display: inline;
		float: none !important;
	}
}


/* ---------------------------------------------------------------------------
   24. PRESENCE PASS — §3.4 still governs. No scroll-reveal, no AOS, no library.
   Everything here is scale, composition and a hover state. The client disliked
   arizonasdj.com for being dark and heavily animated; none of this is either.
   --------------------------------------------------------------------------- */

/* Section headings carried more weight once Spartan-Bold actually loaded, so
   the scale can open up without shouting. h1 is deliberately NOT raised — the
   hero headline is already three lines at 56px. */
body #content h2 { font-size: clamp(28px, 4.4vw, 46px) !important; }
body #content .hm-section > .container > .vc_column_container h2 { letter-spacing: -0.5px !important; }

/* Trust bar — the four proof numbers are the single strongest thing on the
   page and were rendering at the same size as a card title. */
body #content .hm-trust__num { font-size: clamp(40px, 5.6vw, 72px) !important; }
body #content .hm-trust__label { font-size: 12px; letter-spacing: 1.8px; opacity: 0.72; }
.bakery .hm-trust { padding: 56px 0; }

/* Media + copy split: an accent frame set behind the photo. Desktop only —
   below 980px the columns are flush to the container and a negative offset
   would push a horizontal scroll at 390px, which is the one thing §10 gate 5
   will not forgive.

   SESSION 8 — Cody, twice now: "you didn't do anything about making the yellow
   box better." It was a 62% x 62% solid accent1 slab at bottom: -20px / left:
   -20px, and three things were wrong with it.

   It was in the wrong place. `.hm-split__media` is the vc_column, which
   carries `padding: 0 28px` — measured, the column box starts at x=52 and the
   photograph at x=80. So `left: -20px` put the slab 48px left of the photo,
   not 20px, and it broke the page's left margin. It is now positioned against
   the photo's own box via the inner wrapper, so the offsets mean what they say.

   It was a slab. A 310 x 388px flat yellow rectangle beside a photo reads as
   something that failed to load, not as a device — the same "missing asset"
   look §12-F diagnosed on the Bar & Mixology tile. An outline frame carries
   the same accent at a fraction of the mass.

   It pointed the wrong way. The media column is on the left of this row, so
   offsetting down-LEFT pushed the eye off the page. Down-right pushes it into
   the copy, and the 54px gutter between the columns is wide enough to take a
   24px overhang without crowding the text. */
.bakery .hm-split__media { position: relative; display: block; }
.bakery .hm-split__media img { position: relative; z-index: 1; }

@media (min-width: 980px) {
	.bakery .hm-split__media .wpb_text_column { position: relative; }
	.bakery .hm-split__media .wpb_text_column::before {
		border-radius: var(--hm-radius);
		inset: 36px 36px -36px -36px;
		background: var(--accent1);
		position: absolute;
		display: block;
		content: "";
		z-index: 0;
	}
	/* The frame needs room to sit in, or it clips the row below. */
	.bakery div.vc_row.hm-split { padding-bottom: 24px; }
}

/* Card photography reads flat at 4:3 with a static image. A contained zoom on
   hover is the one motion §3.4 allows, and it is reduced-motion gated. */
.bakery .hm-card__media { overflow: hidden; }

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-card__media img { transition: transform 320ms cubic-bezier(0.2, 0.6, 0.3, 1); }
	.bakery .hm-card:hover .hm-card__media img,
	.bakery a.hm-card:hover .hm-card__media img { transform: scale(1.05); }
}

/* Bottom CTA. The old band measured 0.0042 mean luminance — black. Two causes,
   both fixed above: a cold-sparks frame shot in a dark room, and `fixed`
   attachment cropping it to its darkest slice. The replacement frame is the
   brightest landscape image in the library when scored on the crop the band
   ACTUALLY shows (0.376 vs 0.157 for cold-sparks), so the scrim has to go UP,
   not down, or the white headline fails on the tablecloths.

   Solved rather than guessed — alpha swept against the real crop:
       0.30 -> 0.56   mean lum 0.133   25.72% of band below AA
       0.50 -> 0.66   mean lum 0.078    2.87% below AA
       0.60 -> 0.74   mean lum 0.053    0.00% below AA   [shipped]
   Net: 12.6x brighter than what was live, and provably AA across every pixel. */
.bakery div.vc_row.bottom-cta::before,
.bakery .bottom-cta::before {
	background: linear-gradient(180deg,
		rgba(16, 16, 18, 0.60) 0%,
		rgba(16, 16, 18, 0.67) 50%,
		rgba(16, 16, 18, 0.74) 100%);
}
body #content .bottom-cta h2 { text-shadow: 0 2px 20px rgba(16, 16, 18, 0.55); }


/* ---------------------------------------------------------------------------
   25. DESIGN PASS — BUILD-PLAN §16
   Session 6's "presence pass" made Home correct and left it generic. This is
   the composition answer to that: scale, asymmetry and one structural use of
   the yellow, instead of a tune-up.

   §16's constraints still bind and nothing here breaks them — the page stays
   light and photo-led, there is no scroll-reveal and no library, every moving
   part is CSS-only and dies under prefers-reduced-motion, and every new block
   is a [vc_column_text] so WPBakery can still edit the words. The raw-html
   budget is untouched at 1 (the hero video).

   NO BACKSLASH ESCAPES (see the file header). The marquee separator is drawn
   as a border-radius dot rather than a glyph for exactly that reason.
   --------------------------------------------------------------------------- */


/* --- 25.1 Section scale ---------------------------------------------------
   Section headings go up another step, and stop being centred. The all-centred
   rhythm was the single loudest "template" tell on the page: eight sections,
   eight centred headings, every one the same width.

   SESSION 8 — Cody: "headings feel too big". The scale had escalated twice
   (base 38 -> section 17's 46 -> 56 here) and 56px against 18px body copy is a
   3.1x jump. Back to 42px, a 2.3x jump — still a display scale, still a clear
   step above the shipped theme. The measure moves with it: 17ch at 56px was
   524px, so 24ch at 42px (~552px) holds the same line length in pixels. */

body #content h2 { font-size: clamp(26px, 3.3vw, 42px) !important; }

/* `ch` on the text element resolves against the ELEMENT's font, not the
   heading's — .wpb_text_column computes to 24px here, so 18ch was 260px and
   the headings came out one word per line. Measure in px on the wrapper and
   leave the ch measure on the h2 itself, where it means what it looks like. */
.bakery .hm-sechead { max-width: 860px; }

/* Cody, session 15: drop the section head's bottom margin, so the gap under a
   heading is the following row's `hm-mt-lg` and nothing else.

   SCOPED TO :last-child, and that is not a liberty — measured. A flat
   `.hm-sechead { margin-bottom: 0 }` also hits the heads that are followed by
   content INSIDE THE SAME COLUMN, where that margin IS the gap and no row
   margin replaces it: `sechead() + inclusions()` on Packages, DJ, Officiant,
   Bar and Photo Booth, and `sechead() + the accordion` on all six FAQ pages.
   Measured on 2696 immediately after the flat version went live: "Package
   Overview" sat 10px off its own list and the FAQ heading 10px off the first
   panel. `hm_build.py`'s own convention note has said this since it was
   written — "a section-heading-only text block does NOT get mb0 (the margin
   is the gap)".

   As a last child the head has a row below it carrying 40px, so zeroing it
   removes a doubled gap and nothing else. */
.bakery .wpb_wrapper > .hm-sechead:last-child { margin-bottom: 0; }
body #content .hm-sechead h2 { margin-bottom: 10px !important; max-width: 24ch; }
body #content .hm-sechead p:last-child { margin-bottom: 0 !important; }

/* Heading left, an existing CTA pulled up beside it on the right. No new copy
   — the button is the one that used to sit alone under the quote row. */
@media (min-width: 980px) {
	.bakery div.vc_row.hm-sechead-row > .container { align-items: flex-end; }
	.bakery .hm-btn-row.is-right > .wpb_wrapper { justify-content: flex-end; }
}
@media (max-width: 979px) {
	.bakery .hm-sechead { max-width: none; }
	.bakery .hm-btn-row.is-right { margin-top: 20px; }
}


/* --- 25.2 §16.4 HIGHLIGHTER MARK ------------------------------------------
   A yellow swipe behind one phrase of a heading. ONE treatment, one rule, no
   variants and no per-surface override — Cody, session 8: "get rid of the
   is-solid class, the hm-mark one is sufficient," and then, on the override
   that replaced it, "remove this." The same band sits behind the phrase
   everywhere it appears. box-decoration-break keeps it intact across a wrap.

   RESOLVED IN SESSION 9b — THE STANDING AA EXCEPTION IS RETIRED.
   For sessions 8 and 9 this rule carried a known, instructed accessibility
   failure: on the two headings that are white type over imagery (the hero h1
   and the bottom CTA h2) the band passed through the glyphs, white on
   #F7C659 is 1.59:1, and ~69% of the mark's glyph pixels measured below AA.
   §16.0a listed exactly two ways out and said both were ruled out — a variant
   for dark grounds, or taking the mark off those two headings.

   Cody took the second one: "don't use the hm-mark span effect on white
   headings." That is a MARKUP change — the two spans are gone from
   build_home.py — so it does NOT reintroduce the surface-keyed CSS rule he
   deleted twice, and this rule stays exactly as it was: one treatment, one
   band, no variants. The mark now appears only on dark type over light
   grounds, where it measures 11.93:1.

   **The contrast suite passes clean. `.hm-mark` is no longer an expected
   red line, so a FAIL on it from here is a real regression.** Do not
   re-add the mark to a white-over-imagery heading without re-measuring. */

/* The compiled options CSS carries `body, body p, body li, body span, ...
   { font-size: 17px }`. A span is a span wherever it sits, so EVERY inline
   span inside a heading on this site renders at body size — the first cut of
   this mark painted a 17px yellow chip in the middle of a 72px headline.
   Restating the three inherited font properties is not optional here, and the
   same trap applies to any future inline treatment inside an h1-h6. */
body #content .hm-mark {
	font-family: inherit;
	line-height: inherit;
	font-size: inherit;
	background-image: linear-gradient(100deg,
		rgba(247, 198, 89, 0) 0.4%,
		rgba(247, 198, 89, 1) 2.0%,
		rgba(247, 198, 89, 1) 98.0%,
		rgba(247, 198, 89, 0) 99.6%);
	background-position: 0 78%;
	background-size: 100% 0.44em;
	background-repeat: no-repeat;
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
	padding: 0 0.08em;
}


/* 1.32 was derived from the removed below-baseline band — it was whatever
   kept the next line's capitals clear of it. With the band back behind the
   text that constraint is gone and this is now purely leading; the hero ran
   at 1.14 in session 7. Left as-is because it is a visible change to the
   hero and Cody has not asked for one. Flagged, not silently reverted. */
body #content .hm-hero h1,
body #content .bottom-cta h2 { line-height: 1.32 !important; }


/* --- 25.3 HERO SCALE ------------------------------------------------------
   The headline is the whole hero. 56px was a heading; this is a statement.

   SESSION 8 — 72px went with the 56px h2 that Cody called too big, and the
   hero has to stay the largest thing on the page without being the loudest.
   54px keeps that order against the new 42px h2. Measure held at ~713px
   (19ch at 72px was 752px). line-height is set in 25.2, where it belongs —
   it is a function of the mark's descender gutter, not of this scale. */

body #content .hm-hero h1 {
	font-size: clamp(30px, 4.3vw, 54px) !important;
	letter-spacing: -1.1px !important;
	margin-bottom: 22px !important;
	max-width: 24ch;
}
body #content .hm-hero p { font-size: 18px !important; }

@media (max-width: 480px) {
	body #content .hm-hero h1 { letter-spacing: -0.5px !important; }
}


/* --- 25.4 §16.3 OVERLAPPING STAT CARD -------------------------------------
   Was a full-bleed yellow band butted against the hero. Now a white card that
   pulls up over the hero's bottom edge — the cheapest move on this page that
   reads as composed rather than stacked, and it works better on a phone than
   it does on a desktop. The yellow it gives up comes straight back as the
   marquee band directly below. */

.bakery div.vc_row.hm-trust {
	padding: 0 0 var(--hm-section-y);
	background: transparent;
	margin-top: -69px;
	position: relative;
	z-index: 3;
}

/* SESSION 8 — Cody: "the numbers in the stats row are too big, and the
   sublabels too, they should only be one line, the whole row feels clunky."
   Three separate problems, one of them a real bug:

   THE BUG. `body #content .hm-trust__label` set 12px with no `!important`,
   and section 16 sets `body #content p { font-size: 18px !important }`. The
   label is a paragraph. It had been rendering at 18px the whole time, measured
   read off the rule — which is why two of the four wrapped to two lines and
   why the card stood 160px tall. Same family as the `body span` trap in §14:
   on this stack a text property without `!important` is a suggestion.

   THE SCALE. 64px numerals next to a 42px h2 made the stat row compete with
   the section headings. 38px reads as a stat, not a headline.

   ONE LINE. With the label actually at 12px the longest string,
   "OWNERS ON SITE, EVERY EVENT" (27 characters at ~8.4px of advance plus
   tracking), sets in 227px inside a 277px column — so the 20ch cap was the
   only thing still forcing a wrap. It goes. Verified by measuring rendered
   line counts at 1440 and 1024, not by counting characters. */
.bakery .hm-trust__card {
	box-shadow: 0 18px 44px rgba(16, 16, 18, 0.16);
	background: var(--light1);
	border: var(--hm-border);
	padding: 26px 30px 24px;
	border-radius: 22px;
}

.bakery .hm-trust .hm-trust__grid { gap: 18px 28px; }

body #content .hm-trust__stat { text-align: left; position: relative; padding-top: 13px; }
body #content .hm-trust__stat::before {
	background: var(--accent1);
	position: absolute;
	border-radius: 2px;
	display: block;
	content: "";
	height: 3px;
	width: 26px;
	left: 0;
	top: 0;
}
body #content .hm-trust__num {
	font-size: clamp(28px, 2.6vw, 38px) !important;
	letter-spacing: -0.9px;
	line-height: 1.02;
}
body #content .hm-trust__label {
	font-size: 12px !important;
	letter-spacing: 1px;
	line-height: 1.45 !important;
	margin: 4px 0 0 !important;
	max-width: none;
}

/* Four columns need ~227px of label per cell for the longest string. At 1440
   the cell is 283px and every label sets on one line; at 1024 it is 194px and
   two of them wrapped — measured, both viewports. So the 2-up break belongs at
   1200, not at the 979 the rest of the page uses. */
@media (max-width: 1199px) {
	.bakery .hm-trust .hm-trust__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 979px) {
	.bakery div.vc_row.hm-trust { margin-top: -40px; padding-bottom: var(--hm-section-y-mobile); }
	.bakery .hm-trust__card { padding: 20px 20px 18px; border-radius: 18px; }
	.bakery .hm-trust .hm-trust__grid { gap: 16px 18px; }
}

/* One column means one stat per row, and a stacked number-over-label in a
   160px cell is what made this 780px tall on a phone with four-line labels.
   Laid out as four baseline-aligned rows instead, the label gets the full
   card width — ~223px after the numeral column — and every one of them fits
   on a single line at 390px, which is the actual ask. The yellow tick is
   dropped here: the row rule already does that job and the flex row has no
   space above the numeral to hang it in. */
@media (max-width: 680px) {
	.bakery .hm-trust .hm-trust__grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}
	body #content .hm-trust__stat {
		border-top: 1px solid var(--light3);
		padding: 11px 0 11px;
		align-items: baseline;
		display: flex;
		gap: 12px;
	}
	body #content .hm-trust__stat:first-child { border-top: 0; padding-top: 0; }
	body #content .hm-trust__stat:last-child { padding-bottom: 0; }
	body #content .hm-trust__stat::before { display: none; }
	body #content .hm-trust__num {
		font-size: 28px !important;
		flex: 0 0 auto;
		min-width: 56px;
	}
	/* 227px of advance for "OWNERS ON SITE, EVERY EVENT" against 219px of cell
	   was the last label still wrapping at 390. The 27 inter-letter gaps are
	   the cheapest 14px on the row — tracking comes off before the type size
	   does, because 12px uppercase is already at the floor for legibility. */
	body #content .hm-trust__label {
		letter-spacing: 0.5px;
		margin: 0 !important;
	}
}


/* --- 25.5 §16.2 MARQUEE TICKER BAND ---------------------------------------
   Two identical runs inside one track; the track travels exactly -50%, so the
   second run lands where the first started and the loop is seamless. The
   duplicate is aria-hidden, so the phrase list is announced once.

   This is a band, not a scroll effect — nothing about it is tied to scroll
   position, which is what §2 actually objected to on arizonasdj.com. It still
   stops dead under prefers-reduced-motion (see the end of this section) and
   pauses on hover.

   SESSION 8 — Cody: "the marquee feels out of place, or not in the right
   place." It was sitting directly under the stat card, which put three
   full-width bands in the first screen and a half — video, white card, yellow
   strip — and gave the page two competing yellow moments before the reader had
   met a single service. Moved in build_home.py to sit between the Core
   Services bento and the Featured Package row, where its content (the event
   types) is the natural next sentence after the services, and where it does
   real work: the bento is on --light2 and Featured Package on --light1, two
   backgrounds three percent apart that were butting into each other with no
   division at all. Type comes down with it (19px/2.2px tracking to 16px/1.8px)
   — as a divider it should be read, not shouted. */

.bakery div.vc_row.hm-marquee-row {
	border-bottom: 1px solid rgba(16, 16, 18, 0.12);
	border-top: 1px solid rgba(16, 16, 18, 0.12);
	padding: 0;
	margin: 0;
}
.bakery .hm-marquee-row > .container {
	max-width: none;
	padding: 0;
	width: 100%;
}
.bakery .hm-marquee-row .vc_column_container { padding: 0 !important; }

.bakery .hm-marquee { overflow: hidden; padding: 14px 0; width: 100%; }
.bakery .hm-marquee__track {
	animation: hm-marquee-scroll 38s linear infinite;
	will-change: transform;
	width: max-content;
	display: flex;
}
.bakery .hm-marquee__run { flex: 0 0 auto; align-items: center; display: flex; }

body #content .hm-marquee__item {
	font-family: var(--headingfont);
	font-size: clamp(12px, 1.2vw, 12px);
	color: var(--black) !important;
	text-transform: uppercase;
	letter-spacing: 1.8px;
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	padding-left: 26px;
	line-height: 1;
}
/* Separator drawn, not typed — a glyph escape would be eaten by the
   /custom-css PUT handler (§14). */
body #content .hm-marquee__item::after {
	background: rgba(0, 0, 0, 1);
	display: inline-block;
	border-radius: 50%;
	margin-left: 26px;
	content: "";
	height: 4px;
	width: 4px;
}

@keyframes hm-marquee-scroll {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-marquee:hover .hm-marquee__track { animation-play-state: paused; }
}

/* Section 21 blanket-reduces every animation to 0.001ms, which would snap the
   track to its -50% end state and leave the aria-hidden run showing. Kill the
   animation outright instead and lay the phrases out as a static centred row. */
@media (prefers-reduced-motion: reduce) {
	.bakery .hm-marquee__track {
		animation: none !important;
		justify-content: center;
		transform: none !important;
		flex-wrap: wrap;
		width: 100%;
	}
	.bakery .hm-marquee__run[aria-hidden="true"] { display: none !important; }
	.bakery .hm-marquee__run { flex-wrap: wrap; justify-content: center; }
	body #content .hm-marquee__item { padding: 4px 13px; }
	body #content .hm-marquee__item::after { margin-left: 13px; }
}


/* --- 25.6 §16.1 BENTO GRID ------------------------------------------------
   The uniform 4-up card row was the most template-looking element on the page.
   This is the same four services at four different weights: DJ & Emcee is the
   lead service and takes a 2x2 tile, Photo Booth a wide one, Officiant a small
   one, and Bar & Mixology the solid accent1 tile.

   That last one is not a compromise. §12-F means Bar & Mixology has no
   photography in the client library, and a brand panel standing in for a photo
   in a uniform row looked like a missing asset. At bento weights it reads as
   the composition's yellow block, which is what the grid needed anyway.

   Photo-led per §2: the photograph IS the tile. Copy sits over a bottom scrim
   rather than in a white box below the image. */

/* 12 columns, not 4. At 4 columns the two row-2 tiles came out 305px wide and
   their copy block filled 292 of the tile's 304px — the photograph underneath
   was invisible, which defeats the whole point of a photo tile. Measured, then
   re-proportioned: 4/8 on row 1 and 4/4 on row 2 puts the narrowest tile at
   ~410px, where the same copy sets in three lines instead of six. */
.bakery .hm-bento {
	grid-template-columns: repeat(12, minmax(0, 1fr));
	grid-auto-rows: minmax(330px, auto);
	display: grid;
	gap: 20px;
}

.bakery .hm-bento__tile {
	border-radius: 28px;
	background: var(--dark1);
	flex-direction: column;
	justify-content: flex-end;
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: flex;
}
.bakery .hm-bento__tile.is-lg    { grid-column: span 4; grid-row: span 2; }
.bakery .hm-bento__tile.is-wide  { grid-column: span 8; }
.bakery .hm-bento__tile.is-sm    { grid-column: span 4; }
.bakery .hm-bento__tile.is-brand { grid-column: span 4; }

/* Absolute, not static — a box with aspect-ratio or a flex height still takes
   a content-based automatic minimum size, so an in-flow portrait source would
   stretch the tile instead of being cropped by it (§14). */
.bakery .hm-bento__tile img {
	border-radius: 0;
	object-fit: cover;
	position: absolute;
	display: block;
	height: 100%;
	width: 100%;
	z-index: 0;
	inset: 0;
}

/* §16.6 — the house treatment, not a stock photo in a box. A constant warm
   top wash ties the four tiles together; the scrim below carries the copy. */
.bakery .hm-bento__tile::after {
	background:
		linear-gradient(180deg,
			rgba(16, 16, 18, 0) 42%,
			rgba(16, 16, 18, 0.34) 100%),
		linear-gradient(160deg,
			rgba(247, 198, 89, 0.18) 0%,
			rgba(247, 198, 89, 0) 48%);
	position: absolute;
	display: block;
	content: "";
	z-index: 1;
	inset: 0;
}
/* Hover wash. Separate layer so the scrim above it never changes and the
   measured contrast over the copy box holds at every hover state. */
.bakery .hm-bento__tile::before {
	background: linear-gradient(145deg,
		rgba(247, 198, 89, 0.55) 0%,
		rgba(247, 198, 89, 0) 62%);
	position: absolute;
	display: block;
	content: "";
	opacity: 0;
	z-index: 1;
	inset: 0;
}

/* The scrim that carries the copy sits on the BODY, not on the tile, so it is
   exactly as tall as the text is. A fixed-stop gradient on the tile cannot do
   this: the four tiles are four different heights by design, and the copy block
   on the short wide tile filled 257 of its 271px — the text was sitting on the
   transparent part of the tile's gradient and measured 1.4:1. */
.bakery .hm-bento__body {
	background: linear-gradient(180deg,
		rgba(16, 16, 18, 0) 0%,
		rgba(16, 16, 18, 0.66) 22%,
		rgba(16, 16, 18, 0.90) 56%,
		rgba(16, 16, 18, 0.96) 100%);
	padding: 44px 28px 26px;
	position: relative;
	margin-top: auto;
	z-index: 2;
}

body #content .hm-bento__tile h3 {
	font-size: clamp(19px, 1.6vw, 24px) !important;
	color: var(--white) !important;
	margin: 0 0 8px !important;
	letter-spacing: -0.2px;
}
body #content .hm-bento__tile.is-lg h3 {
	font-size: clamp(24px, 2.3vw, 32px) !important;
}
body #content .hm-bento__tile p {
	color: var(--light2) !important;
	margin: 0 0 12px !important;
	line-height: 1.5 !important;
	font-size: 15px !important;
	max-width: 46ch;
}
/* `p.hm-bento__price`, not `.hm-bento__price`. Library 26 also ships
   `body #content .hm-bento__tile p { font-size: 15px !important }` at
   (1,1,2); this rule was (1,1,1), so with both declarations important the
   more specific one won and the price rendered 15px. Naming the element
   makes this (1,1,2) as well, and it is later in the file, so it takes the
   tie. The typeface had the same problem for a different reason — it was
   not important at all, so section 2's bodyfont rule beat it outright and
   the price rendered in Nunito Sans instead of Oswald. Measured in session
   12 by typeaudit.mjs; see the note at the head of section 31. */
body #content p.hm-bento__price {
	font-family: var(--headingfont) !important;
	color: var(--white) !important;
	margin: 0 0 14px !important;
	font-size: 17px !important;
}
/* .hm-card__from is sized by `body #content .hm-card__price .hm-card__from`,
   which does not reach a bento price. Without this it inherits `body span`'s
   17px and the word "From" renders the same size as the number. */
body #content .hm-bento__price .hm-card__from {
	text-transform: uppercase;
	font-size: 12px !important;
	font-family: inherit;
	letter-spacing: 1.5px;
	margin-right: 6px;
	opacity: 0.8;
}
body #content .hm-bento__tile a.hm-card__link { color: var(--white) !important; }
body #content .hm-bento__tile a.hm-card__link:hover { color: var(--accent1) !important; }

/* The accent1 tile. Black on #F7C659 is 12.6:1, so every text rule flips. */
.bakery .hm-bento__tile.is-brand {
	background: linear-gradient(142deg, var(--accent1) 0%, var(--accent1) 58%, #EFB63F 100%);
}
.bakery .hm-bento__tile.is-brand::after,
.bakery .hm-bento__tile.is-brand::before { background: none; }
.bakery .hm-bento__tile.is-brand .hm-bento__body { background: none; padding-top: 28px; }
body #content .hm-bento__tile.is-brand h3 { font-size: clamp(21px, 1.9vw, 27px) !important; }

/* The wide tile is 847px across and its copy only uses the left ~45%, so a
   full-width body scrim was blacking out half a photograph for nothing — and
   §2 asks for light and bright. Scrim the tile diagonally instead and let the
   right-hand side of the frame stay at full brightness. Contrast re-measured
   over the copy box after the change, not assumed. */
@media (min-width: 980px) {
	.bakery .hm-bento__tile.is-wide::after {
		background:
			linear-gradient(82deg,
				rgba(16, 16, 18, 0.93) 0%,
				rgba(16, 16, 18, 0.88) 34%,
				rgba(16, 16, 18, 0.50) 62%,
				rgba(16, 16, 18, 0.10) 86%,
				rgba(16, 16, 18, 0) 100%),
			linear-gradient(160deg,
				rgba(247, 198, 89, 0.18) 0%,
				rgba(247, 198, 89, 0) 48%);
	}
	.bakery .hm-bento__tile.is-wide .hm-bento__body {
		background: none;
		padding-top: 28px;
		max-width: 56%;
	}
}

/* Crops chosen against the subject, not the centre of the file: the DJ tile is
   a 3:4 portrait in a 0.6 frame, and the Sedona ceremony frame is 16:9 in a
   near-square one, so both default-crop straight through the faces. */
.bakery .hm-bento__tile.is-lg img { object-position: center 24%; }
.bakery .hm-bento__tile.is-sm img { object-position: center 34%; }
body #content .hm-bento__tile.is-brand h3,
body #content .hm-bento__tile.is-brand p,
body #content .hm-bento__tile.is-brand .hm-bento__price,
body #content .hm-bento__tile.is-brand a.hm-card__link { color: var(--black) !important; }
body #content .hm-bento__tile.is-brand a.hm-card__link:hover { color: var(--dark2) !important; }

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-bento__tile img { transition: transform 420ms cubic-bezier(0.2, 0.6, 0.3, 1); }
	.bakery .hm-bento__tile::before { transition: opacity var(--hm-ease); }
	.bakery .hm-bento__tile:hover img { transform: scale(1.05); }
	.bakery .hm-bento__tile:hover::before { opacity: 1; }
}

@media (max-width: 979px) and (min-width: 681px) {
	.bakery .hm-bento {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-auto-rows: minmax(300px, auto);
	}
	.bakery .hm-bento__tile.is-lg    { grid-column: span 2; grid-row: span 1; min-height: 340px; }
	.bakery .hm-bento__tile.is-wide  { grid-column: span 2; }
	.bakery .hm-bento__tile.is-sm    { grid-column: span 1; }
	.bakery .hm-bento__tile.is-brand { grid-column: span 1; }
}
@media (max-width: 680px) {
	/* One column means one tile per row, so grid-auto-rows' 330px floor becomes
	   a floor on every tile — including the yellow one, which has no photo to
	   make room for. Let the rows size to their content and put the floors on
	   the tiles that actually need them. */
	.bakery .hm-bento {
		grid-template-columns: minmax(0, 1fr);
		grid-auto-rows: auto;
		gap: 16px;
	}
	.bakery .hm-bento__tile {
		grid-column: span 1 !important;
		grid-row: span 1 !important;
		border-radius: 22px;
		min-height: 400px;
	}
	/* At 340px the copy block was 229 of it, leaving ~100px of photograph —
	   and on these 4:3 sources `cover` scales to HEIGHT in a 351px-wide tile,
	   so the whole frame is already in view and object-position has no Y axis
	   left to move. The only lever is tile height: more of it means the same
	   frame spread over more pixels and a smaller share hidden by the scrim. */
	.bakery .hm-bento__tile.is-lg { min-height: 430px; }
	/* No photograph to show, so no photograph to make room for. */
	.bakery .hm-bento__tile.is-brand { min-height: 0; }
	.bakery .hm-bento__body { padding: 40px 22px 20px; }
}


/* --- 25.7 §16.3 INSET ROUNDED PANEL ---------------------------------------
   The dark video section stops being a full-bleed band and becomes a rounded
   panel inset from the page edges.

   SESSION 8 — Cody: "video showcase row is touching the row above it, and has
   no padding-bottom." Both measured and both real.

   TOP. `margin-top: -40px` was the overlap this section was written for, and
   on Home it lands on the Featured Package price card — an element with its
   own accent border — so the panel cut its bottom edge off. An overlap only
   reads as composition when it crosses a background; across a bordered card it
   reads as a z-index bug. Dropped to 0. The stat card over the hero is still
   the page's overlap moment, and one is enough.

   BOTTOM. The panel's bottom edge measured flush with the Reviews section's
   top edge — 5037.3 on both — so an element inset 32px on its left and right
   had zero gutter on two of its four sides. Nothing was missing from inside
   the panel: the gap has to be margin, because the 88px of padding on the
   neighbouring sections sits inside them, above and below their own content.
   The gutter paints as the white canvas (`body` and `html` are both
   transparent; --light1 is #FFFFFF), so it reads as a continuation of the
   light section above rather than as a seam. */

.bakery div.vc_row.hm-panel,
.bakery section.vc_section.hm-panel {
	width: calc(100% - 64px);
	margin: 0 auto 72px;
	border-radius: 36px;
	position: relative;
	max-width: 1600px;
	overflow: hidden;
	z-index: 2;
}

@media (max-width: 979px) {
	.bakery div.vc_row.hm-panel,
	.bakery section.vc_section.hm-panel {
		width: calc(100% - 24px);
		margin: 0 auto 40px;
		border-radius: 22px;
	}
}


/* --- 25.8 §16.5 STICKY MOBILE BOOKING BAR ---------------------------------
   Phones only. §2's single goal is booked consultations and 70% of traffic is
   on a phone, where both CTAs are otherwise a long scroll apart. Both actions
   already exist on the page — this only keeps them reachable.

   Not rendered at all above 979px. body gets bottom padding so the bar never
   sits on top of the copyright bar at the end of the scroll. */

.bakery div.vc_row.hm-sticky-row { display: none; }

@media (max-width: 979px) {
	.bakery div.vc_row.hm-sticky-row {
		box-shadow: 0 -6px 24px rgba(16, 16, 18, 0.16);
		border-top: 1px solid var(--light3);
		background: var(--light1);
		position: fixed;
		display: block;
		padding: 0;
		margin: 0;
		z-index: 900;
		width: 100%;
		bottom: 0;
		right: 0;
		left: 0;
	}
	.bakery .hm-sticky-row > .container {
		max-width: none;
		padding: 0;
		width: 100%;
	}
	.bakery .hm-sticky-row .vc_column_container { padding: 0 !important; }

	.bakery .hm-sticky {
		padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
		display: flex;
		gap: 10px;
	}
	body #content a.hm-sticky__link {
		font-family: var(--headingfont);
		justify-content: center;
		text-decoration: none !important;
		letter-spacing: 0.4px;
		border-radius: 999px;
		align-items: center;
		padding: 13px 10px;
		text-align: center;
		min-height: 46px;
		font-size: 15px;
		display: flex;
		flex: 1 1 0;
	}
	body #content a.hm-sticky__link.is-solid {
		background: var(--accent1);
		color: var(--black) !important;
	}
	body #content a.hm-sticky__link.is-ghost {
		border: 1px solid rgba(16, 16, 18, 0.28);
		background: var(--light1);
		color: var(--black) !important;
	}

	body { padding-bottom: 74px; }
}


/* --- 25.9 FOOTER LOCKUP ---------------------------------------------------
   §16, asked for by name: footer column 1 leads with the white logo instead of
   the company name set as text. The lockup is the §4 white one that was wrong
   on the white header (§12-M) and is right on the --dark1 footer.

   The footer is NOT inside #content or .bakery (§14) — the component library's
   usual scoping does not reach it, so these carry `body footer#footer` the way
   section 23 does. */

body footer#footer .footer-logo {
	margin: 0 0 20px !important;
	max-width: 180px;
	height: auto;
	display: block;
	width: 100%;
}
@media (max-width: 979px) {
	body footer#footer .footer-logo { max-width: 156px; }
}


/* ===========================================================================
   26. SESSION 9 — Cody's seven items
   ---------------------------------------------------------------------------
   Everything below is additive and sits at the end of the file on purpose:
   each rule here is answering a specific, named complaint, and keeping them
   in one block means the next session can read the whole session-9 pass in
   one place instead of hunting it through sections 16, 23 and 25.

   Cody's own wp-admin edits from 2026-10-07 (tighter --hm-section-y, the 3px
   featured-card border, the accent1 slab behind the split portrait, the video
   glow, the smaller marquee type) were pulled down and adopted as the local
   baseline BEFORE this block was written. Do not revert them.
   =========================================================================== */


/* --- 26.1 FOOTER LINK HOVER — item 1 --------------------------------------
   "The footer link hover color is being heavily overridden."

   Measured, not guessed: hovering a footer menu link left the colour at
   rgb(235,233,226) — light3, the REST colour. Both the hover rules in play
   carry !important, so !important was never the lever. It is specificity:

     rest   body footer#footer .widget a:link:not(.ab-item):not(.btn-bt)
            = (1 id, 4 class, 3 type)
     hover  body footer#footer a:not(.ab-item):not(.btn-bt):hover
            = (1 id, 3 class, 3 type)

   The rest rule carries `.widget` AND `:link`; the hover rule carries
   neither, so the rest rule outranks it ON HOVER and nothing ever changed.
   :link / :visited is the half that matters — a hover selector competing with
   a `:link` selector has to carry `:link` too or it loses. Fixed by matching
   the rest rule's shape and appending :hover.

   This is the same family as the two §14 lessons: on this stack specificity
   beats intent, and an !important that is losing looks exactly like an
   !important that is not there. */

body footer#footer .widget a:link:not(.ab-item):not(.btn-bt):hover,
body footer#footer .widget a:visited:not(.ab-item):not(.btn-bt):hover,
body footer#footer .widget a:link:not(.ab-item):not(.btn-bt):focus-visible,
body footer#footer a:not(.ab-item):not(.btn-bt):hover,
body footer#footer a:not(.ab-item):not(.btn-bt):focus-visible {
	color: var(--accent1) !important;
	text-decoration: none !important;
}
/* The menu links get a small nudge so the hover reads as interactive and not
   only as a colour swap — 15px of type on ink needs the extra signal. */
@media (prefers-reduced-motion: no-preference) {
	body footer#footer .menu li a {
		transition: color 180ms ease, transform 180ms cubic-bezier(0.2, 0.6, 0.3, 1);
		display: inline-block;
	}
	body footer#footer .menu li a:hover { transform: translateX(4px); }
}


/* --- 26.2 FOOTER BUTTON — item 2 ------------------------------------------
   "The footer button sizing and font is a bit off."

   It was. Measured against the same button in #content:

                       footer                      #content
     font-family       Montserrat-Medium           Spartan-Bold
     font-size         15px                        17px
     padding           13px 26px                   14px 28px
     line-height       18px                        28px

   Two different typefaces for the same component. Section 23 wrote the footer
   button from scratch because nothing outside #content styled it, and it was
   written to the body stack rather than to the heading stack every other
   button on the site uses. Matched to #content here. 16px rather than 17px is
   the one deliberate difference: the footer column is 300px at 1440 and
   "Schedule a Consultation" is the longest label on the site. */

body footer#footer a.btn-bt.default {
	font-family: var(--headingfont) !important;
	transition: all 200ms cubic-bezier(0.2, 0.6, 0.3, 1);
	padding: 14px 28px !important;
	letter-spacing: 0.5px !important;
	font-size: 16px !important;
	line-height: 1.3 !important;
}
@media (prefers-reduced-motion: no-preference) {
	body footer#footer a.btn-bt.default:hover { transform: translateY(-2px); }
}


/* --- 26.3 TRUST BAND — items 3 and 7 --------------------------------------
   "The floating stat band needs to pop more, it's pretty boring."

   It was a white card on a white page carrying black numerals — correct and
   invisible. Flipped to ink, which does three things at once: the numerals
   can now be accent1 (the band becomes the page's first yellow moment, which
   the marquee gave up when it moved in session 8), the card reads as an
   object floating over the hero rather than as the top of the next section,
   and the first screen gets a dark-light-dark rhythm instead of a fade.

   accent1 on dark1 is 11.1:1 and light3 on dark1 is 15.4:1, so this is a
   contrast improvement as well as a visual one — black-on-white was already
   fine, but the 0.72 opacity on the label was taking it to the edge.

   Cody zeroed this row's bottom padding in wp-admin via a vc_custom class.
   Honoured here as CSS instead, because the Appendix bans css="" payloads and
   a vc_custom_ class cannot survive a builder re-run. */

.bakery div.vc_row.hm-trust { padding-bottom: 0; }

.bakery .hm-trust__card {
	box-shadow: 0 24px 56px rgba(16, 16, 18, 0.38);
	background: var(--dark1);
	padding: 28px 32px 22px;
	border: 0;
}
body #content .hm-trust__num {
	color: var(--accent1) !important;
	letter-spacing: -1px;
}
body #content .hm-trust__label {
	color: var(--light3) !important;
	opacity: 0.82;
}
/* The yellow tick above each stat was the only colour on the white card and
   it is redundant now that the numeral itself is yellow. Re-cut as a hairline
   rule in the same place so the stats still read as four separate cells. */
body #content .hm-trust__stat::before {
	background: rgba(247, 198, 89, 0.38);
	height: 2px;
	width: 34px;
}

/* --- the soundwave.
   SESSION 10 — every selector in this sub-block was `.bakery .hm-eq` and is
   now unscoped `.hm-eq`. The component left the stat card and became the
   global pre-footer band (section 28.3), which renders outside `.bakery`, so
   the scope would have stopped matching it. Nothing else on the site uses
   this class, so dropping a specificity step costs nothing. The GEOMETRY
   below (height, border-top, margins, padding, the 979/680 breakpoints) was
   cut for a 1176px dark card and is overridden wholesale in 28.3 — what is
   still load-bearing here is the bar material, the five phase groups and the
   reduced-motion fallback.

   This was the "add something exciting" ask answered where it costs least:
   an equalizer along the bottom edge of the stat band. It is on brand
   in a way a generic flourish would not be (the client is a DJ), it is a
   BAND rather than a scroll effect — the same category §16.2 already cleared
   for the marquee — and it is decorative, so it carries aria-hidden and
   disappears entirely under prefers-reduced-motion rather than freezing in a
   half-collapsed state.

   scaleY on a full-height bar, not an animated height: height animates on the
   layout thread and this runs 16 of them continuously. transform-origin is
   the bottom so the bars grow upward out of the baseline.

   Five phase groups via nth-child(5n+k) rather than 16 individual rules —
   the groups are co-prime with the bar count, so the pattern never lines up
   into a visible repeat across the row. */

.hm-eq {
	border-top: 1px solid rgba(247, 198, 89, 0.18);
	gap: clamp(3px, 0.42vw, 6px);
	justify-content: space-between;
	align-items: flex-end;
	padding-top: 16px;
	margin-top: 22px;
	display: flex;
	height: 42px;
}
.hm-eq span {
	background: linear-gradient(180deg, var(--accent1) 0%, var(--accent3) 100%);
	transform: scaleY(0.3);
	transform-origin: bottom;
	border-radius: 3px 3px 0 0;
	display: block;
	flex: 1 1 0;
	height: 100%;
}

@keyframes hm-eq-bounce {
	0%   { transform: scaleY(0.16); }
	100% { transform: scaleY(1); }
}

@media (prefers-reduced-motion: no-preference) {
	.hm-eq span {
		animation: hm-eq-bounce 900ms ease-in-out infinite alternate;
	}
	.hm-eq span:nth-child(5n + 1) { animation-duration: 1180ms; animation-delay: 0ms; }
	.hm-eq span:nth-child(5n + 2) { animation-duration: 760ms;  animation-delay: 190ms; }
	.hm-eq span:nth-child(5n + 3) { animation-duration: 1420ms; animation-delay: 80ms; }
	.hm-eq span:nth-child(5n + 4) { animation-duration: 640ms;  animation-delay: 300ms; }
	.hm-eq span:nth-child(5n + 5) { animation-duration: 1040ms; animation-delay: 130ms; }
}

/* Section 21 reduces every animation to 0.001ms, which would snap all 16 bars
   to scaleY(1) and leave a solid yellow block. Lay them out as a static
   stepped waveform instead — it still reads as a soundwave, it just is not
   moving. Same treatment the marquee gets in 25.5, same reason. */
@media (prefers-reduced-motion: reduce) {
	.hm-eq span { animation: none !important; }
	.hm-eq span:nth-child(5n + 1) { transform: scaleY(0.45); }
	.hm-eq span:nth-child(5n + 2) { transform: scaleY(0.80); }
	.hm-eq span:nth-child(5n + 3) { transform: scaleY(0.30); }
	.hm-eq span:nth-child(5n + 4) { transform: scaleY(1.00); }
	.hm-eq span:nth-child(5n + 5) { transform: scaleY(0.58); }
}

@media (max-width: 979px) {
	.bakery .hm-trust__card { padding: 22px 22px 16px; }
	.hm-eq { height: 32px; margin-top: 16px; padding-top: 12px; }
}
/* 72 bars inside a 318px card is a 1.5px bar — a hairline, not a wave. Drop
   every other one below 680 and the remaining 36 come back to ~5.9px. The
   phase groups are nth-child on the ORIGINAL index, so hiding the even bars
   resamples the wave rather than flattening it. */
@media (max-width: 680px) {
	.hm-eq span:nth-child(even) { display: none; }
}
/* Below 681 the stats stack as four baseline rows against light3 hairlines
   (25.4). Those hairlines were cut for a white card; on ink they vanish. */
@media (max-width: 680px) {
	body #content .hm-trust__stat { border-top-color: rgba(255, 255, 255, 0.14); }
	.hm-eq { height: 26px; }
}


/* --- 26.4 SERVICE AREA — item 4 -------------------------------------------
   "The where we work row needs more color, it's too white and is also boring."

   Two white cards with a 4px coloured edge, on a white section. The only
   colour in the whole band was 8px of it. Rebuilt as two solid blocks that
   carry the hierarchy the copy already implies: the primary zone is where the
   business actually operates, so it takes brand yellow; travel destinations
   are the exception, so they take ink. Reading the two tiers as two different
   materials is the point — it is faster than reading the headings.

   Black on accent1 is 12.6:1 and white on dark1 is 18.9:1. Every text rule
   inside both tiers has to be restated with !important: the section-level
   `body #content p` and `.hm-area__scope` rules both carry it already, and on
   this stack an unqualified text property is a suggestion (§14). */

.bakery .hm-area { gap: 22px; }

.bakery .hm-area__tier {
	border-radius: 22px;
	padding: 34px 32px;
	position: relative;
	overflow: hidden;
	border: 0;
}
/* Primary — brand yellow, with the same 142deg fall the brand bento tile uses
   so the two yellow blocks on the site are the same object. */
.bakery .hm-area__tier.is-primary {
	background: linear-gradient(142deg, var(--accent1) 0%, var(--accent1) 56%, #EFB63F 100%);
	border-left: 0;
}
body #content .hm-area__tier.is-primary h4,
body #content .hm-area__tier.is-primary p { color: var(--black) !important; }
body #content .hm-area__tier.is-primary .hm-area__scope {
	color: rgba(16, 16, 18, 0.78) !important;
}
/* Travel — ink, with the yellow kept as the eyebrow so the pair still reads
   as one component rather than two unrelated boxes. */
.bakery .hm-area__tier.is-travel {
	background: var(--dark1);
	border-left: 0;
}
body #content .hm-area__tier.is-travel h4 { color: var(--white) !important; }
body #content .hm-area__tier.is-travel p { color: var(--light3) !important; }
body #content .hm-area__tier.is-travel .hm-area__scope {
	color: var(--accent1) !important;
}

/* A soft disc bled off the top-right corner of each tile. Costs nothing, and
   it stops two large flat rectangles from reading as placeholder blocks. */
.bakery .hm-area__tier::after {
	border-radius: 50%;
	position: absolute;
	display: block;
	content: "";
	height: 220px;
	width: 220px;
	right: -70px;
	top: -90px;
	z-index: 0;
}
.bakery .hm-area__tier.is-primary::after { background: rgba(255, 255, 255, 0.2); }
.bakery .hm-area__tier.is-travel::after  { background: rgba(247, 198, 89, 0.12); }
.bakery .hm-area__tier > * { position: relative; z-index: 1; }

body #content .hm-area__tier h4 {
	font-size: 22px !important;
	margin: 0 0 8px !important;
}
body #content .hm-area__scope {
	margin: 0 0 16px !important;
	font-size: 12px !important;
	letter-spacing: 1.6px;
}

@media (max-width: 767px) {
	.bakery .hm-area__tier { padding: 26px 24px; border-radius: 18px; }
	.bakery .hm-area__tier::after { height: 150px; width: 150px; right: -50px; top: -60px; }
}


/* --- 26.5 MARQUEE — item 5, then revised in 9b ----------------------------
   TWO decisions are recorded here, in order, because the second one undoes
   most of the first and the reasoning for the first is still what stops it
   being re-litigated a third time.

   SESSION 9, "it still feels like the marquee is not in the right place?"
   Session 8 had already moved it once — off the top of the page, where it
   stacked three full-width bands into the first screen — down to a slot
   between the Core Services bento and the Featured Package row. I kept that
   position and changed the material instead, because what was actually wrong
   was that the bento's bottom-right tile is SOLID ACCENT1 and the marquee was
   a yellow strip 20px below it: two yellow blocks with a hairline between
   them read as a stray rule, not a band. Flipped to ink with accent1 type.

   SESSION 9b, Cody: "change the marquee background back to the yellow, and
   text to black, and make it the last row of the page — it will be replacing
   the yellow border above the footer." That answers the merge problem by
   removing it: at the foot of the page the marquee is nowhere near the yellow
   bento tile, so yellow-on-yellow is no longer a question, and it lands
   directly under the dark bottom-CTA band, which is the contrast the ink
   treatment was buying. So the ground goes back to accent1 and the type back
   to black, and the component is now a PAGE CAP rather than a section divider.

   What that changes structurally:
     - The footer's 4px accent1 top border is REMOVED (section 23, restated
       below). The marquee is that border now; keeping both would stack two
       yellow rules with a 1px gap, which is the exact defect this rule spent
       session 9 fixing one section further up.
     - The top/bottom hairlines go. A divider needs edges because it sits
       between two similar grounds; a cap sits between a dark photographic
       band and the ink footer and has all the edge it needs.
     - The band keeps the session-9 height and type size. As a divider, 12px
       in a 42px band was a caption; as the last thing on the page, before a
       footer, it should be read.

   The slot it vacated is a --light2 to --light1 seam with nothing dividing it.
   That is a real consequence of this move and it is called out in the handoff,
   not papered over here. */

.bakery div.vc_row.hm-marquee-row.accent1 {
	background: var(--accent1);
	border-bottom: 0;
	border-top: 0;
	padding: 0;
	margin: 0;
}
.bakery .hm-marquee { padding: 20px 0; }
body #content .hm-marquee__item {
	font-size: clamp(13px, 1.3vw, 15px) !important;
	color: var(--black) !important;
	letter-spacing: 2.2px;
	padding-left: 30px;
}
body #content .hm-marquee__item::after {
	background: rgba(16, 16, 18, 0.45);
	margin-left: 30px;
	height: 5px;
	width: 5px;
}

/* Section 23 gives the footer `border-top: 4px solid var(--accent1)`. The
   marquee is that border now. */
body footer#footer.site-footer { border-top: 0; }

@media (max-width: 680px) {
	.bakery .hm-marquee { padding: 15px 0; }
	body #content .hm-marquee__item { letter-spacing: 1.6px; padding-left: 20px; }
	body #content .hm-marquee__item::after { margin-left: 20px; }
}


/* --- 26.6 STICKY HEADER — item 6 ------------------------------------------
   "Unless stated otherwise in the direction, make the header sticky.
   header.scrolling is an existing class."

   Checked the direction first: §2, §3.4 and §16 say nothing about the header,
   so there is no instruction to override. The class is real — js/my-script.js
   adds `.scrolling` to `.site-header` past 50px of scroll and removes it
   below. It was being added already; nothing was listening to it.

   position:sticky rather than fixed. The header is a direct child of body
   with no overflow or transform on any ancestor (checked, both), so sticky
   works, and unlike fixed it keeps the header in flow — no 136px of
   compensating padding on body and no layout shift at the top of the page.

   The scrolled state drops the 40px dark utility bar (phone + socials) and
   leaves the 96px white nav, so the sticky bar costs 96px of viewport rather
   than 136px. On a 844px phone that is the difference between giving up 16%
   of the screen and 11%. The utility bar's content is duplicated in the
   footer, so nothing becomes unreachable.

   z-index 800 sits above the hero's stacking context (3) and the inset panel
   (2) and below the mobile booking bar (900), which should stay on top of
   everything including a header that has scrolled down over it.

   WHY `body header#header.site-header` AND NOT `header.site-header`:
   the child theme's own style.css line 258 carries

     header.site-header { background-color: transparent; ...; z-index: 1; }

   and style.css is enqueued AFTER css/custom.css. Identical specificity,
   later source, so it wins. The first cut of this rule used the bare
   `header.site-header` and MEASURED as position:sticky with z-index 1 and a
   transparent ground — sticky applied because style.css does not set it,
   while the two properties it does set were silently lost. A transparent
   sticky header is the worst of both: it pins, and the page scrolls through
   it. style.css is the one sheet in this stack that outranks custom.css by
   source order — anything the component library sets on the header, the
   footer shell or .top-header has to clear it on specificity, not on
   position in the file. This is the same family as the §14 lesson about
   text properties, one level up: here even !important would not have been
   the lever, because the loser was equal-specificity-earlier, not weaker. */

body header#header.site-header {
	background: var(--white);
	position: sticky;
	z-index: 800;
	top: 0;
}
/* Logged-in admins get the 32px admin bar; it is fixed, so sticky top:0 would
   put the nav underneath it. Not a visitor-facing case, but it makes the
   header unusable for the client in wp-admin preview if it is left out. */
body.admin-bar header#header.site-header { top: 32px; }
@media (max-width: 782px) {
	body.admin-bar header#header.site-header { top: 46px; }
}

header.site-header .top-widget {
	transition: max-height 260ms cubic-bezier(0.2, 0.6, 0.3, 1),
	            opacity 180ms ease;
	overflow: hidden;
	max-height: 60px;
}
body header#header.site-header.scrolling {
	box-shadow: 0 8px 28px rgba(16, 16, 18, 0.16);
}
body header#header.site-header.scrolling .top-widget {
	max-height: 0;
	opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
	header.site-header .top-widget { transition: none; }
}


/* --- 26.7 "MAKE IT EXCITING" — item 7 -------------------------------------
   "I have received feedback that the homepage is not exciting at all. To their
   point, it's called hype man entertainment."

   The constraint that makes this hard is §2 and §3.4, which are client
   direction and not preference: light and bright, and NO heavy scroll
   animation — arizonasdj.com was rejected for exactly that. So the answer
   cannot be AOS, scroll-reveal, parallax or anything that fires as the reader
   moves. §16 settled where the energy is allowed to come from: composition,
   scale, rhythm and typography, plus self-contained BANDS of motion that run
   on their own clock regardless of scroll position. The marquee was cleared
   on that basis and the equalizer in 26.3 is the same category.

   What is here:
     1. The equalizer. See 26.3 — the single most on-brand element on the page.
     2. A one-time entrance on the hero. Fires on load, ~800ms, done before the
        reader has finished reading the headline. This is a page-load
        transition, not a scroll effect: scrolling back up does not replay it,
        nothing below the fold is tied to a viewport trigger.
     3. The highlighter mark draws itself in. The mark is the page's signature
        gesture and it was arriving fully formed; a 700ms sweep makes it read
        as a deliberate mark rather than as a yellow background.
     4. Real weight under the bento tiles on hover.

   All four are inside prefers-reduced-motion: no-preference. The page with
   motion reduced is the page as it was, plus the colour work above.

   NOTE for whoever reads this next: item 3 animates background-size on
   .hm-mark for EVERY mark on the page, unscoped. That is deliberate. The
   §16.0a standing exception forbids re-introducing a surface-keyed .hm-mark
   rule, and scoping this to .hm-hero would be exactly that shape even though
   it only touches the reveal. The two below-fold marks finish their sweep
   unseen, which costs nothing. */

@keyframes hm-rise {
	from { opacity: 0; transform: translateY(20px); }
	to   { opacity: 1; transform: none; }
}
@keyframes hm-mark-sweep {
	from { background-size: 0% 0.44em; }
	to   { background-size: 100% 0.44em; }
}

@media (prefers-reduced-motion: no-preference) {
	.bakery .hm-hero .hm-hero__inner {
		animation: hm-rise 640ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
	}
	/* The button row is the second .hm-hero__inner in the column. */
	.bakery .hm-hero .hm-hero__inner.hm-btn-row {
		animation-delay: 220ms;
	}
	/* Starts after the headline has arrived, finishes before the eye reaches
	   the buttons. 100% is restated so the end state is byte-identical to the
	   resting rule in 25.2 and the mark cannot settle a pixel off it. */
	body #content .hm-mark {
		animation: hm-mark-sweep 700ms cubic-bezier(0.3, 0.7, 0.3, 1) 560ms both;
	}

	/* The bento already scales its photo and lifts its wash on hover (25.6).
	   What it had no weight: the tile never left the page. */
	.bakery .hm-bento__tile {
		transition: transform 260ms cubic-bezier(0.2, 0.6, 0.3, 1),
		            box-shadow 260ms cubic-bezier(0.2, 0.6, 0.3, 1);
	}
	.bakery .hm-bento__tile:hover {
		box-shadow: 0 20px 44px rgba(16, 16, 18, 0.3);
		transform: translateY(-7px);
	}

	/* Same lift on the two button styles, so a CTA answers the pointer the way
	   the tiles do. 2px — enough to feel, not enough to jump. */
	body #content a.btn-bt.default,
	body #content a.btn-bt.alternate {
		transition: all 200ms cubic-bezier(0.2, 0.6, 0.3, 1);
	}
	body #content a.btn-bt.default:hover,
	body #content a.btn-bt.alternate:hover { transform: translateY(-2px); }
}

/* Touch devices resolve :hover in a sticky way after a tap — a tile that
   lifts and stays lifted reads as broken. Gate the transform on a real
   pointer; the colour and scale work in 25.6 is harmless either way. */
@media (hover: none) {
	.bakery .hm-bento__tile:hover { transform: none; box-shadow: none; }
	body #content a.btn-bt.default:hover,
	body #content a.btn-bt.alternate:hover { transform: none; }
}


/* ===========================================================================
   27. SESSION 9b — TYPEFACE SWAP: Oswald + Nunito Sans
   ---------------------------------------------------------------------------
   Cody: "Swap the headings font out for Oswald, and for the body font, find
   the closest google font match to Avenir."

   BODY — why Nunito Sans. Avenir is Frutiger's geometric skeleton on humanist
   proportions: low stroke contrast, large but not extreme x-height, open
   apertures, slightly narrow. Nunito Sans is the closest thing Google Fonts
   has to that description. Runner-up was Mulish, which is also very close;
   Montserrat is the usual reflex and is wrong here (it is signage-geometric,
   noticeably wider, and it is the face we are replacing); Jost is a Futura
   clone, which is a different kind of geometric.

   SELF-HOSTED, NOT A GOOGLE CDN LINK, for three reasons. The component
   library is appended to the END of custom.css, so an `@import` would be
   ignored outright — an @import has to come first in a sheet. A head LINK tag
   means editing the theme's header.php or putting an injection on
   all 18 pages. And the theme already self-hosts every other face it uses, so
   this matches the pattern. Files pushed by FTP, verified 200 with a
   font/woff2 content type:
     fonts/oswald/oswald-variable.woff2                 21 KB
     fonts/nunitosans/nunito-sans-variable.woff2        31 KB
     fonts/nunitosans/nunito-sans-italic-variable.woff2 15 KB
   All three are VARIABLE fonts — Google serves one file per family per
   subset and slices it with font-weight. Asking css2 for four Oswald weights
   returns four @font-face blocks pointing at one identical file (checksummed:
   same md5), so the four separate downloads were deduped to one. Latin subset
   only; the other 16 subsets Google emits are Cyrillic/Vietnamese/latin-ext
   and this site does not set a word of any of them.

   OSWALD IS PINNED TO ONE WEIGHT, exactly as Spartan-Bold was. The descriptor
   below declares `font-weight: 600` as a single value, not a range, so the
   variable axis clamps to 600 for every requested weight. That matters here:
   ~19 library rules call the heading font on small uppercase labels (eyebrows,
   prices, stat numerals, marquee items) and NONE of them sets a font-weight,
   because the old face was a single bold cut and did not need one. Declaring
   Oswald as a 200-700 range instead would have inherited body's 400 into every
   one of those and shipped a page of Oswald Light labels. Verified as rendered
   weight after the push, not assumed. */

@font-face {
	font-family: 'Oswald';
	src: url("/wp-content/themes/vds/fonts/oswald/oswald-variable.woff2") format("woff2");
	font-weight: 600;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'Nunito Sans';
	src: url("/wp-content/themes/vds/fonts/nunitosans/nunito-sans-variable.woff2") format("woff2");
	font-weight: 300 800;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'Nunito Sans';
	src: url("/wp-content/themes/vds/fonts/nunitosans/nunito-sans-italic-variable.woff2") format("woff2");
	font-weight: 300 800;
	font-style: italic;
	font-display: swap;
}

/* Every `font-family` in sections 1-26 now resolves through one of these two.
   The 19 `var(--headingfont, 'Spartan-Bold', sans-serif)` fallback lists were
   collapsed to `var(--headingfont)` in the same pass — the fallback could
   never fire once the variable is defined, and a dead face name sitting in 19
   rules is exactly the kind of thing that gets copied forward. */
:root {
	--headingfont: 'Oswald', 'Helvetica Neue Condensed', sans-serif;
	--bodyfont: 'Nunito Sans', 'Avenir Next', Avenir, sans-serif;
}

/* --- the three rules the options compiler hardcodes ------------------------
   option-page-styles.css names the faces as literal strings, and the ACF
   select it compiles from does not offer Oswald or Nunito Sans (§4), so the
   option cannot be changed in wp-admin — it has to be overridden here. All
   three are restated with the same selector lists the compiler uses, so
   nothing is missed and nothing extra is caught. */

body h1, body h2, body h3, body h4, body h5, body h6 {
	font-family: var(--headingfont) !important;
	font-weight: 600 !important;
}

/* `a.btn-bt` is in the compiler's BODY list but the design has always had
   buttons on the heading face — so it comes out of the body rule here and
   gets its own. Without that, an !important body rule would quietly beat
   section 1's non-important button rule. */
/* `body` itself keeps !important: twentytwentyfive's global-styles block sets
   `body { font-family: Literata }` from an INLINE style element in the head,
   which is later in the document than custom.css and wins at equal
   specificity otherwise. §14 flags the same trap for `font-family: inherit`
   on form fields. */
body { font-family: var(--bodyfont) !important; }

/* THE REST DELIBERATELY DO NOT. The first cut of this rule carried
   !important on the whole list and it MEASURED as a regression: the eyebrows,
   bento prices, stat numerals and marquee items came back on Nunito Sans when
   they should be on Oswald. Those live in rules like
   `body #content .hm-marquee__item { font-family: var(--headingfont) }`,
   which is (0,2,2) against this list's `body span` at (0,0,2) — the library
   has always relied on winning that on specificity, because the compiler's
   version of this rule has no !important either. Adding one inverted the
   order for every heading-font rule in sections 1-26 at once. Without it the
   cascade is unchanged and this still beats the compiler, which is all it has
   to do: same selectors, same specificity, custom.css loads later. */
body p,
body li,
body span,
form label,
.gform_footer input[type="submit"],
button,
span.vc_tta-title-text {
	font-family: var(--bodyfont);
}

body a.btn-bt,
body #content a.btn-bt,
body .gform_wrapper .gform_footer input[type="submit"],
body .gform_wrapper .gform_footer button.gform_button,
body .gform_wrapper .gform-footer button.gform_button {
	font-family: var(--headingfont) !important;
	font-weight: 600 !important;
}

/* Nav. Not strictly a heading and not body copy, and the compiler gives it a
   third face (Montserrat-Bold) — which would have left the site on three
   families. Put on the heading face: Oswald is a condensed grotesque and a
   nav is exactly what it was drawn for. One line to reverse if Cody would
   rather it tracked the body font. */
ul#left-menu li a,
ul#right-menu li a,
nav ul#top-menu li a,
nav div#top-menu ul li a,
body .mobile-menu li a {
	font-family: var(--headingfont) !important;
	font-weight: 600 !important;
}


/* --- 27.1 METRIC RETUNE FOR OSWALD ----------------------------------------
   A typeface swap is not a drop-in. Measured off canvas TextMetrics at 100px,
   weight 600, the two faces are not the same size at the same size:

                      cap height   ascent   descent   content box
     Spartan-Bold       0.676em     0.90     0.25       1.15em
     Oswald             0.810em     1.19     0.29       1.48em
     Nunito Sans        0.705em     1.01     0.35       1.36em

   **Oswald's caps are 20% taller than Spartan-Bold's at an identical
   font-size.** Left alone, the swap silently re-inflates every heading on the
   page by a fifth — and in session 8 Cody's explicit correction was that the
   h2 was TOO BIG, which is why it came down from 56px to 42px. A 42px Oswald
   h2 has the same cap height as a 50px Spartan one, so doing nothing here
   would have quietly reversed a standing instruction.

   So the display sizes are normalised on cap height. Not at the full 0.834
   ratio the cap heights alone imply — Oswald is also condensed, so it eats
   less width and can carry a little more height before it dominates. 0.87
   lands the optical size back where Cody signed off:

     hero h1   54 -> 47     section h2  42 -> 37
     bento h3  32 -> 28     feature h4  20 -> 18     stat numeral 38 -> 34

   Small uppercase labels (marquee 15px, bento price 15px, footer title 14px)
   are LEFT ALONE: at that size the cap difference is one or two pixels, and
   uppercase set in a condensed face benefits from the extra height.

   **If Cody wants the headings bigger, this block is the one to edit** — one
   ratio, six values, and nothing else on the page depends on them.

   TRACKING goes to zero. Every negative value in sections 16-25 was dialled
   in against Spartan-Bold, a wide geometric face that needed pulling in.
   Oswald is a condensed grotesque whose sidebearings are already tight;
   -1.1px on a 54px Oswald headline closes the counters.

   LEADING on the hero h1 and bottom-CTA h2 finally moves. `line-height: 1.32`
   was derived in session 7 to clear a below-baseline mark band that session 8
   deleted, and it has been carried as a known-unjustified leftover ever since
   (handoff open item 9). It now has two reasons to go: the mark is off both
   of those headings entirely as of this session, and the face changed under
   it. At 1.12 the gap between one line's descender and the next line's caps
   is 0.12em, which is right for condensed display type.

   The mark band itself needs NO change, which was checked rather than
   assumed. `background-position: 0 78%` with `background-size: 100% 0.44em`
   resolves against the content box, so it moves with the face: on Spartan it
   started 48% down the cap and ended 0.094em below the baseline; on Oswald it
   starts 53% down and ends 0.058em below. Same highlighter, same read. */

body #content .hm-hero h1 {
	font-size: clamp(27px, 3.8vw, 47px) !important;
	letter-spacing: 0 !important;
	line-height: 1.12 !important;
	/* The measure is in `ch`, and `ch` is the advance of "0" — which is 23%
	   narrower in condensed Oswald than in Spartan-Bold. So the SAME 24ch
	   rule that held a 713px measure now holds 612px, and the headline went
	   from two lines to three without a single value changing. Swept the
	   wrap point at 1440: it drops back to two lines at 640px and stays
	   there. 28ch measures 714px, which restores both the two-line set and
	   the ~713px measure session 8 settled on. A `ch` measure does not
	   survive a typeface change — check it, or set it in px. */
	max-width: 28ch;
}
body #content .bottom-cta h2 {
	letter-spacing: 0 !important;
	line-height: 1.12 !important;
}
body #content h2 {
	font-size: clamp(23px, 2.9vw, 37px) !important;
	letter-spacing: 0 !important;
}
body #content .hm-section > .container > .vc_column_container h2 {
	letter-spacing: 0 !important;
}
body #content h3 { font-size: clamp(19px, 2.6vw, 28px) !important; letter-spacing: 0 !important; }
body #content .hm-bento__tile h3 { font-size: clamp(17px, 1.4vw, 21px) !important; }
body #content .hm-bento__tile.is-lg h3 { font-size: clamp(19px, 1.6vw, 25px) !important; }
body #content .hm-bento__tile.is-brand h3 { font-size: clamp(18px, 1.65vw, 23px) !important; }
body #content h4, body #content .hm-feature h4, body #content .hm-area__tier h4 {
	letter-spacing: 0 !important;
}
body #content .hm-area__tier h4 { font-size: 19px !important; }
body #content .hm-trust__num {
	font-size: clamp(25px, 2.3vw, 34px) !important;
	letter-spacing: 0 !important;
}
body #content .hm-price__amount { letter-spacing: 0; font-size: 38px !important; }

@media (max-width: 680px) {
	body #content .hm-trust__num { font-size: 25px !important; }
}
@media (max-width: 480px) {
	body #content .hm-hero h1 { letter-spacing: 0 !important; }
}


/* ===========================================================================
   28. SESSION 10 — Cody's homepage restructure
   ---------------------------------------------------------------------------
   "make the marquee directly after the hero. I love the equalizer, but lets
   make it the row atop the footer instead. since the marquee will now be
   after the hero, the overlapping stat bar will not work. remove the overlap,
   and make them four bold, punchy, card columns. so it will be hero >
   marquee > bold punchy stat cards. then the eq row will be fullwidth right
   above the footer. Make that global for the footer."
   Plus: "make the h2 more like 48px" and a bottom-CTA padding value.

   TWO RULE BLOCKS ABOVE ARE NOW INERT — not deleted, because they are the
   record of how the component got here, but they match nothing:

     - `.bakery .hm-trust__card` (sections 25.4 and 26.3). The single-card
       wrapper is gone from build_home.py; four cards means four elements and
       `.hm-trust__stat` IS the card now.
     - the 680px stacked-row treatment of `.hm-trust__stat` in 25.4 is
       overridden here rather than inert — read 28.2 before re-reading it.

   Everything else in 25.4 / 26.3 that touches `__num`, `__label` or `__stat`
   is still live and is overridden below by position, not by !important —
   section 28 is the end of the file and the selectors match in specificity.
   =========================================================================== */


/* --- 28.1 MARQUEE, THIRD AND FINAL SLOT -----------------------------------
   Straight after the hero. This is the position session 8 moved it OUT of,
   so the objection recorded in 25.5 has to be answered rather than ignored:
   the complaint then was that the first screen and a half carried three
   full-width bands (hero video, white stat card, yellow strip) and spent the
   page's second yellow moment before the reader had met a service.

   Both halves of that are gone. The stat row stops being a full-bleed band in
   28.2 — it is four cards inside an ordinary section now — so the sequence is
   one band (the hero), one rule (the marquee), then content. And the marquee
   is the page's FIRST yellow moment rather than its second, because the stat
   band gave its accent1 numerals up along with its ink ground.

   The material needs no change: 26.5's accent1 ground with black type works
   harder here than it did as the page cap, landing directly under the dark
   hero instead of under the already-dark bottom CTA.

   The footer's `border-top: 0` from 26.5 STAYS. The marquee is no longer the
   thing capping the page, but the equalizer band in 28.3 is, and two yellow
   rules with a gap between them is the exact defect 26.5 was fixing. */

/* The hero's last text block carries the button row; the marquee butts it
   with no air. `mb0` is already on that block, so this is belt-and-braces
   against a theme bottom-margin reappearing on the row itself. */
.bakery div.vc_row.hm-hero { margin-bottom: 0; }
.bakery div.vc_row.hm-marquee-row.accent1 { margin-top: 0; }

/* TRACKING TO ZERO — Cody. 26.5 set 2.2px (1.6px below 680) and that value
   predates the typeface swap: it was dialled in against Spartan-Bold, a wide
   geometric face whose uppercase needed opening up. Oswald is a condensed
   grotesque drawn with tight sidebearings, and 27.1 already zeroed every
   negative tracking value on the display sizes for the same reason — the
   marquee is the one small-uppercase label that was left carrying a positive
   one. The mobile step goes with it; he gave the base rule, and leaving 1.6px
   at 390 would have shown two different treatments of the same band. */
body #content .hm-marquee__item { letter-spacing: 0; }

@media (max-width: 680px) {
	body #content .hm-marquee__item { letter-spacing: 0; }
}

/* FOUR RUNS, -25%. 25.5 built the band as two identical runs travelling -50%,
   which is seamless ONLY while one run is at least as wide as the viewport —
   at the end of the cycle the window has advanced by a full run, so the track
   has to extend a viewport beyond that or the right edge runs empty. At 1440
   the run measures 1151px, and the band was ending every cycle with ~280px of
   blank yellow. Found by seeking the animation with the Web Animations API
   and then LOOKING at the frame, which is the only reason it was caught: the
   defect is invisible for the first three quarters of a 38-second loop and
   does not exist at all at 390 or 768, where the run already exceeds the
   viewport.

   PRE-EXISTING, and worsened rather than caused by this session: at the old
   2.2px item tracking each run was ~1358px, so the gap peaked near 82px.
   Zeroing the tracking took 207px out of the run and the gap to ~280px.

   Four runs travelling -25% cover the same 1151px per cycle, so the speed and
   the 38s duration are untouched — only the margin grows. Seamless to a
   3453px viewport, against 2302px for a three-run version. A new keyframe
   rather than a redefinition of `hm-marquee-scroll`, so the 25.5 rule stays
   readable as what it was. build_home.py emits the four runs; the two must
   change together. */
@keyframes hm-marquee-scroll-4 {
	from { transform: translateX(0); }
	to   { transform: translateX(-25%); }
}
.bakery .hm-marquee__track { animation-name: hm-marquee-scroll-4; }


/* --- 28.2 STAT ROW: FOUR CARDS, NO OVERLAP --------------------------------
   The overlap is not a style that can be toned down — it is `margin-top:-69px`
   plus `z-index: 3` pulling the row up over the hero's bottom edge (25.4), and
   with the marquee now occupying that edge there is nothing left to overlap.
   It comes off completely: no negative margin, no stacking context, normal
   section padding.

   What replaces it is four cards rather than one. Keeping the ink ground that
   Cody asked for in session 9 ("the floating stat band needs to pop more")
   but splitting it four ways is what makes this punchy rather than just large:
   four solid ink blocks on a light section read as objects, and the accent1
   numerals get four separate frames instead of sharing one.

   Contrast is unchanged from 26.3 and still measured there — accent1 on dark1
   is 11.1:1, light3 on dark1 is 15.4:1. The ground did not move, only the
   number of boxes it is cut into.

   SCALE. The numerals go UP, 34px to 46px. In the single card they were
   sharing a 1176px band with three siblings and 38px already competed with
   the section headings (the session-8 complaint). In a 282px card the numeral
   IS the card, there is no heading within 300px of it, and 34px read timid.
   Checked against the h2 at its new 48px (28.4): the numeral sits just under
   it, which is the right order — a stat should not outrank a section heading. */

/* Cody: "padding for the trust row should be 60px 0 0 0." Top only — the
   section that follows (`hm-section light1`) brings its own 60px of top
   padding, so a bottom value here was doubling the gap under the cards. */
.bakery div.vc_row.hm-trust {
	padding: var(--hm-section-y) 0 0 0;
	background: transparent;
	position: static;
	margin-top: 0;
	z-index: auto;
}

.bakery .hm-trust .hm-trust__grid {
	grid-template-columns: repeat(4, minmax(0, 1fr));
	align-items: stretch;
	display: grid;
	gap: 18px;
}

/* `.hm-trust__stat` is the card. The yellow tick from 25.4 becomes a full
   top edge on each card — at 3px x 26px it was a detail on a shared ground;
   across the head of its own card it is what makes the four read as a set. */
/* SESSION 10, SECOND PASS — Cody: "it also doesnt really feel punchy enough
   to me, idk."

   He is right, and the first cut was timid in a specific way: it was the
   session-9 band cut into four pieces. Same 46px numeral, same proportions,
   just more borders. Four small neat boxes are not punchier than one band,
   they are busier than one band.

   What actually makes a stat card hit is SCALE AND ARCHITECTURE, so both
   move:

     - The numeral goes 46px to 72px and the leading to 0.88. At 72px Oswald
       in a 307px card the numeral IS the card; "100+" sets in ~130px of a
       255px content box, so there is still air around the widest value.
     - The card gets a floor (min-height) and `justify-content: space-between`,
       which pins the numeral to the top and the label to the bottom edge
       instead of letting both float in the middle. That gap is what reads as
       deliberate rather than as text in a box.
     - The top edge goes 4px to 5px and the label loses its opacity — light3
       at 0.8 on ink was a grey smudge at 13px.

   NOT DONE, and recorded because it is the obvious next idea: flipping one
   card to solid accent1 as a focal point. The marquee band is a full-width
   yellow rule 60px above this row, and 26.5 spent a session removing exactly
   that defect one section further up the page — a yellow block near a yellow
   band reads as a stray rule, not as emphasis. If Cody wants a focal card the
   cheap version is swapping the 5.0 card's NUMERAL to white, not its ground.

   This does mean the numeral now outranks the h2 (72 against 48), reversing
   what the first cut of this section said. Display numerals are a different
   register from running headings and a stat row is allowed to shout; the
   session-8 complaint was about a 38px numeral next to a 42px h2, which is
   two things competing at the same size, not one deliberately louder. */
body #content .hm-trust__stat {
	background: var(--dark1);
	border-radius: var(--hm-radius);
	padding: 30px 26px 28px;
	box-shadow: 0 14px 34px rgba(16, 16, 18, 0.16);
	transition: transform var(--hm-ease), box-shadow var(--hm-ease);
	justify-content: space-between;
	flex-direction: column;
	text-align: left;
	position: relative;
	min-height: 196px;
	overflow: hidden;
	display: flex;
	border-top: 0;
	gap: 0;
}
/* THIRD PASS — Cody moved the yellow rule off the top of the card and put it
   above the LABEL instead (as a border-top on the label, below). So this is
   zeroed rather than deleted: `width: auto` and the full left/right span stay
   correct, and bringing the top edge back is a one-value change.

   `width: auto` is doing real work and is why this is worth keeping. 25.4 set
   `width: 26px` and 26.3 reset it to 34px, and neither is overridden by
   setting `left`/`right` — an absolute box with left, right AND an explicit
   width ignores `right`. Left alone it rendered as a 34px stub clipped into
   the card's 16px corner radius, reading as a yellow tab floating off the
   card. Caught in the capture, not in the numbers: every value in the block
   measured exactly as authored. */
body #content .hm-trust__stat::before {
	background: var(--accent1);
	border-radius: 0;
	position: absolute;
	display: block;
	content: "";
	height: 0;
	width: auto;
	right: 0;
	left: 0;
	top: 0;
}
@media (prefers-reduced-motion: no-preference) {
	body #content .hm-trust__stat:hover {
		box-shadow: 0 20px 44px rgba(16, 16, 18, 0.24);
		transform: translateY(-3px);
	}
}

body #content .hm-trust__num {
	font-size: clamp(46px, 5vw, 72px) !important;
	color: var(--accent1) !important;
	letter-spacing: -0.5px !important;
	line-height: 0.88 !important;
	display: block;
}
/* The label is the card's base now: a full-width accent1 hairline with the
   text hanging under it. `space-between` on the card pins the whole lockup to
   the bottom edge, so the 32px margin is a floor rather than the actual gap.
   700 on Nunito Sans at 13px uppercase is what makes it hold its own against
   a 72px numeral — at 400 the rule read as the louder of the two. */
.hm-trust__stat p { margin: 0 !important; }

body #content .hm-trust__label {
	border-top: 1px solid var(--accent1);
	color: var(--light3) !important;
	line-height: 1.35 !important;
	margin: 32px 0 0 !important;
	font-size: 13px !important;
	letter-spacing: 1px;
	padding-top: 16px;
	max-width: none;
	opacity: 1;
}
body #content p.hm-trust__label { font-weight: 700 !important; }

/* 25.4 broke to 2-up at 1199 because the LABELS needed 227px of cell and only
   got 194px at 1024. The cards carry 52px of horizontal padding, so the same
   label now needs its cell to be 279px — which a quarter of a 1024 viewport
   (236px before padding) cannot give. The break stays at 1199 for the same
   measured reason, one card wider. */
@media (max-width: 1199px) {
	.bakery .hm-trust .hm-trust__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
}

@media (max-width: 979px) {
	.bakery div.vc_row.hm-trust {
		padding: var(--hm-section-y-mobile) 0 0 0;
		margin-top: 0;
	}
	body #content .hm-trust__stat { padding: 26px 22px 24px; min-height: 168px; }
}

/* 25.4 collapses the stats to four baseline-aligned flex ROWS below 680 with
   hairline rules between them — that was the right answer for one card on a
   phone and it is the wrong answer for four. Overridden back to real cards,
   2-up. Two 169px cards at 390 leave 117px of label after padding, which does
   wrap "OWNERS ON SITE, EVERY EVENT" to two lines; that is fine in a card and
   was never fine in a band, which is what the one-line rule was protecting. */
@media (max-width: 680px) {
	.bakery .hm-trust .hm-trust__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 12px;
	}
	body #content .hm-trust__stat {
		justify-content: space-between;
		border-top: 0 !important;
		flex-direction: column;
		align-items: stretch;
		padding: 22px 16px 20px;
		min-height: 158px;
		display: flex;
		gap: 0;
	}
	/* 25.4's `:first-child`/`:last-child` padding resets are (0,3,1) against
	   this block's (0,2,1) and WON — measured, card 1 came back with
	   padding-top 0 and card 4 with padding-bottom 0. They existed to close
	   the ends of a stacked hairline list that no longer exists. */
	body #content .hm-trust__stat:first-child,
	body #content .hm-trust__stat:last-child { padding: 22px 16px 20px; }
	body #content .hm-trust__stat::before { display: block; }
	body #content .hm-trust__num {
		font-size: 46px !important;
		min-width: 0;
		flex: 0 0 auto;
	}
	/* Cody's 32px/16px lockup is a desktop value. Scaled, not inherited: a
	   16px gap under the hairline in a 158px card leaves the label sitting
	   almost on the card's floor.

	   `min-height` is two lines of 12px at 1.35, and it is not cosmetic. At
	   390 the grid is 2-up and two of the four labels wrap ("STAR RATING, 46+
	   REVIEWS" and "OWNERS ON SITE, EVERY EVENT"); `space-between` pins the
	   label block to the card's floor, so a taller label starts higher and its
	   accent1 hairline sits above its neighbour's. Measured in the capture,
	   not the numbers — the rules were visibly ragged across each row. Giving
	   every label the two-line height aligns all four.

	   The value is a BORDER-box height, which is why it is 46 and not 33: the
	   theme sets `box-sizing: border-box` globally, so min-height has to carry
	   the 12px padding and the 1px rule as well as the 32.4px of text. At 33
	   the one-line cards came out 12px short and the hairlines were still
	   ragged — measured, after the first attempt. */
	body #content .hm-trust__label {
		margin: 20px 0 0 !important;
		font-size: 12px !important;
		letter-spacing: 0.8px;
		padding-top: 12px;
		min-height: 46px;
	}
}


/* --- 28.3 EQUALIZER AS A GLOBAL PRE-FOOTER BAND ---------------------------
   "I love the equalizer, but lets make it the row atop the footer instead...
   fullwidth right above the footer. Make that global for the footer."

   GLOBAL is the part that decides the implementation. The markup is emitted
   by the Site Conductor plugin on the `get_footer` action (v2.1.0 — NEW PHP,
   written this session), which puts it at the end of #content immediately
   immediately above the footer element on all 18 pages with nothing in any page payload. A footer-N
   widget was the no-PHP alternative and was rejected: the widget areas are
   25% columns, so full-bleed would mean absolutely positioning the band out
   of its own grid and reserving its height with footer padding — two coupled
   magic numbers that come apart at every breakpoint.

   The bar material, the five nth-child(5n+k) phase groups and the
   reduced-motion stepped waveform all come from 26.3 unchanged; those
   selectors were re-scoped from `.bakery .hm-eq` to `.hm-eq` this session
   precisely so they would still reach this band, which renders outside
   `.bakery`. Everything 26.3 says about geometry was cut for a 1176px card
   and is replaced here.

   BAR COUNT IS 103, NOT 72. This is the session-9 bar-chart lesson applied to
   a wider element: 72 bars at a 6px gap inside a 1176px card gave a ~10px
   bar, but the same 72 across a full 1440 viewport gives a 14px bar, which is
   a bar chart again. 103 lands an 8px bar at 1440 and ~11px at 1920 (the gap
   ceiling goes 6px to 8px to hold that). 103 is prime, so it stays co-prime
   with the five phase groups and the wave still never repeats across the row.
   Below 680 the even bars are hidden by 26.3 and 52 remain, which is a ~4.6px
   bar at 390 — thin but still a wave. The count lives in SC_FOOTER_EQ_BARS.

   GROUND was dark1 in the first cut of this section, so the band read as the
   top edge of the ink footer. Superseded — see the second pass below.

   SESSION 10, SECOND PASS — Cody replaced the band's own box rules with:

       .hm-eqband { display: block; width: 100%; margin-top: -68px;
                    z-index: 1; position: relative; }

   That is a different component: no ground and no side padding, pulled UP so
   the bars stand over the bottom of whatever section precedes the footer
   rather than sitting in a strip of their own. On Home that is the dark
   parallax CTA, and the waveform now rises out of it into the footer line.
   Taken verbatim, his five declarations are below.

   ONE THING HAD TO BE DERIVED RATHER THAN COPIED: the margin is negative the
   band's own height, so it has to track that height or the footer moves. At
   -68px flat the desktop band (63px tall at 1440) pulls the footer 5px past
   the CTA's bottom edge, which is invisible — but the 38px tablet band and
   the 32px phone band would drag the footer 30-36px UP INTO the CTA and clip
   the button row. So the height and the offset are one value now,
   `--hm-eqband-h`, and his 68px is its desktop ceiling. The number he gave is
   unchanged at the width he gave it at; it just stops being a desktop number
   applied to a phone.

   The band is decorative and aria-hidden, so the yellow bars carry no AA duty
   wherever this lands. Worth knowing for the other 17 pages: with no ground
   of its own it inherits whatever is above the footer, and on a page that
   ends light the bars will read as a pale wash rather than as a glow. */

:root { --hm-eqband-h: clamp(46px, 4.4vw, 68px); }

.hm-eqband {
	margin-top: calc(-1 * var(--hm-eqband-h));
	position: relative;
	display: block;
	z-index: 1;
	width: 100%;
}
.hm-eqband .hm-eq {
	gap: clamp(2px, 0.42vw, 8px);
	height: var(--hm-eqband-h);
	justify-content: space-between;
	align-items: flex-end;
	border-top: 0;
	padding: 0 0 0;
	max-width: none;
	display: flex;
	margin: 0;
}
/* 26.5 took the footer's 4px accent1 border off when the marquee became the
   page cap. The marquee is at the top of the page now and the equalizer is
   the cap, so the border stays off — the bars meet the footer directly. */
body footer#footer.site-footer { border-top: 0; }

@media (max-width: 979px) {
	:root { --hm-eqband-h: clamp(34px, 5vw, 46px); }
}
@media (max-width: 680px) {
	:root { --hm-eqband-h: 32px; }
}


/* --- 28.4 H2 TO 48px ------------------------------------------------------
   "make the h2 more like 48px in font size." 27.1 had it at a 37px ceiling.

   27.1 is the block that was built to be edited for exactly this, and it says
   so — one ratio, six values. Only two of the six move here, and the second
   one is NOT optional:

     h2       37 -> 48
     hero h1  47 -> 60

   **The h1 has to move with it.** At 48px the h2 would otherwise outsize the
   hero h1's 47px ceiling, and the mobile floors invert too (h2's 30px against
   h1's 27px). 48/37 is 1.30, and 47 x 1.30 is 61, so 60 holds the 1.25-1.27
   h1:h2 ratio 27.1 settled on. **This is a consequence of Cody's change, not
   a second opinion about the hero** — one value to put back if he wants the
   hero where it was and is willing to live with h1 ~= h2.

   The `vw` middles are re-derived, not scaled: the ceiling should land at
   1440 and the floor should hold the phone. h2 3.7vw hits 48 at 1297 and
   bottoms out at 810; h1 4.7vw hits 60 at 1277 and bottoms out at 723. So h1
   leads h2 at every width between 390 and 1920 — swept, not assumed.

   The highlighter mark needs no change AGAIN, and for the same reason 27.1
   gives: `background-size: 100% 0.44em` and `background-position: 0 78%`
   resolve against the content box, so the band scales with the type.

   h3 is deliberately LEFT at its 28px ceiling. Cody named h2 and only h2, and
   h3 is a card heading on this page — the bento tiles set their own sizes and
   do not inherit this. Flagged rather than silently adjusted: the h2:h3 step
   is now 1.71, which is a wide interval if a future page sets h2 and h3 as
   adjacent siblings in running copy. */

body #content h2 { font-size: clamp(30px, 3.7vw, 48px) !important; }
body #content .hm-hero h1 { font-size: clamp(34px, 4.7vw, 60px) !important; }


/* --- 28.5 BOTTOM CTA PADDING ----------------------------------------------
   Cody, verbatim: `.bakery .bottom-cta { padding: 160px 0; }` — "its a bit
   narrow looking." Was 96px (section 16).

   Applied as given at desktop. The 64px mobile step from section 16 is
   RESTATED here rather than left to be inherited: that rule is in an earlier
   `@media (max-width: 979px)` block, media queries add no specificity, and
   this rule matches at the same (0,2,0) later in the file — so without the
   restatement 160px would have landed on phones too, where it is half a
   screen of empty parallax above the heading. 112px rather than 64px keeps
   the proportion of the change he asked for.

   AND A PRE-EXISTING BUG THIS SURFACED. The first cut of the rules below was
   written at Cody's `.bakery .bottom-cta` (0,2,0) and MEASURED as 30px on a
   phone, not 80px. themes/vds/style.css line 539 ships
   `.bakery .vc_row:not(.vc_inner) { padding: 30px 0 }` below 480, which is
   (0,3,0) — the `:not()` counts — so it has been beating section 16's 64px
   mobile value since the day that section was written, and nobody measured
   the 480 breakpoint. Library line 145 flags this exact selector as a known
   trap, which is the second time this session that reading §14 would have
   saved a round trip.

   So every step below is restated at `.bakery div.vc_row.bottom-cta` (0,3,1),
   which clears the theme rule at all four widths. Cody's value is unchanged;
   only the selector it is hung on is stronger. */

.bakery div.vc_row.bottom-cta { padding: 160px 0; }


/* --- 28.6 SPLIT ROW CLEARANCE ---------------------------------------------
   Cody: the `hm-split` bottom padding goes 24px to 60px at >= 980 (asked as
   40px, then raised to 60px on the same look).

   The 24px came in with his own session-9 accent1 slab behind the split
   portrait, which is inset `36px 36px -36px -36px` — so it hangs 36px BELOW
   the image, and 24px of row padding left it 12px short of clear, clipping
   into the row beneath. 40px cleared it by 4px, which was correct and still
   read tight; 60px gives it 24px of air and matches `--hm-section-y`, so the
   slab now sits in a full section's worth of space rather than a hairline of
   it. The original is at library line 1750; restated here rather than edited
   in place so the session-9 value and the reason it moved both stay readable.

   NOTE FOR THE NEXT PAGE: `.hm-split` is on TWO rows of Home — the Hype Man
   Difference row and the Featured Package row (`hm-split hm-section light1`).
   Only the first carries the slab, so the second now has 40px of padding it
   does not strictly need. Harmless at a 60px section rhythm and left alone
   because the ask was for the component, not for one instance of it. */
@media (min-width: 980px) {
	.bakery div.vc_row.hm-split { padding-bottom: 60px; }
}

@media (max-width: 979px) {
	.bakery div.vc_row.bottom-cta { padding: 112px 0; }
}
@media (max-width: 680px) {
	.bakery div.vc_row.bottom-cta { padding: 80px 0; }
}
@media (max-width: 480px) {
	.bakery div.vc_row.bottom-cta { padding: 64px 0; }
}


/* ===========================================================================
   29. SESSION 11 — PHASE 5 PROPAGATION: the 17 subpages
   ---------------------------------------------------------------------------
   Sessions 7-10 built, reviewed and revised HOME. Home is the only page that
   has no Top Banner — its ACF `header_background` is cleared so the WPBakery
   hero is the first element in #content (BUILD-PLAN 14, "clearing
   header_background is how you suppress the Top Banner"). Every OTHER page
   leads with `.default-header`.

   So the subpage banner is the one display element that has never been
   rendered since the typeface swap, and handoff open item 11 predicted
   exactly this: "the other 17 pages have not been looked at since the font
   swap. Oswald's 20%-taller caps mean any heading on a stub page is now
   rendering a fifth larger than it was."

   Confirmed by capture before writing a line of this section — /contact/ is
   the only page with a banner image set, and its h1 renders at the section-2b
   value, which is pre-Oswald in all four of its properties.
   --------------------------------------------------------------------------- */


/* --- 29.1 TOP BANNER H1 — the retune 27.1 never reached ------------------
   Section 2b sets `body #content h1, body .default-header h1, body #content
   .hm-hero h1` together. 27.1 (the typeface swap) and 28.4 (h2 to 48) both
   re-declared ONLY `.hm-hero h1`, because Home was the only page in the build
   and Home has no banner. `.default-header h1` has been sitting on the
   September values ever since. Four properties, all four wrong now:

     font-size       clamp(32px, 7.2vw, 56px)   pre-Oswald, un-normalised
     letter-spacing  -0.5px                     27.1 zeroed negative tracking
     line-height     1.08                       27.1 settled display at 1.12
     max-width       18ch                       `ch` moved under the face

   SIZE. 27.1 normalised every display size on CAP HEIGHT because Oswald's
   caps are ~20% taller than Spartan-Bold's at the same px. Doing that alone
   gives 56 x 0.87 = 48.7 — which would land the page h1 exactly on 28.4's
   48px h2, and an h1 that measures the same as the h2 under it is not a
   hierarchy. Deriving it the way 28.4 derived the hero instead: 27.1's h1:h2
   ratio is 47:37 = 1.27, and 48 x 1.27 = 61. So the banner h1 wants ~60 —
   the same value the hero h1 already holds.

   That is not a coincidence and it is not a mistake. BUILD-PLAN 3.2 gives ONE
   h1 size for "Top Banner + home hero"; section 2b honoured that and the two
   only diverged because 27.1 and 28.4 could only see the hero. Putting them
   back on one value restores the design system rather than inventing a third
   display size. The home hero stays the showpiece by being full-bleed video
   with a subhead and two CTAs — not by 8px of type.

   The `vw` middle is re-derived rather than scaled, same method as 28.4: at
   4.7vw the ceiling lands at 1277 and the floor at 723. Below 723 it holds
   34px, which is where the 300px mobile banner (BUILD-PLAN 4,
   `subpage_banner_height_mobile`) stops being able to hold four lines.

   MEASURE. `ch` is the advance of "0" and is 23% narrower in condensed Oswald,
   so the 18ch written against Spartan now holds ~23% less line than it was
   drawn for. 27.1 hit this on the hero and corrected 24ch -> 28ch; the same
   ratio takes 18ch to 21ch. Flagged in 27.1 as a general trap: a `ch` measure
   does not survive a typeface change. */

body #content .default-header h1,
body .default-header h1 {
	font-size: clamp(34px, 4.7vw, 60px) !important;
	letter-spacing: 0 !important;
	line-height: 1.12 !important;
}

body .default-header h1 { max-width: 21ch; }


/* --- 29.2 TOP BANNER CROP — the centring rule has never worked ------------
   Library line 363 says, in a comment written in Phase 4:

     "style.css forces `background-position: top left !important`, which crops
      faces off the top of a portrait-ish banner photo. Centre it."
     .default-header { background-position: center center !important; }

   The diagnosis is right and the fix does nothing. themes/vds/style.css:371 is

     .default-header { background-position: top left !important;
                       background-repeat: no-repeat !important;
                       background-size: cover !important; ... }

   which is ALSO (0,1,0) and ALSO !important, and style.css is enqueued AFTER
   custom.css — so it wins the tie on source order. Two !important rules of
   equal specificity is not a fight our file can win from where it sits. The
   banner has been cropping to its top-left corner since Phase 4 and nothing
   caught it because HOME IS THE ONLY BUILT PAGE AND HOME HAS NO BANNER
   (its ACF header_background is cleared so the hero can be first in #content).

   Measured, not read: computed background-position on /contact/ was `0% 0%`
   at 1440 and at 390. On a 1920x1440 source in a 1440x420 band that shows the
   top 420px of a 4:3 frame — ceiling and lighting truss on most of this
   library, which is the exact §14 failure mode ("a short band only ever shows
   the slice that happens to line up").

   Same class of bug as the 404 fallback three rules above, which is already
   commented "search.css ... is enqueued AFTER custom.css, so it wins every
   tie" — the lesson was written down and then not applied to the rule
   directly beneath it. `body #content` is (1,1,0) against the theme's (0,1,0)
   and is the library's standing answer for exactly this (Appendix). */

body #content .default-header {
	background-position: center center !important;
}


/* --- 29.3 TOP BANNER ALIGNMENT — left, to match the hero -----------------
   style.css:372 sets `.default-header .container { justify-content: center }`,
   so the banner h1 is centred on every subpage.

   The library already assumes otherwise: `.default-header.hm-center h1
   { margin-left: auto; margin-right: auto }` only makes sense if the default
   is LEFT and centring is the opt-in. That rule has been dead for the same
   reason as 29.2 — the theme centres the flex item before it is reached.

   Going left for consistency rather than preference: Home's hero h1 is left,
   every `.hm-sechead` is left, and §16's editorial move was explicitly to
   break "the centred-heading rhythm that read as a template on every
   section." A centred page h1 over a photo is the single most template-
   looking element the subpages would otherwise ship with.

   FOR CODY: this is a judgment call, not a correction, and it is a one-line
   reversal — delete this block and the theme's centring returns. `.hm-center`
   on the banner is still the per-page opt-in either way. */

body #content .default-header .container {
	justify-content: flex-start;
}


/* --- 29.4 DIRECT CONTACT LIST — Contact sidebar §17 ----------------------
   The copy doc's direct-contact bullets are label/value pairs ("Phone / text:
   (602) 551-7181"), not prose, so they get a label line and a value line
   rather than running together at the 320px the 4/12 sidebar gives them on a
   laptop. Same shape as the footer's NAP block, which already reads this way.

   A `strong` element carries the label rather than a description list,
   because the list has to stay editable in WPBakery's text editor — a
   non-developer can add a row by copying a line (§10.10), and a dt/dd pair
   loses that the moment the editor reformats it. (Written without angle
   brackets on purpose: the PUT handler runs wp_strip_all_tags() over this
   file, so a tag name in a COMMENT eats every rule up to the next closing
   bracket. The §14.3 assertion caught exactly that here.)

   The label takes `--hm-gold-text` (#8A6410, 5.37:1 on white, 4.96:1 on
   light2) and NOT accent3 — §14 is explicit that #C9981F is 2.63:1 and is not
   usable as text. This block sits on light2. */

body #content ul.hm-contact-list {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 0 28px !important;
}
body #content ul.hm-contact-list li {
	border-bottom: var(--hm-border);
	list-style: none !important;
	padding: 0 0 12px !important;
	margin: 0 0 12px !important;
}
body #content ul.hm-contact-list li:last-child {
	border-bottom: 0;
	padding-bottom: 0 !important;
	margin-bottom: 0 !important;
}
body #content ul.hm-contact-list strong {
	font-family: var(--headingfont);
	color: var(--hm-gold-text) !important;
	text-transform: uppercase;
	letter-spacing: 1.4px;
	margin-bottom: 3px;
	font-size: 12px;
	display: block;
}
body #content ul.hm-contact-list a { word-break: break-word; }


/* --- 29.5 THE INHERITED TEXT COLOUR IS PINK -------------------------------
   Site-wide, all 18 pages, since the day the site was stood up.

   The parent theme is Twenty Twenty-Five (body carries
   `wp-theme-twentytwentyfive wp-child-theme-vds`), so WordPress injects its
   Global Styles block into the head:

     body { color: var(--wp--preset--color--accent-2); }      (resolves #DB9AB1)

   TT5's `accent-2` is a dusty pink. VDS ships the correct rule in color.css —
   `h1, h2, h3, h4, h5, h6, body, p, li { color: var(--black) }` — but the
   matching compound there is `body`, which is (0,0,1), exactly the same as the
   Global Styles rule, and the Global Styles block is emitted LATER in the head.
   Same tie, same loser, as 29.2 and as the 404 fallback: our file is correct
   and is simply in the wrong place in the cascade.

   Measured, not deduced: computed `color` on body is rgb(219, 154, 177), and
   it inherits unbroken down eighteen ancestors to the Gravity Forms choice
   labels, which scored 2.10:1 against light2 on both viewports.

   WHY NOBODY SAW THIS FOR TEN SESSIONS. Site Conductor requires `body #content`
   + !important for every text property (Appendix), so the library sets an
   explicit colour on essentially everything Home renders. The pink only
   surfaces on text NO RULE NAMES — and until session 11 the only built page
   was Home, which has no form, no accordion, no inclusions list and no
   timeline. The first page to render a component the library had not had to
   colour was this one.

   Fixing it at the root rather than on the one selector that exposed it: the
   failure mode is "any text the library does not explicitly colour", and the
   16 pages still to build will keep producing those. `html body` is (0,0,2)
   and clears the Global Styles rule with no !important — important would be
   wrong here anyway, since it is the INHERITED default that must move while
   every deliberate override (white on dark1, the accent tiers, the footer)
   keeps winning on its own specificity. */

html body { color: var(--black); }


/* --- 29.6 CONTACT LIST LINKS — accent1 on cream is 1.47:1 -----------------
   The theme's global link colour is accent1 #F7C659. On light2 that is 1.47:1,
   measured on both viewports, confirmed a second way by reading the computed
   colour (standing rule 10 — the first read is never enough for a red).

   These are the phone and email on the conversion page, so they are not
   decorative. `--hm-gold-text` is the library's existing answer for gold that
   has to carry text: #8A6410, 4.96:1 on light2, already used for eyebrows,
   price ticks and the required asterisk. §14 is explicit that accent3 #C9981F
   is 2.63:1 and is NOT usable as text, so this does not reach for that.

   The underline stays and is not decoration — at 4.96:1 the colour alone is a
   thin signal, and WCAG 1.4.1 wants link identification not to rest on hue. */

body #content ul.hm-contact-list a {
	color: var(--hm-gold-text) !important;
	text-underline-offset: 3px;
	text-decoration: underline;
}
body #content ul.hm-contact-list a:hover,
body #content ul.hm-contact-list a:focus-visible {
	color: var(--black) !important;
}


/* --- 29.7 GRAVITY FORMS CHOICE LABELS ------------------------------------
   29.5 fixes the inherited pink at the root, which is what actually caused
   this. These are still set explicitly, because a form control's label is the
   last thing on the site that should depend on inheritance surviving a theme
   update — and because §7.13 says this form is a FULL restyle (GF legacy CSS
   is off, so nothing else is styling it).

   The `label` here is GF's own `.gform-field-label--type-inline`, which is a
   different element from `.gfield_label` (already black via library 14). */

body #content .gform_wrapper .gchoice label,
body #content .gform_wrapper .ginput_container label,
body .gform_wrapper .gchoice label {
	color: var(--black) !important;
}


/* --- 29.8 SERVICE-AREA BLOCK IN A NARROW COLUMN --------------------------
   `.hm-area` is `repeat(2, minmax(0, 1fr))` (library 1217), written for Home
   where it spans the full 1280 container and each tier gets ~629px. Contact
   puts it in the 4/12 sidebar §8.8 asks for — about 395px — so the two tiers
   came out ~186px wide, and with session 9's 34px/32px padding that leaves
   ~122px of text measure. Captured: "Phoenix metro," / "Scottsdale," /
   "Tempe, Mesa," — one or two words a line, for seven lines.

   `auto-fit` + a 260px minimum instead of a fixed 2, so the component decides
   from the space it is actually given rather than from the viewport. A
   modifier class would also work and was rejected: every future page that
   drops this into a column would have to remember it, and the one that forgets
   ships the crushed version.

   HOME IS UNCHANGED BY THIS and that is checked, not assumed: at a 1280
   container two tracks of (260 + 22 gap) fit four times over, auto-fit
   collapses the two empty tracks, and the two real tiers split the full width
   exactly as `repeat(2, 1fr)` did. Below ~542px of CONTAINER it stacks. */

.bakery .hm-area {
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}


/* --- 29.9 ASIDE CARD — Contact sidebar, Cody session 11 ------------------
   Three asks, one block: "the form and sidebar need some space between them",
   "should one of those columns have a background with border radius?", and
   "the traveling boxes are also a tad tall."

   THE GAP WAS LITERALLY ZERO. Measured on the live page: the form column ends
   at x=933 and the sidebar begins at x=933. WPBakery columns on this theme
   carry no inner padding at all (`.vc_column-inner` padding computed 0px), so
   there is no Bootstrap-style gutter to inherit and nothing was separating the
   two columns but the whitespace that happened to be inside the form.

   Answering the background question with a card rather than a tint, because a
   card solves the first ask at the same time: once the aside has its own
   ground, the space between the columns is structural and reads as deliberate
   rather than as a margin someone forgot. It takes light1 (white) on the row's
   light2 ground — the same figure-on-ground pair the bento and the price card
   already use, so this is the site's existing card, not a new object.

   The 40px separation is a MARGIN on the card, not padding on the form column:
   padding would shrink the form's own measure, and the nine-field two-column
   layout is already the tightest thing on the page at 853px.

   TIER HEIGHT. Session 9 gave `.hm-area__tier` 34px/32px padding and a 220px
   decorative disc for the full-width Home placement, where each tier is 629px
   wide. In this card they are ~307px and stacked, so the same padding is a
   much larger share of a much smaller box — measured 197px and 228px tall for
   two and four lines of text. Inside the aside they take 22px/22px and a
   140px disc, which is the §7.16 component at the scale its container
   actually gives it. Home is untouched: every rule here is scoped to
   `.hm-aside`. */

.bakery .hm-aside .vc_column-inner {
	border-radius: var(--hm-radius-lg, 22px);
	background: var(--light1);
	border: var(--hm-border);
	padding: 32px 30px;
}

/* The gutter is PADDING ON THE COLUMN, not margin on the card. js_composer
   gives `.vc_column-inner` width:100%, so a margin pushes the card out of its
   own column instead of shrinking it — measured: the card started at x=973 and
   ran to 1400 against a container edge of 1360, overhanging by exactly the
   40px added. With border-box the column keeps its 427px track and the card
   fills what is left. */
@media (min-width: 980px) {
	.bakery .hm-aside { padding-left: 40px; }
}

/* The aside is a card on a card now, so the tiers inside it lose the padding
   and the disc that were sized for a 629px full-width tier. */
.bakery .hm-aside .hm-area { gap: 14px; }
.bakery .hm-aside .hm-area__tier { padding: 22px 22px; border-radius: 16px; }
.bakery .hm-aside .hm-area__tier::after {
	height: 140px;
	width: 140px;
	right: -46px;
	top: -58px;
}
body #content .hm-aside .hm-area__tier h4 { font-size: 19px !important; }
body #content .hm-aside .hm-area__scope { margin-bottom: 10px !important; }

/* The heading is the card's title, so it sits tighter to the top edge than a
   section heading would. */
body #content .hm-aside h3 { margin-top: 0 !important; }

@media (max-width: 979px) {
	/* Stacked: the card keeps its treatment but the 40px side gutter becomes
	   vertical separation instead. */
	.bakery .hm-aside { padding-left: 0; }
	.bakery .hm-aside .vc_column-inner { margin: 32px 0 0; padding: 26px 22px; }
}


/* --- 29.10 STICKY HEADER TWITCH — a state that changes its own trigger ----
   Cody: "the sticky header is twitchy when you slowly scroll."

   REPRODUCED AND MEASURED (claude-made/scripts/probe-sticky-s11.mjs), stepping
   the scroll 2px at a time from 40 to 70:

     asked  actual  drift  .scrolling  headerH  docH
       50     50       0     false       136    3644
       52     39     -13     false       123    3631
       58     49      -9     false       103    3611
       60     62      +2     TRUE        117    3625
       62     47     -15     false       102    3610
       64     62      -2     TRUE         97    3605

   The class flips false - true - false - true across a 12px band and the
   scroll position drifts up to 15px from where it was put. That is the twitch.

   CAUSE. js/my-script.js toggles `.scrolling` on a bare `scrollTop() > 50`
   with no hysteresis, and 26.6 hung a 40px collapse of the utility bar on that
   class. The header is `position: sticky`, so it is IN FLOW — collapsing the
   bar shortens the document by 39px (measured both states directly), the
   browser adjusts scrollY to match, scrollY falls back under 50, the class is
   removed, the document grows again, and it re-fires. The state change moves
   the value that decides the state. Scroll fast and you jump the band; scroll
   slowly and you sit in it.

   WHY NOT FIX THE JS. my-script.js is theme-owned, and handoff open item 1
   records that a re-pull of `vds` from the agency master silently reverts
   local theme patches — the same reason session 10 put the equalizer band in
   the plugin. Adding hysteresis there would work until the next theme pull and
   then stop, silently.

   THE FIX IS TO STOP CHANGING THE DOCUMENT HEIGHT. The utility bar no longer
   collapses; instead the header sticks at `top: -40px`, so the bar scrolls off
   the top of the viewport under its own steam and the 96px nav pins at y=0.
   The header's in-flow footprint is a constant 136px, the document never
   resizes, scrollY never jumps, and `.scrolling` therefore toggles exactly
   once — the shadow it carries is purely visual and moves no geometry.

   This KEEPS 26.6's actual benefit rather than trading it away: the pinned bar
   still costs 96px of viewport, not 136px, because the utility bar is above
   the viewport rather than collapsed inside the header. It is the same result
   by a mechanism that does not feed back. */

:root { --hm-utilbar-h: 40px; }

body header#header.site-header {
	top: calc(-1 * var(--hm-utilbar-h));
}
/* The admin bar is fixed at 32px (46px under 782), so the sticky offset is
   that height minus the utility bar rather than a flat negative. */
body.admin-bar header#header.site-header {
	top: calc(32px - var(--hm-utilbar-h));
}
@media (max-width: 782px) {
	body.admin-bar header#header.site-header {
		top: calc(46px - var(--hm-utilbar-h));
	}
}

/* Undo 26.6's collapse. Stated rather than deleted in place so the session-9
   decision and the reason it was replaced both stay readable. */
body header#header.site-header.scrolling .top-widget {
	max-height: var(--hm-utilbar-h);
	opacity: 1;
}
header.site-header .top-widget { transition: none; }


/* --- 29.11 ANCHOR TARGETS CLEAR THE PINNED HEADER ------------------------
   With a 96px bar pinned at the top and `scroll-behavior: smooth` set by
   style.css line 80, an in-page anchor lands its target UNDER the header.

   This is not hypothetical on this build: Home's bottom CTA and its sticky
   mobile booking bar both link to /contact/#check-your-date, and Contact's own
   intro and closing CTAs do too. Four links into one anchor, and without this
   all four land with the form's first field hidden behind the nav.

   96px of nav plus 24px of breathing room. Applied to any row carrying an id
   rather than to the one id, so every anchor the remaining 16 pages add is
   covered by default. */

.bakery div.vc_row[id],
.bakery section.vc_section[id] {
	scroll-margin-top: 120px;
}


/* --- 29.9b ASIDE TYPE SCALE ----------------------------------------------
   The card is 387px wide with 30px of padding, so its measure is ~327px. At
   the site's 18px/1.68 body setting that is about 36 characters a line — half
   the 60-75 a comfortable measure wants — and the copy reads loose and ragged
   next to the form it is supporting.

   Dropping to 16px/1.55 inside the aside takes the measure to ~41 characters
   and closes the leading to match. It also does the right thing semantically:
   this column is secondary to the form, and until now it was set at exactly
   the same size, which gave two columns of equal typographic weight on a page
   with one job.

   The h3 comes down with it. At the global 28px it wrapped "Direct Contact &
   Service Area" onto two lines inside a card 387px wide; 22px sets it on two
   comfortable lines and keeps it clearly above the 16px body. */

body #content .hm-aside p,
body #content .hm-aside li {
	line-height: 1.55 !important;
	font-size: 16px !important;
}
body #content .hm-aside h3 {
	font-size: 22px !important;
	line-height: 1.18 !important;
}
/* The tier copy is already its own size; only the leading follows. */
body #content .hm-aside .hm-area__tier p { line-height: 1.5 !important; }
body #content .hm-aside .hm-area__scope { font-size: 12px !important; }


/* --- 29.12 FORM TWO-COLUMN LAYOUT HAS NO MOBILE STEP ---------------------
   Library section 14 adds `.hm-form-2col` to two-column the §17 nine-field
   layout, and stops there — there is no breakpoint collapsing it back. Written
   in Phase 4 against a form that was never rendered on a built page, so it was
   never seen at a phone width.

   Measured at 390: `grid-template-columns: 163.5px 163.5px`. Every short field
   is 164px wide, and the date field's own `mm/dd/yyyy` placeholder plus its
   picker button does not fit in it. §2 puts 70%+ of traffic on a phone, and
   this is the form that traffic exists to reach.

   Collapsing at 767 rather than at the 979 where the aside stacks: between
   those two widths the form column runs the full container, which is 768px or
   more of measure, and two columns there are comfortable. 767 is also the
   breakpoint `.hm-inclusions` already uses for the same reason, so the two
   grid components on this site change shape together. */

@media (max-width: 767px) {
	body .hm-form-2col .gform_wrapper.gravity-theme .gform_fields {
		grid-template-columns: minmax(0, 1fr) !important;
	}
	body .hm-form-2col .gform_wrapper.gravity-theme .gfield {
		grid-column: 1 / -1 !important;
	}
}


/* ===========================================================================
   30. SESSION 11b — Cody's Contact edits
   ---------------------------------------------------------------------------
   One add and eleven changes, taken from his message. Restated here rather
   than edited in place, per the file's convention since 28.5 — the earlier
   value and the reason it moved both stay readable.

   Everything is verbatim except the sticky aside, which had to be re-hung to
   do what it was asked to do. That one is documented at 30.1.
   --------------------------------------------------------------------------- */


/* --- 30.1 STICKY ASIDE — his declarations, re-hung so they engage ---------
   Asked for:

     @media (min-width: 980px) {
       .bakery .hm-aside { padding-left: 40px; position: sticky;
                           top: 160px; height: 100%; }
     }

   `position: sticky` needs the element to be SHORTER than its containing
   block, or there is no room for it to travel and it simply never detaches.
   Measured on the live page before applying: the row container is
   `display: flex`, `.hm-aside` is a flex item with `align-self: auto` (so it
   inherits the default `stretch`), and its height is 1416px — exactly the row
   height. `height: 100%` holds it there rather than freeing it.

   So the declarations are correct and the selector is one level too high. The
   card inside it, `.vc_column-inner`, is 818px in that 1416px column, which is
   598px of travel. Sticky goes on the card; the column keeps `padding-left`.

   `height: 100%` is dropped rather than moved — on the card it would re-stretch
   it to the column and reintroduce exactly the problem. Nothing else needs it:
   the card is already as tall as its content.

   `top: 160px` is his value, unchanged, and it is a good one — the pinned nav
   is 96px (29.10), so the card clears it by 64px.

   Below 980 the aside stacks under the form and sticky is removed outright; a
   sticky sidebar on a phone would pin a card over the form it is meant to
   support. */

@media (min-width: 980px) {
	.bakery .hm-aside { padding-left: 40px; }
	.bakery .hm-aside .vc_column-inner {
		position: sticky;
		top: 160px;
	}
}
@media (max-width: 979px) {
	.bakery .hm-aside .vc_column-inner { position: static; }
}


/* --- 30.2 ASIDE SPACING + LABEL COLOUR -----------------------------------
   The contact-list label goes gold -> ink. That is a contrast improvement, not
   a risk: `--dark1` on the white card is 17.58:1 against the 4.97:1 the
   gold-text was measuring, and the gold is still carried by the links beneath
   it (29.6), so the block keeps its accent without the label competing. */

.hm-aside .wpb_text_column.wpb_content_element.hm-tight {
	margin-bottom: 20px;
}

body #content .hm-aside h3 {
	font-size: 22px !important;
	line-height: 1.18 !important;
	margin-bottom: 8px;
}

body #content ul.hm-contact-list strong {
	font-family: var(--headingfont);
	color: var(--dark1) !important;
	text-transform: uppercase;
	letter-spacing: 1.4px;
	margin-bottom: 7px !important;
	font-size: 12px;
	display: block;
}

body #content ul.hm-contact-list {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 0 20px !important;
}


/* --- 30.3 GRAVITY FORM DENSITY -------------------------------------------
   Row gap 20px -> 10px, label margin 7px -> 4px, description 12px and pulled
   up to 4px, checkbox rows made flex so the box and its label sit on one
   baseline, textarea 288px -> 200px. The form was running taller than the
   aside beside it and reading loose for a nine-field form.

   `.gform_fields` here is the SINGLE-column base at (0,3,1). The two-column
   rule (library 14) and the sub-767 collapse (29.12) are both (0,4,1), so they
   still win on specificity and the only thing this changes for them is the
   gap, which is what the edit is for. Verified by measuring the grid at 390,
   768 and 1440 after the push, not assumed.

   NOTE ON `.gform_heading`. It carries exactly one thing on this form — the
   legend reading '"*" indicates required fields' (title and description are
   already off via the shortcode). Hiding it removes the only VISUAL
   explanation of the asterisk. Not a WCAG failure: Gravity Forms sets
   `aria-required="true"` on each required input, so assistive tech is
   unaffected, and every required field still shows its asterisk. Flagged
   because it is a real if minor usability trade, and it is a one-line
   reversal. */

.gform_heading { display: none; }

body .gform_wrapper div.gfield_description {
	padding-top: 0 !important;
	margin-top: 4px !important;
	font-size: 12px !important;
}

body .gform_wrapper.gravity-theme .gform_fields {
	grid-template-columns: minmax(0, 1fr) !important;
	display: grid !important;
	gap: 10px 24px !important;
}

body #content .gform_wrapper .gfield_label,
body .gform_wrapper .gfield_label {
	font-family: var(--headingfont);
	color: var(--black) !important;
	margin: 0 0 4px !important;
	letter-spacing: 0.2px;
	display: block;
	font-size: 14px;
}

input.gfield-choice-input { margin: 0; }

body .gform_wrapper .gfield_checkbox .gchoice,
body .gform_wrapper .gfield_radio .gchoice {
	align-items: center;
	justify-content: flex-start;
	margin: 0 0 10px !important;
	display: flex;
	gap: 10px;
}

/* `body` prefix is load-order, not style. Gravity Forms' own basic.min.css
   ships THE IDENTICAL SELECTOR `.gform_wrapper.gravity-theme .gfield
   textarea.large { height: 288px }` and is enqueued after custom.css, so at
   equal specificity it wins on source order and the 200px never applied —
   measured 288px after the first push. (0,4,2) against its (0,4,1) clears it.
   Fourth rule this session to lose that exact way; see standing rule 12. */
body .gform_wrapper.gravity-theme .gfield textarea.large { height: 200px; }


/* ---------------------------------------------------------------------------
   31. §8.5 A LA CARTE MENU — the Packages rate table as a card grid
   The copy doc ships this as a 9-row [TABLE] of Service / Investment /
   Details. §7.5 is explicit that rate tables do not work at 390px, and the
   same reasoning retires this one: at 390 a 3-column table either overflows
   the viewport or crushes "Production Enhancements" to one word per line.
   Nine cards in a 3-up grid carry the identical words with no horizontal
   scroll and no cell crushing.

   NOT .hm-price: that component is the hipstr hero card, 44px numeral and a
   32px pad, built to be looked at two at a time. Nine of them is a wall.
   This is the quieter sibling — same ground, same radius, smaller numeral,
   and the price sits ON the heading row instead of under it.

   EVERY TEXT PROPERTY HERE CARRIES !important, and that is not decoration.
   Library section 2 ships
     body #content p, body #content li, ... {
       font-family: var(--bodyfont) !important; font-size: 18px !important; }
   An important declaration beats a normal one outright, so a component rule
   that merely has higher specificity still loses. Session 12 measured the
   damage: .hm-price__amount declared 38px rendered at 18px, .hm-price__unit
   declared 12px rendered at 18px, and the whole §7.5 pricing card had been
   shipping as flat 18px body copy on Home since session 7 without anyone
   noticing, because the contrast gate reads the COMPUTED size and is
   perfectly happy with it. `node claude-made/scripts/typeaudit.mjs URL`
   is the gate that catches it; run it on every page before flipping a
   tracker row. This is standing rule 12, in the one form where more
   specificity is NOT the answer.
   --------------------------------------------------------------------------- */

/* THE ROW MUST WRAP. The theme lays every [vc_row] out as a flex container
   with `flex-wrap: nowrap`, and the flex child is the inner `.container`, not
   the row. Home never hit this because its widest card row is four columns,
   which fit one line; nine 1/3 columns do not. Measured before this rule:
   document scrollWidth 2210 against a 1440 viewport, with the nine columns
   shrunk to 204-259px each instead of an even 1/3.

   SESSION 13 — the second paragraph of this note used to say a column gap
   was impossible because WPBakery already pads each column. It does not:
   measured at 1440, every `.hm-menu .vc_column_container` computed `padding:
   0px` and the nine cards ran edge to edge, card 1 ending at x=507 and card 2
   starting at x=507. The row spacing was right because `row-gap` above was
   doing it; nothing was doing the columns.

   The fix is section 3's card-grid pattern, not a `gap` — that note was
   correct about the shorthand. Three 33.33% columns do need the full line, so
   the gutter goes INSIDE each column as padding (the columns are border-box,
   so 33.33% still holds) and the container widens by one gutter to keep the
   outer card edges flush with every other section on the page. `row-gap`
   stays and the columns take no bottom padding, or the two would stack. */
.bakery div.vc_row.hm-menu > .container {
	max-width: calc(1280px + var(--hm-gap));
	width: calc(90% + var(--hm-gap));
	row-gap: var(--hm-gap);
	flex-wrap: wrap;
}
.bakery .hm-menu .vc_column_container { padding: 0 12px !important; }

.bakery .hm-menu .vc_column_container > .vc_column-inner,
.bakery .hm-menu .vc_column_container > .vc_column-inner > .wpb_wrapper,
.bakery .hm-menu .wpb_text_column,
.bakery .hm-menu .wpb_text_column > .wpb_wrapper { height: 100%; }

.bakery .hm-menu__item {
	border-radius: var(--hm-radius);
	background: var(--light1);
	border: var(--hm-border);
	box-shadow: var(--hm-shadow);
	flex-direction: column;
	padding: 24px 22px;
	display: flex;
	height: 100%;
}

/* The heading row. `baseline` not `center`: the service name wraps to two
   lines on the longer entries and centre-aligning would float the price up
   off the first line of the title it belongs to. */
.bakery .hm-menu__head {
	border-bottom: 1px solid var(--light3);
	justify-content: space-between;
	align-items: baseline;
	padding-bottom: 12px;
	margin-bottom: 14px;
	display: flex;
	gap: 14px;
}

body #content .hm-menu__item h3 {
	letter-spacing: -0.2px;
	margin: 0 !important;
	line-height: 1.25 !important;
	font-size: 20px !important;
	flex: 1 1 auto;
}

/* `flex-shrink: 0` keeps a short price like the additional-bartender add-on
   or the DJ flat rate on one line — without it the flex algorithm shrinks the
   price below its content width before it wraps the heading, and the dollar
   sign ends up alone on line two.

   NOTE, and do not undo this by "improving" the comment: the prices are
   described here rather than quoted because the /custom-css replace handler
   feeds this file to preg_replace() as the REPLACEMENT string, which parses
   dollar-digit as a backreference. A literal price in any comment or rule is
   silently deleted on push — session 12 watched "+" and a four-hundred
   become "+0". Same defect as the backslash-escape ban at the top of this
   file; plugin 2.1.1 fixes it at the source, and until that is deployed the
   rule here is: NO DOLLAR SIGN FOLLOWED BY A DIGIT, ANYWHERE IN THIS FILE. */
body #content .hm-menu__price {
	font-family: var(--headingfont) !important;
	color: var(--black) !important;
	text-align: right;
	margin: 0 !important;
	white-space: nowrap;
	line-height: 1.1;
	flex: 0 0 auto;
	font-size: 22px !important;
}

/* The qualifier — "flat", "per event". Small caps-ish, gold-text for 5.37:1
   on light1 rather than accent3's 2.63:1 (§3.1 — this is text, not a glyph). */
body #content .hm-menu__price span {
	color: var(--hm-gold-text) !important;
	text-transform: uppercase;
	font-family: var(--bodyfont) !important;
	letter-spacing: 1.2px;
	font-weight: 600 !important;
	font-size: 11px !important;
	display: block;
	margin-top: 3px;
}

body #content .hm-menu__detail {
	color: var(--dark3) !important;
	margin: 0 0 16px !important;
	line-height: 1.6 !important;
	font-size: 15px !important;
}

/* `margin: auto 0 0` is the §7.4 equal-height trick, and it is on the
   WRAPPER paragraph, not the anchor. That paragraph is the flex child of
   .hm-menu__item; an auto margin on the inline anchor inside it pins
   nothing. Measured on the first push: linkMarginTop "auto" on an element
   whose parent paragraph had marginTop 0px, and the CTAs did not
   bottom-align. The builder emits that paragraph itself, because a bare
   anchor as a direct child of a div is what wpautop wraps, and it leaves
   the wrapper unclosed.

   The four cards with no link (Additional Bartender, Memory Book, Print
   Overlay, Extended Hours) simply end after the detail; their cards still
   stretch, because the flex LINE does the stretching, not the content. */
body #content p.hm-menu__cta {
	margin: auto 0 0 !important;
	padding-top: 4px;
}
body #content a.hm-menu__link {
	border-bottom: 2px solid var(--hm-gold-text);
	color: var(--hm-gold-text) !important;
	font-family: var(--headingfont) !important;
	text-decoration: none !important;
	transition: color var(--hm-ease), border-color var(--hm-ease);
	padding-bottom: 2px;
	display: inline-block;
	font-size: 14px;
}
body #content a.hm-menu__link:hover,
body #content a.hm-menu__link:focus-visible {
	border-color: var(--black);
	color: var(--black) !important;
}

/* 1199 is where the 3-up grid starts crushing "Guest Memory Book Station"
   into four lines against a 20px heading. Two up holds to 767. */
@media (max-width: 1199px) {
	body #content .hm-menu__item h3 { font-size: 18px !important; }
	body #content .hm-menu__price { font-size: 20px !important; }
}
@media (max-width: 767px) {
	.bakery .hm-menu__item { padding: 20px 18px; }
}


/* ---------------------------------------------------------------------------
   32. SESSION 14 — DJ & Emcee Hosting (2695), the first page to render §7.7
   --------------------------------------------------------------------------- */

/* --- 32.1 §7.7 NUMBERED PROCESS: the list reset section 9 never got --------
   Section 9 styles `.hm-step` and draws its numeral with a CSS counter, but
   it never resets the LIST. Every other list component in this library does
   — `ul.hm-price__list` (604), `ul.hm-inclusions` (669), `ul.social` (1363),
   `ul.hm-contact-list` (4042) all carry `list-style: none !important` — and
   `.hm-steps` is the only one that was written as an `ol`, which is the one
   element where the omission actually costs something: the browser draws its
   own decimal marker AND our counter draws a 56px gold one, so every step is
   numbered twice.

   Found offline, before the first render, by reading section 9 against the
   four list components that came before it. §7.7 has never been on a live
   page — the handoff predicted this component would cost a defect round and
   this is that defect, caught one step earlier than usual.

   The theme's own reset (style.css:14) already zeroes `ol` padding/margin, so
   those two are belt-and-braces against WP global styles rather than against
   vds. `list-style` is the one that matters. No `!important` risk here under
   standing rule 15 — nothing animates a static list. */
body #content ol.hm-steps,
body #content ul.hm-steps {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
}

/* MEASURE. The first render put step bodies on a 1280px container at 18px,
   which is ~118 characters a line — roughly double a comfortable measure, and
   visibly looser than everything around it because `.hm-sechead` has been
   capped at 860px since section 25.1. No gate reads line length: typeaudit
   scores the declared size, contrast scores the glyph pixels, and both were
   happy. Same 860px as the heading it sits under, so the two left edges and
   the two right edges agree. Released below 979 where the column is already
   narrower than the cap. */
.bakery .hm-steps { max-width: 860px; }

@media (max-width: 979px) {
	.bakery .hm-steps { max-width: none; }
}

/* --- 32.2 §7.1 BANNER FOCAL POINT, page 2695 ------------------------------
   Section 3 pins every banner to `center center !important` because style.css
   forces `top left` and decapitates portrait sources. For 2759
   (emcee-hyping-crowd-checkered-floor, 4:3) the 420px band keeps only 39% of
   the height, and at dead centre that band lands on the emcee's chin: head
   gone, microphone gone. At 35% the whole head, the mic and the shoulders are
   in frame with the left two thirds of the plate empty for the h1.

   Scored with `claude-made/scripts/bannerfocal.py`, which reproduces
   `background-size: cover` + the section 3 scrim exactly and sweeps the
   vertical position. Same mechanism section 3 already uses for the utility
   fallback at `center 60%` — this is that tool, per page. */
body.page-id-2695 .default-header {
	background-position: center 35% !important;
}


/* ---------------------------------------------------------------------------
   33. SESSION 15 — Officiant (2697), Bar & Mixology (2698),
   Production Enhancements (2699)
   --------------------------------------------------------------------------- */

/* --- 33.1 NOTICE BLOCK — the client's "these are add-ons" line -------------
   §7 of the copy doc carries an explicit client edit: the "these are add-ons,
   not standalone packages, book a consultation" line "displays directly under
   the hero". It is not body copy and it is not a section — it is a notice,
   and nothing in the library was one.

   READ AGAINST ITS SIBLINGS BEFORE THE FIRST RENDER (standing rule 17, which
   is what 14.1 and 14.3 cost us). Three things came out of that read:

   - MEASURE. Section 25.1 capped `.hm-sechead` at 860px and 32.1 had to cap
     `.hm-steps` at the same value after its bodies shipped at 118 characters
     a line. A full-width notice in a 1280px container is that defect again,
     so the cap is here from the start, released below 979 where the column is
     already narrower than it.
   - NO FONT-SIZE DECLARATION. Section 2's base rule is
     `body #content p { font-size: 18px !important }`. A smaller size here
     would need its own important to win (standing rule 12) and typeaudit
     scores declared against computed, so a non-important declaration would
     report as a failure rather than render. The notice reads at body size.
   - NO LIST RESET NEEDED. 32.1 exists because every list component carries
     one and section 9 missed it; this is a paragraph, so there is nothing to
     reset. Noted so the next reader does not go looking.

   The accent edge is a left border rather than `.hm-feature`'s top border
   because this block is one paragraph wide, not a column in a grid — a 3px
   rule across 860px of a single paragraph reads as a divider between
   sections, which is the opposite of what a notice should say. */
.bakery .hm-note {
	border-left: 4px solid var(--accent1);
	border-radius: 0 var(--hm-radius) var(--hm-radius) 0;
	background: var(--light2);
	padding: 18px 24px;
	max-width: 860px;
}
/* The notice sits on light2 on a light1 ground. On a light2 SECTION the two
   would be the same value, so it takes light3 there — the same surface-aware
   pairing section 8's inclusions ground already uses. */
body #content .light2 .hm-note,
body #content .light3 .hm-note { background: var(--light3); }
body #content .dark1 .hm-note,
body #content .dark2 .hm-note {
	background: rgba(255, 255, 255, 0.06);
	color: var(--light3) !important;
}

@media (max-width: 979px) {
	.bakery .hm-note { max-width: none; padding: 16px 18px; }
}

/* --- 33.2 §7.1 BANNER FOCAL POINT, page 2697 ------------------------------
   Same mechanism as 32.2. 2782 (sedona-red-rock-ceremony-guests-seated) is
   16:9, so the 420px band keeps 52% of its height — the best crop in the
   library — but at dead centre the floral arch loses its top and the seated
   guests' heads crowd the bottom edge. Swept with `bannerfocal.py` at 25 / 40
   / 50 / 65: at 40% the whole arch, the officiant at the mic and the couple
   are in frame and the guest heads drop out of the band.

   NOTE FOR THE WEDDINGS PAGE. The handoff had this image earmarked for
   Weddings as well. It is spent here, because the officiant working at the
   mic IS the officiant service, and a page may not share its banner with
   another. Weddings needs its own; `claude-made/s15/banner/officiant-crops.png`
   scores the other nine in this set. */
body.page-id-2697 .default-header {
	background-position: center 40% !important;
}

/* --- 33.3 §7.1 BANNER, page 2698 — no CSS, recorded here ------------------
   Bar & Mixology has no photography anywhere in the supplied set (§12-F,
   confirmed three times now). `page.php` renders no `.default-header` at all
   unless ACF `header_background` is set, so the page cannot simply go
   without one. It carries attachment 2866,
   `bar-services-brand-panel.webp` — an ink field with four crisp gold
   diagonals across the right half, 1920 by 560 so it lands 1:1 on the 1440
   by 420 desktop band, with the left half clear for the h1. Scored through
   `bannersheet.py` against the section-3 scrim before upload, because a soft
   gradient does not survive that scrim: the first three attempts came back as
   brown mush and only hard edges read through it.

   It needs no rule here and that is deliberate. It is a PLACEHOLDER: when the
   client supplies a bar photograph the swap is one ACF field, and a per-page
   override in this file would have to be found and removed first. */

/* --- 33.4 §19 FEATURE BLOCK, STACKED ---------------------------------------
   The component has only ever been laid out by `.hm-cards`, which is a column
   grid and puts the gutter on the COLUMNS — so two feature blocks inside one
   column sat flush against each other, the second one's accent rule reading
   as an underline on the first one's paragraph.

   The Officiant page is the first to stack them: its §18 photograph is the
   only frame of the officiant actually officiating and it is 3:4, so under
   the `is-portrait` crop it stands about 380px beside roughly 90px of copy
   and left the 7 of 12 column about 70% empty. Moving the three blocks into
   that column fills it. Adjacent-sibling only, so nothing already on Home,
   DJ or Bar moves. */
.bakery .hm-feature + .hm-feature { margin-top: 24px; }

/* --- 33.5 §7.4 CARD MEDIA, PORTRAIT SOURCE ---------------------------------
   `.hm-card__media` is `aspect-ratio: 4 / 3` with `object-fit: cover`, and
   the browser default `object-position` is `center center`. A 2:3 source
   therefore keeps the middle 44% of its own height, and on a group photograph
   of standing people that band is torsos: every corporate and community frame
   in the client set loses the tops of its heads.

   This is 14.6's banner problem one component along, and it was found the
   same way — by simulating the real crop at 15 / 25 / 35 / 50% before
   anything was pushed, rather than by looking at a rendered card afterwards.
   At 25% all three test frames keep every face. Section 18 already does
   exactly this for `.hm-split__media.is-portrait` at 20%; cards sit shallower
   so they need a little more.

   Opt-in, because a LANDSCAPE source in a 4:3 box loses almost nothing at
   dead centre and shifting it up would be a crop for no reason. */
.bakery .hm-card__media.is-tall img { object-position: center 25%; }

/* --- 33.6 §7.4 CARD CTA — the flex child moved and the pin did not ---------
   `classaudit` caught `.hm-card__cta` styled nowhere, and the class turns out
   to be load-bearing.

   `hm_build.py`'s `service_card()` wraps its anchor in a paragraph of its own,
   for the reason `menu_card()` spells out: a bare inline element as a direct
   child of a div is exactly what `wpautop` wraps, and on the first Packages
   push it wrapped it badly — the paragraph was never closed. But section 9
   pins the bottom alignment with `.hm-card__body .hm-card__link
   { margin-top: auto }`, and once the anchor is inside a paragraph the ANCHOR
   is no longer the flex child. The paragraph is, and it carries section 9's
   own `.hm-card__body p { margin: 0 0 16px !important }`. So the five cards
   on each landing page would have stopped bottom-aligning their CTAs the
   moment the copy lengths differed — which on these two pages they do, by
   three lines.

   Important for the same reason 31's `p.hm-menu__cta` is: it is overriding an
   important declaration in this same file, and specificity alone never wins
   that (standing rule 12). Nothing animates a card margin, so rule 15 is not
   in play.

   Home is untouched: `build_home.py` predates `hm_build.py`, keeps its own
   copy of this emitter and ships the unwrapped anchor, so section 9's
   original pin is still the one doing the work there. */
body #content p.hm-card__cta { margin: auto 0 0 !important; }
.bakery .hm-card__body .hm-card__cta .hm-card__link { margin-top: 0; }

/* --- 33.7 §7.4 CARD PRICE — section 12's bento fix, one component along ----
   `typeaudit` on the Services landing: `body #content .hm-card__price`
   declares `var(--headingfont)` and computes to Nunito Sans.

   This is **the same defect session 12 fixed for `.hm-bento__price`**, in the
   rule that fix's own comment was written next to. Section 2's running-copy
   rule is `body #content p { font-family: var(--bodyfont) !important }`, and
   against an important declaration specificity never wins (standing rule 12)
   — the component rule was not important at all, so it lost outright.

   It survived because §7.4's price has never been on a live page. Home is the
   only page with service cards and its bento uses `.hm-bento__price`; this
   class first renders on the Services landing. Third time this exact shape of
   thing has turned up — `inclusions()` emitting a description list against a
   stylesheet expecting a list (session 12), `.hm-steps` never reset (14.1),
   and now this. **A component is only as verified as the first page that
   renders it**, and the gate that catches the typeface one is typeaudit.

   Size made important alongside it: section 2 was winning that too, at the
   same 18px, so nothing moved — but a silent tie is how the next change to
   section 2 would move it without anything going red.

   AND IMPORTANT WAS NOT ENOUGH — the first attempt added `!important` to
   `body #content .hm-card__price` and typeaudit still reported Nunito Sans.
   Probed rather than guessed at (standing rules 10 and 12): section 2's group
   selector includes `body #content .hm-card p`, which is one ELEMENT heavier
   than `body #content .hm-card__price`, so important-versus-important came
   down to specificity and the base rule won. Matching `.hm-card` as well puts
   this rule ahead on classes with the element count level. */
body #content .hm-card p.hm-card__price {
	font-family: var(--headingfont) !important;
	font-size: 18px !important;
}

/* --- 33.8 §7.15 CTA BAND WITH A SUBHEAD — measure ---------------------------
   `cta_band()` has taken an optional `sub` since it was written and no page
   had ever passed one: Packages, DJ, Officiant, Bar and Production all use
   the heading-only form. The Services landing is the first, because §2's
   "Bundle and Save" section is a heading, a three-line paragraph and a CTA.

   Centred on a 1280px container that paragraph measured about 110 characters
   a line. Same defect as 14.3 and the reason 25.1 capped `.hm-sechead`, now
   for the third component — so it gets the same 860px, centred rather than
   left-aligned because this band is. Scoped to `.cta-section` so the page-
   ending `.bottom-cta` keeps its full width: that one carries a HEADING at
   30px, which runs about 70 characters on the same measure and is fine.

   Released below 979 where the container is already narrower than the cap. */
.bakery .cta-section .hm-center { max-width: 860px; margin-left: auto; margin-right: auto; }

@media (max-width: 979px) {
	.bakery .cta-section .hm-center { max-width: none; }
}

/* --- 33.9 §7.11 GALLERY — items keep the ratio they declare ----------------
   Section 13 gives `.hm-gallery__item` `aspect-ratio: 1 / 1` and `.is-print`
   overrides it to 2 / 3. Grid items are `align-self: stretch` by default, and
   a stretched item's height comes from the ROW, not from its own ratio — so
   one 2:3 tile makes its whole row half again as tall and every square beside
   it quietly stops being square. Nothing in the gate set can see that: no
   text moves, no colour changes, no overflow.

   Found by reading section 13 against the components before it, before §7.11
   had ever rendered (standing rule 17). The Photo Booth page sidesteps it by
   using one ratio for the whole grid; the Media page will NOT be able to,
   because §8.7 asks it to mix four categories in one filterable grid. So the
   component gets the fix rather than the page getting a workaround: with
   `align-self: start` a mixed grid is merely ragged at the bottom of a row,
   which is what a masonry-ish gallery looks like anyway, instead of wrong.

   Changes nothing where every tile shares a ratio — all rows are the same
   height, so stretching and not stretching land in the same place. */
.bakery .hm-gallery__item { align-self: start; }

/* --- 33.10 §7.1 BANNER FOCAL POINT, page 2696 -----------------------------
   Third per-page focal after 32.2 and 33.2, same tool. 2773
   (photo-booth-red-carpet-courtyard-venue) is 3:4, so the 420px band keeps
   22% of its height; swept at 20 / 35 / 50 and at dead centre the top of the
   mirror's frame is cut off, which on the one image of the product is the
   whole subject. At 35% the frame, the lit Touch Here To Start screen, the
   stanchions and the red carpet are all in the band. */
body.page-id-2696 .default-header {
	background-position: center 35% !important;
}


/* ===========================================================================
   34. SESSION 16 — Weddings (2700) and the remaining event pages.
   =========================================================================== */

/* --- 34.1 §7.8 TIMELINE TIME CELL — the fourth instance of section 2 -------
   `typeaudit` on Weddings, the first page ever to render §7.8:
   `body #content .hm-timeline__time` declares 16px and computes to 18px.

   THE SAME DEFECT AS 33.7, 32.x AND session 12's bento price. Section 2's
   running-copy rule is
   `body #content p { font-family: var(--bodyfont) !important; font-size: 18px
   !important }` and the time cell is a paragraph element, so it was losing
   BOTH properties — the declared heading typeface as well as the size.
   Section 10 has styled this component since §7.8 was written and no page had
   ever emitted it, which is standing rule 19 doing exactly what it says.

   IMPORTANT ALONE IS ENOUGH HERE, AND THAT WAS COUNTED, NOT ASSUMED
   (standing rule 12). Section 2's selector is `body #content p` at one ID and
   two elements; this one is `body #content .hm-timeline__time` at one ID, one
   class and one element. The class outranks the element, so specificity was
   never the problem — only the bang was. 15.6 needed both because section 2's
   `body #content .hm-card p` is one element heavier than the component rule
   it beat; that is not the shape here. Confirmed with
   `CSS.getMatchedStylesForNode` before writing this, not inferred from the
   computed value (standing rules 10 and 13).

   THE MOBILE DECLARATION HAD THE SAME HOLE. Section 10's 979 block sets the
   time cell to the gold label treatment with an important colour but a plain
   13px, so the stacked-card variant was computing 18px too and nothing had
   ever looked at it. Both breakpoints are fixed together.

   Size and family are pinned together deliberately. Family was the visible
   failure; size was ALSO being overridden at both breakpoints. Leaving either
   unpinned leaves a silent tie that the next edit to section 2 would move. */

body #content .hm-timeline__time {
	font-family: var(--headingfont) !important;
	font-size: 16px !important;
}

@media (max-width: 979px) {
	body #content .hm-timeline__time {
		font-size: 13px !important;
	}
}


/* --- 34.2 WEDDINGS BANNER FOCAL POINT (2700) ------------------------------
   2784 `newlyweds-license-wine-barrel-sedona` is a portrait source and keeps
   only 22% of its height in the 420px desktop band, so the default centre
   crop lands below every face: the first capture cut the officiant off above
   the mouth and took the top of the groom's head with it. Swept with
   `bannerfocal.py` at 20 / 35 / 50 before changing anything (standing rule
   21).

   35% is the only one of the three that works. 20% is sky and the top of one
   bald head. 50% is the default and is what shipped broken. At 35% all five
   faces are intact and inside the band, and the Sedona rock formation is
   behind them, which is the thing that makes this frame worth using on the
   wedding page at all.

   Fifth page to need a focal override — Officiant, Photo Booth, DJ, the 404
   fallback and now this. Every one of them a portrait or 4:3 source in a
   420px band. */

body.page-id-2700 .default-header {
	background-position: center 35% !important;
}


/* --- 34.3 §19 FEATURE — A SECOND PARAGRAPH INSIDE ONE BLOCK ---------------
   About's two bio cards are the first §19 blocks on the site to carry more
   than one paragraph, and the two ran flush together with no gap at all:
   `body #content .hm-feature p` has set `margin: 0 !important` since §19 was
   written. That was right for every block before this one — each had exactly
   one paragraph, so the zero was invisible and the gutter between blocks did
   all the spacing work.

   This is the same class of thing as 33.4, one level further in. 33.4 added
   the gap BETWEEN two stacked features, because until Officiant the
   component had only ever been laid out by `.hm-cards`, which puts the gutter
   on the columns. This adds the gap WITHIN one feature, because until About
   the component had only ever held one paragraph. Standing rule 19, twice on
   the same component.

   IMPORTANT IS REQUIRED AND SPECIFICITY ALONE WOULD NOT HAVE DONE IT. The
   rule being beaten is `body #content .hm-feature p` at one ID, one class and
   two elements, carrying `!important`. This selector adds a second adjacent
   element for one ID, one class and three elements — heavier, but against an
   important declaration specificity never wins on its own (standing rule 12),
   so it needs both.

   STANDING RULE 15 WAS CHECKED, NOT ASSUMED PAST. The rule bans `!important`
   on a property a script animates, margin included. What WPBakery animates
   here is the column wrapper (`.wpb_animate_when_almost_visible`), never the
   paragraphs inside our own div — and `.hm-feature p` has carried an
   important margin since §19 shipped with no interaction. Same element, same
   property, same risk as what is already live.

   12px, not 24px. 24px is the gap BETWEEN blocks (33.4); two run-in labelled
   paragraphs describing one person belong closer together than two separate
   people do. */

body #content .hm-feature p + p { margin-top: 12px !important; }


/* --- 34.4 INLINE BODY-COPY LINKS ON A LIGHT GROUND ------------------------
   AA FAILURE, 1.47:1, 100% of glyph pixels below threshold. Found by the
   contrast gate on Thank You, whose "While you wait" blocks are the first
   place on this site where an ORDINARY INLINE LINK appears inside body copy.

   THE THEME'S DEFAULT LINK COLOUR IS THE BRAND YELLOW. Probed rather than
   guessed (standing rule 10): computed colour is the brand yellow on the
   near-white section ground, which is 1.47:1 — unreadable, and nowhere near
   the 4.5 an 18px link owes.

   IT HAS BEEN LATENT SINCE THE FIRST PAGE. Every link the site has shipped
   so far is explicitly styled — the button, the card link, the menu link,
   the panel title — so the theme default has never been allowed to show.
   Thank You is simply the first page to put a bare anchor in a paragraph.
   Any future page that does the same would have failed the same way, which
   is why this is scoped to the pattern rather than patched onto one block.

   THE COLOUR IS THE ONE THE GATE ALREADY TRUSTS. `--hm-gold-text` is the
   darkened gold the timeline's mobile label uses; it measured 5.37:1 on this
   exact ground earlier in the same session, so it is a known-good value
   rather than a new guess. The underline stays — colour alone must never be
   the only thing distinguishing a link.

   SCOPED TO LIGHT SECTIONS ON PURPOSE. On `.dark1` / `.dark2` grounds the
   brand yellow is correct and already passes; darkening it there would make
   things worse. The selector therefore excludes them, and stays inside
   `.hm-section` so the CTA bands and the footer keep their own treatments. */

body #content .hm-section:not(.dark1):not(.dark2) p a:not([class]) {
	color: var(--hm-gold-text) !important;
	text-decoration: underline;
}


/* --- 34.5 FOOTER LEGAL BAR VERTICAL PADDING -------------------------------
   Cody cleared the duplicate legal NAP theme-option fields so the bar falls
   back to the main NAP values. The line it now renders is shorter, and the
   theme's 18px vertical padding left the text crammed against both edges of
   the band — 66px tall for a 22px line.

   32px top and bottom. Not animated: this is the theme's static footer row,
   not a WPBakery widget, so standing rule 15's ban on important padding does
   not reach it.

   THE SELECTOR IS `body > .row.copyright`, NOT `body footer ...`. The bar is
   a DIRECT CHILD OF BODY and sits OUTSIDE the footer element entirely —
   measured, after the first attempt computed 18px unchanged (standing rule
   13: a computed value is not proof a property was used). Anything else
   scoping a footer rule by the footer element will miss this bar too. */

body > .row.copyright {
	padding-top: 32px !important;
	padding-bottom: 32px !important;
}


/* --- 34.6 PRIVACY POLICY TEMPLATE — VERTICAL PADDING ----------------------
   1617 is the one page on the site that does NOT use the default template.
   It renders through `page-template-privacy.php`, which generates the policy
   from theme settings rather than from the page body — which is why its
   `content` field holds nothing but a disabled row and why none of our
   section wrappers are on the page. With no `.hm-section` anywhere, there
   was no vertical padding at all: the policy heading sat flush against the
   bottom edge of the banner, and the last line ran into the legal bar.

   Matched to the site rhythm rather than invented: `--hm-section-y` is the
   same 60px every `.hm-section` on every other page uses, and the mobile
   token steps it down the same way. The rule is scoped to the template body
   class, so it cannot reach the other three legal pages — Terms,
   Accessibility and the Event Service Agreement are all
   `page-template-default` and already get their padding from the normal
   section wrappers (checked, not assumed). */

body.page-template-privacy .bakery {
	padding-top: var(--hm-section-y);
	padding-bottom: var(--hm-section-y);
}

@media (max-width: 979px) {
	body.page-template-privacy .bakery {
		padding-top: var(--hm-section-y-mobile);
		padding-bottom: var(--hm-section-y-mobile);
	}
}


/* --- 34.7 PRIVACY TEMPLATE — LONG URLS MUST WRAP --------------------------
   473px of horizontal scroll in a 390px viewport, the only hscroll failure
   on the site. `page-template-privacy.php` prints raw URLs as their own link
   text — the contact address, the site URL, and the third-party policy links
   for Google, Instagram, LinkedIn and TikTok. The longest is 421px wide and
   nothing in the cascade lets it break, because a URL has no spaces in it.

   `overflow-wrap: anywhere` rather than `word-break: break-all`, so ordinary
   prose in the same block still breaks on spaces and only the unbreakable
   token is split. Scoped to the template body class.

   NOTE FOR MIGRATION: two of those links are DEV-DOMAIN values pulled from
   theme options — the contact address and the site URL both read
   `…vmgagencysites.com`. That is the §13 `website_email` item, now visible
   on a public page rather than only in a settings screen. */

body.page-template-privacy .bakery a {
	overflow-wrap: anywhere;
}


/* ===========================================================================
   35. SESSION 16b — Media (2694). The filterable gallery and the social strip.
   =========================================================================== */

/* --- 35.1 GALLERY FILTER — THE HIDDEN STATE -------------------------------
   Caught by the rule-17 read BEFORE the first render, not by a gate.

   The filter script hides a tile with the `hidden` attribute rather than an
   inline style, which is the right way to do it: `hidden` is semantic, it
   takes the tile out of the accessibility tree as well as out of the layout,
   and it leaves no inline style for a later redraw to fight. But the browser
   implements `hidden` as a UA rule of `display: none` at the LOWEST possible
   specificity, and section 13 sets `.bakery .hm-gallery__item { display:
   block }` — two classes and an element. The UA rule loses outright, and
   every tile would have stayed visible with the filter appearing to do
   nothing at all.

   No `!important` needed: this selector is the section 13 one plus an
   attribute, so it already outranks it. Counted, not assumed (standing
   rule 12). */

.bakery .hm-gallery__item[hidden] { display: none; }

/* --- 35.2 VISUALLY-HIDDEN LIVE REGION -------------------------------------
   The filter announces its result to a screen reader ("6 items shown") via a
   polite live region. Sighted users get that information from the grid
   itself, so the region is hidden visually but must stay in the
   accessibility tree — which rules out `display: none` and `visibility:
   hidden`, both of which remove it from that tree and silence it.

   The clip-rect pattern rather than a negative text-indent, so it also works
   when the page is set right-to-left. First utility class in the library;
   it is deliberately generic, not gallery-scoped. */

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

/* --- 35.3 GALLERY GROUP — the filter scope --------------------------------
   `.hm-gallery-group` wraps the filter bar, the live region and the grid. It
   is what the filter script queries, so that one page can hold more than one
   independent gallery without the filters on one driving the tiles of the
   other — the script scopes every lookup to this element rather than to the
   document.

   `classaudit` flagged it UNSTYLED on the first build, which was the right
   call and not a false alarm: it needs a real rule. The sr-only live region
   inside it is `position: absolute`, and without a positioned ancestor its
   containing block is the viewport — so on a long page it would be anchored
   somewhere else entirely. `position: relative` makes the group the
   containing block, which is what a visually-hidden element always wants. */

.bakery .hm-gallery-group { position: relative; }

/* --- 35.4 SOCIAL STRIP CENTRED IN A PAGE SECTION --------------------------
   §7.17's first render in a page body rather than in the header or footer.
   Section 17 makes `ul.social` a flex row and never sets `justify-content`,
   which is correct where it has always lived — both the top bar and the
   footer column want the icons packed to the start of their own box. In a
   full-width content column the box is the whole 1280 container, so the four
   icons sat hard against the left edge under a centred heading.

   Scoped to `.hm-center`, so it only centres where the markup has asked to
   be centred; the header and footer strips keep the alignment they have. */

.bakery .hm-center ul.social { justify-content: center; }


/* --- 35.5 PROSE BLOCK HEADINGS — the legal pages -------------------------
   Terms of Service is the first page on the build that is a long PROSE
   document rather than a composed layout: eight headed subsections inside a
   single `.hm-narrow` column. Measured gap between a heading and the
   paragraph under it was exactly ZERO — the heading's bottom margin is
   zeroed globally and every other page on the site puts its headings inside
   a `.hm-sechead` block, where the following ROW's `hm-mt-lg` supplies the
   space instead. In a prose block there is no following row; the paragraph
   is the heading's own next sibling.

   Scoped to `.hm-narrow` so no composed layout is touched — the section-head
   spacing Cody set in session 15 (open item 23) is deliberate and must not
   move. Inside a prose column the two numbers are plain typography: a
   heading sits close to the text it introduces and far from the text it
   follows, so 12px below and 40px above, with the first heading in the block
   keeping its own top spacing from the intro rather than doubling it. */

.bakery .hm-narrow h2 {
	margin-top: 40px;
	margin-bottom: 12px;
}
.bakery .hm-narrow > h2:first-child { margin-top: 0; }
