/* app-shell.css — shared styles for persistent nav + Swup transitions. */

/* =========================================================
   ACCESSIBILITY — skip-to-content link for keyboard users.
   Hidden off-screen until focused; then slides into view so
   tab order starts with a way to bypass the nav.
   ========================================================= */
.skip-to-content {
	position: fixed;
	top: 12px;
	left: 12px;
	z-index: 10000;
	padding: 12px 18px;
	border-radius: 999px;
	background: var(--ink, #17191c);
	color: var(--paper, #f4f1ec);
	font-family: var(--font-display, "Space Grotesk", system-ui, sans-serif);
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
	transform: translateY(-200%);
	transition: transform 0.18s ease;
	box-shadow: 0 12px 24px -12px rgba(0, 0, 0, 0.4);
}
.skip-to-content:focus,
.skip-to-content:focus-visible {
	transform: translateY(0);
	outline: 2px solid var(--accent, #ff6a1f);
	outline-offset: 2px;
}

/* Screen-reader-only helper (visible only to assistive tech). */
.sr-only {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* =========================================================
   CORE THEME — must live OUTSIDE per-page <style> blocks so
   head-plugin's style swap never removes them mid-nav. Without
   this, there's a brief frame where the body background rule
   is gone and the browser paints default white — the "reload flash".
   Per-page blocks may redeclare these harmlessly (identical values).
   ========================================================= */
:root {
	--ink: #17191c;
	--ink-2: #2a2d31;
	--paper: #f4f1ec;
	--paper-2: #ebe7df;
	--line: #d6d1c6;
	--accent: #ff6a1f;
	--accent-2: #f7b500;
	--muted: #6a6a68;
	--radius: 14px;
	--font-display: "Space Grotesk", system-ui, sans-serif;
	--font-mono: "Space Mono", ui-monospace, monospace;
	--font-body: "Inter", system-ui, sans-serif;
}
* {
	box-sizing: border-box;
}
html,
body {
	margin: 0;
	padding: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: var(--font-body);
	-webkit-font-smoothing: antialiased;
}
img {
	display: block;
	max-width: 100%;
}
a {
	color: inherit;
	text-decoration: none;
}
button {
	font-family: inherit;
}


/* =========================================================
   PREVENT OFF-SCREEN OVERFLOW from fixed-position elements.
   The Shopify cart drawer sits at translateX(100%) when closed,
   but its box-shadow (-20px 0 60px) leaks ~80px back into the
   viewport. `overflow-x: clip` on <html> clips painted overflow
   at the viewport edge without creating a scroll container.
   ========================================================= */
html {
	overflow-x: clip;
	/* Always reserve space for the vertical scrollbar so the viewport
	   width doesn't jump when navigating between long pages (scrollbar
	   present) and short pages (scrollbar absent). */
	scrollbar-gutter: stable;
}

/* Suppress the drawer's shadow while it's closed — belt to the
   overflow-x: clip suspenders, and fixes older browsers too.
   !important needed because shopify.js injects its own style
   block after app-shell.css loads. */
.sc-drawer {
	transition:
		transform 0.3s cubic-bezier(0.3, 0, 0.2, 1),
		box-shadow 0.2s ease 0.1s !important;
}
.sc-drawer:not(.open) {
	box-shadow: none !important;
}

/* =========================================================
   SHOP-ALL FAB — global rules (lived in index.html before,
   but per-page styles are scoped to [data-page="..."] and the
   FAB is body-level, so the scoped rule wouldn't match).
   ========================================================= */
.sc-fab.is-on-orange {
	background: var(--ink) !important;
	color: var(--paper) !important;
}
.sc-fab.is-on-orange:hover {
	background: var(--accent) !important;
	color: var(--ink) !important;
}

/* Hidden on shop.html — toggled by app-shell.js on every nav.
   Uses the same fade-out pattern as body.sc-drawer-open so the
   transition back in feels consistent. */
body.hide-shop-fab .sc-fab {
	opacity: 0;
	pointer-events: none;
	transform: translateY(8px);
}

/* =========================================================
   CUSTOM SHOWCASE LIGHTBOX — body-level overlay that displays
   full-size images from index.html's custom showcase carousel.
   Lives in app-shell.css (not index.html's inline style) because
   the element is appended to <body>, outside the scoped per-page
   style block. If these rules were page-scoped the lightbox would
   render unstyled inline.
   ========================================================= */
.showcase-lightbox {
	position: fixed;
	inset: 0;
	z-index: 1100;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 40px;
	background: rgba(13, 14, 16, 0.88);
	-webkit-backdrop-filter: blur(8px);
	backdrop-filter: blur(8px);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.22s ease;
}
.showcase-lightbox.is-open {
	opacity: 1;
	pointer-events: auto;
}
.showcase-lightbox-panel {
	position: relative;
	max-width: min(1100px, 100%);
	max-height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	transform: translateY(12px) scale(0.98);
	transition: transform 0.28s cubic-bezier(0.3, 0, 0.2, 1);
}
.showcase-lightbox.is-open .showcase-lightbox-panel {
	transform: translateY(0) scale(1);
}
.showcase-lightbox-image {
	max-width: 100%;
	max-height: calc(100vh - 140px);
	object-fit: contain;
	border-radius: 14px;
	box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.6);
	display: block;
	background: var(--paper);
}
.showcase-lightbox-close,
.showcase-lightbox-nav {
	background: rgba(255, 255, 255, 0.1);
	border: 1px solid rgba(255, 255, 255, 0.22);
	color: var(--paper);
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	transition:
		background 0.15s,
		border-color 0.15s,
		transform 0.15s;
	padding: 0;
}
.showcase-lightbox-close:hover,
.showcase-lightbox-nav:hover {
	background: rgba(255, 255, 255, 0.22);
	border-color: rgba(255, 255, 255, 0.45);
}
.showcase-lightbox-close {
	position: absolute;
	top: -52px;
	right: 0;
	width: 40px;
	height: 40px;
}
.showcase-lightbox-close svg {
	width: 16px;
	height: 16px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
}
.showcase-lightbox-nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 52px;
	height: 52px;
}
.showcase-lightbox-nav:hover {
	transform: translateY(-50%) scale(1.05);
}
.showcase-lightbox-prev {
	left: -76px;
}
.showcase-lightbox-next {
	right: -76px;
}
.showcase-lightbox-nav svg {
	width: 22px;
	height: 22px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}
.showcase-lightbox-caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: -56px;
	text-align: center;
	color: rgba(244, 241, 236, 0.92);
	font-family: var(--font-display);
	font-size: 16px;
	font-weight: 500;
	letter-spacing: -0.01em;
}
.showcase-lightbox-caption .cap-sub {
	display: block;
	margin-top: 4px;
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: rgba(244, 241, 236, 0.55);
	font-weight: 400;
}

/* Mobile: tuck the arrows inside the viewport edges and the close
   button into the top-right corner, keep the caption visible. */
@media (max-width: 720px) {
	.showcase-lightbox {
		padding: 20px;
	}
	.showcase-lightbox-prev {
		left: 8px;
	}
	.showcase-lightbox-next {
		right: 8px;
	}
	.showcase-lightbox-nav {
		background: rgba(0, 0, 0, 0.5);
	}
	.showcase-lightbox-close {
		top: 12px;
		right: 12px;
		background: rgba(0, 0, 0, 0.55);
	}
}

body.showcase-lightbox-open {
	overflow: hidden;
}

/* =========================================================
   SHOP QUICK-VIEW MODAL — lives in app-shell.css (not
   shop.html inline styles) because the overlay is appended
   to <body>, outside [data-page="shop"] where scoped per-page
   CSS would apply. Keeps the overlay properly styled across
   SPA navigations too.
   ========================================================= */
.qv-overlay {
	position: fixed;
	inset: 0;
	z-index: 200;
	background: color-mix(in oklab, var(--ink) 55%, transparent);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.2s ease;
}
.qv-overlay.is-open {
	opacity: 1;
	pointer-events: auto;
}
.qv-panel {
	background: var(--paper);
	border-radius: 20px;
	width: min(960px, 100%);
	max-height: calc(100vh - 48px);
	overflow: hidden;
	display: grid;
	grid-template-columns: 1fr 1fr;
	position: relative;
	transform: translateY(12px) scale(0.98);
	transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
	box-shadow: 0 40px 80px -20px rgba(0, 0, 0, 0.35);
}
.qv-overlay.is-open .qv-panel {
	transform: translateY(0) scale(1);
}
@media (max-width: 720px) {
	.qv-panel {
		grid-template-columns: 1fr;
		max-height: calc(100vh - 32px);
		overflow-y: auto;
	}
}
.qv-close {
	position: absolute;
	top: 14px;
	right: 14px;
	z-index: 3;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid var(--line);
	background: color-mix(in oklab, var(--paper) 90%, transparent);
	backdrop-filter: blur(6px);
	cursor: pointer;
	color: var(--ink);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 16px;
	line-height: 1;
	transition:
		background 0.15s,
		color 0.15s;
}
.qv-close:hover {
	background: var(--ink);
	color: var(--paper);
}
.qv-media {
	aspect-ratio: 1;
	background: var(--paper-2);
	display: flex;
	align-items: center;
	justify-content: center;
	position: relative;
	overflow: hidden;
}
.qv-media::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		linear-gradient(
			0deg,
			transparent 0 calc(100% - 1px),
			color-mix(in oklab, var(--line) 70%, transparent) calc(100% - 1px)
				100%
		),
		linear-gradient(
			90deg,
			transparent 0 calc(100% - 1px),
			color-mix(in oklab, var(--line) 70%, transparent) calc(100% - 1px)
				100%
		);
	background-size: 32px 32px;
	opacity: 0.4;
	pointer-events: none;
}
.qv-media img {
	position: relative;
	z-index: 1;
	width: 86%;
	height: 86%;
	object-fit: contain;
	filter: drop-shadow(0 18px 28px rgba(0, 0, 0, 0.14));
	border-radius: 10px;
}
.qv-body {
	padding: 32px 32px 28px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	overflow-y: auto;
}
.qv-tag {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--accent);
}
.qv-title {
	font-family: var(--font-display);
	font-size: 28px;
	letter-spacing: -0.02em;
	font-weight: 600;
	margin: 0;
	line-height: 1.1;
}
.qv-price-row {
	display: flex;
	align-items: baseline;
	gap: 10px;
	font-family: var(--font-display);
	margin-top: 2px;
}
.qv-price-row .now {
	font-size: 22px;
	font-weight: 600;
	letter-spacing: -0.01em;
}
.qv-price-row .was {
	color: var(--muted);
	text-decoration: line-through;
	font-size: 15px;
}
.qv-price-row .save {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--accent);
	background: color-mix(in oklab, var(--accent) 15%, transparent);
	padding: 4px 8px;
	border-radius: 999px;
}
.qv-desc {
	color: var(--muted);
	font-size: 14px;
	line-height: 1.55;
	max-height: 8em;
	overflow: hidden;
	position: relative;
}
.qv-desc::after {
	content: "";
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	height: 2.5em;
	background: linear-gradient(to bottom, transparent, var(--paper));
	pointer-events: none;
}
.qv-options {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin-top: 4px;
}
.qv-option-group {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.qv-option-label {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--muted);
}
.qv-option-pills {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
}
.qv-option-pill {
	padding: 7px 12px;
	border-radius: 999px;
	border: 1px solid var(--line);
	background: var(--paper);
	font-family: var(--font-display);
	font-size: 13px;
	font-weight: 500;
	color: var(--ink-2);
	cursor: pointer;
	transition: all 0.15s;
}
.qv-option-pill:hover {
	border-color: var(--ink);
	color: var(--ink);
}
.qv-option-pill.on {
	background: var(--ink);
	color: var(--paper);
	border-color: var(--ink);
}
.qv-option-pill.is-disabled {
	opacity: 0.4;
	cursor: not-allowed;
	text-decoration: line-through;
}
.qv-actions {
	display: flex;
	gap: 10px;
	align-items: center;
	margin-top: auto;
	padding-top: 14px;
	flex-wrap: wrap;
}
.qv-add-btn {
	flex: 1;
	min-width: 160px;
	padding: 14px 22px;
	border-radius: 999px;
	border: none;
	cursor: pointer;
	background: var(--accent);
	color: var(--ink);
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 15px;
	letter-spacing: -0.01em;
	transition:
		background 0.15s,
		transform 0.1s;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
}
.qv-add-btn:hover {
	background: var(--ink);
	color: var(--paper);
}
.qv-add-btn:active {
	transform: translateY(1px);
}
.qv-add-btn[disabled] {
	background: var(--paper-2);
	color: var(--muted);
	cursor: not-allowed;
}
.qv-full-link {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ink-2);
	padding: 12px 14px;
	border-radius: 999px;
	border: 1px solid var(--line);
	transition:
		border-color 0.15s,
		color 0.15s;
}
.qv-full-link:hover {
	border-color: var(--ink);
	color: var(--ink);
}
.qv-loading,
.qv-error {
	padding: 48px 32px;
	text-align: center;
	color: var(--muted);
	font-size: 14px;
	grid-column: 1 / -1;
}
body.qv-open {
	overflow: hidden;
}

