/*
Theme Name: B+J's Shaved Ice
Theme URI: https://www.bjsshavedice.com
Author: NewbillTech
Description: Custom block theme for B+J's Shaved Ice food trailer — hot pink script branding, sage and mint accents, watercolor cups and leaf sprigs from the trailer wrap. Visual system ported from the approved Lovable prototype.
Version: 3.94.0
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: bjs-shaved-ice
*/

/* The real wrap caps face, self-hosted from the licensed web-font package. It ships
   as a single weight, so every rule that used to ask Archivo for 700/800/900 now asks
   for 400 — a synthesised bold would thicken the strokes and stop matching the vinyl.
   font-synthesis: none is the belt to that braces.

   This face is declared twice on purpose — here for the front end and the editor
   stylesheet, and again in theme.json so WordPress registers it properly. Change the
   filename in one and you must change it in the other. */
@font-face {
	font-family: 'Vancouver Gothic';
	src: url('assets/fonts/vancouver-gothic-webfont.woff2') format('woff2'),
		url('assets/fonts/vancouver-gothic-webfont.woff') format('woff');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

html {
	scroll-behavior: smooth;
	font-synthesis-weight: none;
	font-synthesis: none;
}
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
	.wp-block-button__link:hover,
	.wp-block-button__link:focus,
	.bjs-social a:hover,
	.bjs-social a:focus {
		transform: none;
	}
	.bjs-menu-bars,
	.bjs-menu-bars::before,
	.bjs-menu-bars::after {
		transition: none;
	}
	.bjs-menu-panel {
		animation: none;
	}
}
[id] {
	scroll-margin-top: 5rem; /* scroll-mt-20 */
}

/* The script lockup is no longer type — it is the actual wrap lettering, cut from the
   trailer photo. Delivered as a mask, the same technique as .bjs-heart, so it takes the
   brand pink from `color` (the has-pink-color preset) and can never render off-brand.
   Size is still driven by font-size, so the three call sites keep their existing hooks
   untouched: header inline 1.7rem, footer has-x-large-font-size, hero has-script-hero-font-size.
   The source PNG is 1016 x 484, aspect ratio 2.0992 — width is that ratio times the height.
   The literal "B+J's" stays in the DOM for search engines and screen readers and is pulled
   out of layout by text-indent, which is inherited by the header's <a>. */
.bjs-script {
	--bjs-script-height: 1.05em;
	display: block;
	width: calc(var(--bjs-script-height) * 2.0992);
	height: var(--bjs-script-height);
	/* Kill the image-replaced text without letting it size the box. */
	text-indent: -9999px;
	white-space: nowrap;
	overflow: hidden;
	text-transform: none !important;
	letter-spacing: 0 !important;
	line-height: 1;
	font-weight: 400 !important;
	color: #ea1d76;
	background-color: currentColor;
	-webkit-mask: url('assets/logo-bjs-v2.png') center / contain no-repeat;
	mask: url('assets/logo-bjs-v2.png') center / contain no-repeat;
}

/* The <p> itself carries the class, so it has to stay display:block — an inline-block <p>
   is no longer centred by its own has-text-align-center. A fixed-width block instead needs
   an auto inline margin, and only where the markup asks to be centred: in the header the
   <p> is a flex item and an auto inline margin would eat the free space and push the
   "Shaved Ice" caps to the far end of the bar. margin-inline (not margin: 0 auto) leaves
   the inline margin-top / margin-bottom on the footer and hero paragraphs alone. */
.bjs-script.has-text-align-center {
	margin-inline: auto;
}

/* The header mark wraps a link. Its text is indented offscreen, so the <a> box has to be
   stretched over the mark or the whole logo stops being clickable. */
.bjs-lockup .bjs-script a {
	display: block;
	width: 100%;
	height: 100%;
}
/* The anchor's border box is exactly its parent's content box, and the parent clips with
   overflow:hidden — so a normal outline, painted outside the border box, is 100% clipped
   and a keyboard user sees nothing at all. A negative offset draws the ring inside the
   box, where it survives. The old text-based logo got a ring for free; this does not. */
.bjs-lockup .bjs-script a:focus-visible {
	outline: 2px solid #ea1d76;
	outline-offset: -2px;
	border-radius: 2px;
}

/* The mark is painted with background-color through a mask, and browsers drop background
   painting in print, while forced-colors mode replaces the colour outright. Either way the
   mark vanishes and there is no fallback, because the real text is parked at -9999px. So
   in both cases put the text back and let it render as ordinary type. */
@media print, (forced-colors: active) {
	.bjs-script {
		width: auto;
		height: auto;
		text-indent: 0;
		overflow: visible;
		background-color: transparent;
		-webkit-mask: none;
		mask: none;
		line-height: 1.2;
	}
	.bjs-lockup .bjs-script a {
		display: inline;
		width: auto;
		height: auto;
	}
}

/* "handcrafted with love" is the wrap's own artwork too — lettering, the pink swash under it
   and the open heart, all one cut-out. It replaces the three pieces the theme used to compose
   by hand (.bjs-hand text, .bjs-hand-flourish, .bjs-heart), so those spans are gone from the
   markup at both call sites.

   Two consequences worth knowing. The footer copy is now BLACK rather than the sage the theme
   had invented — the wrap has no sage there. And unlike the lockup this is a two-colour image,
   so it has to be a background, not a mask: a mask would flatten the black and the pink into
   one colour. That means it cannot inherit the palette, and at 411px it is the lowest-
   resolution asset here — fine at the ~155px it renders at, but it will not take scaling up. */
.bjs-handcrafted {
	display: block;
	width: 6.45em;
	aspect-ratio: 411 / 239;
	margin-inline: auto;
	text-indent: -9999px;
	white-space: nowrap;
	overflow: hidden;
	background: url('assets/handcrafted.png') center / contain no-repeat;
}
/* Same reasoning as the lockup: backgrounds do not print and forced-colors replaces them,
   so put the real text back rather than leaving a reserved blank. */
@media print, (forced-colors: active) {
	.bjs-handcrafted {
		width: auto;
		aspect-ratio: auto;
		text-indent: 0;
		overflow: visible;
		background: none;
	}
}

/* Handwritten accent lines (Caveat Brush — stands in for Awesome) — "made fresh, every single cup" */
.bjs-hand {
	font-family: 'Caveat Brush', cursive !important;
	text-transform: none !important;
	letter-spacing: 0.01em;
	font-size: 1.5rem; /* text-2xl */
	font-weight: 400;
}

/* Caps tagline — font-brand bold, tracking 0.15em, sage */
.bjs-tagline {
	font-family: 'Vancouver Gothic', 'Archivo', sans-serif;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	font-weight: 400;
}

/* Tagline carries the wrap's short sage rules either side */
.bjs-tagline-rules::before,
.bjs-tagline-rules::after {
	content: '';
	display: inline-block;
	width: 1.65rem;
	height: 2px;
	border-radius: 1px;
	background: #6a835e;
	vertical-align: 0.28em;
}
.bjs-tagline-rules::before { margin-right: 0.75rem; }
.bjs-tagline-rules::after  { margin-left: 0.75rem; }

