/**
 * Base — reset, body defaults, root typography, light mode support.
 *
 * Minimal reset + site-wide defaults. Everything else is handled by
 * components and templates.
 */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	scroll-behavior: smooth;
	background-color: #000 !important;
	/* `color-scheme: dark` tells iOS + Chrome to paint overscroll bounce
	   areas and scrollbars dark by default — without this, Instagram's
	   webview shows its own light overscroll area when you pull past the
	   top. Combined with overscroll-behavior: contain, most webviews now
	   show a black bounce area with elastic feel. */
	color-scheme: dark;
	overflow-x: clip;
	overscroll-behavior-y: contain;
	overscroll-behavior-x: contain;
}

body {
	margin: 0;
	min-height: 100vh;
	background-color: #000 !important;
	overflow-x: clip;
	overscroll-behavior-y: contain;
	overscroll-behavior-x: contain;
	position: relative;
	color: var(--slist-text-primary);
	font-family: var(--slist-font-body);
	font-size: var(--slist-text-body);
	line-height: var(--slist-lh-default);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-variant-ligatures: common-ligatures;
	text-rendering: optimizeLegibility;
	/* Sticky-footer scaffold: body + .site are flex columns so the
	   footer rides the bottom of the viewport when content is short,
	   and sits right under content when content is tall. Prevents the
	   perceived seam where empty body-bg used to show below a short
	   page's footer. */
	display: flex;
	flex-direction: column;
}

body > .site,
body > #page.site {
	display: flex;
	flex-direction: column;
	flex: 1 0 auto;
}

body > .site > .slist-main,
body > #page.site > .slist-main {
	flex: 1 0 auto;
}

/*
 * GeneratePress's `.grid-container` class on `#page` sets
 * `max-width: 1200px; margin: 0 auto;` to center the page in the viewport.
 * That shrinks #page's box, which cascades down to constrain every direct
 * child including `.slist-footer` — so the footer can't bleed to viewport
 * edges without escape hacks (negative margins or pseudo-element overlays).
 *
 * Architectural fix (2026-05-13): keep #page full-viewport, move the
 * content-width constraint to `.site-content` (and anywhere else that
 * needs it). Children of #page that *should* bleed (like .slist-footer)
 * now naturally fill the viewport with no tricks; children that should
 * stay narrow get a max-width on their own container.
 *
 * Why padding wasn't used on #page: padding would create the visual inset
 * but children would still default to the content-area width (after
 * padding) and require negative margins to escape. Removing the
 * constraint entirely and pushing it to specific containers is cleaner
 * — each element opts into its own width policy.
 */
body > #page.site,
body > #page.site.grid-container {
	max-width: none;
	margin-left: 0;
	margin-right: 0;
	width: 100%;
}

/*
 * Image fade-in baseline — images fade from slightly dimmed to full brightness
 * over 240ms when they finish decoding. The `img[loading="lazy"]` trick uses
 * the fact that lazy images start with a "decoding pending" state; once the
 * browser completes the decode, the transition fires. For eager images, no
 * fade is applied (they're expected above the fold).
 *
 * The effect is Shopify-tier: nothing pops in abruptly; every image eases in.
 */
img {
	/* Baseline smoothness — transition any opacity changes (Perfmatters +
	   native decoding both touch opacity during lazy-load). */
	transition: opacity 240ms var(--slist-ease-out), filter 240ms var(--slist-ease-out);
}

/* Defensive override: ensure no image ever gets stuck at opacity 0 because
   of a Perfmatters class lifecycle we don't control. If src has a value,
   show the image. (The earlier rule forcing lazy-unloaded images to opacity:0
   caused blog thumbnails to hang invisibly when the .pmloaded class never
   arrived.) */
img {
	opacity: 1;
}

/* Respect user preference — no animation for reduced-motion users */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	img { transition: none; opacity: 1 !important; }
}

/*
 * iOS-only: body becomes a locked viewport, `.site` becomes the scroll
 * container. The bounce happens INSIDE .site so Instagram's webview never
 * sees overscroll at its own level — no host-app peek on swipe-down, and
 * the elastic feel is preserved because .site itself bounces.
 *
 * Desktop + Android: use normal document scroll (this @supports block
 * matches only WebKit Mobile/iOS Safari/Instagram-webview).
 */
@supports (-webkit-touch-callout: none) {
	html,
	body {
		height: 100%;
		height: 100dvh;
		overflow: hidden;
	}

	body > .site,
	body > .site.grid-container {
		height: 100%;
		height: 100dvh;
		/* `hidden auto`, NOT `clip auto`. `overflow-x: clip` creates a
		   containment context that breaks `position: sticky` on descendants
		   (known WebKit bug). `hidden` works. */
		overflow: hidden auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-y: contain;
		overscroll-behavior-x: contain;
		background: #000;
		/* Anchor for sticky nav children inside the scroll container */
		position: relative;
	}

	/*
	 * Direct children of `.site` must NOT shrink under flex pressure.
	 *
	 * `.site` is a flex column with a fixed `height: 100dvh` on iOS. When
	 * total content (e.g. .site-content + footer on a PDP) exceeds 100dvh,
	 * the default `flex-shrink: 1` on children kicks in and shrinks them
	 * proportionally to flex-basis instead of letting `overflow: hidden auto`
	 * scroll the page. On the PDP this collapsed `<footer.slist-footer>`
	 * from ~552px to ~113px (clipped by its existing `overflow: hidden`),
	 * making the footer appear to be missing content even though the markup
	 * was intact in the DOM (verified 2026-04-28).
	 *
	 * `.slist-main` was already protected via `flex: 1 0 auto` at line 62
	 * but only when it's a direct child of `.site` (front-page and event
	 * archives). On product templates, `<main>` is nested inside
	 * `.site-content`, so the targeted rule didn't apply. This wildcard
	 * protects every direct child uniformly — the right level of generality
	 * for "iOS scroll container with locked-viewport children".
	 */
	body > .site > * {
		flex-shrink: 0;
	}
}