/* =========================================================
   APP FOOTER — shared across every page.
   Three-column layout: socials · centered logo · quick links.
   Injected at body level by app-shell.js so it persists across
   SPA navigation (no duplication in per-page HTML).
   ========================================================= */
.app-footer {
	background: var(--ink);
	color: var(--paper);
	padding: 64px 32px 28px;
	position: relative;
}
.app-footer-inner {
	max-width: 1280px;
	margin: 0 auto;
}
.app-footer-grid {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	gap: 48px;
	align-items: center;
	padding-bottom: 32px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
@media (max-width: 880px) {
	.app-footer-grid {
		grid-template-columns: 1fr;
		gap: 32px;
		text-align: center;
	}
}

/* Left — social icons only. Icons are brand-colored SVGs (TikTok cyan/red,
   Instagram gradient) so the circle frame stays neutral on hover — we just
   lift + brighten the ring instead of flooding orange over the brand marks. */
.af-left {
	display: flex;
	flex-direction: column;
	gap: 16px;
	align-items: flex-start;
}
@media (max-width: 880px) {
	.af-left { align-items: center; }
}
.af-socials {
	display: inline-flex;
	gap: 12px;
}
.af-social {
	width: 48px;
	height: 48px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.14);
	background: rgba(255, 255, 255, 0.03);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	color: var(--paper);
	transition:
		background 0.15s,
		border-color 0.15s,
		transform 0.15s,
		box-shadow 0.15s;
}
.af-social:hover {
	border-color: rgba(255, 255, 255, 0.45);
	background: rgba(255, 255, 255, 0.07);
	transform: translateY(-2px);
	box-shadow: 0 8px 20px -10px rgba(0, 0, 0, 0.5);
}
.af-social img,
.af-social svg {
	width: 22px;
	height: 22px;
	display: block;
}

