/*
 * ZooHouse Fit Club — dark brutalist luxury.
 *
 * Everything is scoped under .zhfc-* and the .zhfc-panel wrapper so the
 * plugin never fights the surrounding WordPress theme. Sharp edges, heavy
 * display type, monospace for labels and data.
 */

@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Space+Mono:wght@400;700&display=swap');

body.zhfc-page,
body.zhfc-catalog-page,
.zhfc-panel {
	--zh-ink: #0a0a0a;
	--zh-ink-soft: #121212;
	--zh-ink-raised: #1a1a1a;
	--zh-gold: #c9a04d;
	--zh-gold-bright: #e8c368;
	--zh-red: #e5322d; /* ZooHouse brand red */
	--zh-bone: #f5f3ee;
	--zh-bone-dim: #a8a49a;
	--zh-line: #2a2a2a;
	--zh-danger: #b0463c;
	--zh-success: #4a9d5f;

	--zh-display: 'Bebas Neue', Impact, sans-serif;
	--zh-mono: 'Space Mono', 'Courier New', monospace;
}

.zhfc-panel {
	background: var(--zh-ink);
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	padding: clamp(1.5rem, 4vw, 3rem);
	max-width: 56rem;
	margin: 0 auto;
	line-height: 1.6;
}

/* Sharp edges everywhere — but scoped, so we don't restyle the whole site. */
.zhfc-panel,
.zhfc-panel * {
	border-radius: 0 !important;
	box-sizing: border-box;
}

.zhfc-panel--center {
	text-align: center;
}

.zhfc-panel--notice {
	text-align: center;
	border: 1px solid var(--zh-line);
}

/* Brand ------------------------------------------------------------- */

.zhfc-nav {
	position: sticky;
	/* Sit under the admin bar for logged-in staff, flush to the top otherwise. */
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 50;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem 1.5rem;
	flex-wrap: wrap;
	padding: 1rem clamp(1rem, 5vw, 2.5rem);
	background: rgba(10, 10, 10, 0.92);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	border-bottom: 1px solid var(--zh-line);
}

.zhfc-main {
	display: block;
}

.zhfc-nav-brand {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	text-decoration: none;
}

.zhfc-nav-word {
	font-family: var(--zh-display);
	font-size: 1.35rem;
	letter-spacing: 0.1em;
	line-height: 1;
	text-transform: uppercase;
	color: var(--zh-bone);
}

.zhfc-nav-sub {
	font-family: var(--zh-display);
	font-size: 1.35rem;
	letter-spacing: 0.1em;
	line-height: 1;
	text-transform: uppercase;
	color: var(--zh-gold);
}

.zhfc-nav-right {
	display: flex;
	align-items: center;
	gap: 1.25rem;
}

.zhfc-nav-menu {
	display: flex;
	align-items: center;
	gap: 1.5rem;
	flex-wrap: wrap;
}

.zhfc-nav-links,
.zhfc-nav-session {
	display: flex;
	align-items: center;
	gap: 1.5rem;
	flex-wrap: wrap;
}

.zhfc-nav-toggle {
	display: none;
	flex-direction: column;
	justify-content: center;
	gap: 0.3rem;
	width: 1.75rem;
	height: 1.75rem;
	padding: 0;
	background: transparent;
	border: none;
	cursor: pointer;
	flex: none;
}

.zhfc-nav-toggle-bar {
	display: block;
	width: 100%;
	height: 2px;
	background: var(--zh-bone);
	transition: transform 0.2s ease, opacity 0.2s ease;
}

.zhfc-nav-toggle[aria-expanded="true"] .zhfc-nav-toggle-bar:nth-child(1) {
	transform: translateY(0.4rem) rotate(45deg);
}

.zhfc-nav-toggle[aria-expanded="true"] .zhfc-nav-toggle-bar:nth-child(2) {
	opacity: 0;
}

.zhfc-nav-toggle[aria-expanded="true"] .zhfc-nav-toggle-bar:nth-child(3) {
	transform: translateY(-0.4rem) rotate(-45deg);
}

.zhfc-nav-link {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone-dim);
	text-decoration: none;
	transition: color 0.15s ease;
}

.zhfc-nav-link:hover {
	color: var(--zh-gold);
}

.zhfc-nav-cta {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-gold);
	text-decoration: none;
	border: 1px solid var(--zh-gold);
	padding: 0.6rem 1.1rem;
	transition: background-color 0.15s ease, color 0.15s ease;
	white-space: nowrap;
}

.zhfc-nav-cta:hover {
	background: var(--zh-gold);
	color: var(--zh-ink);
}

.zhfc-nav-session-link {
	border: 1px solid var(--zh-line);
	padding: 0.6rem 1.1rem;
	transition: border-color 0.15s ease, color 0.15s ease;
}

.zhfc-nav-session-link:hover {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-nav-instagram {
	display: none;
	align-items: center;
	color: var(--zh-bone-dim);
	transition: color 0.15s ease;
}

.zhfc-nav-instagram:hover {
	color: var(--zh-gold);
}

.zhfc-nav-install {
	align-items: center;
	gap: 0.3rem;
	background: linear-gradient(135deg, var(--zh-gold-bright), var(--zh-gold));
	color: var(--zh-ink);
	border: none;
	padding: 0.35rem 0.65rem;
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	cursor: pointer;
	flex: none;
	white-space: nowrap;
	animation: zhfc-install-glow 2.6s ease-in-out infinite;
}

.zhfc-nav-install:not([hidden]) {
	display: inline-flex;
	/* Desktop: sit right against the brand instead of floating in
	 * whatever gap space-between happens to leave — this absorbs all the
	 * remaining room on its own right side, pushing the link/session
	 * group to the far right same as before. Overridden back to auto/auto
	 * (centered in the row) on mobile below. */
	margin-right: auto;
}

.zhfc-nav-install:hover {
	filter: brightness(1.08);
}

@keyframes zhfc-install-glow {
	0%, 100% {
		box-shadow: 0 0 6px 0 rgba(201, 160, 77, 0.45), 0 0 14px 2px rgba(201, 160, 77, 0.25);
	}
	50% {
		box-shadow: 0 0 12px 2px rgba(201, 160, 77, 0.85), 0 0 22px 6px rgba(201, 160, 77, 0.45);
	}
}

.zhfc-nav-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	color: var(--zh-bone-dim);
	transition: color 0.15s ease;
}

.zhfc-nav-cart:hover {
	color: var(--zh-gold);
}

.zhfc-nav-cart-count {
	position: absolute;
	top: -0.5rem;
	right: -0.6rem;
	min-width: 1.1rem;
	height: 1.1rem;
	padding: 0 0.25rem;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--zh-gold);
	color: var(--zh-ink);
	font-family: var(--zh-mono);
	font-size: 0.6rem;
	line-height: 1;
}

/* Below this the full links+session row no longer fits — Den, My Program,
 * Challenges, Dashboard, Archive, Admin, Log Out and the cart icon all at
 * once. Collapse everything but the cart behind the hamburger instead of
 * reflowing it onto a second row. */
@media (max-width: 40rem) {
	.zhfc-nav {
		flex-wrap: nowrap;
		gap: 0.6rem;
	}

	.zhfc-nav-right {
		gap: 0.85rem;
	}

	.zhfc-nav-sub,
	.zhfc-nav-word { font-size: 1.1rem; }

	.zhfc-nav-brand {
		flex: none;
	}

	.zhfc-nav-toggle {
		display: flex;
	}

	.zhfc-nav-instagram {
		display: inline-flex;
	}

	.zhfc-nav-install:not([hidden]) {
		margin: 0 auto;
	}

	.zhfc-nav-menu {
		display: none;
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		background: var(--zh-ink);
		border-bottom: 1px solid var(--zh-line);
		padding: 0.5rem clamp(1rem, 5vw, 2.5rem) 1.25rem;
		max-height: calc(100vh - 100%);
		overflow-y: auto;
	}

	.zhfc-nav-menu.is-open {
		display: flex;
	}

	.zhfc-nav-menu .zhfc-nav-links,
	.zhfc-nav-menu .zhfc-nav-session {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.zhfc-nav-menu .zhfc-nav-link {
		padding: 0.85rem 0;
		border-bottom: 1px solid var(--zh-line);
	}

	.zhfc-nav-menu .zhfc-nav-session-link {
		border: none;
		border-bottom: 1px solid var(--zh-line);
		padding: 0.85rem 0;
	}

	.zhfc-nav-menu .zhfc-nav-cta {
		text-align: center;
		margin-top: 0.85rem;
	}
}

/* Brand mark — signs off the bottom of every screen rather than repeating
 * at the top. The logo is the stamp; the wordmark is the page furniture. */

.zhfc-footer {
	margin-top: clamp(3rem, 8vw, 5rem);
	padding-top: 2rem;
	border-top: 1px solid var(--zh-line);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
	text-align: center;
}

/* Fine print, centered with the rest of the footer. */
.zhfc-footer-copyright {
	margin: 0;
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	letter-spacing: 0.04em;
	color: var(--zh-bone-dim);
}

.zhfc-footer .zhfc-footer-logo {
	height: 1.75rem;
	width: auto;
	max-width: 60vw;
	display: block;
	opacity: 0.75;
}

.zhfc-footer-nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	/* Row-gap only — column spacing is owned by each separator's own
	   margin below, not a flex gap, so the bullet sits centered between
	   items instead of needing to fight a gap that was already there. */
	row-gap: 0.6rem;
}

.zhfc-footer-nav:empty {
	display: none;
}

/* A bullet between every link (and the Close My Account button) — never
   before the first one, and never orphaned mid-row on wrap since it's
   tied to each item rather than inserted as a separate flex child. */
.zhfc-footer-nav > *:not(:first-child)::before {
	content: '•';
	display: inline-block;
	margin: 0 0.5rem;
	color: var(--zh-line);
}

.zhfc-footer-nav a {
	color: var(--zh-bone-dim);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	text-decoration: none;
}

.zhfc-footer-nav a:hover {
	color: var(--zh-gold);
}

/* Same sign-off weight as the legal links beside it — a button, not an
   <a>, since it opens the modal rather than navigating, but styled
   identically at rest so it doesn't stick out until someone's actually
   near it. */
.zhfc-footer-nav-danger {
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	color: var(--zh-bone-dim);
	font-family: inherit;
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.zhfc-footer-nav-danger:hover {
	color: var(--zh-danger);
}

/* Smaller again on a phone — it is a sign-off, not a headline. */
@media (max-width: 34rem) {
	.zhfc-footer .zhfc-footer-logo {
		height: 1.25rem;
		max-width: 40vw;
	}
}


/* Accent colour picker ---------------------------------------------- */

.zhfc-color-row {
	display: flex;
	align-items: center;
	gap: 1rem;
	flex-wrap: wrap;
}

.zhfc-color {
	appearance: none;
	-webkit-appearance: none;
	width: 4rem;
	height: 3rem;
	padding: 0;
	border: 1px solid var(--zh-line);
	background: transparent;
	cursor: pointer;
}

.zhfc-color::-webkit-color-swatch-wrapper { padding: 3px; }
.zhfc-color::-webkit-color-swatch { border: none; }
.zhfc-color::-moz-color-swatch { border: none; }

.zhfc-color-value {
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--zh-bone-dim);
}

/* Six per row, two rows of six. A flex row of twelve fixed-width swatches
 * overflowed the viewport on a phone, which is what made the page rock
 * sideways. */
.zhfc-swatches {
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	gap: 0.4rem;
	margin-left: auto;
	max-width: 14rem;
}

.zhfc-swatch {
	width: 100%;
	aspect-ratio: 1;
	min-height: 1.6rem;
	border: 1px solid var(--zh-line);
	cursor: pointer;
	padding: 0;
}

.zhfc-swatch:hover {
	border-color: var(--zh-bone);
}

/* Type -------------------------------------------------------------- */

.zhfc-display {
	font-family: var(--zh-display);
	font-size: clamp(2.5rem, 7vw, 4rem);
	line-height: 0.95;
	letter-spacing: 0.02em;
	color: var(--zh-bone);
	margin: 0 0 0.5rem;
	text-transform: uppercase;
}

.zhfc-display--sm {
	font-size: clamp(1.5rem, 3.5vw, 2rem);
}

.zhfc-gold {
	color: var(--zh-gold);
}

.zhfc-eyebrow {
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.3em;
	color: var(--zh-gold);
	margin: 0 0 0.35rem;
}

.zhfc-label {
	display: block;
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone);
	margin: 1.75rem 0 0.35rem;
}

/* The coach-voice "why this matters" line under every question. */
.zhfc-hint {
	font-size: 0.8rem;
	color: var(--zh-bone-dim);
	margin: 0 0 0.75rem;
}

.zhfc-progress-note.is-error {
	color: var(--zh-danger);
	margin: 0 0 0.75rem;
}

.zhfc-divider {
	border: none;
	border-top: 1px solid var(--zh-line);
	margin: 1rem 0;
}

.zhfc-meta {
	font-size: 0.75rem;
	color: var(--zh-bone-dim);
}

.zhfc-error {
	color: var(--zh-danger);
	font-size: 0.8rem;
	margin: 1rem 0 0;
}

.zhfc-login-links {
	text-align: center;
	margin-top: 1.25rem;
}

.zhfc-login-links a {
	color: var(--zh-gold);
	text-decoration: none;
}

.zhfc-login-links a:hover {
	text-decoration: underline;
}

.zhfc-login-logo-wrap {
	position: relative;
	width: 9rem;
	margin: 0 auto 2rem;
}

/* The same gold-fill logo, reused as a between-pages transition for
 * [data-nav-loading] links (initNavLoadingOverlay() in app.js) — "Load My
 * Program" on the homepage, and entering an active challenge. Sits above
 * everything as a full-screen cover while the real navigation is in
 * flight underneath it. */
.zhfc-nav-loading-overlay {
	/* display:none by default is load-bearing, not decorative: a bare
	 * class selector setting `display` overrides the browser's own
	 * [hidden]{display:none} UA rule (author styles beat the UA
	 * stylesheet regardless of specificity), so without this the overlay
	 * stayed laid out and pointer-events:auto at opacity 0 — invisible,
	 * full-screen, eating every click on the whole site. */
	display: none;
	position: fixed;
	inset: 0;
	z-index: 999;
	align-items: center;
	justify-content: center;
	background: var(--zh-ink);
	opacity: 0;
	transition: opacity 0.25s ease;
}

.zhfc-nav-loading-overlay:not([hidden]) {
	display: flex;
}

.zhfc-nav-loading-overlay.is-visible {
	opacity: 1;
}

.zhfc-nav-loading-overlay .zhfc-login-logo-wrap {
	margin: 0;
	width: 10rem;
}

.zhfc-login-logo {
	display: block;
	width: 100%;
}

/* Recolors the same logo file solid gold via mask (the mask-image URL is
 * set inline per-render in PHP) rather than shipping a second asset, then
 * clip-path reveals it left to right as initLoginLoader() (app.js) drives
 * the fill — the logo doubles as its own loading bar. */
.zhfc-login-logo-fill {
	position: absolute;
	inset: 0;
	background: linear-gradient(135deg, var(--zh-gold-bright), var(--zh-gold));
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	clip-path: inset(0 100% 0 0);
}

/* Launching the installed app lands on this page first — on a phone that
 * is effectively the app's splash/login screen, so the form centers
 * top-to-bottom in the viewport instead of stacking from the top like an
 * ordinary web page. Desktop and non-app visits keep the regular layout. */
@media (max-width: 34rem) {
	.zhfc-panel--login-pwa {
		min-height: 100vh;
		min-height: 100dvh;
		display: flex;
		flex-direction: column;
		justify-content: center;
		/* Default align-items:stretch would force every unwidthed child —
		 * the Continue/Log In button included — to fill the full cross
		 * axis, turning an inline-block button into a full-bleed one. */
		align-items: center;
	}

	.zhfc-panel--login-pwa .zhfc-btn {
		width: auto;
	}

	/* Logo fades in first (3s). initLoginLoader() (app.js) catches that
	 * animation's end and drives the gold clip-path fill in randomized
	 * bursts, with a randomized total duration too, so the loading beat
	 * never plays out quite the same way twice. Everything else stays
	 * invisible until the fill hits 100%, at which point JS adds
	 * is-revealed and this fades it all in together — a splash-screen
	 * beat, not everything popping in at once. */
	.zhfc-panel--login-pwa .zhfc-login-logo-wrap {
		opacity: 0;
		animation: zhfc-login-fade-in 3s ease forwards;
	}

	.zhfc-panel--login-pwa > *:not(.zhfc-login-logo-wrap) {
		opacity: 0;
	}

	.zhfc-panel--login-pwa.is-revealed > *:not(.zhfc-login-logo-wrap) {
		animation: zhfc-login-fade-in 0.6s ease forwards;
	}

	@keyframes zhfc-login-fade-in {
		from {
			opacity: 0;
			transform: translateY(0.6rem);
		}
		to {
			opacity: 1;
			transform: translateY(0);
		}
	}
}

/* Inputs ------------------------------------------------------------ */

.zhfc-input,
.zhfc-textarea {
	width: 100%;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-line);
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	font-size: 0.9rem;
	padding: 0.75rem 1rem;
}

.zhfc-input:focus,
.zhfc-textarea:focus {
	outline: none;
	border-color: var(--zh-gold);
}

.zhfc-textarea {
	resize: vertical;
	min-height: 5rem;
}

/* The endgame title gets the hero treatment — it is the signature field. */
.zhfc-input--endgame {
	font-family: var(--zh-display);
	font-size: clamp(1.75rem, 5vw, 2.75rem);
	text-align: center;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--zh-gold);
	background: transparent;
	border: 0;
	border-bottom: 2px solid var(--zh-line);
	padding: 1rem 0.5rem;
}

.zhfc-input--endgame::placeholder {
	color: var(--zh-line);
}

.zhfc-input--endgame:focus {
	border-bottom-color: var(--zh-gold);
}

.zhfc-range {
	width: 100%;
	accent-color: var(--zh-gold);
}

.zhfc-range-row {
	display: flex;
	align-items: center;
	gap: 1rem;
}

.zhfc-range-value {
	font-family: var(--zh-display);
	font-size: 1.75rem;
	color: var(--zh-gold);
	min-width: 2rem;
}

/* Choice / multi chips ---------------------------------------------- */

/* Endgame naming help: a seed box the member can leave empty. */
.zhfc-endgame-helper {
	margin-top: 1.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--zh-line);
}