/* Contrast fix: sage #6a835e on this paragraph's cream background is 4.04:1 at this
   normal (1rem, non-bold) size — WCAG AA needs 4.5:1 for text this size, so it fails.
   (On the site's other light backgrounds it's no better: 3.72:1 on mint-soft, 4.18:1
   on white — all still short of 4.5:1.) This is the readable hero tagline text, not
   the decorative rule beside it (that stays #6a835e — border/rule use is unaffected).
   #4f6347 is #6a835e's hue darkened until it clears AA with margin on every light bg
   this site uses it against: 6.33:1 on cream, 5.82:1 on mint-soft, 6.55:1 on white. */
.bjs-tagline-rules.has-sage-color {
	color: #4f6347;
}
/* Whisker marks flanking the pink section headings. Traced from the FLAVORS
   lockup on the wrap (IMG_7820.png, IMG_7493.png): three strokes radiating
   from a virtual centre on the text side — a horizontal middle ray plus two at
   ±35° — with the apex pointing at the word and the fan opening outward. The
   middle stroke is the longest at both ends. Round caps, stroke 0.086 of the
   cap height.

   Same delivery as .bjs-heart: an inline SVG as a CSS mask over
   background-color: currentColor, so the marks always are the heading's own
   pink and can never be swapped for a platform glyph.

   Sizing is cap-relative. Vancouver Gothic's sCapHeight is 1446/2048 = 0.706em,
   and on the wrap the mark's total ink height equals the cap height exactly, so
   height is 0.71em and the viewBox aspect (149:278) gives the 0.38em width. The
   pseudo-element has no in-flow content, so its baseline is its bottom margin
   edge; sitting that on the text baseline puts the mark's centre 0.355em up
   against a cap centre of 0.353em — optically cap-centred, and shorter than the
   1.15 line-height so it never grows the line box. */
.bjs-accent::before,
.bjs-accent::after,
.bjs-accent-word::before,
.bjs-accent-word::after {
	content: '';
	display: inline-block;
	width: 0.38em;
	height: 0.71em;
	vertical-align: 0; /* bottom margin edge on the baseline — see above */
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 149 278' fill='none' stroke='%23000' stroke-width='23' stroke-linecap='round'%3E%3Cpath d='M11.5 139H119.5'/%3E%3Cpath d='M61.65 11.67L137.01 64.43'/%3E%3Cpath d='M61.65 266.33L137.01 213.57'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 149 278' fill='none' stroke='%23000' stroke-width='23' stroke-linecap='round'%3E%3Cpath d='M11.5 139H119.5'/%3E%3Cpath d='M61.65 11.67L137.01 64.43'/%3E%3Cpath d='M61.65 266.33L137.01 213.57'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* 0.22em is the wrap's own gap: 83px against a 267px cap height. */
.bjs-accent::before,
.bjs-accent-word::before {
	margin-right: 0.22em;
}
.bjs-accent::after,
.bjs-accent-word::after {
	margin-left: 0.22em;
	transform: scaleX(-1); /* the right-hand mark is a pure mirror on the wrap */
}

/* "Toppings (add $1)" carries a trailing sage parenthetical, so a mark on the heading
   itself lands after the price rather than after the word — the pair stops being
   symmetric about the thing it is flanking. Headings that split like this mark up an
   inner .bjs-accent-word instead, and suppress the heading's own pair. */
.bjs-accent.bjs-accent-split::before,
.bjs-accent.bjs-accent-split::after {
	content: none;
}
/* The "(add $1)" parenthetical is sage at 0.6em of a large heading (~14.4px), not the
   large-text size that would let it stop at 3:1 — same 4.5:1 failure as the tagline
   above (3.72:1 on this section's mint-soft background), same fix. */
.bjs-accent-split .has-sage-color {
	color: #4f6347;
}
/* The pink swash under "handcrafted with love" — drawn on the wrap, redrawn here */
.bjs-hand-flourish {
	position: relative;
	display: inline-block;
	padding-bottom: 0.22em;
}
.bjs-hand-flourish::after {
	content: '';
	position: absolute;
	left: 2%;
	right: -3%;
	bottom: 0;
	height: 0.16em;
	background: #ea1d76;
	border-radius: 0.1em;
	transform: rotate(-1.2deg);
}

/* Hero "handcrafted with love" is quiet ink, not sage (footer keeps sage) */
.bjs-hero .bjs-hand {
	color: rgba(31, 31, 31, 0.7);
}
/* Sticky header — translucent cream with blur, mint hairline */
/* The sticky has to live on the template-part wrapper, not on .bjs-header. WordPress
   wraps the part in <header class="wp-block-template-part">, and that wrapper is the
   sticky element's containing block — it is exactly as tall as the header, so sticking
   .bjs-header itself gives it zero travel and it just scrolls away like static markup. */
header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 50;
}
.bjs-header {
	/* Still positioned, so the phone menu panel keeps anchoring to it. */
	position: relative;
	border-bottom: 1px solid rgba(195, 210, 180, 0.6);
	background-color: rgba(252, 251, 248, 0.9) !important;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
}
/* Header lockup — stacked script over small caps, like the prototype */
.bjs-lockup {
	line-height: 1;
}
.bjs-lockup p {
	margin: 0;
	line-height: 1.1;
}
/* Deliberately NOT the trailer's proportion, so do not "correct" this again. Measured on
   IMG_7747 the wrap's SHAVED ICE caps are 0.855 of the whole B+J mark's ink height, which
   works out to 2.16rem here. That was tried and rejected on sight — at nav-bar scale it
   reads as shouting, where on a 12-foot trailer panel it reads as confident. 0.75rem keeps
   the header lockup compact. Brand fidelity loses to legibility in this one spot. */
.bjs-lockup-caps {
	font-family: 'Vancouver Gothic', 'Archivo', sans-serif;
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 0.75rem; /* text-xs */
	color: #ea1d76;
}
/* Header lockup sits on one baseline like the side wrap: script + heavy caps */
.bjs-lockup a {
	text-decoration: none;
	color: inherit;
}
.bjs-lockup-caps {
	align-self: flex-end;
	margin-bottom: 0.35rem !important;
	margin-left: 0.4rem !important;
}

/* Open heart traced from the trailer wrap. Delivered as a mask so it takes the
   brand pink from `color` and can never be substituted by a platform emoji. */
