/* ============================================================================
   Wonderboy Creative — shared UI primitives.
   Button, eyebrow, badge, section, container, reveal, sticky nav, footer,
   reading-progress bar. Used by every page on the site.
   ============================================================================ */

* { box-sizing: border-box; }

/* The [hidden] attribute only carries `display:none` from the UA sheet, so any
   class that sets its own display beats it and the element stays on screen.
   That is how four form success messages ended up visible on page load. Make
   the attribute mean what it says, everywhere. */
[hidden] { display: none !important; }
/* ---- WordPress admin bar --------------------------------------------------
   WP pushes the document down with html{margin-top} when the toolbar is on,
   but position:fixed and position:sticky elements ignore that margin, so a
   logged-in editor sees the site header tucked underneath the toolbar.

   One variable, set on the root so html-level properties can read it too, and
   every fixed or sticky top anchor on the site offsets by it. Only above 783px:
   below that WP switches the toolbar to position:absolute so it scrolls away,
   and a permanent offset would leave a gap.                                  */
:root { --wb-admin-bar: 0px; }
@media screen and (min-width: 783px) {
  html:has(body.admin-bar) { --wb-admin-bar: 32px; }
}

/* scroll-padding keeps anchor targets clear of the fixed nav at every width.
   Smooth scrolling is opt-out: CSS smooth scroll overrides whatever a script
   asks for, so it has to be gated here or a reduced-motion visitor gets
   animated jumps no amount of JS can prevent. */
html { scroll-padding-top: calc(84px + var(--wb-admin-bar)); }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
	margin: 0;
	font-family: var(--font-body);
	color: var(--fg-primary);
	background: var(--white);
	letter-spacing: var(--tracking-body);
	-webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
a { text-decoration: none; color: inherit; }

.wb-container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 28px; }
.wb-accent { color: var(--electric-400); }

/* ---- Icon wrapper --------------------------------------------------------
   An inline <svg> sits on the text baseline, so its line box is a few pixels
   taller than the glyph — enough to make every icon-bearing button and label
   overshoot its designed height. The design system's Icon component avoids
   that by laying the wrapper out as a flex box with a block-level svg; this
   reproduces it, once, for every icon the theme inlines. inline-flex, not flex:
   inside a flex parent it blockifies to flex anyway, but in an inline run it
   stays on the line instead of forcing a break. */
.wb-i { display: inline-flex; }
.wb-i > svg { display: block; }

/* ---- Buttons ------------------------------------------------------------ */
.wb-btn {
	display: inline-flex; align-items: center; justify-content: center; gap: 8px;
	font-family: var(--font-display); font-weight: 700;
	text-transform: uppercase; letter-spacing: .04em;
	border: none; border-radius: var(--radius-pill); cursor: pointer; white-space: nowrap;
	text-decoration: none;
	transition: transform var(--dur-base) var(--ease-out),
				box-shadow var(--dur-base) var(--ease-out),
				background var(--dur-base) var(--ease-out),
				color var(--dur-base) var(--ease-out);
}
.wb-btn-sm { font-size: 12.5px; padding: 9px 16px; }
.wb-btn-md { font-size: 14px;   padding: 13px 22px; }
.wb-btn-lg { font-size: 15px;   padding: 16px 28px; }
.wb-btn:active { transform: scale(.96); }
.wb-btn:focus-visible { outline: none; box-shadow: var(--shadow-glow); }

/* The resting colour is hero-600, not hero-500, and the reason is contrast.
   White on hero-500 (#6375FF) measures 3.81:1. WCAG AA asks 4.5:1 for text
   this size - the button runs 12.5px to 15px, which is normal text by that
   rule, not large - so the site's main call to action was the one element on
   every page that failed it. hero-600 (#4F5EE8) measures 5.12:1 and passes.

   Nothing new was invented to get there. hero-600 is already in the palette
   and was already this button's hover colour, so the button keeps the brand
   blue, keeps darkening on press, and the whole scale shifts down one step:
   rest hero-600, hover hero-700. The glow behind it still comes off hero-500,
   because a shadow carries no text and answers to nobody's contrast ratio. */
.wb-btn-primary { background: var(--hero-600); color: #fff; box-shadow: var(--shadow-brand); }
.wb-btn-primary:hover { background: var(--hero-700); transform: translateY(-2px); box-shadow: 0 12px 30px rgba(79,107,246,.42); }
.wb-btn-ghost { background: transparent; color: var(--hero-600); border: 1.5px solid var(--gray-200); }
.wb-btn-ghost:hover { border-color: var(--hero-300); background: var(--hero-50); }
.wb-btn-ghost-dark { background: rgba(255,255,255,.06); color: #fff; border: 1.5px solid rgba(255,255,255,.22); }
.wb-btn-ghost-dark:hover { background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.4); }
.wb-btn-electric { background: var(--electric-500); color: var(--midnight-950); box-shadow: 0 8px 24px rgba(56,189,248,.4); }
.wb-btn-electric:hover { background: var(--electric-400); transform: translateY(-2px); }

/* ---- Eyebrow / badge --------------------------------------------------- */
.wb-eyebrow {
	font-family: var(--font-mono); font-weight: 500; font-size: 12px;
	letter-spacing: .18em; text-transform: uppercase; color: var(--hero-600);
}

/* ---- Reveal-on-scroll wrapper ----------------------------------------- */
.wb-reveal { opacity: 0; transform: translateY(18px);
	transition: opacity .6s var(--ease-out), transform .6s var(--ease-out); }
.wb-reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
	.wb-reveal { opacity: 1 !important; transform: none !important; }
}