.zhfc-endgame-helper .zhfc-input {
	margin-bottom: 1rem;
}

.zhfc-endgame-helper .zhfc-choices {
	margin-top: 1rem;
}

.zhfc-equip-suggest {
	margin-top: 1.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--zh-line);
}

.zhfc-equip-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: 0.75rem;
}

.zhfc-equip-tag {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--zh-gold);
	border: 1px solid var(--zh-gold);
	padding: 0.35rem 0.75rem;
}

.zhfc-choices {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 2rem;
}

/* The submit sits directly after the last field on the signup form and would
 * otherwise butt straight up against it. */
.zhfc-choices + .zhfc-error + .zhfc-btn,
.zhfc-choices + .zhfc-btn {
	margin-top: 0.5rem;
}

.zhfc-chip {
	background: transparent;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	padding: 0.6rem 1rem;
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.zhfc-chip:hover {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-chip[aria-pressed='true'] {
	background: var(--zh-gold);
	border-color: var(--zh-gold);
	color: var(--zh-ink);
}

/* Buttons ----------------------------------------------------------- */

.zhfc-btn {
	display: inline-block;
	background: var(--zh-gold);
	border: 1px solid var(--zh-gold);
	color: var(--zh-ink);
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	padding: 0.9rem 2rem;
	cursor: pointer;
	text-decoration: none;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}

.zhfc-btn:hover {
	background: var(--zh-gold-bright);
	border-color: var(--zh-gold-bright);
	color: var(--zh-ink);
}

.zhfc-btn:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}

.zhfc-btn--ghost {
	background: transparent;
	color: var(--zh-bone-dim);
	border-color: var(--zh-line);
}

.zhfc-btn--ghost:hover {
	background: transparent;
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-btn--danger {
	background: transparent;
	color: var(--zh-danger);
	border-color: var(--zh-danger);
}

.zhfc-btn--danger:hover {
	background: var(--zh-danger);
	border-color: var(--zh-danger);
	color: var(--zh-bone);
}

.zhfc-danger {
	color: var(--zh-danger);
}

.zhfc-checkbox-row {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin: 1rem 0;
	font-size: 0.85rem;
	color: var(--zh-bone-dim);
	cursor: pointer;
}

/* Dashboard hub — current program card + active challenge cards -------- */

.zhfc-hub-cards {
	margin-top: 1.5rem;
	display: flex;
	flex-direction: column;
	gap: 1rem;
	text-align: left;
}

a.zhfc-hub-card {
	display: block;
	border: 1px solid var(--zh-line);
	padding: 1.25rem 1.5rem;
	text-decoration: none;
	color: inherit;
	transition: border-color 0.15s ease;
}

a.zhfc-hub-card:hover,
a.zhfc-hub-card:focus-visible {
	border-color: var(--zh-gold);
	outline: none;
}

.zhfc-hub-card--empty {
	border: 1px dashed var(--zh-line);
	padding: 1.25rem 1.5rem;
}

.zhfc-hub-card .zhfc-progress-track {
	margin: 0.9rem 0 0.5rem;
}

/* Weekly Recap — the gamified, shareable stat card. Built to read cleanly
   as a standalone screenshot crop (see initWeeklyRecapShare() in app.js,
   which redraws this same data as a 9:16 image), so it gets its own gold
   gradient border rather than the plain .zhfc-card outline. */
.zhfc-recap-card {
	text-align: center;
	background: linear-gradient(160deg, var(--zh-ink-raised) 0%, var(--zh-ink-soft) 100%);
	border: 1px solid var(--zh-gold);
	box-shadow: 0 0 2rem rgba(201, 160, 77, 0.12);
}

/* The three big lifetime numbers — total points, days on app, total
   workouts — read at a glance before any of the weekly/daily detail below. */
.zhfc-recap-top {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.5rem;
	margin: 1rem 0 1.25rem;
}

.zhfc-recap-top-stat {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.zhfc-recap-top-num {
	font-family: var(--zh-display);
	font-size: clamp(2rem, 9vw, 2.75rem);
	line-height: 1;
	color: var(--zh-gold-bright);
}

.zhfc-recap-top-label {
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-bone-dim);
	margin-top: 0.3rem;
	text-align: center;
}

/* Single big number + "Perfect Week" badge — the frozen Weekly Recap page
   only (render_weekly_recap_share_view()), not the live daily scorecard,
   which uses .zhfc-recap-top's three-column layout instead. */
.zhfc-recap-hero {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin: 1rem 0 0.5rem;
}

.zhfc-recap-hero-num {
	font-family: var(--zh-display);
	font-size: clamp(3.5rem, 14vw, 5rem);
	line-height: 1;
	color: var(--zh-gold-bright);
}

.zhfc-recap-hero-label {
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.25em;
	color: var(--zh-bone-dim);
	margin-top: 0.25rem;
}

.zhfc-recap-badge {
	display: inline-block;
	margin: 0 0 1rem;
	padding: 0.3rem 0.8rem;
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-ink);
	background: var(--zh-gold);
}

.zhfc-recap-stats {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.75rem;
	border-top: 1px solid var(--zh-line);
	border-bottom: 1px solid var(--zh-line);
	padding: 1rem 0;
	margin-bottom: 1.25rem;
}

.zhfc-recap-stat {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

.zhfc-recap-stat-num {
	font-family: var(--zh-display);
	font-size: 1.5rem;
	color: var(--zh-bone);
}

.zhfc-recap-stat-label {
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-bone-dim);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.zhfc-recap-eyebrow {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
}

.zhfc-recap-info {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.1rem;
	height: 1.1rem;
	border-radius: 50%;
	border: 1px solid var(--zh-gold);
	color: var(--zh-gold);
	background: transparent;
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	line-height: 1;
	padding: 0;
	cursor: pointer;
}

.zhfc-recap-info:hover {
	background: var(--zh-gold);
	color: var(--zh-ink);
}

/* Log form — a compact row so it reads as part of the scorecard, not a
   separate settings panel bolted onto it. */
.zhfc-recap-log {
	margin-bottom: 1.25rem;
	text-align: left;
}

.zhfc-recap-log-label {
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone-dim);
	margin: 0 0 0.5rem;
}

.zhfc-recap-log-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}

.zhfc-recap-log-rings {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	font-size: 0.75rem;
	color: var(--zh-bone);
	white-space: nowrap;
}

.zhfc-recap-log-input {
	flex: 1 1 6rem;
	min-width: 5rem;
	background: var(--zh-ink);
	border: 1px solid var(--zh-line);
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	font-size: 0.85rem;
	padding: 0.5rem 0.6rem;
}

.zhfc-recap-log-input:focus {
	outline: none;
	border-color: var(--zh-gold);
}

.zhfc-recap-log-msg {
	margin: 0.5rem 0 0;
	font-size: 0.7rem;
	color: var(--zh-bone-dim);
}

.zhfc-recap-log-msg.is-error {
	color: var(--zh-danger);
}

/* My programs --------------------------------------------------------- */

.zhfc-my-programs {
	margin-top: 2rem;
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.zhfc-my-program {
	border: 1px solid var(--zh-line);
	padding: 1.25rem 1.5rem;
}

.zhfc-my-program-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
}

.zhfc-my-program-status {
	flex-shrink: 0;
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	padding: 0.25rem 0.6rem;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
}

.zhfc-my-program-status--ready {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-my-program-status--failed {
	border-color: var(--zh-danger);
	color: var(--zh-danger);
}

.zhfc-my-program .zhfc-progress-track {
	margin: 0.9rem 0 0.5rem;
}

.zhfc-my-program .zhfc-btn {
	margin-top: 0.75rem;
}

.zhfc-actions {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	margin-top: 3rem;
}

/* Progress ---------------------------------------------------------- */

.zhfc-progress-meta {
	display: flex;
	justify-content: space-between;
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone-dim);
	margin-bottom: 0.5rem;
}

.zhfc-progress-track {
	height: 2px;
	background: var(--zh-line);
	width: 100%;
}

.zhfc-progress-fill {
	height: 2px;
	background: var(--zh-gold);
	width: 0;
	transition: width 0.4s ease;
}

/* Trainer presence on the generating screen -------------------------- */

.zhfc-gen-trainer {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin: 1rem 0 1.5rem;
}

.zhfc-gen-trainer-img {
	height: clamp(11rem, 26vw, 18rem);
	width: auto;
	max-width: 100%;
	object-fit: contain;
	filter: drop-shadow(0 12px 20px rgba(0, 0, 0, 0.5));
}

.zhfc-gen-speech {
	position: relative;
	margin-top: 0.75rem;
	max-width: 28rem;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-gold);
	padding: 1rem 1.25rem;
}

.zhfc-gen-speech::before,
.zhfc-gen-speech::after {
	content: '';
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	border-left: 0.5rem solid transparent;
	border-right: 0.5rem solid transparent;
}

.zhfc-gen-speech::before {
	top: -0.5rem;
	border-bottom: 0.5rem solid var(--zh-gold);
}

.zhfc-gen-speech::after {
	top: -0.4rem;
	border-left-width: 0.42rem;
	border-right-width: 0.42rem;
	border-bottom: 0.42rem solid var(--zh-ink-soft);
}

.zhfc-gen-speech-label {
	color: var(--zh-gold);
	font-weight: 700;
	margin: 0 0 0.35rem;
}

.zhfc-gen-speech-line {
	color: var(--zh-bone-dim);
	font-size: 0.85rem;
	margin: 0;
}

/* Generation log ---------------------------------------------------- */

.zhfc-log {
	list-style: none;
	padding: 0;
	margin: 2rem 0 0;
	text-align: left;
	font-size: 0.85rem;
}

.zhfc-log li {
	display: flex;
	gap: 0.75rem;
	color: var(--zh-bone-dim);
	margin-bottom: 0.4rem;
}

.zhfc-log li.is-active {
	color: var(--zh-gold);
}

.zhfc-log li.is-error {
	color: var(--zh-danger);
}

/* Cards ------------------------------------------------------------- */

.zhfc-card {
	position: relative;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
	padding: 1.5rem;
	margin-top: 1.5rem;
}

.zhfc-card--current {
	border-color: var(--zh-gold);
}

.zhfc-stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 1rem;
	margin: 1rem 0;
}

.zhfc-stat {
	border: 1px solid var(--zh-line);
	padding: 0.75rem 1rem;
}

.zhfc-stat-label {
	display: block;
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone-dim);
}

.zhfc-stat-value {
	display: block;
	font-family: var(--zh-display);
	font-size: 1.6rem;
	color: var(--zh-bone);
}

.zhfc-list {
	list-style: none;
	padding: 0;
	margin: 0.5rem 0;
	font-size: 0.85rem;
	color: var(--zh-bone-dim);
}

.zhfc-list li {
	margin-bottom: 0.4rem;
}

.zhfc-list strong {
	color: var(--zh-bone);
	font-weight: 700;
}

/* Week 1 / Phase 1 weight-reps-time logging — mandatory, so it needs to
   read as part of the exercise line, not an optional aside. */
.zhfc-exlog-hint {
	margin: 0.5rem 0;
	font-size: 0.75rem;
	color: var(--zh-gold);
}

.zhfc-exlog-row {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 0.6rem;
	margin: 0.5rem 0 0.75rem;
	padding: 0.6rem 0.75rem;
	background: var(--zh-ink);
	border: 1px solid var(--zh-line);
}

.zhfc-exlog-label {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-exlog-input {
	width: 5rem;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-line);
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	font-size: 0.85rem;
	padding: 0.4rem 0.5rem;
}

.zhfc-exlog-input:focus {
	outline: none;
	border-color: var(--zh-gold);
}

.zhfc-exlog-saved {
	font-size: 0.7rem;
	color: var(--zh-gold);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/* Days / exercises -------------------------------------------------- */

.zhfc-day {
	border-left: 2px solid rgba(201, 160, 77, 0.4);
	padding-left: 1rem;
	margin-top: 1.5rem;
}

.zhfc-day-focus {
	font-family: var(--zh-display);
	font-size: 1.25rem;
	color: var(--zh-bone);
	margin: 0.1rem 0 0.5rem;
}

.zhfc-play {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.4rem;
	height: 1.4rem;
	margin-left: 0.4rem;
	background: transparent;
	border: 1px solid var(--zh-line);
	border-radius: 50%;
	color: var(--zh-gold);
	font-size: 0.6rem;
	line-height: 1;
	cursor: pointer;
	vertical-align: middle;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.zhfc-play:hover,
.zhfc-play:focus-visible {
	border-color: var(--zh-gold);
	background: rgba(201, 160, 77, 0.12);
	outline: none;
}

.zhfc-play-icon {
	transform: translateX(1px);
}

/* Exercise modal ------------------------------------------------------ */

.zhfc-modal--exercise {
	max-width: min(32rem, calc(100vw - 3rem));
}

.zhfc-exercise-video {
	margin: 1rem 0;
}

.zhfc-exercise-video-el {
	width: 100%;
	display: block;
	background: var(--zh-ink);
	border: 1px solid var(--zh-line);
}

.zhfc-exercise-video-frame {
	width: 100%;
	aspect-ratio: 16 / 9;
	display: block;
	background: var(--zh-ink);
	border: 1px solid var(--zh-line);
}

.zhfc-video-soon {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 10rem;
	border: 1px dashed var(--zh-line);
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	text-align: center;
	padding: 0 1rem;
}

.zhfc-exercise-tips-label {
	margin-top: 1rem;
}

.zhfc-exercise-tips {
	margin-top: 0.4rem;
	font-size: 0.85rem;
	color: var(--zh-bone-dim);
	line-height: 1.6;
}

.zhfc-exercise-tips p {
	margin: 0;
}

.zhfc-coachnote {
	font-size: 0.8rem;
	font-style: italic;
	color: var(--zh-bone-dim);
	margin: 0.75rem 0 0;
}

/* Phase-checkpoint photos --------------------------------------------- */

.zhfc-checkpoint-slots {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.75rem;
	margin-top: 1rem;
}

.zhfc-checkpoint-slot {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	border: 1px solid var(--zh-line);
	padding: 0.75rem;
	text-align: center;
}

.zhfc-checkpoint-thumb {
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	border: 1px solid var(--zh-line);
}

.zhfc-checkpoint-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 3 / 4;
	border: 1px dashed var(--zh-line);
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
}

.zhfc-checkpoint-upload-btn {
	display: block;
	width: 100%;
	box-sizing: border-box;
	background: transparent;
	border: 1px solid var(--zh-gold);
	color: var(--zh-gold);
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	padding: 0.5rem;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.zhfc-checkpoint-upload-btn:hover {
	background: var(--zh-gold);
	color: var(--zh-ink);
}

.zhfc-checkpoint-upload-btn.is-uploading {
	opacity: 0.6;
	pointer-events: none;
}

@media (max-width: 30rem) {
	.zhfc-checkpoint-slots {
		grid-template-columns: 1fr;
	}
}

/* Missing an angle: keeps glowing and blinking red until the third photo
   lands, so it never quietly sits there half-done. */
.zhfc-checkpoint.is-incomplete {
	animation: zhfc-checkpoint-blink 1.6s ease-in-out infinite;
}

@keyframes zhfc-checkpoint-blink {
	0%, 100% {
		border-color: var(--zh-line);
		box-shadow: none;
	}
	50% {
		border-color: var(--zh-danger);
		box-shadow: 0 0 0 1px var(--zh-danger), 0 0 1.5rem 0.25rem rgba(176, 70, 60, 0.55);
	}
}

/* Warning triangle in the summary line — blinks in lockstep with the box
   glow above so the two read as one signal, not two competing ones. */
/* Bumped up from the default .zhfc-eyebrow size so this reads as a real
 * prompt, not a small-print label someone's thumb scrolls straight past —
 * and goes larger still, bold, and red while a checkpoint is actually
 * incomplete, matching the box's own glow/blink urgency instead of just
 * describing it in a whisper-sized eyebrow. */
.zhfc-checkpoint-title {
	font-size: 0.85rem;
}

.zhfc-checkpoint.is-incomplete .zhfc-checkpoint-title {
	font-size: 1.05rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	color: var(--zh-danger);
}

.zhfc-checkpoint-warn-icon {
	display: inline-block;
	vertical-align: -0.2em;
	margin-right: 0.35em;
	color: var(--zh-danger);
	animation: zhfc-checkpoint-warn-blink 1.6s ease-in-out infinite;
}

@keyframes zhfc-checkpoint-warn-blink {
	0%, 100% {
		opacity: 0.35;
	}
	50% {
		opacity: 1;
	}
}

/* On mobile the checkpoint box sat flush against the week tabs right below
   it with nothing to tell them apart — give it its own breathing room. */
@media (max-width: 34rem) {
	.zhfc-checkpoint {
		margin-bottom: 1.5rem;
	}
}

.zhfc-checkpoint-gallery {
	margin-bottom: 1.5rem;
}

.zhfc-checkpoint-row {
	margin-top: 1.25rem;
}

.zhfc-checkpoint-row-photos {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.5rem;
	margin-top: 0.5rem;
}

.zhfc-checkpoint-row-thumb {
	display: block;
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	border: 1px solid var(--zh-line);
	transition: border-color 0.15s ease;
}

a:hover > .zhfc-checkpoint-row-thumb {
	border-color: var(--zh-gold);
}

.zhfc-checkpoint-row-thumb--empty {
	border-style: dashed;
	background: var(--zh-ink-raised);
}

@media (max-width: 30rem) {
	.zhfc-checkpoint-row-photos {
		grid-template-columns: repeat(3, 1fr);
		gap: 0.35rem;
	}
}

/* Dashboard hub: progress-photo carousel ----------------------------- */

.zhfc-hub-carousel {
	margin-top: 1.5rem;
}

.zhfc-carousel {
	display: flex;
	gap: 0.75rem;
	margin-top: 1rem;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
	padding-bottom: 0.25rem;
}

.zhfc-carousel-item {
	flex: 0 0 auto;
	width: 7.5rem;
	scroll-snap-align: start;
	text-decoration: none;
}

.zhfc-carousel-item img {
	display: block;
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	border: 1px solid var(--zh-line);
	transition: border-color 0.15s ease;
}

.zhfc-carousel-item:hover img {
	border-color: var(--zh-gold);
}

.zhfc-carousel-caption {
	display: block;
	margin-top: 0.4rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--zh-bone-dim);
}

/* Dashboard hub: medals carousel — horizontal scroll on purpose (per TJ)
 * so the roster can grow without a layout rework, standing in for a real
 * trophy-case page until one gets built. */

.zhfc-medals-section {
	margin-top: 1.5rem;
}

.zhfc-medals-carousel {
	display: flex;
	gap: 0.75rem;
	margin-top: 0.75rem;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
	padding-bottom: 0.25rem;
}

.zhfc-medal {
	flex: 0 0 auto;
	width: 6rem;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	text-align: center;
	border: 1px solid var(--zh-gold);
	background: linear-gradient(180deg, rgba(201, 160, 77, 0.1), transparent 70%);
	padding: 1rem 0.5rem;
	scroll-snap-align: start;
}

.zhfc-medal-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	color: var(--zh-gold);
}