/* Etsy — no brand SVG provided, use the wordmark-style letter treatment.
   Matches Etsy's recognizable orange serif italic, but rendered here in
   paper cream so it stays legible against the dark circle. */
.af-etsy {
	font-family: "Georgia", "Times New Roman", serif;
	font-weight: 700;
	font-style: italic;
	font-size: 14px;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--paper);
}
.af-social-etsy:hover .af-etsy {
	color: var(--accent);
}

/* Center — logo, brand, tagline */
.af-logo {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	color: var(--paper);
	text-decoration: none;
}
.af-logo img {
	width: 108px;
	height: auto;
	display: block;
	/* brightness(0) → crushes the SVG to solid black, invert(1) → flips
	   that black to pure white. The drop-shadow is chained last so it
	   applies to the recoloured silhouette, not the original. */
	filter: brightness(0) invert(1) drop-shadow(0 6px 16px rgba(0, 0, 0, 0.35));
	margin-bottom: 4px;
}
.af-brand {
	font-family: var(--font-display);
	font-size: 20px;
	font-weight: 700;
	letter-spacing: -0.02em;
}
.af-tag {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: rgba(244, 241, 236, 0.55);
}

/* Right — vertical link list, right-aligned on desktop */
.af-right {
	display: flex;
	flex-direction: column;
	gap: 10px;
	align-items: flex-end;
	font-family: var(--font-display);
}
@media (max-width: 880px) {
	.af-right { align-items: center; }
}
.af-right a,
.af-right button {
	font-family: inherit;
	font-size: 15px;
	font-weight: 500;
	color: rgba(244, 241, 236, 0.72);
	background: transparent;
	border: 0;
	padding: 4px 0;
	cursor: pointer;
	transition: color 0.15s;
	text-align: inherit;
}
.af-right a:hover,
.af-right button:hover {
	color: var(--accent);
}