.bjs-heart {
	display: inline-block;
	width: 0.95em;
	height: 0.95em;
	vertical-align: -0.11em;
	margin-left: 0.12em;
	background-color: currentColor;
	color: #ea1d76;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 90' fill='none'%3E%3Cpath d='M51.2 84.5C34 72.6 20.4 61.4 12.4 50.6 5.6 41.4 4 32 7.6 23.6c4.4-10.2 15.6-14 24.6-8.6 4.6 2.8 7.8 7 9.4 11.9 2.6-6 7-10.6 12.6-12.7 10.4-3.9 21 1.9 23.6 12.3 2.2 8.8-1 18.1-8.6 27.6-6.9 8.6-16.9 17.5-30.2 26.8-.4.3-.9.3-1.3 0z' stroke='%23000' stroke-width='6.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 90' fill='none'%3E%3Cpath d='M51.2 84.5C34 72.6 20.4 61.4 12.4 50.6 5.6 41.4 4 32 7.6 23.6c4.4-10.2 15.6-14 24.6-8.6 4.6 2.8 7.8 7 9.4 11.9 2.6-6 7-10.6 12.6-12.7 10.4-3.9 21 1.9 23.6 12.3 2.2 8.8-1 18.1-8.6 27.6-6.9 8.6-16.9 17.5-30.2 26.8-.4.3-.9.3-1.3 0z' stroke='%23000' stroke-width='6.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---------------------------------------------------------------------------
   Adaptive nav. Three tiers, switched at the iPad portrait width: desktop and
   tablet get the inline links, phones get a disclosure panel under the bar.
   Built on <details> so the open/closed state, keyboard handling and the
   expanded semantics come from the browser — the script below only closes it.
   --------------------------------------------------------------------------- */
.bjs-nav {
	display: flex;
	align-items: center;
	gap: 2.25rem;
	margin: 0;
}
.bjs-nav a,
.bjs-menu-panel a {
	text-decoration: none;
	/* DM Sans (the site's body font), not Vancouver Gothic — nav links are
	   functional UI text and the condensed caps display face is harder to scan
	   for that than for headings. See the matching note on .wp-block-button__link. */
	font-family: var(--wp--preset--font-family--body);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	font-size: 0.875rem; /* text-sm */
	color: #1f1f1f;
	transition: color 0.15s ease;
}
.bjs-nav a:hover,
.bjs-nav a:focus,
.bjs-menu-panel a:hover,
.bjs-menu-panel a:focus {
	color: #ea1d76;
}

/* iPad: the three items still fit, they just need less air between them. */
@media (min-width: 768px) and (max-width: 1023px) {
	.bjs-nav {
		gap: 1.35rem;
	}
	.bjs-nav a {
		font-size: 0.8125rem;
	}
}

/* The hamburger only exists below the tablet breakpoint. */
.bjs-menu {
	display: none;
	position: static;
}
@media (max-width: 767px) {
	.bjs-nav {
		display: none;
	}
	.bjs-menu {
		display: block;
	}
}

.bjs-menu > summary {
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px; /* full tap target — this is the phone entry point from the QR code */
	height: 44px;
	margin: -0.35rem -0.6rem -0.35rem 0;
	border-radius: 0.6rem;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
}
.bjs-menu > summary::-webkit-details-marker {
	display: none;
}
.bjs-menu > summary:focus-visible {
	outline: 2px solid #ea1d76;
	outline-offset: 2px;
}

.bjs-menu-bars,
.bjs-menu-bars::before,
.bjs-menu-bars::after {
	display: block;
	width: 26px;
	height: 3px;
	border-radius: 2px;
	background-color: #ea1d76;
	transition: transform 0.2s ease, background-color 0.2s ease;
}
.bjs-menu-bars {
	position: relative;
}
.bjs-menu-bars::before,
.bjs-menu-bars::after {
	content: '';
	position: absolute;
	left: 0;
}
.bjs-menu-bars::before {
	top: -8px;
}
.bjs-menu-bars::after {
	top: 8px;
}
/* Open state folds the three bars into a close X. */
.bjs-menu[open] .bjs-menu-bars {
	background-color: transparent;
}
.bjs-menu[open] .bjs-menu-bars::before {
	transform: translateY(8px) rotate(45deg);
}
.bjs-menu[open] .bjs-menu-bars::after {
	transform: translateY(-8px) rotate(-45deg);
}

/* Panel hangs off the sticky header's padding box, so it spans the full width
   regardless of the header's own side padding. */
.bjs-menu-panel {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	display: flex;
	flex-direction: column;
	padding: 0.25rem 1.5rem 0.75rem;
	/* Solid, unlike the bar above it — at 0.98 the page text ghosted through the links. */
	background-color: #fcfbf8;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border-bottom: 1px solid rgba(195, 210, 180, 0.6);
	box-shadow: 0 14px 20px -14px rgba(31, 31, 31, 0.3);
	animation: bjs-menu-drop 0.18s ease-out;
}
.bjs-menu-panel a {
	font-size: 1rem;
	padding: 0.9rem 0;
	border-bottom: 1px solid rgba(195, 210, 180, 0.5);
}
.bjs-menu-panel a:last-child {
	border-bottom: none;
}
@keyframes bjs-menu-drop {
	from {
		opacity: 0;
		transform: translateY(-0.4rem);
	}
}

/* Hero — both watercolor leaf sprigs again: upper-left at full size/opacity,
   lower-right knocked down ~25% so it stays a background accent behind the
   cups rather than a second focal point. The logo no longer sits pinned to
   the top of the hero (the section is vertically centered now), so the
   upper-left sprig has clear room above and beside the logo instead of
   crowding it the way it did in the old top-aligned layout. */
.bjs-hero {
	position: relative;
	overflow: hidden;
	display: flex;
	align-items: center;
	min-height: calc(100vh - 80px);
}
.bjs-hero::before,
.bjs-hero::after {
	content: "";
	position: absolute;
	/* leaf-sprig.png is cropped to its artwork: 498x341, aspect 1.46. */
	background: url('assets/leaf-sprig.png') no-repeat center / contain;
	pointer-events: none;
	z-index: 0;
}
.bjs-hero::before {
	width: 420px;
	aspect-ratio: 498 / 341;
	opacity: 0.7;
	left: -5.5rem;
	top: 2rem;
}
.bjs-hero::after {
	/* 315px / 0.5 opacity = 420px / 0.7 each cut by roughly a quarter. */
	width: 315px;
	aspect-ratio: 498 / 341;
	opacity: 0.5;
	right: -5.5rem;
	bottom: 0;
	transform: scaleX(-1);
}
.bjs-hero > * {
	position: relative;
	z-index: 1;
}
@media (max-width: 781px) {
	.bjs-hero {
		min-height: 0;
	}
	.bjs-hero::before {
		width: 240px;
		left: -4rem;
	}
	.bjs-hero::after {
		width: 180px;
		right: -4rem;
	}
}

/* Watercolor cups illustration — w-64 / sm:w-80 */
.bjs-cups {
	background: url('assets/cups-lighter.png') center / contain no-repeat;
	height: clamp(256px, 30vw, 320px);
}

/* Hero — left-aligned copy beside the cups.
   Text defaults to left-aligned (the WP blocks carry no has-text-align-center
   here); the phone override below re-centers everything, matching the
   original stacked mobile hero this replaced. */
.bjs-hero-text {
	text-align: left;
	padding-left: 2rem;
	padding-top: 1.5rem;
	/* The cups column bleeds left into this one (see the negative margin on
	   .bjs-cups-wrap below) and paints after it in DOM order, so without an
	   explicit stacking context here the cups column renders over this
	   column's text wherever the two overlap. */
	position: relative;
	z-index: 2;
}
.bjs-hero-text .bjs-script {
	margin-inline: 0;
}
/* The script mark's preset bottoms out at 3.75rem, so on a phone it dropped to about
   60% of its desktop size while the leaf art and tagline around it did not — the
   lockup read as shrunken rather than scaled. Raising the floor keeps it closer to
   full size on a narrow screen. Same !important-plus-preset-class trick as the caps
   below it, for the same reason. */
.bjs-hero-text .bjs-script.has-script-hero-font-size {
	font-size: clamp(4.75rem, 17vw, 6rem) !important;
}
.bjs-hero-text .wp-block-buttons {
	justify-content: flex-start;
	flex-wrap: wrap;
	gap: 0.75rem;
}
/* Above the columns breakpoint the two hero pills stay on one line. The text column is
   only about 45% of the content width there, and at full button size VIEW MENU plus
   GET DIRECTIONS overflow it — the outline pill dropped to a second row and the pair
   read as stacked rather than as a primary action with a secondary beside it.

   Two parts: nowrap on the row so they cannot break apart at any desktop width, and a
   tighter pill through the narrow band where they genuinely do not fit at full size.
   Past 1100px the column has room and the buttons go back to their normal scale. The
   labels never break internally, so neither pill ever renders as two lines of text. */
@media (min-width: 782px) {
	.bjs-hero-text .wp-block-buttons {
		flex-wrap: nowrap;
	}
	.bjs-hero-text .wp-block-button__link {
		white-space: nowrap;
	}
}
@media (min-width: 782px) and (max-width: 1100px) {
	.bjs-hero-text .wp-block-button__link {
		font-size: 0.875rem;
		padding-left: 1.25rem;
		padding-right: 1.25rem;
	}
	.bjs-hero-text .wp-block-buttons {
		gap: 0.5rem;
	}
}

/* Two copies of the address/hours row ship in the hero, and exactly one of them is
   ever rendered: the copy inside .bjs-hero-text sits under the CTA on desktop, and
   this one — the last thing in the cups column — takes over below 781px so the row
   reads under the artwork instead of pushing the button down the phone screen. CSS
   alone cannot do this with one copy: the row lives inside the text column, and no
   ordering property moves a child out of one flex item and into a later sibling.

   EDIT BOTH OR NEITHER. They are the same address, hours and maps link twice. */
/* Compound selector on purpose: the element carries BOTH classes, and .bjs-hero-info
   sets display:flex further down this file. At equal specificity the later rule wins,
   so a bare .bjs-hero-info-mobile lost and the row rendered twice on desktop. */
.bjs-hero-info.bjs-hero-info-mobile {
	display: none;
}
/* Address / hours / social block under the hero CTA — location and hours
   stack as two lines, socials sit beside that stack. */
.bjs-hero-info {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 1.75rem;
	font-size: 0.9rem;
	color: #1f1f1f;
}
.bjs-hero-info-lines {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}
.bjs-hero-info-item {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}
.bjs-hero-info-item svg {
	width: 17px;
	height: 17px;
	flex: none;
	color: #6a835e;
}
/* SHAVED ICE sized up under the script. On the trailer panel the two lines read as
   one lockup — the caps run nearly the full width of the B+J's script above them. At
   the xx-large preset (max 3rem) the caps came in noticeably short of that, so the
   hero read as a big script with a small label under it. Set here rather than on the
   block's fontSize in the page markup so it stays one value to tune and the header's
   own smaller lockup is untouched. */
/* !important and the preset class in the selector, because WordPress emits
   `.has-xx-large-font-size { font-size: var(--...) !important }` for every preset
   font-size class. Without both, this rule loses silently and the caps stay at the
   xx-large preset — which is exactly what happened the first time this was set. */
.bjs-hero-text h1.has-xx-large-font-size {
	font-size: clamp(2.7rem, 6.8vw, 4rem) !important;
	line-height: 1.02;
	/* padding, not margin: the block markup carries an inline style="margin-top:0" on
	   this h1, and an inline declaration beats any selector here. On a phone the clamp
	   bottoms out at its floor while the script above bottoms out at 3.75rem, so the
	   caps sat tight under the script's descender with nothing between them. */
	padding-top: 0.5rem;
}

/* The address is the directions link now — the hero's single CTA is View Menu, so
   the maps link lives on the address line itself. Kept as the same
   .bjs-hero-info-item as the hours span so the icon/text alignment is identical;
   only the hover and focus states mark it as interactive. */
.bjs-hero-info-link {
	color: inherit;
	text-decoration: none;
}
.bjs-hero-info-link:hover,
.bjs-hero-info-link:focus-visible {
	color: #ea1d76;
	text-decoration: underline;
	text-underline-offset: 2px;
}
.bjs-hero-info-link:hover svg,
.bjs-hero-info-link:focus-visible svg {
	color: #ea1d76;
}
/* Cups sit on the plain hero background — the mint blob backdrop that used to
   paint here read as an egg behind them, so it's gone at every width. */
.bjs-cups-wrap {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
}
.bjs-cups-wrap .bjs-cups {
	position: relative;
	z-index: 1;
	width: 100%;
	height: clamp(315px, 36vw, 470px);
}
/* Pull the cups toward the text column so the two halves read as one
   composition instead of two columns with a gap between them. Left-only,
   and only once the columns are actually side by side — a negative margin
   here on a stacked mobile layout would just clip the cups. */
@media (min-width: 782px) {
	.bjs-cups-wrap {
		margin-left: -2.5rem;
	}
}
@media (max-width: 781px) {
	.bjs-hero-text {
		text-align: center;
		padding-left: 0;
		padding-top: 0;
	}
	.bjs-hero-text .bjs-script {
		margin-inline: auto;
	}
	/* Phone hero is the fold: the script lockup, SHAVED ICE, the tagline, one button.
	   The lede sentence is cut outright — it pushed the CTA down a screen where most
	   visitors arrive by scanning the QR code on the trailer. The address/hours row is
	   not cut, just moved: the copy under the CTA is hidden and the copy at the end of
	   the cups column takes its place, so it reads below the artwork. */
	.bjs-hero-lede,
	.bjs-hero-text .bjs-hero-info {
		display: none;
	}
	/* Get Directions is desktop-only. On a phone the address right below this row is
	   itself the maps link, and a second tap target for the same destination just
	   pushed View Menu off the fold. Compound selector because .wp-block-button
	   carries its own display from core — a lone .bjs-desktop-only would tie on
	   specificity and lose to whichever rule came later. */
	.wp-block-button.bjs-desktop-only {
		display: none;
	}
	.bjs-hero-info.bjs-hero-info-mobile {
		display: flex;
		justify-content: center;
		margin-top: 1.25rem;
	}
	/* The cups were a fixed 315px box painting a `contain` background. Below about
	   430px the image fits by width, so the leftover height became empty space split
	   above and below it — measured 45px at 320px, 29px at 360px, 16px at 390px. That
	   dead band above the artwork is what read as too much air under View Menu.

	   Giving the box the artwork's own 1112:919 ratio means `contain` fills it exactly
	   and there is no letterbox left to distribute, at any width. Size is then set by
	   width alone, so the cups can be made smaller without reintroducing a gap. */
	/* Scoped to .bjs-cups-wrap because that descendant selector further down sets
	   width:100% and its own height clamp — a bare .bjs-cups loses to it on
	   specificity and this rule did nothing at all until it was scoped. */
	.bjs-cups-wrap .bjs-cups {
		height: auto;
		aspect-ratio: 1112 / 919;
		width: min(72%, 240px);
		margin-inline: auto;
	}
	.bjs-hero-text .wp-block-buttons {
		justify-content: center;
	}
	.bjs-hero-info {
		justify-content: center;
	}
}

/* Menu cards — 2px mint border, rounded-3xl, white/70, p-7 */
/* Padding was 1.75rem and .bjs-price carried line-height 2, which together left the
   two product cards noticeably taller than their three lines of content -- the price
   rows floated in the middle of an oversized box. Tightened so a phone can hold the
   prices and the top of the flavor list in one screen. */
.bjs-card {
	border: 2px solid #c3d2b4;
	border-radius: 1.5rem;
	padding: 1.25rem 1.5rem;
	background: rgba(255, 255, 255, 0.7);
}
.bjs-card h3 {
	font-size: 1.25rem; /* text-xl */
	color: #1f1f1f;
	letter-spacing: 0.025em;
}
.bjs-price {
	font-size: 1.125rem; /* text-lg */
	line-height: 1.65;
}
.bjs-card-note {
	color: rgba(31, 31, 31, 0.7);
	font-size: 0.875rem; /* text-sm */
}

/* Flavor chips — soft pink pills, sentence case, text-sm medium */
/* "we bring the trailer..." subheading — zero its own bottom margin so the
   only gap before the cards/photo row is the 24px each of them now carries
   on its own (first card + trailer photo), not a stacked double gap. */
#book .bjs-hand {
	margin-bottom: 0;
}