.zhfc-medal-icon svg {
	width: 100%;
	height: 100%;
}

.zhfc-medal-name {
	font-family: var(--zh-mono);
	font-size: 0.62rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--zh-bone-dim);
	line-height: 1.3;
}

/* Cart page: "New In Store" carousel ---------------------------------- */

body.zhfc-woo-page .zhfc-shop-carousel-section {
	margin-top: 2.5rem;
	padding-top: 2rem;
	border-top: 1px solid var(--zh-line);
}

body.zhfc-woo-page .zhfc-shop-carousel-track {
	display: flex;
	gap: 1rem;
	margin-top: 1rem;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
	padding-bottom: 0.5rem;
}

/* Image and button share the item's first grid track (same overlay
 * technique as the shop grid — see zhfc-catalog-page) so "Options" sits
 * pinned over the photo's bottom-left corner instead of below it. */
body.zhfc-woo-page .zhfc-shop-carousel-item {
	flex: 0 0 auto;
	width: 9rem;
	display: grid;
	grid-template-columns: 1fr;
}

body.zhfc-woo-page .zhfc-shop-carousel-image {
	grid-row: 1;
	grid-column: 1;
	position: relative;
	display: block;
	scroll-snap-align: start;
}

body.zhfc-woo-page .zhfc-shop-carousel-image img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border: 1px solid var(--zh-line);
	border-radius: 0 !important;
}

body.zhfc-woo-page .zhfc-shop-carousel-btn {
	grid-row: 1;
	grid-column: 1;
	align-self: end;
	justify-self: start;
	z-index: 2;
	margin: 0 0 0.5rem 0.5rem;
	background: linear-gradient(135deg, var(--zh-gold-bright), var(--zh-gold));
	color: var(--zh-ink);
	font-family: var(--zh-mono);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-weight: 700;
	font-size: 0.6rem;
	padding: 0.4rem 0.75rem;
	text-decoration: none;
}

body.zhfc-woo-page .zhfc-shop-carousel-title {
	display: block;
	margin-top: 0.6rem;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	color: var(--zh-bone);
	text-decoration: none;
	line-height: 1.35;
}

body.zhfc-woo-page .zhfc-shop-carousel-price {
	display: block;
	margin-top: 0.2rem;
	color: var(--zh-gold-bright);
	font-family: var(--zh-display);
	letter-spacing: 0.02em;
	font-size: 1.1rem;
}

/* Challenges -------------------------------------------------------- */

.zhfc-rules {
	margin: 1rem 0;
	font-size: 0.8rem;
	color: var(--zh-bone-dim);
}

.zhfc-rules summary {
	cursor: pointer;
	color: var(--zh-gold);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	font-size: 0.7rem;
	display: flex;
	align-items: center;
	gap: 0.4rem;
	list-style: none;
}

.zhfc-rules summary::-webkit-details-marker {
	display: none;
}

/* Custom arrow instead of the native marker so it can actually be animated —
   bounces left/right to draw the eye to the fact that rules exist to read,
   and stops once the member has actually opened it. */
.zhfc-rules summary::before {
	content: '\25B8';
	display: inline-block;
	animation: zhfc-rules-arrow-bounce 1.3s ease-in-out infinite;
}

.zhfc-rules[open] summary::before {
	content: '\25BE';
	animation: none;
}

@keyframes zhfc-rules-arrow-bounce {
	0%, 100% {
		transform: translateX(0);
	}
	50% {
		transform: translateX(0.3rem);
	}
}

/* Home --------------------------------------------------------------
 *
 * The theme wraps our panels in its own light chrome, which leaves a dark
 * card floating on a white page. `zhfc-page` (added to <body> whenever a
 * plugin shortcode is present) darkens the surrounding page so the panel
 * reads as the design rather than as an embed.
 */

body.zhfc-page {
	background: #0a0a0a;
}

body.zhfc-page .zhfc-panel {
	max-width: 68rem;
}

.zhfc-panel--home {
	padding-top: clamp(2rem, 6vw, 4rem);
}

.zhfc-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-height: 100vh;
	min-height: 100dvh;
	/* Full-bleed: breaks out of .zhfc-panel's centered max-width so the
	 * background reaches both edges of the viewport regardless of how
	 * narrow the panel content column is. body.zhfc-page already carries
	 * overflow-x:hidden as a guard against exactly this kind of breakout. */
	width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
	padding: clamp(4rem, 12vw, 8rem) 1.5rem clamp(6rem, 14vw, 10rem);
}

/* Oversized and offset so the scroll-driven translateY in initHeroParallax()
 * (app.js) never runs the image out of frame — the JS clamps its own
 * travel distance to stay within this buffer. */
.zhfc-hero-bg {
	position: absolute;
	top: -15%;
	left: 0;
	right: 0;
	height: 130%;
	z-index: 0;
	overflow: hidden;
}

.zhfc-hero-bg-img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 30%;
	filter: grayscale(1);
	transform: scale(1);
	animation: zhfc-hero-zoom 55s ease-in-out infinite alternate;
	will-change: transform;
}

@keyframes zhfc-hero-zoom {
	from {
		transform: scale(1);
	}
	to {
		transform: scale(1.16);
	}
}

/* Fades all the way to solid --zh-ink at the very bottom, so the hero
 * dissolves straight into the page background below it instead of ending
 * on a visible seam. */
.zhfc-hero-overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.75) 0%, rgba(10, 10, 10, 0.88) 55%, var(--zh-ink) 100%);
}

.zhfc-hero > *:not(.zhfc-hero-bg):not(.zhfc-hero-overlay) {
	position: relative;
	z-index: 2;
}

.zhfc-hero .zhfc-brand {
	justify-content: center;
}

.zhfc-display--hero {
	font-size: clamp(3rem, 10vw, 6rem);
	margin: 0.5rem 0 1rem;
}

.zhfc-lede {
	max-width: 34rem;
	margin: 0 auto;
	font-size: 0.95rem;
	color: var(--zh-bone-dim);
}

.zhfc-hero-actions {
	display: flex;
	gap: 1rem;
	justify-content: center;
	flex-wrap: wrap;
	margin-top: 2.5rem;
}

/* A quoted line from the member's own trainer, replacing the sales-pitch
   paragraph once they already have a program or an active challenge. */
.zhfc-hero-quote {
	max-width: 30rem;
	margin: 0 auto;
}

.zhfc-hero-quote p {
	font-family: var(--zh-display);
	font-size: clamp(1.3rem, 3.5vw, 1.75rem);
	line-height: 1.3;
	color: var(--zh-bone);
	margin: 0;
}

.zhfc-hero-quote cite {
	display: block;
	margin-top: 0.6rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-gold);
	font-style: normal;
}

.zhfc-pillars {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 2.5rem;
	padding: clamp(2.5rem, 6vw, 4rem) 0;
	border-bottom: 1px solid var(--zh-line);
}

.zhfc-pillar {
	border-top: 1px solid var(--zh-gold);
	padding-top: 1.25rem;
}

.zhfc-pillar-num {
	font-family: var(--zh-display);
	font-size: 2.5rem;
	line-height: 1;
	color: rgba(232, 195, 104, 0.7);
	display: block;
}

.zhfc-pillar h3 {
	margin: 0.25rem 0 0.5rem;
}

/* Program lineup ----------------------------------------------------
 *
 * The row of shorter runs reads as a range; the flagship sits below it
 * with its own weight so it is obviously the top of that range rather
 * than a seventh equal option.
 */

.zhfc-programs {
	padding: clamp(2.5rem, 6vw, 4rem) 0;
	border-bottom: 1px solid var(--zh-line);
	text-align: center;
}

.zhfc-programs-lede {
	max-width: 30rem;
	margin: 0 auto 2.5rem;
}

.zhfc-runs {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
	gap: 1rem;
	text-align: left;
}

/* Phones are too narrow for auto-fit to give more than one card, which
 * turns the lineup into a long scroll. Force two up. */
@media (max-width: 34rem) {
	.zhfc-runs {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* Five run lengths in a 2-column grid leaves the last one (20 weeks) an
	 * orphan: alone on the left with a dead gap beside it. run_options()
	 * always renders 4/8/12/16/20 in that order, so the last card is always
	 * the 20-week one — span it across both columns as a closing highlight
	 * instead of leaving it half-width and stranded. */
	.zhfc-run:last-child {
		grid-column: 1 / -1;
	}
}

.zhfc-run {
	width: 100%;
	background: transparent;
	color: inherit;
	font: inherit;
	text-align: left;
	cursor: pointer;
	border: 1px solid var(--zh-line);
	padding: 1.25rem 1rem;
	display: flex;
	flex-direction: column;
	transition: border-color 0.15s ease;
}

.zhfc-run:hover,
.zhfc-run:focus-visible {
	border-color: var(--zh-gold);
	outline: none;
}

.zhfc-run-weeks {
	font-family: var(--zh-display);
	font-size: 3rem;
	line-height: 0.9;
	color: var(--zh-bone);
}

.zhfc-run-unit {
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.2em;
	color: var(--zh-bone-dim);
}

.zhfc-run-phases {
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-gold);
	margin-top: 0.75rem;
}

.zhfc-run-body {
	font-size: 0.75rem;
	color: var(--zh-bone-dim);
	margin: 0.4rem 0 0;
	line-height: 1.5;
}

/* Challenges — feature showcase ---------------------------------------- */

.zhfc-feature-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1rem;
	margin: 1.5rem 0 2.5rem;
}

@media (max-width: 34rem) {
	.zhfc-feature-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.zhfc-feature {
	position: relative;
	width: 100%;
	background: var(--zh-ink-soft);
	color: inherit;
	font: inherit;
	cursor: pointer;
	border: 1px solid var(--zh-line);
	padding: 2.25rem 1.25rem;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
	transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, background 0.35s ease, box-shadow 0.35s ease;
}

/* A targeting-reticle mark, not a border swap — reads as "locking on" when
 * a member's attention lands on one, which fits a challenge system built
 * around scoring and standings better than a plain hover outline would. */
.zhfc-feature::before,
.zhfc-feature::after {
	content: '';
	position: absolute;
	width: 0.85rem;
	height: 0.85rem;
	border: 2px solid var(--zh-gold);
	opacity: 0;
	transition: opacity 0.25s ease, width 0.25s ease, height 0.25s ease;
}

.zhfc-feature::before {
	top: -1px;
	left: -1px;
	border-right: none;
	border-bottom: none;
}

.zhfc-feature::after {
	bottom: -1px;
	right: -1px;
	border-left: none;
	border-top: none;
}

.zhfc-feature:hover,
.zhfc-feature:focus-visible {
	border-color: transparent;
	background: linear-gradient(135deg, rgba(201, 160, 77, 0.16), var(--zh-ink-soft) 65%);
	transform: translateY(-4px);
	box-shadow: 0 0 0 1px var(--zh-line), 0 1.5rem 2.5rem -1.25rem rgba(201, 160, 77, 0.6);
	outline: none;
}

.zhfc-feature:hover::before,
.zhfc-feature:hover::after,
.zhfc-feature:focus-visible::before,
.zhfc-feature:focus-visible::after {
	opacity: 1;
	width: 1.3rem;
	height: 1.3rem;
}

.zhfc-feature-name {
	display: inline-block;
	position: relative;
	font-family: var(--zh-display);
	font-size: 1.65rem;
	letter-spacing: 0.01em;
	color: var(--zh-bone);
	padding-bottom: 0.65rem;
}

.zhfc-feature-name::after {
	content: '';
	position: absolute;
	left: 50%;
	bottom: 0;
	width: 2rem;
	height: 2px;
	background: var(--zh-gold);
	transform: translateX(-50%);
	transition: width 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.zhfc-feature:hover .zhfc-feature-name::after,
.zhfc-feature:focus-visible .zhfc-feature-name::after {
	width: 100%;
}

.zhfc-feature-teaser {
	font-size: 0.75rem;
	color: var(--zh-bone-dim);
	margin-top: 0.6rem;
	line-height: 1.45;
	transition: color 0.25s ease;
}

.zhfc-feature:hover .zhfc-feature-teaser,
.zhfc-feature:focus-visible .zhfc-feature-teaser {
	color: var(--zh-bone);
}

@media (prefers-reduced-motion: reduce) {
	.zhfc-feature,
	.zhfc-feature::before,
	.zhfc-feature::after,
	.zhfc-feature-name::after,
	.zhfc-feature-teaser {
		transition: none;
	}

	.zhfc-feature:hover,
	.zhfc-feature:focus-visible {
		transform: none;
	}
}

/* The image (or, empty, the placeholder icon) is the top half of the
 * card itself rather than a boxed-in thumbnail — full width within the
 * card, border to border, no dashed box. The card itself stays the
 * normal .zhfc-modal size; only its padding/overflow are stripped so the
 * image can actually reach that card's own edges. Compound selector: the
 * shared .zhfc-modal padding rule sits later in this file, and at equal
 * specificity later-in-source wins, so a bare .zhfc-modal--feature here
 * would lose that fight and leave the base padding in place. */
.zhfc-modal.zhfc-modal--feature {
	/* Noticeably roomier than the shared .zhfc-modal cap (26rem) — this
	 * card is built around a hero photo, not a couple lines of copy — but
	 * nowhere near full-viewport; still a card, not a takeover. */
	max-width: min(34rem, calc(100vw - 3rem));
	padding: 0;
	overflow: hidden;
}

.zhfc-modal--feature .zhfc-modal-close {
	background: rgba(10, 10, 10, 0.55);
	border-color: rgba(245, 243, 238, 0.35);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
	z-index: 1;
}

.zhfc-feature-modal-image {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 4 / 3;
	color: var(--zh-bone-dim);
	background-color: var(--zh-ink-raised);
	background-size: cover;
	background-position: center;
}

/* The blend: a gray-to-transparent wash reading up from the modal's own
 * background color, so the photo fades into the card rather than
 * stopping at a hard edge. */
.zhfc-feature-modal-image::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 40%, var(--zh-ink-soft) 100%);
}

.zhfc-feature-modal-content {
	padding: 1.5rem 1.75rem 1.75rem;
}

/* Flagship */

.zhfc-flagship {
	margin-top: 1rem;
	border: 1px solid var(--zh-gold);
	background: linear-gradient( 180deg, rgba(201, 160, 77, 0.08), transparent 60% );
	padding: clamp(1.75rem, 4vw, 2.75rem);
	text-align: center;
}

.zhfc-flagship-badge {
	margin-bottom: 0.75rem;
}

.zhfc-flagship-title {
	font-size: clamp(1.75rem, 4.5vw, 3.25rem);
	line-height: 1.05;
	margin: 0 0 0.5rem;
	text-wrap: balance;
}

.zhfc-flagship-meta {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.2em;
	color: var(--zh-bone-dim);
	margin: 0 0 1.25rem;
}

.zhfc-flagship .zhfc-hint {
	max-width: 34rem;
	margin: 0 auto 1.75rem;
}

/* Playlist series — one carousel section per named series ------------- */

.zhfc-playlist-series {
	margin: 2rem 0;
}

.zhfc-playlist-series-head {
	display: flex;
	align-items: baseline;
	gap: 0.75rem;
	flex-wrap: wrap;
}

.zhfc-playlist-series--coming-soon {
	opacity: 0.7;
}

.zhfc-playlist-carousel {
	position: relative;
	margin-top: 1rem;
}

.zhfc-playlist-carousel-track {
	display: flex;
	gap: 1.25rem;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	padding-bottom: 0.5rem;
	/* Firefox: keep the scrollbar out of the way rather than hidden —
	   this is a real interaction affordance, not decoration. */
	scrollbar-width: thin;
}

.zhfc-carousel-nav {
	display: none;
}

@media (min-width: 48rem) {
	.zhfc-carousel-nav {
		display: flex;
		align-items: center;
		justify-content: center;
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		width: 2.5rem;
		height: 2.5rem;
		background: var(--zh-ink);
		border: 1px solid var(--zh-gold);
		color: var(--zh-gold-bright);
		font-size: 1.1rem;
		cursor: pointer;
		z-index: 2;
	}

	.zhfc-carousel-nav:hover {
		background: var(--zh-ink-raised);
	}

	.zhfc-carousel-nav--prev {
		left: -1.25rem;
	}

	.zhfc-carousel-nav--next {
		right: -1.25rem;
	}
}

.zhfc-playlist-card {
	scroll-snap-align: start;
	flex: 0 0 min(20rem, 85vw);
	border: 1px solid var(--zh-line);
	background: rgba(255, 255, 255, 0.02);
	padding: 1.25rem;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.zhfc-playlist-card-title-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6rem;
}

.zhfc-playlist-card-title-row h3 {
	margin: 0;
}

/* Explicit-content badge — same weight/shape wherever it shows, next to
   a series name or a single playlist's title. */
.zhfc-explicit-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.3rem;
	height: 1.3rem;
	flex: 0 0 auto;
	/* Sitting inline inside a Bebas Neue heading, baseline alignment (the
	   default for an inline-flex element) puts it visibly low against the
	   display font's tall caps — vertical-align: middle centers it on the
	   heading's x-height instead. */
	vertical-align: middle;
	font-family: var(--zh-mono);
	font-size: 0.72rem;
	font-weight: 700;
	line-height: 1;
	color: var(--zh-bone);
	background: var(--zh-danger);
	border-radius: 3px;
}

/* "Most Popular" badge — click-tracking-driven (see ZHFC_Playlist_Clicks),
   so it only ever shows on a real, un-tied leader within its series. Gold
   rather than the explicit badge's red: a callout, not a warning. */
.zhfc-most-popular-badge {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
	vertical-align: middle;
	font-family: var(--zh-mono);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	line-height: 1;
	padding: 0.35rem 0.5rem;
	color: var(--zh-ink);
	background: var(--zh-gold);
	border-radius: 3px;
}

.zhfc-playlist-card .zhfc-hint {
	margin: 0;
}