/* ===========================================================================
   FORMS — the lead form and its success state.

   Shared chrome, not a page's own furniture: the home page's quote modal and
   the contact page both draw these, so they are defined once here rather than
   copied into each surface's stylesheet. Moved out of home.css when the contact
   page needed them.
   ========================================================================== */
.wb-form { display: flex; flex-direction: column; gap: 16px; }
.wb-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.wb-form label { display: flex; flex-direction: column; gap: 7px; font-family: var(--font-body); font-weight: 600; font-size: 13.5px; color: var(--midnight-900); }
.wb-form input, .wb-form select, .wb-form textarea {
  font-family: var(--font-body); font-size: 15px; padding: 12px 14px; border: 1.5px solid var(--gray-200);
  border-radius: var(--radius-md); background: #fff; color: var(--midnight-900); font-weight: 400; transition: border-color var(--dur-base), box-shadow var(--dur-base); width: 100%;
}
.wb-form input::placeholder, .wb-form textarea::placeholder { color: var(--gray-400); }
.wb-form input:focus, .wb-form select:focus, .wb-form textarea:focus { outline: none; border-color: var(--hero-500); box-shadow: var(--shadow-glow); }
.wb-form textarea { resize: vertical; }
.wb-form .wb-btn { margin-top: 6px; }
.wb-modal-success { text-align: center; padding: 16px 0; }
.wb-modal-success-icon { width: 72px; height: 72px; border-radius: 50%; background: var(--success-bg); color: var(--success); display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; }
.wb-modal-success h2 { font-family: var(--font-display); font-weight: 800; font-size: 26px; color: var(--midnight-900); margin: 0 0 10px; }
.wb-modal-success p { font-size: 15px; line-height: 1.6; color: var(--fg-secondary); margin: 0 0 24px; }
@media (max-width: 600px) {
	.wb-form-row { grid-template-columns: 1fr; }
}
/* Safari on iOS zooms the whole page in when a field smaller than 16px takes
   focus, and it does not zoom back out. Every form on the site was between
   14px and 15px, so tapping any of them threw the layout sideways and left
   the visitor pinch-zooming to find the next field. 16px is the threshold,
   not a preference. */
@media (max-width: 860px) {
	.wb-form input, .wb-form select, .wb-form textarea { font-size: 16px; }
}

/* ===========================================================================
   STICKY NAV — fixed header, transparent over dark hero, frosts on scroll.
   ========================================================================== */
.wb-nav {
	position: fixed; top: var(--wb-admin-bar); left: 0; right: 0; z-index: 100;
	transition: background var(--dur-base) var(--ease-out),
				box-shadow var(--dur-base) var(--ease-out),
				backdrop-filter var(--dur-base);
}
.wb-nav.is-scrolled {
	/* Opaque, deliberately.

	   This was rgba(255,255,255,.85) leaning on the blur below it to stay
	   legible. At .85 the bar is a 15% window onto the article: measured on
	   /winery-seo/ at scrollY 1500, roughly 15,700 pixels of the nav band
	   differed depending on whether the article behind it was visible, worst
	   rows around y57-y62 where the logo sits. That is what "a paragraph
	   renders behind the logo" was. The blur smeared it rather than hiding it,
	   and where a browser or a setting drops backdrop-filter there was no
	   fallback at all and the copy read straight through.

	   The scroll offsets were never the cause. html{scroll-padding-top} and
	   .wsp-sec{scroll-margin-top} already clear the 72px bar with room over. */
	background: #fff;
	backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
	box-shadow: 0 1px 0 var(--gray-200), var(--shadow-sm);
}
/* A mega panel is a white shelf hanging off the bar. At the top of a page the
   bar is transparent over a dark hero, which would leave the panel floating
   under a strip of photograph, so opening one makes the bar opaque too. The
   panel supplies its own shadow, so the bar drops its own to avoid a seam. */