/* Book-Us cards — rounded-3xl, soft shadow, pink line icon over caps label.
   Forced to fill its grid cell (height:100%, box-sizing:border-box) and
   center its own content instead of relying on default grid stretch — one
   card was rendering shorter than its row and sitting top-anchored inside
   the leftover space, so cells looked mismatched card to card. */
.bjs-book-card {
	/* No border on these four. They were standardized to the site's other card types
	   (2px mint + white/70) and that read as too much frame around a single icon and a
	   one-word label — the menu and review cards hold real content and earn theirs.
	   The white/70 panel on cream is enough separation on its own. */
	background: rgba(255, 255, 255, 0.7);
	border-radius: 1.5rem;
	padding: 2rem 1rem; /* px-4 py-8 */
	box-sizing: border-box;
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
/* WP core's default flow-layout child spacing (:root :where(.is-layout-flow) > *
   { margin-block-start: 24px }) lands on 3 of these 4 cards' children but not
   the first — inconsistent enough (and stubborn enough to override cleanly)
   that fighting it card-by-card wasn't working. Simpler: stop trying to zero
   it out and instead give the first card the same 24px the other three
   already get from core, so all four sit at the same vertical offset. */
.bjs-book-cards > .bjs-book-card:first-child {
	margin-top: 24px;
}

.bjs-book-card h3 {
	margin-top: 0.75rem;
	font-size: 1rem; /* text-base */
	letter-spacing: 0.025em;
	color: #1f1f1f;
}
.bjs-book-icon {
	display: flex;
	justify-content: center;
	color: #ea1d76;
}
.bjs-book-icon svg {
	width: 36px;
	height: 36px;
	display: block;
}
/* Book Us — the four cards form a 2×2 grid beside the trailer photo, at
   every width, instead of running four across or stacking into one tall
   column. The outer wp:columns row (.bjs-book-columns) has no explicit
   alignment set anywhere, so its default align-items:stretch was forcing
   THIS column to match the trailer column's height — the grid's own two
   auto rows don't grow to fill that extra leftover space evenly, so cards
   ended up with mismatched, partly-empty cells. Overriding it here so the
   cards column keeps its own natural, content-driven height instead of
   inheriting height from the unrelated trailer column next to it. */
.bjs-book-columns {
	align-items: flex-start;
}
.bjs-book-cards {
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: stretch;
	gap: 1rem;
}
/* Three equal columns across the row, not 25/25/50. Core gives both wp:columns children
   flex-basis:0 / flex-grow:1, so the cards block and the photo each took half — and
   because the cards are a 2-up grid inside their half, the row read as two quarter-width
   cards beside a half-width photo. Giving the cards two thirds and the photo one third
   makes each card and the photo the same width, so it reads as three columns.

   Compound selector to clear core's own .wp-block-columns .wp-block-column rule rather
   than relying on this file loading later. Only above the columns breakpoint — below it
   the columns stack full width and thirds are meaningless. */
@media (min-width: 782px) {
	.bjs-book-columns > .wp-block-column.bjs-book-cards {
		flex-basis: 66.666%;
		flex-grow: 0;
	}
	.bjs-book-columns > .wp-block-column.bjs-trailer-col {
		flex-basis: 33.333%;
		flex-grow: 0;
	}
}
/* The trailer column is a flex column so the pricing table and the Reserve button
   stack and align to the top of the card grid beside them. It previously held the
   trailer photo, whose height had to be reconciled with the 2x2 grid; with the photo
   gone the column simply takes its natural height. */
@media (min-width: 782px) {
	.bjs-trailer-col {
		display: flex;
		flex-direction: column;
	}
}

/* Stacked below the columns breakpoint, the trailer column sits directly under the
   last row of book cards with nothing between them — the photo's top edge butts into
   the card border. WP core's column gap only applies across the row, not when the
   columns stack, so the separation has to be added here.

   An explicit spacer element rather than a margin on .bjs-trailer-col: the margin was
   there first and the gap still read as too tight, so this makes the separation a real
   box with one height to tune instead of a margin competing with core's flex rules.
   It carries no text and is aria-hidden — it exists only to hold space, and only on
   phones; above 781px the columns sit side by side and it collapses to nothing. */
.bjs-mobile-spacer {
	display: none;
}
@media (max-width: 781px) {
	.bjs-mobile-spacer {
		display: block;
		height: 4rem;
	}
}

/* Review cards — sibling of .bjs-card: same mint border/rounded-3xl/white-70 treatment,
   left-aligned since these hold a quote instead of centered menu copy. Six reviews ship
   as one horizontally scrollable row (CSS scroll-snap, no JS carousel needed) — smaller
   cards than the old three-up grid, so more of the row is visible at once and the rest
   is a swipe/scroll away on every viewport, phone included. */
.bjs-review-slider {
	display: flex;
	align-items: flex-start;
	gap: 1rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding-bottom: 0.5rem;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: #c3d2b4 transparent;
}
.bjs-review-card {
	flex: 0 0 auto;
	width: min(240px, 76vw);
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	border: 2px solid #c3d2b4;
	/* 1.5rem, not 1.25rem — the comment above this rule already claimed "same mint
	   border/rounded-3xl/white-70 treatment" as .bjs-card, but the radius had drifted
	   to 1.25rem. Matching it for real now that all three card types are standardized. */
	border-radius: 1.5rem;
	padding: 1rem;
	background: rgba(255, 255, 255, 0.7);
}
.bjs-review-stars {
	display: flex;
	gap: 0.2rem;
	margin-bottom: 0.6rem;
}
.bjs-review-stars svg {
	width: 13px;
	height: 13px;
	display: block;
}
.bjs-review-quote {
	color: #1f1f1f;
	font-size: 0.85rem;
	line-height: 1.5;
	flex-grow: 1;
	/* Caps every card at the John Bromfield card's height (his 2-line quote
	   is the tallest this design allows) — longer quotes truncate with an
	   ellipsis instead of growing the card. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.bjs-review-name {
	margin-top: 0.85rem;
	margin-bottom: 0;
	font-weight: 600;
	font-size: 0.9rem;
	letter-spacing: 0.025em;
	color: #1f1f1f;
}
.bjs-review-meta {
	margin-top: 0.15rem;
	margin-bottom: 0;
	color: rgba(31, 31, 31, 0.7);
	font-size: 0.75rem;
}
.bjs-review-link {
	display: inline-block;
	margin-top: 0.6rem;
	color: #ea1d76;
	font-size: 0.75rem;
	font-weight: 600;
	text-decoration: none;
}
.bjs-review-link:hover,
.bjs-review-link:focus {
	text-decoration: underline;
}

/* Review slider nav — prev/next arrows overlaid on the row's edges (so they never steal
   width from the cards at narrow viewports) plus pagination dots below. The row still
   peeks a partial card at its right edge on purpose: with the arrows and dots now telling
   visitors there's more to see, that peek reads as an affordance instead of a clipping bug. */
.bjs-review-slider-wrap {
	position: relative;
}
.bjs-slider-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: none;
	border: none;
	border-radius: 50%;
	background: #ea1d76;
	box-shadow: 0 2px 6px rgba(31, 31, 31, 0.25);
	cursor: pointer;
	transition: background-color 0.15s ease, transform 0.15s ease;
}
.bjs-slider-arrow:hover,
.bjs-slider-arrow:focus-visible {
	background: #c3135f;
	transform: translateY(-50%) scale(1.1);
}
.bjs-slider-arrow svg {
	width: 16px;
	height: 16px;
	display: block;
}
.bjs-slider-arrow--prev {
	left: -6px;
}
.bjs-slider-arrow--next {
	right: -6px;
}
@media (max-width: 480px) {
	.bjs-slider-arrow {
		width: 34px;
		height: 34px;
	}
	.bjs-slider-arrow--prev {
		left: -2px;
	}
	.bjs-slider-arrow--next {
		right: -2px;
	}
}
/* Desktop: let the review row break out of the 760px content width and run to the
   theme's wideSize (1100px), so four cards plus the intentional partial-card peek
   fit instead of three. Core's constrained layout caps children at contentSize from
   a zero-specificity :where() rule, so this plain class overrides it. */
@media (min-width: 900px) {
	.bjs-review-block {
		width: 100%;
		max-width: var(--wp--style--global--wide-size, 1100px);
		margin-left: auto;
		margin-right: auto;
	}
	.bjs-review-card {
		width: 250px;
	}
}
.bjs-review-slider:focus-visible {
	outline: 2px solid #ea1d76;
	outline-offset: 4px;
	border-radius: 1rem;
}
.bjs-slider-dots {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	margin-top: 1.25rem;
}
.bjs-slider-dot {
	width: 9px;
	height: 9px;
	padding: 0;
	border: none;
	border-radius: 50%;
	background: #c3d2b4;
	cursor: pointer;
	transition: background-color 0.15s ease, transform 0.15s ease;
}
.bjs-slider-dot:hover,
.bjs-slider-dot:focus-visible {
	background: #ea1d76;
}
.bjs-slider-dot.is-active {
	background: #ea1d76;
	transform: scale(1.2);
}

/* Toppings — 2-col grid, small text, filled pink heart markers */
ul.bjs-hearts {
	list-style: none;
	padding-left: 0;
	max-width: 672px; /* max-w-2xl */
	margin-left: auto;
	margin-right: auto;
}
@media (min-width: 600px) {
	ul.bjs-hearts {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 2rem;
	}
}
/* Flavors used to be pink pills, which wrapped organically at 19 items but read as
   visual noise at 20. Reusing the toppings list instead means Flavors and Toppings
   read as one system.

   Sugar-Free is a column inside step 2 rather than a section under it: it is a subset
   of the same choice, and stacking it as its own block implied a fourth step. The full
   list takes the wider column at its two-column default; the five sugar-free flavors
   take the narrow one, single file. */
ul.bjs-hearts.bjs-hearts-1 {
	display: block;
	max-width: none;
}
ul.bjs-hearts.bjs-hearts-2 {
	max-width: none;
}
/* The twenty flavors run three-up in the wide column. .bjs-hearts is two columns from
   600px, so this has to widen it again -- and only above the point where the flavor
   and sugar-free columns sit side by side, since below that the whole thing is one
   narrow stack and three columns would shred the longer names. */
/* Two columns is the FLOOR for the flavors, not the default. The shared .bjs-hearts
   rule only goes two-up from 600px and is a plain block below that, which dropped
   twenty flavors into one 20-item column on a phone -- a scroll with no shape to it.
   Declaring the grid here instead of inheriting it means the list is two-up at every
   width and only widens to three where there is room. */
ul.bjs-hearts.bjs-hearts-3 {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	column-gap: 0.75rem;
	max-width: none;
}
@media (min-width: 782px) {
	ul.bjs-hearts.bjs-hearts-3 {
		grid-template-columns: repeat(3, 1fr);
		column-gap: 1.5rem;
	}
}
/* The longest names -- Blue Raspberry, Pink Lemonade -- have to survive a half-width
   phone column without wrapping, so the heart gutter tightens up where it is scarcest. */
@media (max-width: 480px) {
	ul.bjs-hearts.bjs-hearts-3 li {
		padding-left: 1.15rem;
		font-size: 0.82rem;
	}
}

/* Sugar-Free is the fourth column and the only one that is a different KIND of thing --
   a filtered view of the same twenty flavors, not more of them.

   It was a bordered card first, and that was wrong: an outlined white box is what the
   price cards use, so it read as a featured or premium item rather than "these five are
   also sugar-free". A single hairline rule does the separating instead. The label steps
   down to sage at the toppings sub-label's weight, well under the pink section headings,
   so the column reads as an aside rather than a fourth thing to choose between. */
.bjs-flavor-sf {
	align-self: stretch;
	position: relative;
}
/* The preset class is in the selector and the size carries !important because
   WordPress emits `.has-medium-font-size { font-size: var(--...) !important }` for
   every preset. Without both, this loses silently and the label stays at 18px --
   the same way the hero h1 did. */
.bjs-sf-title.has-medium-font-size {
	text-transform: uppercase;
	letter-spacing: 0.09em;
	font-size: 0.75rem !important;
	margin: 0;
}
/* The label is lifted out of flow so the five sugar-free names sit on the same rows as
   the flavors beside them. In flow it occupied a line the other three columns did not
   have, so every row in this column was pushed down by one and nothing lined up. It
   parks in the gap the columns block already leaves under the "Pick a Flavor" heading. */
@media (min-width: 782px) {
	.bjs-sf-title.has-medium-font-size {
		position: absolute;
		top: -1.45rem;
		left: 2rem;
	}
}
.bjs-flavor-sf ul.bjs-hearts {
	margin-bottom: 0;
}
.bjs-flavor-sf ul.bjs-hearts li:last-child {
	margin-bottom: 0;
}

/* Side by side, the rule goes on the left edge and does the work the box was doing.
   Stacked, a left rule would sit under the flavor list pointing at nothing, so it moves
   to the top and the label re-centres over its own list. */
@media (min-width: 782px) {
	.bjs-flavor-sf {
		border-left: 1px solid rgba(154, 178, 154, 0.5);
		padding-left: 2rem;
	}
}

/* Core gives every column flex-basis:0 and equal growth unless a width is set; the
   inline flex-basis from the block markup handles that above the breakpoint. Below it
   the columns stack, and the boxed list needs air above it so it does not butt into the
   flavor list it filters. */
/* Stacked below the breakpoint, the boxed-less list needs air above it so it does not
   butt into the flavor list it filters, and the label re-centres over its own list.

   An earlier attempt merged both lists into a single 13-row column-major grid here, so
   Sugar-Free would fill the bottom half of the second column with no dead space. It used
   display:contents on the columns and the ULs to lift the items into one grid; the items
   did not take the intended column flow and packed inline instead. Reverted rather than
   shipped -- the stacked version is plain, but it is correct at every width. */
@media (max-width: 781px) {
	.bjs-flavor-columns > .bjs-flavor-sf {
		margin-top: 2.5rem;
		padding-top: 2rem;
		border-top: 1px solid rgba(154, 178, 154, 0.5);
	}
	.bjs-sf-title.has-medium-font-size {
		text-align: center;
	}
}

ul.bjs-hearts li {
	position: relative;
	padding-left: 1.5rem;
	margin-bottom: 0.5rem;
	font-size: 0.875rem; /* text-sm */
}
ul.bjs-hearts li::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0.28em;
	width: 0.85em;
	height: 0.85em;
	background-color: #ea1d76;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 90' fill='none'%3E%3Cpath d='M51.2 84.5C34 72.6 20.4 61.4 12.4 50.6 5.6 41.4 4 32 7.6 23.6c4.4-10.2 15.6-14 24.6-8.6 4.6 2.8 7.8 7 9.4 11.9 2.6-6 7-10.6 12.6-12.7 10.4-3.9 21 1.9 23.6 12.3 2.2 8.8-1 18.1-8.6 27.6-6.9 8.6-16.9 17.5-30.2 26.8-.4.3-.9.3-1.3 0z' stroke='%23000' stroke-width='6.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 90' fill='none'%3E%3Cpath d='M51.2 84.5C34 72.6 20.4 61.4 12.4 50.6 5.6 41.4 4 32 7.6 23.6c4.4-10.2 15.6-14 24.6-8.6 4.6 2.8 7.8 7 9.4 11.9 2.6-6 7-10.6 12.6-12.7 10.4-3.9 21 1.9 23.6 12.3 2.2 8.8-1 18.1-8.6 27.6-6.9 8.6-16.9 17.5-30.2 26.8-.4.3-.9.3-1.3 0z' stroke='%23000' stroke-width='6.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Buttons — pink pill CTA with glow; outline style inverts on hover */
.wp-block-button__link {
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
	/* Nav links and button labels are the functional UI text on the site, and the
	   condensed caps display face (Vancouver Gothic, set as the default via
	   theme.json's button element) is harder to scan for that than for headings.
	   DM Sans is the site's own body font (already loaded — see functions.php's
	   Google Fonts enqueue), reused here rather than adding a new face. Headings,
	   the hero, and decorative taglines are untouched and keep Vancouver Gothic. */
	font-family: var(--wp--preset--font-family--body);
}
.wp-block-button:not(.is-style-outline) .wp-block-button__link {
	/* White text on the brand pink #ea1d76 is only 4.25:1 — short of the 4.5:1 AA
	   needs for this button label's size (1rem/16px, not large text). #d91469 is
	   #ea1d76 darkened ~10% in lightness only (same hue/saturation), which clears
	   AA at 4.94:1 while staying visually on-brand. The hover state (#c3135f,
	   already 5.87:1) and every other brand-pink use on the site — logo, links,
	   icons — are untouched; this narrows to just the default button surface. */
	background-color: #d91469;
	box-shadow: 0 10px 15px -3px rgba(234, 29, 118, 0.3);
}
.wp-block-button__link:hover,
.wp-block-button__link:focus {
	background-color: #c3135f;
	color: #ffffff;
	transform: scale(1.05);
}
.is-style-outline .wp-block-button__link {
	border: 2px solid #ea1d76;
	color: #ea1d76;
	background: #fcfbf8; /* bg-brand-cream */
	box-shadow: none;
}
.is-style-outline .wp-block-button__link:hover,
.is-style-outline .wp-block-button__link:focus {
	/* Same white-on-pink contrast failure as the filled button's default state
	   (4.25:1 with #ea1d76) — same fix, same darkened shade. */
	background-color: #d91469;
	color: #ffffff;
	transform: none;
}

/* Follow-Us strip + footer — pink circles (h-11 w-11) beside the handle. The rotated
   "Follow Us!" brush blob that used to sit here was a Lovable invention, not a wrap
   device, and it was the thing pushing the row off both edges on a phone. Removed at
   the owner's request, along with the .bjs-brush rules that only served it. */
.bjs-follow {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 1.4rem;
}
.bjs-follow .bjs-social {
	margin: 0;
}
.bjs-social {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1rem; /* gap-4 */
	margin: 1.5rem 0 1rem;
}
.bjs-social a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px; /* h-11 w-11 */
	height: 44px;
	flex: none;
	border-radius: 50%;
	background: #ea1d76;
	transition: background-color 0.15s ease, transform 0.15s ease;
}
.bjs-social a:hover,
.bjs-social a:focus {
	background: #c3135f;
	transform: scale(1.1);
}