.zhfc-playlist-embed {
	border-radius: 8px;
	display: block;
}

/* One-shot click catcher over each embed: invisible, sits above the
   iframe just long enough to record a "meant to press play" click (see
   initPlaylistClickTracking() in app.js), then removes itself so every
   normal interaction with the embed passes straight through afterward. */
.zhfc-playlist-embed-wrap {
	position: relative;
}

.zhfc-playlist-click-overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	cursor: pointer;
	background: transparent;
	border: 0;
	padding: 0;
}

.zhfc-playlist-embeds {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	margin: 1.25rem 0;
}

.zhfc-playlist-embeds iframe {
	border-radius: 8px;
	display: block;
	width: 100%;
}

.zhfc-gms-card {
	margin-top: 1.25rem;
	border: 1px solid var(--zh-line);
	background: rgba(255, 255, 255, 0.02);
	padding: clamp(1.5rem, 3.5vw, 2.25rem);
	text-align: center;
}

.zhfc-gms-card .zhfc-hint {
	max-width: 34rem;
	margin: 0 auto 1.5rem;
}

.zhfc-closer {
	text-align: center;
	padding: clamp(3rem, 8vw, 5rem) 0 1rem;
}

.zhfc-closer .zhfc-hint {
	max-width: 28rem;
	margin: 0 auto 2rem;
}

/* Respect people who don't want motion. */
@media (prefers-reduced-motion: reduce) {
	.zhfc-progress-fill,
	.zhfc-chip,
	.zhfc-btn {
		transition: none;
	}

	#zhfc-info-modal-title.is-spinning {
		animation: none;
	}

	.zhfc-checkpoint.is-incomplete {
		animation: none;
		border-color: var(--zh-danger);
		box-shadow: 0 0 0 1px var(--zh-danger), 0 0 1.5rem 0.25rem rgba(176, 70, 60, 0.55);
	}

	.zhfc-checkpoint-warn-icon {
		animation: none;
		opacity: 1;
	}
}


/* Completion tracking ------------------------------------------------ */

.zhfc-progress {
	margin: 1.25rem 0 1rem;
}

.zhfc-progress-bar {
	height: 4px;
	background: var(--zh-ink-raised);
	overflow: hidden;
}

.zhfc-progress-bar span {
	display: block;
	height: 100%;
	background: var(--zh-gold);
	transition: width 0.25s ease;
}

.zhfc-weeks {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 1.5rem;
}

.zhfc-week-tab {
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	padding: 0.55rem 0.9rem;
	background: transparent;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	cursor: pointer;
	white-space: nowrap;
}

.zhfc-week-tab.is-done {
	color: var(--zh-gold);
	border-color: var(--zh-gold);
}

.zhfc-week-tab.is-active {
	background: var(--zh-gold);
	border-color: var(--zh-gold);
	color: var(--zh-ink);
}

/* Browsable, not yet earned — still clickable to look ahead, just visibly
 * not "live" the way the current week is. */
.zhfc-week-tab.is-upcoming {
	opacity: 0.4;
	border-style: dashed;
}

.zhfc-week-tab.is-upcoming.is-active {
	opacity: 1;
	background: transparent;
	color: var(--zh-bone-dim);
	border-color: var(--zh-bone-dim);
}

/* Viewing a week ahead of where a member actually is: the session content
 * dims and every checkbox is disabled — look, don't check off. */
.zhfc-week-locked .zhfc-day {
	opacity: 0.55;
}

.zhfc-week-locked .zhfc-check-ex,
.zhfc-week-locked .zhfc-check input[type="checkbox"] {
	cursor: not-allowed;
}

/* Big enough to hit with a thumb, mid-set, with the phone on a bench. */
.zhfc-check input[type="checkbox"],
.zhfc-check-ex {
	width: 1.35rem;
	height: 1.35rem;
	accent-color: var(--zh-gold);
	flex: none;
	cursor: pointer;
}

.zhfc-check {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	cursor: pointer;
}

.zhfc-check-ex {
	margin-right: 0.5rem;
	vertical-align: middle;
}

/* General Maintenance dashboard settings — see render_gms_settings() */
.zhfc-gms-focus-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
	gap: 0.5rem 1rem;
	margin: 0.5rem 0 1.25rem;
}

.zhfc-gms-settings [data-gms-msg].is-error {
	color: var(--zh-danger);
}

.zhfc-day.is-done {
	opacity: 0.55;
}

.zhfc-day.is-done .zhfc-day-focus {
	text-decoration: line-through;
}

@media (max-width: 34rem) {
	.zhfc-weeks {
		display: grid;
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
	.zhfc-week-tab {
		padding: 0.6rem 0.25rem;
		text-align: center;
	}
}


/* Weekday tabs ------------------------------------------------------- */

.zhfc-days-tabs {
	display: grid;
	grid-template-columns: repeat(7, minmax(0, 1fr));
	gap: 0.35rem;
	margin-bottom: 1.5rem;
}

.zhfc-day-tab {
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	padding: 0.7rem 0.2rem;
	text-align: center;
	background: transparent;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	cursor: pointer;
}

.zhfc-day-tab.is-done {
	color: var(--zh-gold);
	border-color: var(--zh-gold);
}

.zhfc-day-tab.is-active {
	background: var(--zh-gold);
	border-color: var(--zh-gold);
	color: var(--zh-ink);
}

/* A rest day is still reachable, just visibly not work. */
.zhfc-day-tab.is-rest {
	opacity: 0.5;
}

.zhfc-day.is-hidden {
	display: none;
}


/* Mobile stability ---------------------------------------------------- */

/* A single overflowing child makes the whole page rock sideways on a
 * phone. The offenders are fixed above; this stops a future one doing it
 * again, and keeps media from pushing the layout wider than the screen. */
body.zhfc-page {
	overflow-x: hidden;
}

.zhfc-panel img,
.zhfc-panel video,
.zhfc-panel iframe {
	max-width: 100%;
}

@media (max-width: 34rem) {
	/* Swatches get their own row rather than fighting the picker for space. */
	.zhfc-swatches {
		margin-left: 0;
		max-width: none;
		width: 100%;
	}

	/* backdrop-filter on a sticky element makes iOS Safari repaint on every
	 * scroll frame, which reads as the header shimmering. Solid instead. */
	.zhfc-nav {
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		background: var(--zh-ink);
	}

	/* iOS Safari zooms the whole page in on focus for any text input under
	 * 16px, then zooms back out on blur. On a form with several fields —
	 * signup, intake — that reads as the page wobbling as you fill it in. */
	.zhfc-input,
	.zhfc-textarea {
		font-size: 1rem;
	}
}


/* Phase tabs ----------------------------------------------------------- */

.zhfc-phase-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 2rem;
}

.zhfc-phase-tab {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	padding: 0.6rem 1rem;
	background: transparent;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	cursor: pointer;
	white-space: nowrap;
}

.zhfc-phase-tab.is-done {
	color: var(--zh-gold);
	border-color: var(--zh-gold);
}

.zhfc-phase-tab.is-active {
	background: var(--zh-gold);
	border-color: var(--zh-gold);
	color: var(--zh-ink);
}

/* Not just dimmed — disabled, so a phase a member has not earned cannot be
 * clicked into. There is nothing behind it to click into anyway; the panel
 * is never rendered until the phase before it is done. */
.zhfc-phase-tab.is-locked {
	opacity: 0.35;
	cursor: not-allowed;
}

.zhfc-phase-lock {
	font-size: 0.55rem;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-phase-panel.is-hidden {
	display: none;
}

@media (max-width: 34rem) {
	.zhfc-phase-tab {
		padding: 0.55rem 0.75rem;
		font-size: 0.6rem;
	}
}


/* Info cards -- shared by the supplement stack and the suggested meals,
 * both of which open the same popup. ------------------------------------ */

.zhfc-supp-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
	gap: 0.75rem;
	margin: 0.75rem 0 0.5rem;
}

/* Always exactly 3 cards (Breakfast/Lunch/Dinner) — auto-fit collapses empty
 * tracks so the 3 real cards actually share the full row width instead of
 * sitting narrow with dead space beside them, which auto-fill would leave. */
.zhfc-meal-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
	gap: 0.75rem;
	margin: 0.75rem 0 0.5rem;
}

.zhfc-info-card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.3rem;
	text-align: left;
	width: 100%;
	background: var(--zh-ink-raised);
	border: 1px solid var(--zh-line);
	padding: 0.9rem 1rem;
	cursor: pointer;
	font-family: var(--zh-mono);
	transition: border-color 0.15s ease;
}

.zhfc-info-card:hover,
.zhfc-info-card:focus-visible {
	border-color: var(--zh-gold);
	outline: none;
}

.zhfc-info-label {
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: var(--zh-bone-dim);
}

.zhfc-supp-badge {
	display: inline-block;
	font-size: 0.58rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	padding: 0.2rem 0.5rem;
	border: 1px solid var(--zh-line);
}

.zhfc-supp-badge--taking {
	color: var(--zh-gold);
	border-color: var(--zh-gold);
}

.zhfc-supp-badge--new {
	color: var(--zh-bone-dim);
}

.zhfc-info-name {
	font-family: var(--zh-display);
	font-size: 1.1rem;
	letter-spacing: 0.02em;
	color: var(--zh-bone);
}

.zhfc-info-sub {
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-gold);
}

/* Info modal -------------------------------------------------------------- */

.zhfc-modal-overlay {
	position: fixed;
	inset: 0;
	z-index: 100;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
	background: rgba(10, 10, 10, 0.82);
}

.zhfc-modal-overlay[hidden] {
	display: none;
}

.zhfc-modal {
	position: relative;
	width: 100%;
	/* min() guards against the exact overflow class of bug already fixed
	 * elsewhere on mobile — this can never exceed the viewport. */
	max-width: min(26rem, calc(100vw - 3rem));
	max-height: calc(100vh - 3rem);
	overflow-y: auto;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-gold);
	padding: 2rem 1.75rem 1.75rem;
}

.zhfc-modal-close {
	position: absolute;
	top: 0.75rem;
	right: 0.75rem;
	width: 2rem;
	height: 2rem;
	background: transparent;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.zhfc-modal-close:hover {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

/* Field count varies by card type (2 for a supplement, 3 for a meal) — JS
 * builds these fresh per open, so auto-fit rather than a fixed column count. */
.zhfc-modal-meta {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
	gap: 0.75rem;
	margin: 1rem 0;
}

.zhfc-modal-meta:empty {
	display: none;
}

.zhfc-modal-field {
	border: 1px solid var(--zh-line);
	padding: 0.6rem 0.75rem;
}

.zhfc-modal-value {
	display: block;
	font-family: var(--zh-mono);
	font-size: 0.85rem;
	color: var(--zh-bone);
	margin-top: 0.2rem;
}

/* Ingredients, when the card has any — a supplement never does. */
.zhfc-modal-list {
	list-style: none;
	margin: 0 0 1rem;
	padding: 0;
	font-size: 0.85rem;
	color: var(--zh-bone-dim);
}

.zhfc-modal-list:empty {
	display: none;
	margin: 0;
}

.zhfc-modal-list li {
	padding-left: 1rem;
	position: relative;
	margin-bottom: 0.3rem;
}

.zhfc-modal-list li::before {
	content: '-';
	position: absolute;
	left: 0;
	color: var(--zh-gold);
}

.zhfc-modal-body {
	font-size: 0.9rem;
	color: var(--zh-bone-dim);
	line-height: 1.6;
	margin: 0;
}

.zhfc-modal .zhfc-btn {
	display: block;
	text-align: center;
	margin-top: 1.5rem;
}

/* Intake's pre-submit review — a full sweep of every section's answers,
 * so noticeably wider than the shared .zhfc-modal cap (26rem), which is
 * sized for a couple lines of copy, not an entire questionnaire. */
.zhfc-modal.zhfc-modal--review {
	max-width: min(34rem, calc(100vw - 3rem));
}

.zhfc-review-section {
	margin-top: 1.5rem;
}

.zhfc-review-section:first-of-type {
	margin-top: 1.25rem;
}

.zhfc-review-section-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	border-bottom: 1px solid var(--zh-line);
	padding-bottom: 0.4rem;
	margin-bottom: 0.6rem;
}

.zhfc-review-fields {
	margin: 0;
	display: grid;
	gap: 0.5rem;
}

.zhfc-review-field {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 1rem;
	font-size: 0.85rem;
}

.zhfc-review-field dt {
	color: var(--zh-bone-dim);
	flex: 0 0 auto;
}

.zhfc-review-field dd {
	margin: 0;
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	text-align: right;
}

.zhfc-review-actions {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	margin-top: 2rem;
}

.zhfc-review-actions .zhfc-btn {
	margin-top: 0;
}

/* Locks background scroll behind the modal without disturbing the
 * permanent overflow-x:hidden guard set elsewhere. */
body.zhfc-modal-open {
	overflow-y: hidden;
}

/* Phase-open trainer overlay --------------------------------------------- */

.zhfc-phase-intro-overlay {
	position: fixed;
	inset: 0;
	z-index: 150;
	padding: 0;
	background: rgba(10, 10, 10, 0.88);
	opacity: 0;
	transition: opacity 0.35s ease;
}

.zhfc-phase-intro-overlay.is-open {
	opacity: 1;
}

/* The character is the whole point of the moment — sized big enough to
   actually read as "your trainer showed up," not a thumbnail in the
   corner. The speech bubble lives up near the top instead of stacking on
   top of it, so a tall portrait never gets buried under its own text. */
.zhfc-phase-intro-trainer {
	position: absolute;
	left: -8rem;
	bottom: 0;
	max-height: 88vh;
	width: auto;
	max-width: 92vw;
	object-fit: contain;
	filter: drop-shadow(0 1rem 1.5rem rgba(0, 0, 0, 0.55));
	transition: left 0.55s cubic-bezier(0.22, 0.9, 0.32, 1);
}

.zhfc-phase-intro-overlay.is-open .zhfc-phase-intro-trainer {
	left: -1rem;
}

.zhfc-phase-intro-bubble {
	position: absolute;
	top: 3rem;
	right: 1rem;
	left: 1rem;
	max-width: min(22rem, calc(100vw - 2rem));
	margin-left: auto;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-gold);
	padding: 1.25rem 1.25rem 1.5rem;
	opacity: 0;
	transform: translateY(-0.6rem);
	transition: opacity 0.35s ease 0.3s, transform 0.35s ease 0.3s;
}

.zhfc-phase-intro-overlay.is-open .zhfc-phase-intro-bubble {
	opacity: 1;
	transform: translateY(0);
}

.zhfc-phase-intro-bubble::after {
	content: '';
	position: absolute;
	left: 2.25rem;
	bottom: -0.65rem;
	width: 1.1rem;
	height: 1.1rem;
	background: var(--zh-ink-soft);
	border-right: 1px solid var(--zh-gold);
	border-bottom: 1px solid var(--zh-gold);
	transform: rotate(45deg);
}

.zhfc-phase-intro-name {
	margin: 0 0 0.5rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-gold);
}

.zhfc-phase-intro-message {
	margin: 0 0 1.25rem;
	font-size: 1rem;
	line-height: 1.55;
	color: var(--zh-bone);
}

.zhfc-phase-intro-dismiss {
	width: 100%;
}

.zhfc-phase-intro-gms {
	display: block;
	width: 100%;
	margin-top: 0.75rem;
	text-align: center;
}

@media (max-width: 34rem) {
	.zhfc-phase-intro-trainer {
		max-height: 72vh;
	}

	.zhfc-phase-intro-bubble {
		top: 1.5rem;
	}
}

/* On anything wider than a phone, the trainer has real horizontal room to
   stand in, so the bubble belongs right next to him, not stranded on the
   opposite side of the screen. His portrait is a fixed 2:3 canvas capped at
   88vh, so 58.7vh (88 * 2/3) is where his right edge actually lands. */
@media (min-width: 34rem) {
	.zhfc-phase-intro-bubble {
		left: calc(min(58.7vh, 92vw) + 1rem);
		right: auto;
		margin-left: 0;
		max-width: min(22rem, calc(100vw - min(58.7vh, 92vw) - 2rem));
	}
}


/* Time-today selector -------------------------------------------------- */

.zhfc-time-today {
	margin-bottom: 1.5rem;
}

.zhfc-time-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.zhfc-time-chip {
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	padding: 0.55rem 0.9rem;
	background: transparent;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	cursor: pointer;
	white-space: nowrap;
}

.zhfc-time-chip-unit {
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	margin-left: 0.2rem;
	opacity: 0.75;
}

.zhfc-time-chip.is-active {
	background: var(--zh-gold);
	border-color: var(--zh-gold);
	color: var(--zh-ink);
}

.zhfc-time-hint {
	margin-top: 0.65rem;
}

.zhfc-time-reset {
	background: none;
	border: none;
	padding: 0;
	color: var(--zh-gold);
	text-decoration: underline;
	cursor: pointer;
	font-family: inherit;
	font-size: inherit;
}

/* Accessory movements ---------------------------------------------------- */

.zhfc-accessory-tag {
	font-family: var(--zh-mono);
	font-size: 0.55rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	padding: 0.05rem 0.4rem;
	margin-left: 0.4rem;
	vertical-align: middle;
}

.zhfc-list li.is-trimmed {
	display: none;
}


.zhfc-trainer-tag {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-top: 0.6rem;
	color: var(--zh-gold);
}

/* A round crop zoomed on the trainer's head. Background-image rather than
 * object-fit: the source portraits are a waist-up bust (Zeus) and full-body
 * shots (Zee, Fiona), so filling the box isn't enough — it has to zoom in
 * past what object-fit alone can frame. Sizes are tuned per trainer since
 * the portraits are framed completely differently. */
.zhfc-trainer-badge {
	display: inline-block;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background-repeat: no-repeat;
	flex: none;
}

.zhfc-trainer-badge--zeus {
	background-size: 310% auto;
	background-position: 50% 2%;
}

.zhfc-trainer-badge--zee {
	background-size: 215% auto;
	background-position: 55% 4%;
}

.zhfc-trainer-badge--fiona {
	background-size: 260% auto;
	background-position: 50% 2%;
}


/* Archive accordions --------------------------------------------------- */

.zhfc-phase-acc {
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
	margin-top: 1.5rem;
}

.zhfc-phase-acc--current {
	border-color: var(--zh-gold);
}

.zhfc-acc-summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.25rem 1.5rem;
	cursor: pointer;
	list-style: none;
}

.zhfc-acc-summary::-webkit-details-marker {
	display: none;
}