img,
svg,
video,
canvas {
	max-width: 100%;
	height: auto;
	display: block;
}

a {
	color: inherit;
	text-decoration: none;
}

p {
	margin: 0 0 var(--slist-space-3);
}

ul,
ol {
	padding-left: var(--slist-space-4);
	margin: 0 0 var(--slist-space-3);
}

hr {
	border: 0;
	border-top: 1px solid var(--slist-separator);
	margin: var(--slist-space-5) 0;
}

::selection {
	background: var(--slist-primary);
	color: #ffffff;
}

/*
 * Kill AIOSEO's admin-bar frontend notification counter (the floating "2"
 * badge next to the SEO admin-bar item). On frontend pages it vertically
 * overlaps the main nav's "Events" link, reading as if there's a count
 * above "Events." Since we already dequeued AIOSEO's Vue app on the
 * frontend (inc/enqueue.php), the badge is purely cosmetic noise.
 *
 * Scoped to `.aioseo-menu-notification-counter-frontend` so wp-admin
 * counters stay intact.
 */
#wpadminbar .aioseo-menu-notification-counter-frontend,
#wpadminbar .aioseo-menu-notification-counter {
	display: none !important;
}

/*
 * Hide scrollbars site-wide — keep scroll behavior, drop the visual
 * chrome. Matches the Apple-glass aesthetic (no UI furniture between
 * the content and the edge of the screen). Applies to:
 *   - document scroll (html, body)
 *   - iOS inner scroll container (body > .site)
 *   - horizontal scroll rows on home (.slist-scroll-row)
 *   - PDP gallery, any div that ends up scrollable
 *
 * Keyboard + trackpad + touch scroll still work — we're only hiding
 * the draggable scrollbar affordance. Accessibility note: users who
 * rely on the visible scrollbar for orientation can still scroll via
 * arrow keys / Page Up / Page Down, and screen readers are unaffected.
 */
html,
body,
body > .site,
.slist-scroll-row,
.slist-scroll-x {
	scrollbar-width: none;          /* Firefox + modern browsers */
	-ms-overflow-style: none;       /* IE 10+ / old Edge (harmless elsewhere) */
}

html::-webkit-scrollbar,
body::-webkit-scrollbar,
body > .site::-webkit-scrollbar,
.slist-scroll-row::-webkit-scrollbar,
.slist-scroll-x::-webkit-scrollbar,
*::-webkit-scrollbar {
	width: 0 !important;
	height: 0 !important;
	display: none;                  /* Chrome/Safari/Edge */
}

:focus-visible {
	outline: 2px solid var(--slist-primary);
	outline-offset: 2px;
}

/**
 * GP base override — GP sets global text color based on its customizer;
 * we want our tokens to win. Background is NOT set here — body/html
 * already force #000 above, and leaving .entry-content / .site-content
 * transparent lets the body color show through without a distinct
 * content-area rectangle (avoids the "middle black" visual artifact
 * that appeared under some cache/color-scheme combinations).
 */
body,
body .entry-content,
.site-content {
	color: var(--slist-text-primary);
}

/**
 * Neutralize GP's .site-content layout.
 * GP sets `display: flex; padding: 40px` to host an optional sidebar.
 * In flex-row with one child, <main> sizes to its largest descendant
 * (.slist-container--wide @ max-width 1120px) and pins to flex-start —
 * killing margin: auto centering on our containers (auto computes to 0
 * when there's no unused space).
 *
 * `.site-content` also takes over the content-width constraint that
 * previously lived on `#page` (see 2026-05-13 architecture note above).
 * #page is now full-viewport so the footer can bleed naturally; content
 * inside `.site-content` is centered to `--slist-content-wide` here.
 *
 * Use .slist-body specificity (0,2,0) to beat GP's .site-content (0,1,0)
 * since GP's CSS is concatenated AFTER ours by perfmatters.
 */
.slist-body .site-content {
	display: block;
	padding: 0;
	max-width: var(--slist-content-wide);
	margin-left: auto;
	margin-right: auto;
	width: 100%;
}

/**
 * GP container neutralization — we use our own layout widths.
 */
.inside-article,
.entry-content,
.inside-page-content {
	background: transparent;
}

/**
 * JetWooBuilder PhotoSwipe — hide when inactive.
 *
 * JetWooBuilder renders `.jet-woo-product-gallery-pswp` on every page,
 * not just product galleries. The element uses `visibility:hidden`
 * inline which still reserves layout space — visible as a tall black
 * bar below the footer on non-product pages. We hide it entirely when
 * aria-hidden="true" (JetWoo flips this to "false" when it opens the
 * gallery, so the lightbox still works on shop pages).
 */
.jet-woo-product-gallery-pswp[aria-hidden="true"] {
	display: none !important;
}

/**
 * Reduced motion — users who've opted out of animation see instant changes.
 */
@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;
	}
}