/* Dropping the blob reclaims most of the width this row was short of on a phone — it used
   to measure 3px to 384px in a 390px viewport. Keep a smaller guard so the two circles and
   the handle still have air at the frame: the handle cannot wrap out of trouble on its own,
   because it sits inside .bjs-social and only .bjs-follow wraps. */
@media (max-width: 480px) {
	.bjs-follow {
		gap: 0.85rem;
		padding-inline: 1rem;
	}
	.bjs-social {
		gap: 0.65rem;
	}
}
.bjs-social svg {
	width: 20px;
	height: 20px;
	display: block;
}
/* The handle sits inline beside the icons in ink, with the URL in pink beneath —
   that is the order and the colour split used on the wrap. */
.bjs-handle {
	font-family: 'Vancouver Gothic', 'Archivo', sans-serif;
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	font-size: 1rem;
	color: #1f1f1f;
	margin-left: 0.35rem;
	white-space: nowrap;
}
.bjs-footer a {
	text-decoration: none;
}
/* Wrap roles: the handle is ink beside the circles, the URL is pink on the line below */
.bjs-tagline.bjs-url {
	color: #ea1d76;
}

/* Footer "find us" column — the lockup that used to sit here (script mark + SHAVED
   ICE caps) is gone; the footer now leads with the business name in plain caps and
   spends the space on the thing a visitor at the bottom of the page actually wants:
   where the trailer is and when it is open. The address itself is the maps link — a
   Get Directions pill sat under it briefly and was cut as one CTA too many for a
   footer; the hero's address line links to the same place. */