.zhfc-acc-summary::after {
	content: '+';
	flex: none;
	width: 1.75rem;
	height: 1.75rem;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--zh-mono);
	font-size: 1rem;
	color: var(--zh-gold);
	border: 1px solid var(--zh-line);
}

details[open] > .zhfc-acc-summary::after {
	content: '\2212';
}

.zhfc-acc-summary .zhfc-eyebrow,
.zhfc-acc-summary .zhfc-display {
	margin: 0;
}

.zhfc-acc-body {
	padding: 0 1.5rem 1.5rem;
	border-top: 1px solid var(--zh-line);
	padding-top: 1.25rem;
}

/* Day accordions nest inside a phase — indented and quieter than the
 * phase level so the hierarchy reads at a glance. */
.zhfc-day-acc {
	border: 1px solid var(--zh-line);
	margin-top: 0.75rem;
}

.zhfc-day-acc .zhfc-acc-summary {
	padding: 0.9rem 1.1rem;
}

.zhfc-acc-summary--day {
	flex-direction: row;
	align-items: baseline;
	gap: 0.75rem;
}

.zhfc-acc-summary--day .zhfc-eyebrow {
	flex: none;
}

.zhfc-day-acc .zhfc-acc-body {
	padding: 0 1.1rem 1.1rem;
	padding-top: 1rem;
}

.zhfc-day-acc .zhfc-acc-summary::after {
	width: 1.4rem;
	height: 1.4rem;
	font-size: 0.85rem;
}

@media (max-width: 34rem) {
	.zhfc-acc-summary {
		padding: 1rem;
	}
	.zhfc-acc-summary--day {
		flex-wrap: wrap;
	}
}


.zhfc-day-sched {
	margin-top: -0.4rem;
	margin-bottom: 0.75rem;
	color: var(--zh-gold);
}


/* Trainer picker (intake) ----------------------------------------------- */

.zhfc-trainer-picks {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
	gap: 1rem;
}

.zhfc-trainer-pick {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-line);
	padding: 1rem 1rem 1.25rem;
	cursor: pointer;
	font-family: var(--zh-mono);
	transition: border-color 0.15s ease;
}

.zhfc-trainer-pick:hover {
	border-color: var(--zh-bone-dim);
}

.zhfc-trainer-pick[aria-pressed='true'] {
	border-color: var(--zh-gold);
	background: var(--zh-ink-raised);
}

.zhfc-trainer-pick-img {
	width: 100%;
	max-width: 9rem;
	height: 9rem;
	object-fit: contain;
	object-position: bottom;
}

.zhfc-trainer-pick-name {
	font-family: var(--zh-display);
	font-size: 1.5rem;
	letter-spacing: 0.03em;
	color: var(--zh-bone);
}

.zhfc-trainer-pick[aria-pressed='true'] .zhfc-trainer-pick-name {
	color: var(--zh-gold);
}

.zhfc-trainer-pick-tag {
	font-size: 0.65rem;
	color: var(--zh-bone-dim);
	text-align: center;
	line-height: 1.4;
}

@media (max-width: 26rem) {
	.zhfc-trainer-pick-img {
		height: 7rem;
	}
}

/* Blog ------------------------------------------------------------------ */

.zhfc-panel--blog {
	padding-top: clamp(1.5rem, 4vw, 3rem);
}

/* Fixed column counts, not auto-fit — 3 (desktop) / 2 (mobile) is a
   deliberate layout spec (13 posts total = 1 featured + 4 rows of 3, or
   6 rows of 2 on mobile), not a "fit whatever's comfortable" grid. */
.zhfc-blog-list {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.5rem;
	margin-top: 1.5rem;
}

.zhfc-blog-card-cta {
	display: none;
}

/* The newest post, full-width above the grid — same card DNA as
   .zhfc-blog-card (image bg, gradient, border) just bigger, on both
   mobile and desktop since this sits outside the column grid entirely. */
.zhfc-blog-featured {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 24rem;
	gap: 0.5rem;
	text-decoration: none;
	color: inherit;
	background-color: var(--zh-ink-raised);
	background-size: cover;
	background-position: center;
	border: 1px solid var(--zh-line);
	padding: 2rem;
	overflow: hidden;
	transition: border-color 0.15s ease;
	margin-top: 2rem;
}

.zhfc-blog-featured::before {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.3) 0%, rgba(10, 10, 10, 0.7) 55%, rgba(10, 10, 10, 0.97) 100%);
}

.zhfc-blog-featured:hover {
	border-color: var(--zh-gold);
}

.zhfc-blog-featured > * {
	position: relative;
	z-index: 1;
}

.zhfc-blog-featured h2 {
	margin: 0.2rem 0 0;
}

.zhfc-blog-featured .zhfc-hint {
	margin: 0;
	max-width: 42rem;
}

@media (max-width: 34rem) {
	.zhfc-blog-featured {
		min-height: 18rem;
		padding: 1.25rem;
	}
}

.zhfc-blog-card {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 18rem;
	gap: 0.4rem;
	text-decoration: none;
	color: inherit;
	background-color: var(--zh-ink-raised);
	background-size: cover;
	background-position: center;
	border: 1px solid var(--zh-line);
	padding: 1.25rem;
	overflow: hidden;
	transition: border-color 0.15s ease;
}

.zhfc-blog-card::before {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.45) 0%, rgba(10, 10, 10, 0.75) 55%, rgba(10, 10, 10, 0.97) 100%);
}

.zhfc-blog-card:hover {
	border-color: var(--zh-gold);
}

.zhfc-blog-card > * {
	position: relative;
	z-index: 1;
}

.zhfc-blog-card h2 {
	margin: 0.2rem 0 0;
}

.zhfc-blog-card .zhfc-hint {
	margin: 0;
}

/* Declared after every base .zhfc-blog-card rule above (not just after
   the ones it touches) so this always wins the cascade on a narrow
   viewport, regardless of which base rule a future edit adds or
   reorders — media-query specificity does not beat source order on an
   equal-specificity property fight, only being later in the file does. */
@media (max-width: 34rem) {
	.zhfc-blog-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1rem;
	}

	/* Mobile grid card: headline only. Date and excerpt add clutter at
	   this size when two cards sit side by side — the featured post above
	   the grid keeps its full meta/excerpt, this is scoped to the grid
	   cards specifically. */
	.zhfc-blog-card {
		min-height: 12rem;
		padding: 1rem;
		/* Extra room under the title specifically, so a long headline's
		   last line never runs into the corner CTA sitting on top of it. */
		padding-bottom: 2.5rem;
	}

	.zhfc-blog-card .zhfc-meta,
	.zhfc-blog-card .zhfc-hint {
		display: none;
	}

	.zhfc-blog-card .zhfc-blog-card-cta {
		display: inline-block;
		position: absolute;
		right: 0.6rem;
		bottom: 0.6rem;
		font-family: var(--zh-mono);
		font-size: 0.6rem;
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: 0.08em;
		color: var(--zh-ink);
		background: var(--zh-gold-bright);
		border-radius: 3px;
		padding: 0.3rem 0.55rem;
	}
}

/* Single article ---------------------------------------------------- */

.zhfc-post-hero {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: 22rem;
	background-color: var(--zh-ink);
	background-size: cover;
	background-position: center;
	box-sizing: border-box;
}

.zhfc-post-hero::before {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.2) 0%, rgba(10, 10, 10, 0.6) 60%, rgba(10, 10, 10, 0.96) 100%);
}

.zhfc-post-hero-content {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 68rem;
	margin: 0 auto;
	padding: clamp(1.5rem, 4vw, 3rem);
	box-sizing: border-box;
	font-family: var(--zh-mono);
}

.zhfc-post-hero-content .zhfc-display {
	margin: 0.3rem 0 0;
}

.zhfc-article {
	max-width: 42rem;
	margin: 0 auto;
}

.zhfc-article-body {
	margin-top: 1.5rem;
	font-size: 0.95rem;
	line-height: 1.75;
	color: var(--zh-bone-dim);
}

.zhfc-article-body p,
.zhfc-article-body ul,
.zhfc-article-body ol {
	margin: 0 0 1.25rem;
}

.zhfc-article-body h2,
.zhfc-article-body h3,
.zhfc-article-body h4 {
	font-family: var(--zh-display);
	color: var(--zh-bone);
	letter-spacing: 0.02em;
	margin: 2rem 0 0.75rem;
}

.zhfc-article-body h2 {
	font-size: 1.6rem;
}

.zhfc-article-body h3 {
	font-size: 1.3rem;
}

.zhfc-article-body a {
	color: var(--zh-gold);
}

.zhfc-article-body blockquote {
	border-left: 2px solid var(--zh-gold);
	margin: 1.5rem 0;
	padding: 0.25rem 0 0.25rem 1.25rem;
	color: var(--zh-bone);
	font-style: italic;
}

.zhfc-article-body img {
	max-width: 100%;
	height: auto;
	border: 1px solid var(--zh-line);
}

.zhfc-article-body li {
	margin-bottom: 0.4rem;
}

/* A playlist announcement post's embed, dressed as a real callout card
   instead of a bare label dropped into the article. */
.zhfc-playlist-listen-block {
	border: 1px solid var(--zh-line);
	border-top: 2px solid var(--zh-gold);
	background: var(--zh-ink-soft);
	padding: 1.5rem;
	margin: 2rem 0;
}

.zhfc-playlist-listen-block .zhfc-eyebrow {
	margin-bottom: 1rem;
}

.zhfc-playlist-listen-block .zhfc-playlist-embeds {
	margin: 0;
}

.zhfc-article-back {
	max-width: 42rem;
	margin: 2.5rem auto 0;
}

/* Pagination ---------------------------------------------------------- */

.zhfc-pagination {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: 2.5rem;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
}

.zhfc-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2rem;
	height: 2rem;
	padding: 0 0.5rem;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
	text-decoration: none;
}

.zhfc-pagination .page-numbers:hover {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-pagination .page-numbers.current {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

/* Challenge room: check-ins + group feed ------------------------------ */

.zhfc-room-tabs {
	display: flex;
	gap: 0.5rem;
	margin: 1.5rem 0;
	border-bottom: 1px solid var(--zh-line);
}

.zhfc-room-tab {
	background: transparent;
	border: none;
	border-bottom: 2px solid transparent;
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	padding: 0.75rem 0.25rem;
	margin-right: 1.5rem;
	cursor: pointer;
}

.zhfc-room-tab.is-active {
	color: var(--zh-gold);
	border-bottom-color: var(--zh-gold);
}

.zhfc-field {
	display: block;
	margin-bottom: 0.85rem;
	text-align: left;
}

.zhfc-btn--sm {
	padding: 0.5rem 1rem;
	font-size: 0.75rem;
}

.zhfc-checkin-card {
	text-align: left;
}

.zhfc-checkin-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex-wrap: wrap;
}

/* Groups the +/- toggle with the title so justify-content: space-between
   on .zhfc-checkin-head reads as [toggle+title] <-> [status], not three
   evenly-spread items with the title stranded in the middle. */
.zhfc-checkin-title-group {
	display: flex;
	align-items: flex-end;
	gap: 0.6rem;
}

/* .zhfc-display carries its own bottom margin for normal page use, which
   here just pushes the heading's flex box (and the toggle aligned to its
   bottom) below the actual glyphs — kill it so flex-end lines up with the
   text itself, not the margin under it. */
.zhfc-checkin-title-group .zhfc-display {
	margin-bottom: 0;
}

/* The collapse/expand control — compact by default (see
   .zhfc-checkin-body) is the whole point of this page, so every card
   opens closed and this is the only way back in. */
.zhfc-checkin-toggle {
	flex: none;
	width: 1.6rem;
	height: 1.6rem;
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: 1px solid var(--zh-gold);
	color: var(--zh-gold);
	font-family: var(--zh-mono);
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
	transition: background 0.15s ease-out, color 0.15s ease-out;
}

.zhfc-checkin-toggle:hover {
	background: var(--zh-gold);
	color: var(--zh-ink);
}

.zhfc-checkin-body {
	margin-top: 0.75rem;
}

.zhfc-checkin-status {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
	white-space: nowrap;
}

.zhfc-checkin-status.is-verified {
	color: var(--zh-gold);
}

.zhfc-checkin-status.is-rejected {
	color: var(--zh-danger);
}

.zhfc-checkin-form {
	margin-top: 1rem;
}

.zhfc-checkin-passphrase {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	border: 1px solid var(--zh-gold);
	padding: 0.65rem 0.9rem;
	margin-bottom: 1rem;
}

.zhfc-checkin-passphrase-label {
	font-family: var(--zh-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-checkin-passphrase-words {
	font-family: var(--zh-mono);
	font-size: 1.1rem;
	letter-spacing: 0.04em;
	color: var(--zh-gold);
}

/* Next week's phrase is visible in the markup (it's deterministic from the
 * challenge id and week number, so hiding it server-side buys nothing real)
 * but blurred so nobody reads ahead and stages a video early. */
.zhfc-checkin-passphrase-words.is-blurred {
	filter: blur(6px);
	user-select: none;
}

.zhfc-checkin-measurements {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
	gap: 0 1rem;
}

/* No max-width here on purpose — this used to be capped at 24rem for no
 * real reason, leaving most of a wide desktop panel empty. Three columns
 * now just grow with whatever room the card actually has. */
.zhfc-checkin-media {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.25rem;
	margin: 1.25rem 0;
}

.zhfc-checkin-media-slot {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-raised);
	padding: 1.5rem 1.1rem;
	text-align: center;
	transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

/* A slot that already has a submission reads as "locked in," not just a
 * plain box that happens to have a thumbnail in it — same gold-glow
 * language the challenge feature cards use for their own hover state. */
.zhfc-checkin-media-slot--done {
	border-color: var(--zh-gold);
	box-shadow: 0 0 0 1px rgba(201, 160, 77, 0.2), 0 0.75rem 1.5rem -1rem rgba(201, 160, 77, 0.45);
}

.zhfc-checkin-media-slot-check {
	position: absolute;
	top: -0.6rem;
	right: -0.6rem;
	width: 1.4rem;
	height: 1.4rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--zh-gold);
	color: var(--zh-ink);
}

.zhfc-checkin-media-slot .zhfc-label {
	margin: 0;
	font-size: 0.68rem;
	letter-spacing: 0.1em;
	/* Reserves room for a 2-line label (the Active Calories tier list wraps,
	   Closed Rings and Steps don't) so every slot's thumbnail/placeholder
	   box below it lines up at the same height regardless of how long that
	   particular slot's label is. */
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 1.75rem;
	line-height: 1.3;
}

.zhfc-steps-input {
	width: 100%;
	text-align: center;
}

.zhfc-checkin-thumb {
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	border: 1px solid var(--zh-line);
}

.zhfc-checkin-media-slot--done .zhfc-checkin-thumb {
	border-color: var(--zh-gold);
}

/* Today's Activity slot, before a screenshot exists — same box the real
   thumbnail will occupy once one is uploaded, holding the ZooHouse mark
   centered so the slot reads as "waiting for a photo" rather than an
   empty hole in the layout. */
.zhfc-evidence-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--zh-ink);
	border-style: dashed;
}

.zhfc-evidence-placeholder-logo {
	width: 45%;
	opacity: 0.35;
}

.zhfc-checkin-video-ok {
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	color: var(--zh-gold);
}

/* AI-confirmed evidence — the submitted number was actually read off this
   image/video and matched (or was corrected to match) it. Sits opposite
   the plain submission checkmark (top-right, see .zhfc-checkin-media-
   slot-check) so the two badges never collide: the checkmark says
   "something was uploaded here," this one says "and it checked out." */
.zhfc-checkin-confirmed-star {
	position: absolute;
	top: -0.6rem;
	left: -0.6rem;
	width: 1.4rem;
	height: 1.4rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--zh-gold-bright);
	color: var(--zh-ink);
	box-shadow: 0 0 0 1px var(--zh-ink);
}

/* The earned-points readout, standing off from plain hint text — this is
 * a score, not a caption. */
.zhfc-checkin-points-pill {
	display: inline-block;
	font-family: var(--zh-mono);
	font-size: 0.68rem;
	letter-spacing: 0.03em;
	color: var(--zh-gold);
	background: rgba(201, 160, 77, 0.12);
	border: 1px solid rgba(201, 160, 77, 0.35);
	padding: 0.3rem 0.6rem;
}

.zhfc-checkin-media-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	width: 100%;
	box-sizing: border-box;
	background: transparent;
	border: 1px solid var(--zh-gold);
	color: var(--zh-gold);
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	padding: 0.65rem 0.5rem;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}

.zhfc-checkin-media-btn:hover {
	background: var(--zh-gold);
	color: var(--zh-ink);
	transform: translateY(-2px);
}

.zhfc-checkin-media-btn.is-uploading {
	opacity: 0.6;
	pointer-events: none;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.zhfc-checkin-media-btn {
		transition: none;
	}

	.zhfc-checkin-media-btn:hover {
		transform: none;
	}
}

/* Stamped proof, not a caption — dim enough to stay out of the way but
 * always present under a submitted photo/video. */
.zhfc-checkin-timestamp {
	font-family: var(--zh-mono);
	font-size: 0.62rem;
	letter-spacing: 0.03em;
	color: var(--zh-bone-dim);
}

.zhfc-checkin-submitted-at {
	font-family: var(--zh-mono);
	font-size: 0.68rem;
	color: var(--zh-bone-dim);
	margin: 0.35rem 0 0;
}

.zhfc-checkin-msg {
	min-height: 1.2em;
}

.zhfc-checkin-msg.is-error {
	color: var(--zh-danger);
}

/* Log / Add photo side by side under a Today's Activity slot — Log is
   the primary action now that a photo is optional evidence rather than
   required, Add photo (and Post to Locker Room, sharing this same
   secondary look) sit visually one step down from it. */
.zhfc-checkin-actions {
	display: flex;
	gap: 0.5rem;
	width: 100%;
}

.zhfc-checkin-actions .zhfc-checkin-media-btn {
	width: auto;
	flex: 1;
}

/* A dedicated modifier rather than reusing .zhfc-btn--ghost: that class's
   own background/border/color come from a rule declared earlier in this
   file than .zhfc-checkin-media-btn's, so on equal specificity the later
   rule (this button's own gold-outline base) would silently win instead —
   the exact cascade trap already hit once this session, not repeating it. */
.zhfc-checkin-media-btn--ghost {
	border-color: var(--zh-line);
	color: var(--zh-bone-dim);
}