.wb-nav.is-mega-open { background: #fff; box-shadow: none; }
/* A light-topped page (see the wb-nav-solid body class): the bar is solid
   from the first pixel and holds its own space, so the page below starts
   under it rather than behind it. This is the header the design draws on the
   contact page; the dark-hero pages are untouched. */
body.wb-nav-solid .wb-nav { background: #fff; box-shadow: 0 1px 0 var(--gray-200); }
body.wb-nav-solid .wp-site-blocks > main { padding-block-start: 72px; }
/* The fixed nav overlays a full-bleed hero on every page. WordPress's default
   block-gap puts a top margin on <main>, which pushed the hero ~24px down so
   the nav's upper band floated over white and clipped the logo. Zero it out so
   the hero sits flush at the very top, behind the transparent nav. */
.wp-site-blocks > main { margin-block-start: 0; }
.wb-nav-inner { display: flex; align-items: center; justify-content: space-between; height: 72px; }
.wb-nav-logo { display: inline-flex; align-items: center; }
.wb-nav-logo img { height: 40px; display: block; }
.wb-nav .wb-logo-light { display: none; }
.wb-nav .wb-logo-dark  { display: block; }
/* Opening a mega panel turns the bar white, so the wordmark has to swap with
   it. Without this the on-dark (white ink) logo sat on a white bar at the top
   of a page and the word WONDERBOY simply disappeared, leaving the mascot and
   the word CREATIVE floating on their own. */
.wb-nav.is-scrolled .wb-logo-light,
.wb-nav.is-mega-open .wb-logo-light,
body.wb-nav-solid .wb-logo-light { display: block; }
.wb-nav.is-scrolled .wb-logo-dark,
.wb-nav.is-mega-open .wb-logo-dark,
body.wb-nav-solid .wb-logo-dark  { display: none; }
.wb-nav-links { display: flex; gap: 30px; align-self: stretch; align-items: center; }
.wb-nav-links a,
.wb-nav-links .wbm-link {
	font-family: var(--font-display); font-weight: 700; font-size: 13px;
	text-transform: uppercase; letter-spacing: .1em;
	color: rgba(255,255,255,.88);
	position: relative; padding: 4px 0;
	transition: color var(--dur-fast);
}
.wb-nav.is-scrolled .wb-nav-links a,
.wb-nav.is-scrolled .wb-nav-links .wbm-link,
body.wb-nav-solid .wb-nav-links a,
body.wb-nav-solid .wb-nav-links .wbm-link,
.wb-nav.is-mega-open .wb-nav-links a,
.wb-nav.is-mega-open .wb-nav-links .wbm-link { color: var(--midnight-900); }
.wb-nav-links a:hover,
.wb-nav-links .wbm-link:hover,
.wb-nav-links .wbm-link.is-hot { color: var(--hero-500); }
.wb-nav-links a::after,
.wb-nav-links .wbm-link::after {
	content: ''; position: absolute; left: 0; right: 100%; bottom: -2px; height: 2px;
	background: var(--hero-500); transition: right var(--dur-base) var(--ease-out);
}
.wb-nav-links a:hover::after,
.wb-nav-links .wbm-link:hover::after,
.wb-nav-links .wbm-link.is-hot::after,
.wb-nav-links .wbm-link.is-active::after { right: 0; }

.wb-nav-actions { display: flex; align-items: center; gap: 18px; }
.wb-nav-phone {
	display: inline-flex; align-items: center; gap: 6px;
	font-family: var(--font-mono); font-size: 13px; font-weight: 500;
	color: rgba(255,255,255,.86);
}
.wb-nav.is-scrolled .wb-nav-phone,
.wb-nav.is-mega-open .wb-nav-phone,
body.wb-nav-solid .wb-nav-phone { color: var(--midnight-900); }
.wb-nav-phone:hover { color: var(--electric-400); }
body.wb-nav-solid .wb-nav-phone:hover { color: var(--hero-600); }
.wb-nav.is-scrolled .wb-nav-phone:hover { color: var(--hero-600); }
.wb-nav-burger {
	display: none; background: none; border: none; cursor: pointer;
	color: #fff; padding: 4px;
}
.wb-nav.is-scrolled .wb-nav-burger,
.wb-nav.is-mega-open .wb-nav-burger,
body.wb-nav-solid .wb-nav-burger { color: var(--midnight-900); }
/* Burger glyphs are two inline SVGs; CSS swaps them so the JS never has to
   rewrite the button's contents. */
.wb-nav-burger .wb-burger-open,
.wb-nav-burger .wb-burger-close { display: inline-flex; }
.wb-nav-burger .wb-burger-close { display: none; }
.wb-nav-burger.is-open .wb-burger-open { display: none; }
.wb-nav-burger.is-open .wb-burger-close { display: inline-flex; }
.wb-nav-mobile { display: none; padding: 16px 28px 24px; flex-direction: column; gap: 14px; }
.wb-nav-mobile a {
	font-family: var(--font-display); font-weight: 700; font-size: 16px;
	text-transform: uppercase; letter-spacing: .08em; color: var(--midnight-900);
}
/* Nested page sits visually under its hub parent in the mobile list. */
.wb-nav-mobile a.wb-nav-mobile-sub {
	padding-left: 16px; font-size: 14px; color: var(--gray-600);
	border-left: 2px solid var(--gray-200);
}
.wb-nav.is-open .wb-nav-mobile {
	display: flex; background: #fff;
	border-top: 1px solid var(--gray-100); box-shadow: var(--shadow-md);
}

/* ---------------------------------------------------------------------------
   THE BAR ON A PHONE

   Collapsing to a burger at 860px was only half the job. Nothing below that
   ever did the arithmetic, and the three things left in the bar do not fit
   inside a phone: at 390px the wordmark wants 177px, the quote button and the
   burger want 197px, and the container's 28px gutters leave 334px between
   them. Flex has to take 40px from somewhere, and it takes them from the
   wordmark - which is a fixed-ratio SVG, so it did not scale down, it was cut.
   The word WONDERBOY ran under the quote button on every page of the site, at
   every phone width, which is the first thing anyone sees.

   So the items are given sizes that add up. The wordmark stops shrinking, the
   bar loses eight pixels of height and gutter, and the burger grows to a real
   44px target instead of the 30px box it was.
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
	/* The bar collapses to a burger here, which is this site's breakpoint, not
	   the prototype's 900. The panels go with it: below this the drawer is the
	   menu. */
	.wb-nav-links, .wb-nav-phone { display: none; }
	.wbm-panel { display: none; }
	.wb-nav-inner { height: 64px; gap: 10px; padding-left: 20px; padding-right: 20px; }
	/* Never squeeze the wordmark. Everything else in the bar yields first. */
	.wb-nav-logo { flex: 0 0 auto; min-height: 44px; }
	.wb-nav-logo img { height: 30px; width: auto; }
	.wb-nav-actions { flex: 0 1 auto; gap: 8px; margin-left: auto; min-width: 0; }
	.wb-nav-actions .wb-btn-sm { font-size: 12px; padding: 11px 15px; }
	/* Pulled into the gutter so the glyph stays optically where it was while
	   the tappable box around it grows to the full 44px. */
	.wb-nav-burger {
		display: inline-flex; flex: 0 0 auto; width: 44px; height: 44px; padding: 0;
		margin-right: -9px; align-items: center; justify-content: center;
	}
	.wb-nav.is-open .wb-nav-mobile { padding: 14px 20px 22px; }
	/* The rows inside an opened Services or Work group. These are the links to
	   the actual pages, so they are the ones most likely to be pressed, and
	   they were the shortest thing in the drawer at 35px. */
	.wbm-dsub a { display: flex; align-items: center; min-height: 44px; padding: 0; }
	/* The drawer's own quote button. Full width, thumb height, last in the
	   list because the menu is what you opened the drawer to read.

	   The colour needs the parent in the selector, not just the class. Every
	   link in the drawer is coloured by `.wb-nav-mobile a`, which is a class
	   and a type - more specific than `.wb-btn-primary`, and more specific
	   than a bare `.wbm-dcta` too. Without beating it the button renders dark
	   navy ink on the brand blue: the same button, two different colours,
	   depending which of the two places you meet it in. */
	.wbm-dcta { width: 100%; margin-top: 4px; }
	.wb-nav-mobile a.wbm-dcta { color: #fff; }
}

/* Under about 380px the bar cannot hold the wordmark, a button and a burger at
   readable sizes however the padding is spent. The button steps out and the
   drawer's copy of it takes over - it is two taps instead of one, on the
   narrowest phones sold, and it is the only item of the three that has a
   second home. */
@media (max-width: 380px) {
	.wb-nav-inner { padding-left: 16px; padding-right: 16px; }
	.wb-nav-actions .wb-btn { display: none; }
	.wb-nav-logo img { height: 32px; }
}

/* ---------------------------------------------------------------------------
   THE BUTTON LABEL, ON A NARROW PHONE

   .wb-btn is white-space:nowrap, which is what makes a pill a pill. The cost
   only shows up at the bottom of the range: "Start the conversation" is 211px
   of unbreakable text, and with the button's padding, the card it sits in and
   the wrapper's gutters it made the page 340px wide before a single word of
   the article was laid out. A phone narrower than that does not get a
   horizontal scrollbar - it gets shrink-to-fit, so a 360px Android was reading
   the whole site at 88% with no way to tell why the type was small.

   The label wraps below 480px. Above it nothing changes: a button wide enough
   for its text is laid out identically either way.
   -------------------------------------------------------------------------- */
@media (max-width: 480px) {
	.wb-btn { white-space: normal; text-wrap: balance; }
}

/* ===========================================================================
   MEGA MENU — the panels that hang off the bar.

   A verbatim port of the .wbm-* rules in content/design/css/contact.css, minus
   that prototype's own header bar (.wbm, .wbm-inner, .wbm-logo, .wbm-phone,
   .wbm-burger). This site keeps the header it already had, because every page's
   hero is built to sit underneath a transparent fixed bar; what it adopts is
   the menu inside it. Tokens are the ones already in tokens.css, which carry
   the same values as the prototype's colors_and_type.css, so nothing here
   needed a second copy of the palette.
   ========================================================================== */
/* The bar's own layout is unchanged: .wb-nav-links already lays these out and
   already hides them at 860px. Declaring display here as well re-showed the
   whole row on a phone, because this block sits after that breakpoint and won
   on source order - the five items then pushed the burger off the screen. */
.wbm-slot { display: flex; align-items: center; }
/* The bar's items are anchors and buttons now. The button needs its chrome
   removed before the shared .wb-nav-links treatment above can land on it. */
.wb-nav-links button.wbm-link {
	border: 0; background: none; cursor: pointer; font-size: 13px;
	display: inline-flex; align-items: center; gap: 5px;
}
.wbm-caret { transition: transform var(--dur-base) var(--ease-out); opacity: .55; }
.wbm-link.is-hot .wbm-caret { transform: rotate(180deg); opacity: 1; }
/* Only one underline at a time: the open panel wins over the current page. */
.wb-nav.is-mega-open .wb-nav-links .wbm-link.is-active:not(.is-hot)::after { right: 100%; }

/* the panel: full-bleed white shelf hanging off the bar */
.wbm-panel {
	/* theme.json puts line-height:1.65 on body, and WordPress emits it as a body
	   rule on every page. The prototype's stylesheet has no such rule, so every
	   element in this menu that does not name its own line-height was laid out
	   against `normal`. Inheriting 1.65 instead made each focus area 5px taller
	   and each panel 13 to 19px taller than the design. Resetting it here, on
	   the panel only, restores the design's inheritance without touching the
	   body rule the rest of the site is built on: the rules below that do name
	   a line-height still win, exactly as they do in the prototype. */
	line-height: normal;
	position: absolute; left: 0; right: 0; top: 100%; background: var(--white);
	border-top: 1px solid var(--gray-200); box-shadow: 0 22px 44px rgba(22,33,58,.13);
	animation: wbm-drop .18s var(--ease-out);
}
@keyframes wbm-drop { from { opacity: 0; transform: translateY(-7px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .wbm-panel { animation: none; } }
.wbm-grid { display: grid; gap: 0; padding: 34px 0 6px; }
.wbm-grid.is-pillars { grid-template-columns: 300px 1fr; }
.wbm-grid.is-cards { grid-template-columns: 270px 1fr; }
.wbm-grid.is-index { grid-template-columns: 420px 1fr; }
.wbm-rail { padding-right: 36px; border-right: 1px solid var(--gray-200); padding-bottom: 28px; }
.wbm-body { padding: 0 0 30px 36px; }
/* Pillar panels vary in item count; a floor stops the shelf collapsing when
   you move from a 7-item pillar to a 3-item one. */
.wbm-grid.is-pillars .wbm-body { min-height: 290px; }
.wbm-grid.is-pillars .wbm-rail { min-height: 290px; }
/* Every pillar body is in the document so a crawler sees all of them; only the
   selected one is on screen. grid-area keeps the hidden ones out of the flow
   without a second column opening up behind them. */
.wbm-grid.is-pillars .wbm-body { grid-column: 2; grid-row: 1; }
.wbm-rail-title, .wbm-sub {
	font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
	letter-spacing: .16em; text-transform: uppercase; color: var(--gray-400); margin: 0 0 14px;
}

/* pillar rail (two-level services menu) */
.wbm-pill {
	display: flex; align-items: center; gap: 11px; width: 100%; padding: 10px 12px;
	border: 0; border-radius: var(--radius-md); background: none; cursor: pointer;
	text-align: left; color: var(--midnight-900);
	transition: background var(--dur-fast), color var(--dur-fast);
}
.wbm-pill-ico {
	display: inline-flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; border-radius: 9px; background: var(--gray-100);
	color: var(--hero-600); flex-shrink: 0;
	transition: background var(--dur-fast), color var(--dur-fast);
}
.wbm-pill-name { font-family: var(--font-display); font-weight: 700; font-size: 15.5px; flex: 1; }
.wbm-pill-arrow { opacity: 0; color: var(--hero-500); transition: opacity var(--dur-fast), transform var(--dur-fast); }
.wbm-pill:hover, .wbm-pill.is-on { background: var(--hero-50); color: var(--hero-700); }
.wbm-pill.is-on .wbm-pill-ico { background: var(--hero-500); color: #fff; }
.wbm-pill.is-on .wbm-pill-arrow { opacity: 1; transform: translateX(2px); }

/* pillar body */
.wbm-lede {
	display: flex; align-items: flex-start; justify-content: space-between; gap: 30px;
	padding-bottom: 18px; margin-bottom: 20px; border-bottom: 1px solid var(--gray-200);
}
.wbm-lede p { font-size: 15px; line-height: 1.6; color: var(--fg-secondary); margin: 0; max-width: 58ch; }
.wbm-more {
	display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0;
	font-family: var(--font-display); font-weight: 700; font-size: 12.5px;
	text-transform: uppercase; letter-spacing: .08em; color: var(--hero-600);
	transition: gap var(--dur-fast);
}
.wbm-more:hover { gap: 11px; }
.wbm-areas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px 10px; }
.wbm-foot { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--gray-200); width: 100%; }
.wbm-area { display: block; padding: 10px 12px; border-radius: var(--radius-md); transition: background var(--dur-fast); }
.wbm-area b {
	display: block; font-family: var(--font-body); font-weight: 600; font-size: 14.5px;
	color: var(--midnight-900); margin-bottom: 3px;
}
.wbm-area span { display: block; font-size: 12.5px; line-height: 1.45; color: var(--gray-500); }
.wbm-area:hover { background: var(--gray-50); }
.wbm-area:hover b { color: var(--hero-600); }

/* category lists */
.wbm-cats { display: grid; gap: 1px; }
.wbm-cats.is-two { grid-template-columns: 1fr 1fr; gap: 1px 18px; }
.wbm-cat {
	display: flex; align-items: baseline; gap: 7px; padding: 6px 0;
	font-size: 14.5px; color: var(--fg-secondary); transition: color var(--dur-fast);
}
.wbm-cat i { font-style: normal; color: var(--hero-400); font-size: 13px; }
.wbm-cat:hover { color: var(--hero-600); }

/* featured cards */
.wbm-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 20px; }
.wbm-card {
	display: flex; flex-direction: column; gap: 12px; padding: 14px;
	border: 1px solid var(--gray-200); border-radius: var(--radius-lg); background: var(--white);
	transition: border-color var(--dur-base), box-shadow var(--dur-base), transform var(--dur-base);
}
.wbm-card:hover { border-color: var(--hero-300); box-shadow: 0 8px 20px rgba(22,33,58,.08); transform: translateY(-2px); }
.wbm-thumb {
	display: flex; align-items: center; justify-content: center; height: 74px;
	border-radius: var(--radius-md); background: var(--gray-50);
	border: 1px solid var(--gray-100); color: var(--hero-500);
}
.wbm-thumb img {
	max-width: 78%; max-height: 44px; width: auto; height: auto; object-fit: contain;
	filter: grayscale(1); opacity: .72;
	transition: filter var(--dur-base), opacity var(--dur-base);
}
.wbm-card:hover .wbm-thumb img { filter: none; opacity: 1; }
.wbm-thumb.is-guide { background: var(--midnight-900); border-color: var(--midnight-900); color: var(--electric-400); }
.wbm-card-txt { display: flex; flex-direction: column; gap: 4px; }
.wbm-card-txt em {
	font-family: var(--font-mono); font-style: normal; font-size: 10px; font-weight: 600;
	letter-spacing: .12em; text-transform: uppercase; color: var(--hero-600);
}
.wbm-card-txt b { font-family: var(--font-display); font-weight: 700; font-size: 15px; line-height: 1.25; color: var(--midnight-900); }
.wbm-card-txt span { font-size: 12.5px; line-height: 1.45; color: var(--gray-500); }
.wbm-card-txt u { text-decoration: none; font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; color: var(--success); margin-top: 2px; }

/* mobile drawer */
/* The drawer's groups are separated by their own rules, so the shell's gap
   would double every divider. It scrolls, because Services alone is five
   rows before anything else is open. */
.wb-nav-mobile.wbm-drawer { gap: 0; max-height: 74vh; overflow: auto; }
.wbm-dgroup { border-bottom: 1px solid var(--gray-100); }
.wbm-drow {
	display: flex; align-items: center; justify-content: space-between; width: 100%;
	padding: 15px 0; border: 0; background: none; cursor: pointer;
	font-family: var(--font-display); font-weight: 700; font-size: 14px;
	text-transform: uppercase; letter-spacing: .08em; color: var(--midnight-900);
}
.wbm-dsub { display: flex; flex-direction: column; padding: 0 0 14px; gap: 2px; }
.wbm-dsub a { padding: 7px 0; font-size: 15px; color: var(--fg-secondary); text-transform: none; letter-spacing: 0; font-family: var(--font-body); font-weight: 400; }
.wbm-dphone {
	display: flex; align-items: center; gap: 8px; padding: 16px 0;
	font-family: var(--font-mono); font-size: 14px; color: var(--hero-600);
	text-transform: none; letter-spacing: 0;
}
.wbm-drow .wbm-dminus { display: none; }
.wbm-drow[aria-expanded="true"] .wbm-dplus { display: none; }
.wbm-drow[aria-expanded="true"] .wbm-dminus { display: inline-flex; }

/* Panel internals reflow before the nav itself collapses, so the mega menu
   survives a laptop window rather than jumping straight to a burger. */
@media (max-width: 1240px) {
	.wbm-grid.is-pillars, .wbm-grid.is-cards { grid-template-columns: 246px 1fr; }
	.wbm-grid.is-index { grid-template-columns: 330px 1fr; }
	.wbm-areas { grid-template-columns: 1fr 1fr; }
	.wbm-rail { padding-right: 26px; }
	.wbm-body { padding-left: 26px; }
	.wbm-lede { flex-direction: column; gap: 14px; }
}
@media (max-width: 1120px) {
	.wbm-cards { gap: 10px; }
	.wbm-card { padding: 12px; }
	.wbm-thumb { height: 62px; }
}
/* ===========================================================================
   FOOTER — midnight band, brand blurb, three link columns, legal row.
   ========================================================================== */
.wb-footer { background: var(--midnight-950); color: #cdd5e6; padding: 64px 0 24px; }
.wb-footer-inner {
	display: grid; grid-template-columns: 1.2fr 2fr; gap: 48px;
	padding-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,.08);
}
.wb-footer-brand img { height: 38px; margin-bottom: 16px; }
.wb-footer-brand p { font-size: 14.5px; line-height: 1.6; color: #aeb9cf; margin: 0 0 16px; max-width: 320px; }
.wb-footer-social { display: flex; gap: 12px; }
.wb-footer-social a {
	width: 38px; height: 38px; border-radius: 50%;
	background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.08);
	display: inline-flex; align-items: center; justify-content: center;
	color: #aeb9cf; transition: background var(--dur-base), color var(--dur-base);
}
.wb-footer-social a:hover { background: var(--hero-500); color: #fff; border-color: var(--hero-500); }
/* Legal links sit on one row with real spacing rather than butting together. */
.wb-footer-base-links { display: flex; gap: 20px; }
.wb-footer-base-links a:hover { color: var(--electric-400); }
/* The services block takes the width it needs for its own internal columns;
   More is one narrow column beside it. */
.wb-footer-cols { display: grid; grid-template-columns: minmax(0, 1fr) 190px; gap: 40px; }
/* Hubs across, spokes down. Five silos wrap to as many rows as the width
   allows rather than being pinned to a fixed count. */
.wb-footer-silos { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 28px 32px; }
.wb-footer-silo h3 {
	font-family: var(--font-display); font-weight: 800; font-size: 14px;
	margin: 0 0 8px; letter-spacing: -.01em;
}
/* The hub is the bold row and its spokes hang under it, so the shape of the
   silo is legible without reading a single label. */
.wb-footer-silo h3 a, .wb-footer-silo h3 .wb-pending { color: #fff; }
.wb-footer-silo h3 a:hover { color: var(--electric-400); }
.wb-footer-silo > a, .wb-footer-silo > .wb-pending {
	display: block; padding: 4px 0; font-size: 13.5px; line-height: 1.45;
	color: #9aa6bf; transition: color var(--dur-fast);
}
.wb-footer-silo > a:hover { color: var(--electric-400); }
.wb-footer-svc > h2, .wb-footer-reading > h2 {
	font-family: var(--font-display); font-weight: 800; font-size: 13px;
	text-transform: uppercase; letter-spacing: .08em; color: #fff; margin: 0 0 18px;
}

/* Three recent articles, at footer scale. */
.wb-footer-reading { padding: 34px 0 0; }
/* The article archives, as one wrapping row of topics. */
.wb-footer-topics { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 0 0 22px; }
.wb-footer-topics a {
	font-size: 13px; color: #9aa6bf; transition: color var(--dur-fast);
	display: inline-flex; align-items: center; min-height: 24px;
}
.wb-footer-topics a:hover { color: var(--electric-400); }
.wb-footer-post-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wb-footer-posts { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; }
.wb-footer-post { display: flex; gap: 14px; align-items: center; min-height: 44px; }
.wb-footer-post-thumb {
	flex: 0 0 84px; width: 84px; height: 56px; border-radius: var(--radius-sm);
	overflow: hidden; background: rgba(255,255,255,.06);
}
.wb-footer-post-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wb-footer-post-txt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.wb-footer-post-title {
	font-family: var(--font-display); font-weight: 700; font-size: 13.5px;
	line-height: 1.35; color: #e7ecf7; text-wrap: pretty;
}
.wb-footer-post:hover .wb-footer-post-title { color: var(--electric-400); }
.wb-footer-post time { font-family: var(--font-mono); font-size: 11px; color: #7d8aa5; }
/* Same type as the column links, so the footer still reads as one thing. The
   standfirst above it already carries the 16px gap. */
.wb-footer-contact { display: flex; flex-direction: column; margin: 0 0 18px; }
.wb-footer-contact a {
	display: flex; align-items: center; min-height: 30px;
	font-size: 14.5px; color: #aeb9cf; transition: color var(--dur-fast);
}
.wb-footer-contact a:hover { color: var(--electric-400); }
.wb-footer-col h2 {
	font-family: var(--font-display); font-weight: 800; font-size: 13px;
	text-transform: uppercase; letter-spacing: .08em; color: #fff; margin: 0 0 14px;
}
.wb-footer-col a {
	display: block; padding: 5px 0; font-size: 14px; color: #aeb9cf;
	transition: color var(--dur-fast);
}
.wb-footer-col a:hover { color: var(--electric-400); }
.wb-footer-base {
	display: flex; align-items: center; justify-content: space-between;
	flex-wrap: wrap; gap: 12px; padding-top: 24px;
	font-family: var(--font-mono); font-size: 12px; color: #6f7c97;
}
.wb-footer-base a { color: #aeb9cf; }
.wb-footer-base a + a { margin-left: 18px; }
.wb-footer-base a:hover { color: #fff; }

@media (max-width: 760px) {
	.wb-footer-inner { grid-template-columns: 1fr; gap: 36px; }
	.wb-footer-cols { grid-template-columns: 1fr; gap: 32px; }
	.wb-footer-silos { grid-template-columns: 1fr 1fr; gap: 24px; }
	.wb-footer-posts { grid-template-columns: 1fr; }
	/* Every footer link is a thumb target below this width. WCAG 2.2 asks for
	   44px and the responsive harness measures it; the contact links shipped at
	   30 and were caught there. */

}

/* ---------------------------------------------------------------------------
   THUMB TARGETS

   A mouse pointer is one pixel and a thumb is about eleven millimetres, which
   is where the 44px floor in WCAG 2.2 comes from. Every control on this site
   was drawn for the pointer: the footer's link columns are 33px rows, its
   social buttons 38px, its legal links 20px, and the two links in that last
   row sit 20px apart, so on a phone you aim at Privacy and open Terms.

   Sizes only, and no type, colour or copy changes with them. The one place a
   width moves is the footer's social circles, which are round and cannot grow
   in one direction alone. None of it exists above 860px: the desktop bar,
   footer and buttons are the ones that were signed off, and they are the same
   pixels they were.
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
	.wb-btn { min-height: 44px; }
	.wb-footer-col a { display: flex; align-items: center; min-height: 44px; padding: 0; }
	.wb-footer-social a { width: 44px; height: 44px; }
	/* The legal row: real rows on a phone rather than two words on one line. */
	.wb-footer-base { gap: 4px; }
	.wb-footer-base-links { flex-wrap: wrap; gap: 0 24px; }
	.wb-footer-base-links a,
	.wb-footer-base a { display: inline-flex; align-items: center; min-height: 44px; }
	.wb-footer-base a + a { margin-left: 24px; }
}

/* Same arithmetic as .wb-btn above: the three link columns in two tracks want
   about 121px each, which with the gap and the container's gutters makes 323px
   the narrowest the page can be drawn - so a 320px phone was shrunk to fit.
   They stack below 480px. This has to sit after the 760px block above, not
   with the other narrow-phone rules further up the file: same selector, same
   specificity, so the later one is the one that counts. */
@media (max-width: 480px) {
	.wb-footer-cols { grid-template-columns: 1fr; gap: 20px; }
}

/* ---- Lead forms ----------------------------------------------------------
   The honeypot is moved off-screen rather than display:none — bots skip fields
   they can tell are hidden, and a screen reader is kept out with aria-hidden
   on the wrapper. */
.wbc-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.wbc-form-error {
	margin: 8px 0 0; font-family: var(--font-body); font-size: 13px; line-height: 1.45;
	color: var(--danger);
}

/* ---- Not-built-yet destinations ------------------------------------------
   Pages in the sitemap that have not shipped render as an <a> with no href.
   Every `a` rule around them still applies, so they sit in place looking as
   designed, but an anchor without href is not a link — no link role, not
   focusable, cannot navigate. That keeps the footer and the silo navigation
   complete without shipping 404s, and each one becomes a real link the day its
   page is published, with no edit anywhere.

   Lives here rather than in a page-type stylesheet because the footer uses it
   on every page of the site. */
.wb-pending { cursor: default; }

/* Thumb targets in the footer, to the width this site serves a touch layout:
   860px, the same breakpoint the nav uses for its burger and the width
   tests/responsive.mjs measures at. These lived in the 760px block and left
   every footer link 15 to 30px tall at 768. */
@media (max-width: 860px) {
	.wb-footer-contact a,
	.wb-footer-col a, .wb-footer-col .wb-pending,
	.wb-footer-silo h3 a, .wb-footer-silo h3 .wb-pending,
	.wb-footer-silo > a, .wb-footer-silo > .wb-pending {
		min-height: 44px; display: flex; align-items: center;
	}
	.wb-footer-silo h3 { margin-bottom: 2px; }
	.wb-footer-base-links a { min-height: 44px; display: inline-flex; align-items: center; }
	.wb-footer-post { min-height: 56px; }
	.wb-footer-topics a { min-height: 44px; }
}

/* Icon presentation, once, instead of on every instance.
   These six attributes - fill, stroke, both linecaps, the default stroke-width
   and the viewBox - were repeated on all 121 icons of the winery hub, 145 bytes
   apiece. The viewBox moved to the <symbol> in the sprite; the rest are here.
   A caller wanting a different weight still emits stroke-width itself, and an
   attribute beats a class selector, so that keeps working. */
.wb-icon {
	fill: none; stroke: currentColor; stroke-width: 2;
	stroke-linecap: round; stroke-linejoin: round;
}

/* The hub row inside the phone drawer, and its spokes indented under it.
   The Services drawer is 27 rows now that the spokes are in it, and without a
   difference between the two levels it reads as one undifferentiated list. */
.wbm-dsub a.wbm-dhub {
	font-family: var(--font-display); font-weight: 800; font-size: 15px;
	color: #fff; text-transform: none; letter-spacing: -.01em;
	margin-top: 10px; padding-bottom: 2px;
}
.wbm-dsub a.wbm-dhub:first-child { margin-top: 0; }
.wbm-dsub a:not(.wbm-dhub) { padding-left: 14px; }