/* Bottom strip — copyright + fine print */
.app-footer-bottom {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 16px;
	flex-wrap: wrap;
	padding-top: 22px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(244, 241, 236, 0.4);
}
@media (max-width: 720px) {
	.app-footer-bottom {
		justify-content: center;
		text-align: center;
	}
}

/* =========================================================
   NAV — single source of truth. Declared here so the nav is
   never part of the per-page <style> swap pool, which means
   zero flicker across page navigations.
   body-prefix specificity beats per-page `.nav` rules.
   ========================================================= */
body .nav {
	position: sticky;
	top: 0;
	z-index: 50;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 18px 32px;
	background: color-mix(in oklab, var(--paper) 80%, transparent);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	border-bottom: 1px solid color-mix(in oklab, var(--line) 60%, transparent);
}
body .nav-logo {
	display: flex;
	align-items: center;
	gap: 12px;
	font-family: var(--font-display);
	font-weight: 700;
	letter-spacing: -0.02em;
	font-size: 20px;
	line-height: 1;
}
body .nav-logo img {
	width: 40px;
	height: 40px;
	object-fit: contain;
	display: block;
}

/* =========================================================
   NAV GROUPS — left (sections w/ scroll-spy) | nozzle | right (pages)
   The nozzle acts as the visual divider between groups.
   ========================================================= */