.zhfc-checkin-media-btn--ghost:hover {
	background: transparent;
	border-color: var(--zh-gold);
	color: var(--zh-gold);
	transform: none;
}

@media (max-width: 30rem) {
	.zhfc-checkin-media {
		gap: 0.65rem;
	}

	.zhfc-checkin-media-slot {
		padding: 0.9rem 0.6rem;
	}
}

/* Group feed */

.zhfc-feed-composer {
	text-align: left;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
	padding: 1.25rem;
	margin-bottom: 1.5rem;
}

.zhfc-feed-composer textarea.zhfc-input {
	width: 100%;
	resize: vertical;
}

.zhfc-feed-composer-row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-top: 0.75rem;
	flex-wrap: wrap;
}

.zhfc-feed-composer-row .zhfc-btn {
	margin-left: auto;
}

/* Sits between Add Photo/Video and the file name — without this it would
   also claim the generic rule's auto margin and get shoved to the far
   right next to Post, away from the button it belongs beside. */
.zhfc-feed-composer-row .zhfc-feed-link-btn {
	margin-left: 0;
}

.zhfc-feed-list {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.zhfc-feed-post {
	text-align: left;
	margin-top: 0;
}

.zhfc-feed-post-head {
	display: flex;
	align-items: center;
	gap: 0.6rem;
}

.zhfc-feed-post-namecol {
	flex: 1;
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	min-width: 0;
}

.zhfc-feed-post-name {
	color: var(--zh-gold);
	font-weight: 700;
}

.zhfc-feed-post-body {
	margin: 0.6rem 0;
	white-space: pre-wrap;
}

/* Color emoji glyphs render taller than the text around them at 1em —
 * shrunk back down closer to the surrounding line height. See
 * appendTextWithSmallEmoji() in app.js, which is what wraps a member's
 * typed emoji in this span; nothing else in the app uses this class.
 *
 * WordPress core rewrites a raw emoji character into <img class="emoji">
 * (twemoji, via wp-emoji-release.js, which this page loads even though it
 * never prints core's own accompanying img.emoji{height:1em} rule) — an
 * unstyled one renders at its native SVG size, which is enormous. The
 * height/width/vertical-align below are core's own convention, just
 * declared locally so this doesn't depend on core's inline styles being
 * present; text-only emoji (no img.emoji conversion) falls back to this
 * span's own smaller font-size instead. */
.zhfc-emoji {
	font-size: 0.75em;
}

.zhfc-emoji img.emoji {
	display: inline-block;
	height: 1em;
	width: 1em;
	vertical-align: -0.15em;
}

/* A small tappable thumbnail, not the media itself — the full-size photo
 * or video only ever shows in the lightbox (see buildMediaLightbox() in
 * app.js). Deliberately tiny: this is a feed of check-in chatter, not a
 * photo gallery, one oversized image shouldn't push everything below it
 * off screen. */
.zhfc-feed-post-media-btn {
	display: block;
	position: relative;
	width: 6rem;
	height: 6rem;
	margin: 0.75rem 0;
	padding: 0;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink);
	cursor: pointer;
	overflow: hidden;
}

.zhfc-feed-post-media-btn:hover,
.zhfc-feed-post-media-btn:focus-visible {
	border-color: var(--zh-gold);
}

.zhfc-feed-post-photo {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

/* A centered play glyph over the video thumbnail — the thumbnail itself
 * has no controls (see renderPost() in app.js), so without this it would
 * just look like a static, slightly odd photo. */
.zhfc-feed-post-media-play {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 1.75rem;
	height: 1.75rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: rgba(10, 10, 10, 0.6);
	color: var(--zh-bone);
	font-size: 0.7rem;
	/* Optically center the triangle glyph, which otherwise reads left-shifted. */
	padding-left: 0.15rem;
	pointer-events: none;
}

/* The lightbox itself — a wide, unpadded modal built purely to frame
 * whatever media is inside it (same shape as .zhfc-modal--feature),
 * rather than the shared .zhfc-modal's copy-card padding. */
.zhfc-lightbox-modal {
	max-width: min(40rem, calc(100vw - 3rem));
	padding: 0;
	background: transparent;
	border: none;
}

/* The shared close button assumes it's sitting on the app's own dark
 * background — against an arbitrary member photo it needs its own
 * backing to stay legible, same treatment as .zhfc-modal--feature's. */
.zhfc-lightbox-modal .zhfc-modal-close {
	background: rgba(10, 10, 10, 0.6);
	border-color: rgba(245, 243, 238, 0.35);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
	z-index: 1;
}

.zhfc-lightbox-media {
	display: flex;
	align-items: center;
	justify-content: center;
	/* A flex item's default min-width is auto, which lets an <img>'s
	 * intrinsic width win over its own max-width: 100% and overflow the
	 * modal instead of shrinking to fit — this is what actually makes
	 * max-width respected inside a flex container. */
	min-width: 0;
}

.zhfc-lightbox-img,
.zhfc-lightbox-video {
	display: block;
	box-sizing: border-box;
	max-width: 100%;
	max-height: calc(100vh - 6rem);
	border: 1px solid var(--zh-line);
	background: var(--zh-ink);
}

/* A pasted social-post link, shown as a plain outbound card — never an
   embed, see ZHFC_Challenge_Feed::create_post(). Host name reads as the
   headline (what site this goes to); the full URL sits under it, muted,
   for the member who wants to check before clicking. */
.zhfc-feed-post-link {
	display: block;
	margin: 0.75rem 0;
	padding: 0.75rem 1rem;
	border: 1px solid var(--zh-line);
	text-decoration: none;
	transition: border-color 0.15s ease-out;
}

.zhfc-feed-post-link:hover {
	border-color: var(--zh-gold);
}

.zhfc-feed-post-link-host {
	display: block;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--zh-gold);
}

.zhfc-feed-post-link-url {
	display: block;
	margin-top: 0.2rem;
	font-size: 0.8rem;
	color: var(--zh-bone-dim);
	overflow-wrap: anywhere;
}

.zhfc-feed-post-actions {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin-top: 0.5rem;
}

.zhfc-standings-list {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.zhfc-standings-row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.65rem 0.85rem;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
}

.zhfc-standings-row.is-self {
	border-color: var(--zh-gold);
}

.zhfc-standings-row.is-winner {
	background: var(--zh-ink-raised);
}

/* The current Weekly Warrior's row — steady, not pulsing, since this sits
 * for the entire week until the next one is picked. A looping animation
 * that long would just be noise; the constant glow is the whole point. */
.zhfc-standings-row.is-warrior {
	border-color: var(--zh-gold);
	box-shadow: 0 0 0 1px rgba(201, 160, 77, 0.25), 0 0 1.25rem 0 rgba(201, 160, 77, 0.35);
}

.zhfc-standings-rank {
	width: 2.25rem;
	flex: none;
	font-family: var(--zh-mono);
	color: var(--zh-bone-dim);
}

.zhfc-standings-name {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Marks a participant who administers part of the site — still ranked
   normally, just not payout-eligible (see
   ZHFC_Challenges::is_payout_ineligible_admin()). Muted, not a status
   color, since this isn't a score outcome. */
.zhfc-standings-ineligible {
	flex: none;
	font-family: var(--zh-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	padding: 0.1rem 0.4rem;
}

.zhfc-standings-medals {
	display: flex;
	align-items: center;
	gap: 0.3rem;
	flex: none;
}

.zhfc-standings-medal {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 1.1rem;
	height: 1.1rem;
	color: var(--zh-gold);
}

.zhfc-standings-medal svg {
	width: 100%;
	height: 100%;
}

.zhfc-standings-points {
	flex: none;
	font-family: var(--zh-mono);
	color: var(--zh-gold);
}

.zhfc-feed-cheer {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	background: transparent;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
	padding: 0.35rem 0.75rem;
	cursor: pointer;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
}

.zhfc-feed-cheer.is-active {
	border-color: var(--zh-red);
	color: var(--zh-red);
}

.zhfc-feed-delete {
	background: transparent;
	border: none;
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	cursor: pointer;
}

.zhfc-feed-delete:hover {
	color: var(--zh-danger);
}

.zhfc-feed-comment-toggle {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	background: transparent;
	border: 1px solid var(--zh-line);
	color: var(--zh-bone-dim);
	padding: 0.35rem 0.75rem;
	cursor: pointer;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	transition: border-color 0.15s ease, color 0.15s ease;
}

.zhfc-feed-comment-toggle:hover {
	border-color: var(--zh-gold);
	color: var(--zh-gold);
}

.zhfc-feed-comments {
	margin-top: 0.85rem;
	padding-top: 0.85rem;
	border-top: 1px solid var(--zh-line);
}

.zhfc-feed-comments-list {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	margin-bottom: 0.85rem;
}

.zhfc-feed-comment {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
}

.zhfc-feed-comment-body {
	flex: 1;
	min-width: 0;
}

.zhfc-feed-comment-text {
	margin: 0;
	line-height: 1.5;
	word-break: break-word;
}

.zhfc-feed-comment-name {
	color: var(--zh-gold);
	font-weight: 700;
}

.zhfc-feed-comment-meta {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-top: 0.2rem;
}

.zhfc-feed-comment-delete {
	background: transparent;
	border: none;
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	cursor: pointer;
}

.zhfc-feed-comment-delete:hover {
	color: var(--zh-danger);
}

.zhfc-feed-comment-form {
	display: flex;
	gap: 0.5rem;
}

.zhfc-feed-comment-form .zhfc-input {
	flex: 1;
}

/* Group chat trigger — sits inline in the room's own tab bar, pushed to the
   opposite end from Check-Ins/Group Feed/Standings via margin-left:auto,
   so it reads as part of that nav rather than a floating page-level button. */
.zhfc-chat-trigger {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin-left: auto;
	align-self: center;
	background: var(--zh-gold);
	color: var(--zh-ink);
	border: none;
	padding: 0.5rem 0.9rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	cursor: pointer;
}

.zhfc-chat-trigger:hover {
	background: var(--zh-gold-bright);
}

.zhfc-chat-overlay {
	position: fixed;
	inset: 0;
	z-index: 100;
	display: flex;
	justify-content: flex-end;
	background: rgba(10, 10, 10, 0.6);
}

.zhfc-chat-overlay[hidden] {
	display: none;
}

.zhfc-chat-drawer {
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 24rem;
	height: 100%;
	background: var(--zh-ink-soft);
	border-left: 1px solid var(--zh-line);
	border-top: 2px solid var(--zh-gold);
	box-sizing: border-box;
	animation: zhfc-chat-slide-in 0.25s ease-out;
}

@media (prefers-reduced-motion: reduce) {
	.zhfc-chat-drawer {
		animation: none;
	}
}

@keyframes zhfc-chat-slide-in {
	from { transform: translateX(100%); }
	to { transform: translateX(0); }
}

.zhfc-chat-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.25rem 1.25rem 1rem;
	border-bottom: 1px solid var(--zh-line);
	flex-shrink: 0;
}

.zhfc-chat-head .zhfc-modal-close {
	position: static;
}

.zhfc-chat-messages {
	flex: 1;
	overflow-y: auto;
	padding: 1rem 1.25rem;
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
}

.zhfc-chat-day-divider {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0.25rem 0;
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.zhfc-chat-day-divider::before,
.zhfc-chat-day-divider::after {
	content: '';
	flex: 1;
	height: 1px;
	background: var(--zh-line);
}

.zhfc-chat-msg {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
}

.zhfc-chat-msg-body {
	flex: 1;
	min-width: 0;
}

.zhfc-chat-msg-text {
	margin: 0;
	line-height: 1.5;
	word-break: break-word;
}

.zhfc-chat-msg-name {
	color: var(--zh-gold);
	font-weight: 700;
}

.zhfc-chat-msg--own .zhfc-chat-msg-name {
	color: var(--zh-gold-bright);
}

.zhfc-chat-msg-meta {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-top: 0.2rem;
}

.zhfc-chat-form {
	display: flex;
	gap: 0.5rem;
	padding: 1rem 1.25rem;
	border-top: 1px solid var(--zh-line);
	flex-shrink: 0;
}

.zhfc-chat-form .zhfc-input {
	flex: 1;
}

.zhfc-challenge-image {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border: 1px solid var(--zh-line);
	margin-bottom: 1rem;
}

/* Challenge dates and active state ------------------------------------ */

/* Start date and sign-up deadline get their own bordered strip, same
   weight of attention as .zhfc-score-summary, rather than blending into
   .zhfc-meta text where a member could easily scroll past them. */
.zhfc-challenge-dates {
	display: flex;
	gap: 1.5rem;
	flex-wrap: wrap;
	border: 1px solid var(--zh-gold);
	background: var(--zh-ink-soft);
	padding: 0.85rem 1.25rem;
	margin: 0.75rem 0 1rem;
}

.zhfc-challenge-date {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

.zhfc-challenge-date-label {
	font-family: var(--zh-mono);
	font-size: 0.68rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-challenge-date-value {
	font-family: var(--zh-display);
	font-size: 1.35rem;
	letter-spacing: 0.01em;
	color: var(--zh-gold-bright);
	line-height: 1.1;
}

/* A closed sign-up deadline still needs to be visible, just not urgent
   the way an open one is — the red flags the strict pricing gate. */
.zhfc-challenge-date--deadline .zhfc-challenge-date-value {
	color: #f2524c;
}

/* Price story under the dates: ended tiers struck through, then the
   countdown to the next change. Mono and small, so it supports the
   dates box above it rather than competing with it. */
.zhfc-pricing {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.4rem 1.25rem;
	margin: -0.35rem 0 1rem;
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.zhfc-pricing-tier.is-past {
	display: inline-flex;
	gap: 0.5rem;
	align-items: baseline;
	color: var(--zh-bone-dim);
}

.zhfc-pricing-tier.is-past s {
	text-decoration-thickness: 1px;
}

.zhfc-pricing-tier-state {
	color: var(--zh-bone-dim);
}

.zhfc-pricing-countdown {
	color: var(--zh-gold-bright);
	font-variant-numeric: tabular-nums;
}

.zhfc-challenge-active-tag {
	display: inline-block;
	margin-top: 0.75rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-ink);
	background: var(--zh-gold-bright);
	border: 1px solid var(--zh-gold-bright);
	padding: 0.35rem 0.75rem;
}

/* Only present once a challenge has at least one paid, public sponsor —
 * see render_challenge_sponsors(). Sits inline next to the title, inside
 * .zhfc-card-title-group, so it shares the Pot badge's row rather than
 * stacking as its own line; sized against the meta line's weight, not
 * the display font, since this is a credit line, not a headline. */
.zhfc-challenge-sponsors {
	margin: 0;
	font-size: 0.8rem;
	color: var(--zh-bone-dim);
}

/* A sponsor with a website on file gets credited as a real link, not just
 * a name — only when render_challenge_sponsors() actually has one; a
 * sponsor with none on file stays plain text right next to a linked one. */
.zhfc-challenge-sponsors a {
	color: var(--zh-bone-dim);
	text-decoration: underline;
	text-decoration-color: var(--zh-line);
	text-underline-offset: 0.15em;
}

.zhfc-challenge-sponsors a:hover,
.zhfc-challenge-sponsors a:focus-visible {
	color: var(--zh-gold);
	text-decoration-color: var(--zh-gold);
}

.zhfc-challenge-sponsors-label {
	font-family: var(--zh-mono);
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-gold);
	margin-right: 0.4rem;
}

/* Coming-soon challenges --------------------------------------------- */

.zhfc-coming-soon-head {
	margin-top: 2.5rem;
	color: var(--zh-bone-dim);
}

.zhfc-card--coming-soon {
	opacity: 0.88;
}

.zhfc-coming-soon-tag {
	display: inline-block;
	margin-top: 0.75rem;
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--zh-bone-dim);
	border: 1px solid var(--zh-line);
	padding: 0.35rem 0.75rem;
}

/* Challenge points ----------------------------------------------------- */

.zhfc-score-summary {
	display: flex;
	align-items: baseline;
	gap: 1rem;
	flex-wrap: wrap;
	border: 1px solid var(--zh-gold);
	background: var(--zh-ink-soft);
	padding: 1rem 1.25rem;
	margin-bottom: 1.5rem;
}

.zhfc-score-total {
	font-family: var(--zh-display);
	font-size: 1.75rem;
	color: var(--zh-gold);
	line-height: 1;
}

.zhfc-score-breakdown {
	font-size: 0.75rem;
	color: var(--zh-bone-dim);
}

.zhfc-checkin-points {
	font-size: 0.75rem;
	color: var(--zh-bone-dim);
	margin: 0.4rem 0 0;
}

.zhfc-checkin-points.is-positive {
	color: var(--zh-gold);
}

.zhfc-checkin-points.is-negative {
	color: var(--zh-danger);
}

.zhfc-activity-card {
	text-align: left;
	border-color: var(--zh-gold);
	background: linear-gradient(160deg, var(--zh-ink-raised) 0%, var(--zh-ink-soft) 55%);
}

.zhfc-activity-card .zhfc-checkin-media {
	margin-top: 1rem;
}

/* WooCommerce cart / checkout / account — branded ---------------------- */

body.zhfc-woo-page .zhfc-main {
	max-width: 68rem;
	margin: 0 auto;
	padding: clamp(1.5rem, 4vw, 3rem);
	font-family: var(--zh-mono);
	color: var(--zh-bone);
}

/* Sharp edges everywhere on these pages too, matching every other screen. */
body.zhfc-woo-page .zhfc-main,
body.zhfc-woo-page .zhfc-main * {
	border-radius: 0 !important;
}

body.zhfc-woo-page h1,
body.zhfc-woo-page h2,
body.zhfc-woo-page h3 {
	font-family: var(--zh-display);
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: var(--zh-bone);
}

/* Section titles, order summary heading, totals title */
.wc-block-components-checkout-step__title,
.wc-block-cart__totals-title,
.wc-block-components-checkout-order-summary__title-text,
.wc-block-components-order-summary__content .wc-block-components-product-name {
	color: var(--zh-bone) !important;
}

.wc-block-components-checkout-step__heading-content,
.wc-block-checkout__guest-checkout-notice,
.wc-block-components-totals-item__label,
.wc-block-components-totals-item__description,
.wc-block-components-product-metadata__description,
.wc-block-components-address-card,
.wc-blocks-components-select__label,
.wc-block-components-checkbox__label,
.wc-block-checkout__terms {
	color: var(--zh-bone-dim) !important;
}

.wc-block-components-totals-item__value,
.wc-block-formatted-money-amount,
.wc-block-components-order-summary-item__quantity {
	color: var(--zh-bone) !important;
}

.wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
.wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	color: var(--zh-gold) !important;
	font-weight: 700;
}

/* Product links */
.wc-block-components-product-name {
	color: var(--zh-bone) !important;
	text-decoration: none;
}
.wc-block-components-product-name:hover {
	color: var(--zh-gold) !important;
}

/* Cart items table */
.wc-block-cart-items {
	background: transparent;
	border-collapse: collapse;
	width: 100%;
}
.wc-block-cart-items__header th {
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	border-bottom: 1px solid var(--zh-line);
	padding-bottom: 0.75rem;
}
.wc-block-cart-items__row td {
	border-bottom: 1px solid var(--zh-line);
	padding: 1.25rem 0.5rem;
}
.wc-block-cart-item__remove-link {
	color: var(--zh-bone-dim) !important;
}
.wc-block-cart-item__remove-link:hover {
	color: var(--zh-danger) !important;
}

/* Empty-cart state: WooCommerce Blocks draws its own icon as a CSS
 * mask-image on this ::before (currentColor SVG, tinted via
 * background-color) rather than an <img> — swapping it for Zeus means
 * killing the mask and painting our own image into the same box instead.
 * !important for the same reason as the totals panels above: Woo's own
 * block stylesheet loads after app.css. */
.wc-block-cart__empty-cart__title.with-empty-cart-icon::before {
	mask-image: none !important;
	-webkit-mask-image: none !important;
	background-color: transparent !important;
	background-image: url('https://zoohousefitclub.com/wp-content/uploads/2026/08/zeus-empty-cart-2.png') !important;
	background-size: contain !important;
	background-position: center !important;
	background-repeat: no-repeat !important;
	width: 220px !important;
	height: 220px !important;
	margin: 0 auto 1.5rem !important;
}

/* Order summary card + totals panels. !important because WooCommerce's own
 * checkout.css loads after app.css and resets padding on these same
 * classes for its own layout — without it, "Add coupons" and the totals
 * rows end up flush against the card edge on mobile. */
.wc-block-components-order-summary,
.wc-block-components-totals-wrapper,
.wc-block-components-sidebar,
.wc-block-components-address-card-wrapper {
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-line);
	padding: 1.25rem !important;
}