.bjs-footer-find {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	text-align: center;
}
.bjs-footer-name {
	color: #ea1d76;
	font-size: 1.1rem;
	margin: 0;
}
.bjs-footer-info {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	font-size: 0.9rem;
	color: #1f1f1f;
}
.bjs-footer-info-item {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}
.bjs-footer-info-item svg {
	width: 17px;
	height: 17px;
	flex: none;
	color: #6a835e;
}
.bjs-footer-info-link {
	color: inherit;
	text-decoration: none;
}
.bjs-footer-info-link:hover,
.bjs-footer-info-link:focus-visible {
	color: #ea1d76;
	text-decoration: underline;
	text-underline-offset: 2px;
}
.bjs-footer-info-link:hover svg,
.bjs-footer-info-link:focus-visible svg {
	color: #ea1d76;
}
/* The wrap's own "handcrafted with love" artwork — the cut-out lettering with the pink
   swash and open heart, not type. It was briefly set as one line of green text; the
   artwork is black script with a pink swash and cannot be recoloured, so it is back as
   the image it has always been. It sits bottom right of the footer, and it is the only
   call site now that the hero no longer carries it. */
.bjs-footer-mark {
	margin-top: 1.75rem;
}

/* Desktop footer: three columns instead of one tall stack. Left is where to find us,
   middle is where to follow us, right is the handcrafted mark. Grouping is by meaning —
   who we are and where, how to reach us, the sign-off — so each column reads on its own.

   It was briefly two columns, when the mark was going to run full width underneath; that
   left the middle column carrying the socials, the URL and the mark stacked under each
   other, badly out of balance with the left. Three columns is what this footer wants.

   Done with grid placement on the existing children, so the phone layout below 900px is
   the plain stack the markup already gives.

   900px, not the theme's usual 781px: three columns of a location block, a 44px icon pair
   with a handle beside it, and a 6.45em image need more room than a tablet has before the
   middle column starts wrapping the handle under the circles.

   padding-inline with max() is what keeps the columns from sprawling on a wide monitor.
   The section is alignfull and paints the cream background edge to edge, so it cannot take
   a max-width itself without the background shrinking with it — the padding centres a
   1100px content box while the element stays full-bleed. */