.nav .nav-links {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0;
	padding-right: 0;
	font-size: 16px;
	font-family: var(--font-display);
	font-weight: 500;
}
.nav .nav-group {
	position: relative;
	display: flex;
	align-items: center;
	gap: 32px;
}

/* Unified link styling for both groups — outspecs page-inline `.nav-links > a`
   which no longer matches the new nested layout. */
.nav .nav-group > a {
	position: relative;
	padding: 8px 2px;
	color: var(--ink-2);
	transition: color 0.2s;
}
.nav .nav-group > a:hover { color: var(--ink); }
.nav .nav-group > a.is-active { color: var(--ink); }

/* Nozzle — now an inline flex item between the two groups.
   Motion is a transform translate from its natural (home) position. */
.nav .nav-nozzle {
	position: relative;
	top: auto;
	left: auto;
	width: 28px;
	height: 36px;
	margin: 0 14px;
	flex: 0 0 auto;
	align-self: center;
	transform: none;
	transition: transform 0.6s cubic-bezier(0.5, 0, 0.25, 1);
	pointer-events: none;
	z-index: 2;
}
.nav .nav-nozzle svg {
	width: 100%;
	height: 100%;
	display: block;
	overflow: visible;
}
.nav .nav-nozzle.is-printing { transition-duration: 0.5s; }
/* Always-hidden tip-glow. `!important` because per-page inline styles
   (scoped to [data-page="X"]) have an equal-specificity rule that would
   otherwise turn the glow back on during printing. */
.nav .nav-nozzle .tip-glow,
.nav .nav-nozzle.is-printing .tip-glow { opacity: 0 !important; }

/* Underline — absolutely positioned inside .nav-links; JS sets left/width
   in wrap-local coordinates so it can sit under either group. */
.nav .nav-underline {
	position: absolute;
	bottom: 2px;
	height: 3px;
	background: var(--accent);
	border-radius: 2px;
	left: 0;
	width: 0;
	pointer-events: none;
	box-shadow: 0 0 8px color-mix(in oklab, var(--accent) 50%, transparent);
}

/* Hide the nav divider span if any stale ones remain in the markup */
.nav-divider { display: none; }

@media (max-width: 720px) {
	.nav .nav-links { display: none; }
}

/* =========================================================
   CROSS-DOCUMENT VIEW TRANSITIONS
   Tells the browser to take a snapshot of the current page before
   navigation and crossfade to the new one — no JS framework needed,
   no flash. Chrome 126+, Safari 18+. Older browsers get a regular
   page load (still no flash; just not animated).
   ========================================================= */
@view-transition {
	navigation: auto;
}
/* Fast, subtle crossfade — 160ms feels instant without a hard cut */
::view-transition-old(root),
::view-transition-new(root) {
	animation-duration: 0.16s;
}