.wc-block-components-panel__button,
.wc-block-components-totals-item,
.wc-block-components-totals-footer-item {
	padding-left: 0.25rem !important;
	padding-right: 0.25rem !important;
}

@media (max-width: 34rem) {
	.wc-block-components-order-summary,
	.wc-block-components-totals-wrapper,
	.wc-block-components-sidebar,
	.wc-block-components-address-card-wrapper {
		padding: 1rem 1.1rem !important;
	}
}

.wc-block-components-panel__button {
	color: var(--zh-bone-dim) !important;
	font-family: var(--zh-mono);
}

/* Inputs and selects — match .zhfc-input */
.wc-block-components-text-input input,
.wc-blocks-components-select__select,
.wc-block-components-combobox-control input {
	background: var(--zh-ink-soft) !important;
	border: 1px solid var(--zh-line) !important;
	color: var(--zh-bone) !important;
	font-family: var(--zh-mono);
}
.wc-block-components-text-input input:focus,
.wc-blocks-components-select__select:focus {
	border-color: var(--zh-gold) !important;
	box-shadow: none !important;
}
.wc-block-components-text-input label,
.wc-blocks-components-select__label {
	color: var(--zh-bone-dim) !important;
}
.wc-blocks-components-select__container svg,
.wc-blocks-components-select__container path {
	fill: var(--zh-bone-dim) !important;
}

/* Buttons — match .zhfc-btn */
.wc-block-components-button.contained,
.wc-block-components-checkout-place-order-button {
	background: var(--zh-gold) !important;
	border: 1px solid var(--zh-gold) !important;
	color: var(--zh-ink) !important;
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	box-shadow: none !important;
}
.wc-block-components-button.contained:hover,
.wc-block-components-checkout-place-order-button:hover {
	background: var(--zh-gold-bright) !important;
	border-color: var(--zh-gold-bright) !important;
}

/* Notices (errors, guest-checkout banner, etc.) */
.wc-block-components-notice-banner {
	background: var(--zh-ink-soft) !important;
	border: 1px solid var(--zh-danger) !important;
	color: var(--zh-bone) !important;
}
.wc-block-components-notice-banner.is-success {
	border-color: var(--zh-gold) !important;
}
.wc-block-components-notice-banner svg {
	fill: currentColor;
}

/* Checkbox (terms and conditions) */
.wc-block-components-checkbox__input {
	accent-color: var(--zh-gold);
}

@media (max-width: 34rem) {
	body.zhfc-woo-page .zhfc-main {
		padding: 1.25rem;
	}
}

/* WooCommerce classic forms (My Account: login, register, orders, addresses,
 * account details) — separate markup system from WC Blocks (cart/checkout
 * above), so it needs its own selectors. */

.woocommerce-Input,
.woocommerce form .input-text,
.woocommerce-page form .input-text,
.woocommerce-form-row select {
	background: var(--zh-ink-soft) !important;
	border: 1px solid var(--zh-line) !important;
	color: var(--zh-bone) !important;
	font-family: var(--zh-mono);
	padding: 0.75rem;
}
.woocommerce-Input:focus {
	border-color: var(--zh-gold) !important;
	outline: none;
}

.woocommerce-form-row label,
.woocommerce-form__label {
	color: var(--zh-bone-dim) !important;
}

/* Classic single-product variation picker (table.variations, e.g. Size,
 * Colors) — a different markup system again from both the My Account forms
 * above and the WC Blocks cart/checkout selects further up, and previously
 * had no rule of its own here at all: left to the theme's native <select>
 * styling against this page's dark background, which rendered as dark grey
 * text on a dark grey field. */
table.variations select {
	background: var(--zh-ink-soft) !important;
	border: 1px solid var(--zh-line) !important;
	color: var(--zh-bone) !important;
	font-family: var(--zh-mono);
	padding: 0.75rem;
}
table.variations select:focus {
	border-color: var(--zh-gold) !important;
	outline: none;
}
table.variations label {
	color: var(--zh-bone-dim) !important;
}

.woocommerce-button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
	background: var(--zh-gold) !important;
	border: 1px solid var(--zh-gold) !important;
	color: var(--zh-ink) !important;
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	padding: 0.75rem 1.25rem;
	box-shadow: none !important;
}
.woocommerce-button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover {
	background: var(--zh-gold-bright) !important;
	border-color: var(--zh-gold-bright) !important;
}

.woocommerce-form__input-checkbox {
	accent-color: var(--zh-gold);
}

.woocommerce-notices-wrapper .woocommerce-error,
.woocommerce-notices-wrapper .woocommerce-message,
.woocommerce-notices-wrapper .woocommerce-info {
	background: var(--zh-ink-soft) !important;
	border: 1px solid var(--zh-danger) !important;
	color: var(--zh-bone) !important;
	list-style: none;
	padding: 1rem 1.25rem;
	font-family: var(--zh-mono);
	font-size: 0.85rem;
}
.woocommerce-notices-wrapper .woocommerce-message {
	border-color: var(--zh-gold) !important;
}
.woocommerce-notices-wrapper .woocommerce-error::before,
.woocommerce-notices-wrapper .woocommerce-message::before,
.woocommerce-notices-wrapper .woocommerce-info::before {
	display: none;
}

/* Account dashboard: nav tabs + content */
.woocommerce-MyAccount-navigation ul {
	list-style: none;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.5rem;
	border-bottom: 1px solid var(--zh-line);
	margin-bottom: 1.5rem;
}
.woocommerce-MyAccount-navigation li a {
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	text-decoration: none;
	display: inline-block;
	padding: 0.75rem 0;
}
.woocommerce-MyAccount-navigation li.is-active a {
	color: var(--zh-gold);
	border-bottom: 2px solid var(--zh-gold);
}
.woocommerce-MyAccount-content a {
	color: var(--zh-gold);
}

/* Order/table listings (order history, addresses) */
.woocommerce table.shop_table,
.woocommerce-orders-table {
	border: 1px solid var(--zh-line);
	border-collapse: collapse;
	width: 100%;
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	font-size: 0.85rem;
}
.woocommerce table.shop_table th,
.woocommerce table.shop_table td {
	border-bottom: 1px solid var(--zh-line);
	padding: 0.85rem;
}
.woocommerce table.shop_table th {
	color: var(--zh-bone-dim);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 0.7rem;
}

.woocommerce-Address-title h3,
.woocommerce-MyAccount-content h2,
.woocommerce-MyAccount-content h3 {
	font-family: var(--zh-display);
	text-transform: uppercase;
	color: var(--zh-bone);
}

.woocommerce-Addresses .woocommerce-Address {
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
	padding: 1.25rem;
}

/* "Other" follow-up detail input in the intake ------------------------- */

.zhfc-other-detail {
	margin-top: 0.75rem;
	max-width: 24rem;
}

.zhfc-other-detail[hidden] {
	display: none;
}

/* Meal reroll ("spin") button inside the info modal --------------------- */

.zhfc-modal-spin {
	margin-top: 1.25rem;
}

/* .zhfc-btn's own display:inline-block would otherwise defeat the browser's
   default [hidden]{display:none} rule, showing this on every popup instead
   of only meals. */
.zhfc-modal-spin[hidden] {
	display: none;
}

.zhfc-modal-spin-msg {
	margin: 0.5rem 0 0;
}

/* The reel tick while a reroll is spinning — the JS swaps the text every
   80ms, this just adds the motion blur so it reads as a slot machine
   rather than the title flickering between random words. */
#zhfc-info-modal-title.is-spinning {
	animation: zhfc-spin-tick 0.16s linear infinite;
}

@keyframes zhfc-spin-tick {
	0% {
		opacity: 0.5;
		transform: translateY(-0.2em);
		filter: blur(1px);
	}
	50% {
		opacity: 1;
		transform: translateY(0);
		filter: blur(0);
	}
	100% {
		opacity: 0.5;
		transform: translateY(0.2em);
		filter: blur(1px);
	}
}

/* Challenge pot total + sponsorship ------------------------------------- */

/* Title + pot badge share one row directly under the artwork — the badge's
   own right edge lands flush with the image's right edge above it, since
   neither this row nor .zhfc-card-title-row carries any side padding of
   its own beyond the card's. */
.zhfc-card-title-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex-wrap: wrap;
	/* Breathing room before the description/active-tag/dates that follow —
	   without this the Pot badge's own bottom edge sits right on top of
	   the next line of text. */
	margin-bottom: 0.85rem;
}

.zhfc-card-title-row h3 {
	margin: 0;
}

/* Title + sponsor credit share the row's left side as one flexible group,
 * so both can sit on the same line as the Pot badge pinned to the right
 * by .zhfc-card-title-row's own space-between — this wraps onto its own
 * line first (min-width: 0 lets it shrink below the title's natural
 * width) if the combination doesn't fit next to the badge. */
.zhfc-card-title-group {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	column-gap: 0.75rem;
	row-gap: 0.2rem;
	min-width: 0;
}

.zhfc-pot-corner {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	border: 1px solid var(--zh-gold);
	padding: 0.2rem 0.85rem;
	white-space: nowrap;
}

.zhfc-pot-corner-label {
	font-family: var(--zh-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-pot-corner-amount {
	font-family: var(--zh-mono);
	font-size: 1.1rem;
	color: var(--zh-gold);
}

/* A real pot to compete for reads as good news; an empty one is a stall
   worth flagging at a glance, not just a neutral number. */
.zhfc-pot-corner-amount--positive {
	color: var(--zh-success);
}

.zhfc-pot-corner-amount--zero {
	color: var(--zh-danger);
}

/* Holds the artwork plus the Entry badge overlaid on its top-left corner —
   position:relative on the wrap, not the <img> itself, so the image keeps
   its own plain display:block sizing rules untouched. */
.zhfc-challenge-image-wrap {
	position: relative;
	margin-bottom: 1rem;
}

.zhfc-challenge-image-wrap .zhfc-challenge-image {
	margin-bottom: 0;
}

/* Entry cost, pinned to the artwork itself rather than sitting in the
   title row — solid ink background (not just a line border like the Pot
   badge) since this has to stay legible sitting on top of a photo, not a
   flat card background. */
.zhfc-entry-fee-corner {
	position: absolute;
	top: 0.75rem;
	left: 0.75rem;
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	background: var(--zh-ink);
	border: 1px solid var(--zh-line);
	padding: 0.2rem 0.85rem;
	white-space: nowrap;
}

.zhfc-entry-fee-corner-label {
	font-family: var(--zh-mono);
	font-size: 0.6rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--zh-bone-dim);
}

.zhfc-entry-fee-corner-amount {
	font-family: var(--zh-mono);
	font-size: 1.1rem;
	color: var(--zh-bone);
}

@media (max-width: 34rem) {
	.zhfc-pot-corner,
	.zhfc-entry-fee-corner {
		padding: 0.15rem 0.55rem;
		gap: 0.35rem;
	}

	.zhfc-entry-fee-corner {
		top: 0.5rem;
		left: 0.5rem;
	}

	.zhfc-pot-corner-label,
	.zhfc-entry-fee-corner-label {
		font-size: 0.5rem;
	}

	.zhfc-pot-corner-amount,
	.zhfc-entry-fee-corner-amount {
		font-size: 0.8rem;
	}
}

.zhfc-card-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	align-items: center;
}

.zhfc-sponsor-form {
	margin-top: 1rem;
	padding-top: 1rem;
	border-top: 1px solid var(--zh-line);
	text-align: left;
}

.zhfc-checkbox {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 0.85rem;
	font-size: 0.85rem;
	cursor: pointer;
}

.zhfc-sponsor-error {
	color: #d9534f;
}

/* Compact "Challenges" widget on the dashboard ---------------------------- */

.zhfc-challenges-widget {
	margin-top: 1.5rem;
	padding: 1.25rem 1.5rem;
}

.zhfc-challenges-widget h3 {
	margin-bottom: 0.6rem;
}

.zhfc-challenge-row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.5rem 0;
	border-top: 1px solid var(--zh-line);
}

.zhfc-challenge-row:first-of-type {
	border-top: none;
	padding-top: 0;
}

.zhfc-challenge-row-name {
	flex: 1;
	font-size: 0.85rem;
}

.zhfc-challenge-row-status {
	font-family: var(--zh-mono);
	font-size: 0.62rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--zh-bone-dim);
	white-space: nowrap;
}

/* Member avatars — selfie upload or a ZooHouse Fit Club Crew pick --------- */

.zhfc-avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	object-fit: cover;
	/* Crew portraits are full-body shots scaled (not cropped) server-side —
	   biasing the visible crop toward the top is what keeps the face in
	   frame instead of the torso. Harmless for a selfie too, since a face
	   photo is rarely framed with the face at the very bottom. */
	object-position: center top;
	flex: none;
}

/* Applied to the trigger avatar when the member's pick is a Crew portrait
   (not a selfie) — same chest-up crop as the picker grid, with the same
   per-portrait --crew-x/--crew-y override when one is needed. */
/* ZHFC_Accounts::DEFAULT_AVATAR_URL — the head sits centered on its own
   canvas, not framed top-heavy like the Crew portraits object-position:
   center top on .zhfc-avatar assumes, so that crop shows mostly blank
   space above it. Matched by filename since this is the one known static
   fallback URL, not a per-member upload — no need to thread an
   "is this the default" flag through every avatar-rendering call site. */
img[src$="zee-head-CENTERED-gray_1-scaled.png"] {
	object-position: center !important;
}

.zhfc-avatar--crew {
	transform: scale(2);
	transform-origin: var(--crew-x, 50%) var(--crew-y, 8%);
}

.zhfc-avatar--sm {
	width: 2rem;
	height: 2rem;
}

.zhfc-avatar--lg {
	width: 5.5rem;
	height: 5.5rem;
}

.zhfc-avatar--fallback {
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-line);
	color: var(--zh-gold);
	font-family: var(--zh-mono);
	font-weight: 700;
}

.zhfc-avatar--sm.zhfc-avatar--fallback {
	font-size: 0.85rem;
}

.zhfc-avatar--lg.zhfc-avatar--fallback {
	font-size: 1.5rem;
}

.zhfc-avatar-row {
	display: block;
}

/* Same clip container render_avatar_picker()'s .zhfc-avatar-trigger
   provides for the editable avatar — without it, a Crew portrait's
   transform:scale(2) zoom (see .zhfc-avatar--crew) paints past its own
   88px box with nothing to contain it, since border-radius/overflow on
   the <img> itself doesn't clip its own transform. */
.zhfc-avatar-frame {
	display: inline-block;
	overflow: hidden;
}

/* Always applied now — there is always someone to speak from the
 * bubble: the member's own crew avatar if they picked one, otherwise
 * their assigned trainer (see render_avatar_picker()'s PHP). The
 * --crew-y override below only ever affects an actual crew portrait
 * (.zhfc-avatar--crew), so it is harmless on the selfie/initial/trainer
 * cases where it simply does not apply to anything. */
.zhfc-avatar-row--with-bubble {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin-bottom: 2rem;
	/* Crops lower into the portrait (more chest/torso, less headroom) to
	 * make better use of the circle next to a two-line bubble — an
	 * inherited default only. A portrait with its own --crew-x/--crew-y
	 * override (set inline per avatar, see crew_roster()'s 'origin') still
	 * wins for that avatar; this only changes the ones with no override,
	 * currently falling back to the shared 8% default. */
	--crew-y: 20%;
}

.zhfc-avatar-row--with-bubble .zhfc-avatar-picker {
	margin-bottom: 0;
	flex: none;
}

/* Extra breathing room specifically when the trainer speaker badge
   (.zhfc-avatar-bubble-speaker) is present, so it has room to sit in
   the gap between the member's own avatar picker and the bubble without
   overlapping either one. */
.zhfc-avatar-row--with-speaker {
	gap: 2.75rem;
}

.zhfc-avatar-picker {
	display: block;
	margin-bottom: 2rem;
}

.zhfc-avatar-bubble {
	position: relative;
	flex: 1;
	min-width: 0;
	background: var(--zh-ink-soft);
	border: 1px solid var(--zh-gold);
	padding: 0.85rem 1.1rem;
}

.zhfc-avatar-bubble-tail {
	position: absolute;
	left: -0.55rem;
	top: 50%;
	width: 1rem;
	height: 1rem;
	margin-top: -0.5rem;
	background: var(--zh-ink-soft);
	border-left: 1px solid var(--zh-gold);
	border-bottom: 1px solid var(--zh-gold);
	transform: rotate(45deg);
}