@media (min-width: 900px) {
	.bjs-footer {
		display: grid;
		grid-template-columns: repeat(3, 1fr);
		align-items: center;
		justify-items: center;
		column-gap: 2.5rem;
		padding-inline: max(1.5rem, calc((100% - 1100px) / 2));
	}
	/* WordPress' block gap puts a top margin on every sibling after the first. In a
	   stack that is the spacing; in a grid it drops row 1 of columns 2 and 3 below row 1
	   of column 1. The rule that sets it is wrapped in :where(), which contributes zero
	   specificity, so this plain selector wins without !important. */
	.bjs-footer > * {
		margin-block-start: 0;
	}
	/* The location block is the tallest of the three — name, two lines, and a pill — so
	   it spans both rows and the other columns centre against it. */
	.bjs-footer > .bjs-footer-find {
		grid-column: 1;
		grid-row: 1 / span 2;
	}
	.bjs-footer > .bjs-follow {
		grid-column: 2;
		grid-row: 1;
	}
	.bjs-footer > .bjs-url {
		grid-column: 2;
		grid-row: 2;
	}
	/* The mark is one piece and taller than the middle column's two rows, so it spans
	   both and centres against them rather than sitting on one row's baseline. */
	.bjs-footer > .bjs-footer-mark {
		grid-column: 3;
		grid-row: 1 / span 2;
		margin-top: 0;
	}
	/* This margin was the gap between the social row and the tagline above it in the
	   stack. In a column of its own there is nothing above it to clear. */
	.bjs-footer .bjs-social {
		margin: 0;
	}
}