/* Only present when the trainer is speaking in place of a crew avatar
   (see render_avatar_picker()) — sits left of the tail so it reads as
   "this is who is talking," separate from the member's own avatar
   picker further to the left, which stays the account's own edit
   control either way. */
.zhfc-avatar-bubble-speaker {
	position: absolute;
	left: -2.75rem;
	top: 50%;
	transform: translateY(-50%);
	border: 1px solid var(--zh-gold);
}

.zhfc-avatar-bubble-text {
	position: relative;
	display: block;
	font-size: 0.85rem;
	line-height: 1.55;
	color: var(--zh-bone);
	text-align: left;
}

/* iMessage-style typing indicator, shown while the encouragement line is
   still generating (see initAvatarBubble() — real text just overwrites
   this via textContent once the line arrives). */
.zhfc-typing-dots {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	height: 0.85rem;
}

.zhfc-typing-dots span {
	width: 0.4rem;
	height: 0.4rem;
	border-radius: 50%;
	background: var(--zh-bone-dim);
	animation: zhfc-typing-bounce 1.2s ease-in-out infinite;
}

.zhfc-typing-dots span:nth-child(2) {
	animation-delay: 0.15s;
}

.zhfc-typing-dots span:nth-child(3) {
	animation-delay: 0.3s;
}

@keyframes zhfc-typing-bounce {
	0%, 60%, 100% {
		transform: translateY(0);
		opacity: 0.5;
	}
	30% {
		transform: translateY(-0.2rem);
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.zhfc-typing-dots span {
		animation: none;
		opacity: 0.8;
	}
}

.zhfc-avatar-trigger {
	position: relative;
	display: inline-block;
	padding: 0;
	border: none;
	background: none;
	cursor: pointer;
	overflow: hidden;
}

.zhfc-avatar-trigger .zhfc-avatar--lg {
	border: 2px solid var(--zh-gold);
}

.zhfc-avatar-edit-tag {
	position: absolute;
	bottom: -0.35rem;
	right: -0.35rem;
	font-family: var(--zh-mono);
	font-size: 0.55rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	background: var(--zh-gold);
	color: var(--zh-ink);
	padding: 0.15rem 0.4rem;
}

.zhfc-avatar-tabs {
	display: flex;
	gap: 1.5rem;
	border-bottom: 1px solid var(--zh-line);
	margin: 1rem 0 1.25rem;
}

.zhfc-avatar-tab {
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	color: var(--zh-bone-dim);
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	padding: 0.5rem 0;
	cursor: pointer;
}

.zhfc-avatar-tab.is-active {
	color: var(--zh-gold);
	border-bottom-color: var(--zh-gold);
}

.zhfc-avatar-crew-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 0.6rem;
	margin-top: 0.75rem;
}

/* The class above sets its own `display`, which otherwise beats the
   browser's default [hidden] rule (author styles always outrank the
   user-agent stylesheet) — same fix as .zhfc-modal-overlay[hidden]. */
.zhfc-avatar-crew-grid[hidden] {
	display: none;
}

@media (max-width: 34rem) {
	.zhfc-avatar-crew-grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* Full-body preview shown after tapping a crew thumbnail — the member's
   one look at the whole portrait before "Select as Avatar" commits it. */
.zhfc-avatar-crew-preview {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin-top: 0.75rem;
}

.zhfc-avatar-crew-preview[hidden] {
	display: none;
}

.zhfc-avatar-crew-preview-img {
	max-width: 100%;
	max-height: 22rem;
	object-fit: contain;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
}

.zhfc-avatar-crew-preview-name {
	font-family: var(--zh-mono);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--zh-gold);
	margin: 0.75rem 0;
}

.zhfc-avatar-crew-preview-actions {
	display: flex;
	gap: 0.75rem;
}

.zhfc-avatar-crew-option {
	padding: 0;
	border: 1px solid var(--zh-line);
	background: var(--zh-ink-soft);
	cursor: pointer;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	align-items: stretch;
}

.zhfc-avatar-crew-option:hover {
	border-color: var(--zh-gold);
}

.zhfc-avatar-crew-option img {
	width: 100%;
	aspect-ratio: 1;
	object-fit: cover;
	object-position: center top;
	/* The source portraits are full-body shots — object-fit:cover alone
	   still shows more than half the body. Scaling up around a near-top
	   origin crops the thumbnail to chest-up instead; the full body is
	   still one tap away in the preview. transform-origin is overridden
	   per-image below (--crew-x/--crew-y) for portraits where tall ears,
	   horns, or a turned pose put the face somewhere other than the
	   shared default. */
	transform: scale(2.4);
	transform-origin: var(--crew-x, 50%) var(--crew-y, 8%);
	display: block;
}

/* Precropped portraits (see crew_roster()'s doc comment) are already
 * framed tight — no additional zoom on top, or the crop doubles up. */
.zhfc-avatar-crew-option img.is-precropped {
	transform: none;
}

.zhfc-avatar-crew-name {
	font-family: var(--zh-mono);
	font-size: 0.62rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--zh-bone-dim);
	padding: 0.35rem 0.2rem;
	text-align: center;
}

.zhfc-avatar-error {
	color: #d9534f;
	margin-top: 0.75rem;
}

/* Install-as-app: nav button + on-brand modal ------------------------------ */

.zhfc-install-modal {
	text-align: center;
}

.zhfc-install-modal-icon {
	width: 4rem;
	height: 4rem;
	display: block;
	margin: 0 auto 1rem;
	border: 1px solid var(--zh-line);
}

.zhfc-install-modal .zhfc-modal-body {
	margin-bottom: 0.5rem;
}

/* .zhfc-modal .zhfc-btn is display:block, but a <button> shrink-to-fits
 * its own width even at display:block (form controls don't stretch to
 * fill like a <div> would) — text-align:center on the modal only centers
 * inline content, never a block box's own position, so without this the
 * button sits flush against the modal's left padding instead of centered
 * under the centered copy above it. */
.zhfc-install-modal-actions .zhfc-btn {
	margin-left: auto;
	margin-right: auto;
}

/* Manual-install fallback: plain numbered steps per platform, left-aligned
 * against the rest of the (centered) install modal since a step list reads
 * as a list, not a centered caption. Two platform blocks show together only
 * when we can't tell which phone the visitor will actually install on
 * (desktop/unrecognized browser) — see initPwaInstall(). */
.zhfc-install-steps-wrap {
	text-align: left;
	margin: 1rem 0 0.5rem;
}

.zhfc-install-platform + .zhfc-install-platform {
	margin-top: 1.25rem;
	padding-top: 1.25rem;
	border-top: 1px solid var(--zh-line);
}

.zhfc-install-steps {
	margin: 0.4rem 0 0;
	padding-left: 1.25rem;
	color: var(--zh-bone-dim);
	font-size: 0.9rem;
	line-height: 1.6;
}

.zhfc-install-steps li {
	margin-bottom: 0.3rem;
}

.zhfc-install-steps li::marker {
	color: var(--zh-gold);
	font-family: var(--zh-mono);
}

/* WooCommerce catalog: single product, shop, product taxonomy archives ----
 * These stay on the theme's own block template (see is_woo_catalog()'s
 * docblock in class-zhfc-shortcodes.php for why) rather than our canvas.php
 * shell, so branding here means hiding the theme's own block-template
 * header/footer, injecting our nav via wp_body_open, and reskinning
 * WooCommerce's block markup in place instead of swapping the template. */

body.zhfc-catalog-page {
	background: var(--zh-ink);
}

/* The theme's header/footer template parts are no longer rendered on these
   pages at all (zhfc_drop_theme_chrome_on_catalog()). This stays only as a
   belt-and-braces fallback if a future theme names its parts differently. */
body.zhfc-catalog-page header.wp-block-template-part,
body.zhfc-catalog-page footer.wp-block-template-part {
	display: none !important;
}

/* Our brand footer, injected on catalog pages in place of the theme's. It
   sits outside WooCommerce's main column, so it brings its own width. */
.zhfc-catalog-footer {
	max-width: 68rem;
	margin: 0 auto;
	padding: 0 clamp(1.5rem, 4vw, 3rem) clamp(2rem, 5vw, 3rem);
	font-family: var(--zh-mono);
	color: var(--zh-bone);
}

body.zhfc-catalog-page main.wp-block-group {
	max-width: 68rem;
	margin: 0 auto;
	padding: clamp(1.5rem, 4vw, 3rem);
	font-family: var(--zh-mono);
	color: var(--zh-bone);
}

body.zhfc-catalog-page a {
	color: var(--zh-gold);
}

body.zhfc-catalog-page h1.wp-block-post-title {
	font-family: var(--zh-display);
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: var(--zh-bone);
	font-size: clamp(2rem, 5vw, 3rem);
	margin: 0 0 1rem;
}

body.zhfc-catalog-page .woocommerce-breadcrumb,
body.zhfc-catalog-page .wc-block-breadcrumbs {
	color: var(--zh-bone-dim) !important;
	font-family: var(--zh-mono);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	margin-bottom: 1.5rem;
}

body.zhfc-catalog-page .woocommerce-breadcrumb a,
body.zhfc-catalog-page .wc-block-breadcrumbs a {
	color: var(--zh-gold) !important;
}

body.zhfc-catalog-page .woocommerce-Price-amount,
body.zhfc-catalog-page .wp-block-woocommerce-product-price {
	color: var(--zh-gold-bright) !important;
	font-family: var(--zh-display);
	letter-spacing: 0.02em;
	font-size: 1.8rem !important;
}

body.zhfc-catalog-page .single_add_to_cart_button,
body.zhfc-catalog-page .wp-block-woocommerce-product-button a,
body.zhfc-catalog-page .added_to_cart {
	background: linear-gradient(135deg, var(--zh-gold-bright), var(--zh-gold)) !important;
	color: var(--zh-ink) !important;
	font-family: var(--zh-mono);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-weight: 700;
	border: none !important;
	border-radius: 0 !important;
	padding: 0.85rem 1.5rem !important;
}

body.zhfc-catalog-page .wp-block-woocommerce-product-image-gallery,
body.zhfc-catalog-page .wp-block-woocommerce-product-image-gallery img {
	border-radius: 0 !important;
}

body.zhfc-catalog-page .wp-block-woocommerce-product-image-gallery {
	border: 1px solid var(--zh-line);
}

/* Ringer Tee model shot is a tall portrait crop into a roughly square box —
 * center crop cuts her face off, so bias the visible window toward the top. */
.post-517 img {
	object-position: center top;
}

/* Beanie lifestyle shot: same tall-portrait-into-square-box crop, but the
 * beanie itself sits right at the top of the frame — a center crop left
 * only a sliver of it visible. */
.post-636 img {
	object-position: center top;
}

/* Shop grid: the image and the button now share the card's first grid
 * track instead of stacking in normal flow — that's what lets the button
 * sit pinned over the bottom-left corner of the photo instead of floating
 * below the title/price at whatever height those happen to wrap to. Title
 * and price auto-place into the next rows below, same as plain flow. */
body.zhfc-catalog-page ul.wc-block-product-template li.wc-block-product {
	display: grid;
	grid-template-columns: 1fr;
}

body.zhfc-catalog-page ul.wc-block-product-template li.wc-block-product > .wp-block-woocommerce-product-image {
	grid-row: 1;
	grid-column: 1;
	position: relative;
}

body.zhfc-catalog-page ul.wc-block-product-template li.wc-block-product > .wp-block-woocommerce-product-button {
	grid-row: 1;
	grid-column: 1;
	align-self: end;
	justify-self: start;
	z-index: 2;
	margin: 0 0 0.6rem 0.6rem !important;
}

/* Compact badge instead of a full-width CTA, and "Options" only — "Select
 * options" / "Add to cart" reads fine as a full sentence below the fold on
 * the single-product page, but crowds a photo-corner badge on the grid. */
body.zhfc-catalog-page ul.wc-block-product-template .wp-block-woocommerce-product-button a {
	padding: 0.5rem 1rem !important;
	font-size: 0.65rem !important;
}

body.zhfc-catalog-page ul.wc-block-product-template .wp-block-woocommerce-product-button a span {
	font-size: 0;
}

body.zhfc-catalog-page ul.wc-block-product-template .wp-block-woocommerce-product-button a::after {
	content: 'Options';
	font-size: 0.65rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

body.zhfc-catalog-page .woocommerce-tabs,
body.zhfc-catalog-page .wp-block-woocommerce-product-details {
	border-top: 1px solid var(--zh-line);
	margin-top: 2rem;
	padding-top: 1.5rem;
}

body.zhfc-catalog-page ul.tabs.wc-tabs {
	display: flex;
	gap: 1.5rem;
	list-style: none;
	padding: 0;
	margin: 0 0 1.5rem;
	border-bottom: 1px solid var(--zh-line);
}

body.zhfc-catalog-page ul.tabs.wc-tabs li {
	font-family: var(--zh-mono);
	text-transform: uppercase;
	letter-spacing: 0.05em;
	font-size: 0.8rem;
	padding-bottom: 0.75rem;
}

body.zhfc-catalog-page ul.tabs.wc-tabs li a {
	color: var(--zh-bone-dim);
}

body.zhfc-catalog-page ul.tabs.wc-tabs li.active {
	border-bottom: 2px solid var(--zh-gold);
}

body.zhfc-catalog-page ul.tabs.wc-tabs li.active a {
	color: var(--zh-gold);
}

body.zhfc-catalog-page .woocommerce-Tabs-panel {
	color: var(--zh-bone);
	font-family: var(--zh-mono);
	line-height: 1.6;
}

body.zhfc-catalog-page ins {
	background: none;
	color: var(--zh-gold-bright);
}

body.zhfc-catalog-page del {
	color: var(--zh-bone-dim);
}

/* Pulse survey (class-zhfc-shortcodes.php::survey()) — one star row per
   question, filled left-to-right on click/hover. Unfilled stars are a dim
   outline rather than plain gray so the row still reads as "rate me" at
   a glance, not decorative dead space. */
.zhfc-survey-q {
	margin-bottom: 1.5rem;
}

.zhfc-star-rating {
	display: flex;
	gap: 0.35rem;
	margin-top: 0.5rem;
}

.zhfc-star-btn {
	background: none;
	border: none;
	padding: 0;
	font-size: 1.75rem;
	line-height: 1;
	color: transparent;
	-webkit-text-stroke: 1px var(--zh-line);
	cursor: pointer;
	transition: color 0.15s ease-out, -webkit-text-stroke 0.15s ease-out;
}

.zhfc-star-btn:hover {
	color: var(--zh-gold);
	-webkit-text-stroke: 1px var(--zh-gold);
}

.zhfc-star-btn.is-active {
	color: var(--zh-gold-bright);
	-webkit-text-stroke: 1px var(--zh-gold-bright);
}

@media (prefers-reduced-motion: reduce) {
	.zhfc-star-btn {
		transition: none;
	}
}

/* ------------------------------------------------------------------ */
/* Intake drip — this week's questions, on the dashboard               */
/* ------------------------------------------------------------------ */

/* Sits between the member and next week, so it reads as a gate rather
   than a suggestion: gold hairline, gold-tinted ground, full width. */
.zhfc-drip {
	/* Explicit, because this same card renders both inside the centered
	   dashboard hub and the left-aligned program view. */
	text-align: left;
	margin: 1.5rem 0;
	padding: 1.25rem 1.25rem 1.5rem;
	border: 1px solid var(--zh-gold);
	background:
		linear-gradient(
			180deg,
			color-mix(in srgb, var(--zh-gold) 8%, transparent),
			transparent 70%
		),
		var(--zh-ink-soft);
}

.zhfc-drip .zhfc-eyebrow {
	color: var(--zh-gold);
}

.zhfc-drip .zhfc-display--sm {
	margin: 0.35rem 0 0.5rem;
}

.zhfc-drip .zhfc-hint {
	margin: 0 0 1.1rem;
	max-width: 58ch;
}

.zhfc-drip .zhfc-actions {
	margin: 0;
}

@media (max-width: 34rem) {
	.zhfc-drip {
		padding: 1rem 1rem 1.25rem;
	}

	.zhfc-drip .zhfc-btn {
		width: 100%;
	}
}

/* ------------------------------------------------------------------ */
/* Moderation: report dialog, room safety line, blocked members        */
/* ------------------------------------------------------------------ */

/* Opened from inside the chat drawer too, so it has to sit above it
   (both overlays otherwise share z-index 100). */
.zhfc-report-modal {
	z-index: 110;
}

.zhfc-report-reasons {
	margin: 0.75rem 0 1rem;
}

.zhfc-report-reasons .zhfc-checkbox-row {
	margin: 0.45rem 0;
	color: var(--zh-bone);
}

.zhfc-report-reasons input[type="radio"] {
	accent-color: var(--zh-gold);
}

/* The shared textarea style is content-box at 100% width, which pushes it
   past the dialog's padding here. */
.zhfc-report-modal .zhfc-textarea {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
}

.zhfc-report-block {
	margin-top: 1.25rem;
	padding-top: 1rem;
	border-top: 1px solid var(--zh-line);
}

.zhfc-report-trigger:hover,
.zhfc-report-trigger:focus-visible {
	color: var(--zh-gold);
}

.zhfc-room-safety {
	margin-top: 1.5rem;
	font-size: 0.75rem;
}

.zhfc-blocked-list {
	list-style: none;
	margin: 0.75rem 0 0;
	padding: 0;
}

.zhfc-blocked-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.6rem 0;
	border-top: 1px solid var(--zh-line);
}

.zhfc-blocked-name {
	font-family: var(--zh-mono);
	color: var(--zh-bone);
	overflow-wrap: anywhere;
}


/* Accessibility baseline (WCAG 2.4.1, 2.4.7, 2.3.3). Components that define
 * their own focus treatment keep it; this only covers everything that would
 * otherwise show nothing. */
.zhfc-skip-link {
	position: absolute;
	left: 0.5rem;
	top: -4rem;
	z-index: 10000;
	padding: 0.75rem 1rem;
	background: var(--zh-gold-bright);
	color: var(--zh-ink);
	font-family: var(--zh-mono);
	font-size: 0.85rem;
	text-decoration: none;
}

.zhfc-skip-link:focus {
	top: 0.5rem;
}

.zhfc-main:focus {
	outline: none;
}

:where(a, button, summary, select, input, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--zh-gold-bright);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