/* Kill the blank band above the footer. WordPress' root block gap emits
   `:where(.wp-site-blocks) > * { margin-block-start: 24px }`, which drops a
   24px strip of cream body background between <main> and <footer> — it reads
   as an empty seam between the mint JOIN section and the footer's mint
   hairline. Every section already carries its own vertical padding, so the
   top-level parts need no gap. `:where()` contributes zero specificity, so a
   single class beats it without !important. */
footer.wp-block-template-part {
	margin-block-start: 0;
}

/* Closing SEO blurb. It exists for search engines — the words "shaved ice",
   "Vandalia", and "Dayton" have to be real text on the page — but a visitor who
   reads it should not feel sold to, so it sits quiet: smaller than body copy,
   sage rather than ink, and narrow enough to read as a caption. */
.bjs-blurb {
	max-width: 62ch;
	margin-left: auto;
	margin-right: auto;
	font-size: 0.9rem;
	line-height: 1.75;
	/* Same AA failure/fix as the tagline and toppings-price sage text above: 3.72:1 on
	   this section's mint-soft background, short of the 4.5:1 this 14.4px text needs. */
	color: #4f6347;
}

/* ---------------------------------------------------------------------------
   Event Pricing page (page-event-pricing.html)

   Two rate tables — minimum-sales by event length, and flat packages by guest
   count. Core's table block ships a 1px border on every cell, which reads as a
   spreadsheet next to the rounded cards everywhere else on the site. These
   rules strip that back to horizontal rules only and wrap the whole thing in
   the same 1.25rem radius the .bjs-card group uses.

   The radius has to live on the figure with overflow:hidden, not on the table:
   border-radius on a border-collapse:collapse table is ignored by every engine,
   so the sage header corners would stay square.
   --------------------------------------------------------------------------- */
.bjs-price-table {
	max-width: 40rem;
	margin-inline: auto;
	border-radius: 1.25rem;
	overflow: hidden;
	background-color: var(--wp--preset--color--white);
	box-shadow: 0 1px 2px rgba(31, 41, 36, 0.06);
}
.bjs-price-table table {
	border-collapse: collapse;
	width: 100%;
}
.bjs-price-table th,
.bjs-price-table td {
	border: 0;
	padding: 0.95rem 1.25rem;
	text-align: left;
}
.bjs-price-table thead th {
	background-color: var(--wp--preset--color--sage);
	color: var(--wp--preset--color--white);
	font-family: 'Vancouver Gothic', 'Archivo', system-ui, sans-serif;
	font-weight: 400;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	font-size: 0.95rem;
}
.bjs-price-table tbody tr + tr td {
	border-top: 1px solid rgba(154, 178, 154, 0.35);
}
/* The rate is the thing being scanned for, so it carries the brand pink and the
   caps face — the same treatment $4.00 gets on the menu cards. Last-child rather
   than a class because the tables have two and three columns respectively and
   the price is the final column in both. */
.bjs-price-table tbody td:last-child {
	color: var(--wp--preset--color--pink);
	font-family: 'Vancouver Gothic', 'Archivo', system-ui, sans-serif;
	font-weight: 400;
	font-size: 1.15rem;
	text-align: right;
	white-space: nowrap;
}
.bjs-price-table thead th:last-child {
	text-align: right;
}

/* The how-it-works card is a .bjs-card group rather than a column, so it has no
   column width to constrain it — it would otherwise run the full content width
   while the table above it stops at 40rem. */
.bjs-pricing-note {
	max-width: 40rem;
	margin-inline: auto;
}

@media (max-width: 600px) {
	.bjs-price-table th,
	.bjs-price-table td {
		padding: 0.8rem 0.9rem;
	}
	.bjs-price-table thead th {
		font-size: 0.85rem;
		letter-spacing: 0.04em;
	}
	.bjs-price-table tbody td:last-child {
		font-size: 1.05rem;
	}
}

/* The Book Us teaser table. Same shell as the full table on the pricing page,
   dialled down: it sits in a column beside the four cards rather than centred
   under a heading, so the 40rem cap and auto margins would leave it floating
   off to one side of its own column. */
.bjs-price-table.bjs-price-mini {
	max-width: none;
	margin-inline: 0;
}
.bjs-price-mini th,
.bjs-price-mini td {
	padding: 0.65rem 0.9rem;
}
.bjs-price-mini thead th {
	font-size: 0.8rem;
}
.bjs-price-mini tbody td {
	font-size: 0.95rem;
}
.bjs-price-mini tbody td:last-child {
	font-size: 1rem;
}

/* The step numerals on the three menu headings. They are wayfinding, not a checkout
   flow -- nothing on this site submits an order -- so they sit quietly in sage at the
   head of each section rather than reading as required stages. Tabular-ish sizing keeps
   the numeral from crowding the caps face beside it. */
.bjs-step {
	display: inline-block;
	min-width: 1.9em;
	margin-inline-end: 0.15em;
	padding: 0.1em 0.4em;
	border-radius: 999px;
	background-color: var(--wp--preset--color--sage);
	color: var(--wp--preset--color--white);
	font-size: 0.62em;
	line-height: 1.5;
	vertical-align: 0.22em;
}

/* The cream topping's ingredient gloss. It has to stay readable but must not compete
   with the topping name it explains. */
.bjs-item-note {
	display: block;
	font-size: 0.85rem;
	color: #6a7a63;
	line-height: 1.35;
}
