/* ============================================================================
   In-game shop UI — matches the play "video game" design system, with a
   distinct visual identity per park store (data-shop-theme).
   Tokens: --gold/--text/--text-muted/--border from styles.css.
   Currency (gold pills, wallet) and the "Today's Pick" deal stay gold across all
   stores; everything else is themed by --shop-accent / --shop-card / --shop-bg.
   ============================================================================ */

.play-shop {
	/* default theme (fallback / unknown park) */
	--shop-accent: var(--gold);
	--shop-card: #1a1d28;
	--shop-bg: radial-gradient(
			120% 80% at 50% -10%,
			rgba(241, 196, 15, 0.08),
			transparent 60%
		),
		#15161c;
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	padding: 0.9rem;
	border-radius: 14px;
	background: var(--shop-bg);
}

/* ── Per-store themes ────────────────────────────────────────────────────── */
.play-shop[data-shop-theme="mk"] {
	--shop-accent: #e6b84d;
	--shop-card: #201a26;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(230, 184, 77, 0.12), transparent 60%),
		linear-gradient(180deg, #1b1622, #14111a);
}
.play-shop[data-shop-theme="epcot"] {
	--shop-accent: #5aa9e6;
	--shop-card: #161d28;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(90, 169, 230, 0.13), transparent 60%),
		linear-gradient(180deg, #121826, #0e1320);
}
.play-shop[data-shop-theme="hs"] {
	--shop-accent: #ef6a55;
	--shop-card: #241619;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(239, 106, 85, 0.13), transparent 60%),
		linear-gradient(180deg, #1f1316, #160f11);
}
.play-shop[data-shop-theme="ak"] {
	--shop-accent: #76b35e;
	--shop-card: #18211a;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(118, 179, 94, 0.13), transparent 60%),
		linear-gradient(180deg, #141d15, #0f160f);
}
.play-shop[data-shop-theme="usf"] {
	--shop-accent: #5b86d6;
	--shop-card: #161a26;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(91, 134, 214, 0.13), transparent 60%),
		linear-gradient(180deg, #121524, #0d101d);
}
.play-shop[data-shop-theme="ioa"] {
	--shop-accent: #d8923f;
	--shop-card: #241a10;
	--shop-bg: radial-gradient(120% 80% at 50% -10%, rgba(216, 146, 63, 0.14), transparent 60%),
		linear-gradient(180deg, #1d160d, #150f09);
}
.play-shop[data-shop-theme="epu"] {
	--shop-accent: #9b7ff0;
	--shop-card: #1c1730;
	--shop-bg: radial-gradient(100% 70% at 80% -10%, rgba(155, 127, 240, 0.18), transparent 55%),
		radial-gradient(1px 1px at 20% 30%, rgba(255, 255, 255, 0.5), transparent),
		radial-gradient(1px 1px at 60% 18%, rgba(255, 255, 255, 0.35), transparent),
		radial-gradient(1px 1px at 85% 40%, rgba(255, 255, 255, 0.4), transparent),
		radial-gradient(1px 1px at 38% 12%, rgba(255, 255, 255, 0.3), transparent),
		linear-gradient(180deg, #161130, #0e0a1d);
}

/* ── Shop / Inventory tabs ───────────────────────────────────────────────── */
.play-shop-tabs {
	display: flex;
	gap: 0.4rem;
}
.play-shop-tab {
	flex: 1 1 auto;
	padding: 0.5rem 0.6rem;
	border-radius: 10px;
	border: 1px solid var(--border);
	background: rgba(255, 255, 255, 0.03);
	color: var(--text-muted);
	font-weight: 700;
	font-size: 0.85rem;
	cursor: pointer;
	transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.play-shop-tab:hover {
	color: var(--text);
}
.play-shop-tab.is-active {
	color: var(--shop-accent, var(--gold));
	border-color: color-mix(
		in srgb,
		var(--shop-accent, var(--gold)) 55%,
		transparent
	);
	background: color-mix(in srgb, var(--shop-accent, var(--gold)) 12%, transparent);
}
.play-inv-qty {
	color: var(--gold);
	font-weight: 800;
	font-size: 0.85em;
}

/* ── Park switcher (modern segmented strip) ──────────────────────────────── */
.play-shop-parks {
	display: flex;
	gap: 0.4rem;
	overflow-x: auto;
	padding: 0.15rem 0.15rem 0.4rem;
	margin: -0.15rem;
	scrollbar-width: none;
	scroll-snap-type: x proximity;
}
.play-shop-parks::-webkit-scrollbar {
	display: none;
}
.play-shop-park-chip {
	flex: 0 0 auto;
	scroll-snap-align: start;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.4rem 0.75rem;
	border-radius: 999px;
	border: 1px solid var(--border);
	background: rgba(255, 255, 255, 0.04);
	color: var(--text-muted);
	font-size: 0.82rem;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
	transition: border-color 0.15s, color 0.15s, background 0.15s, transform 0.1s;
}
.play-shop-park-chip:hover {
	color: var(--text);
	border-color: color-mix(in srgb, var(--shop-accent) 45%, transparent);
}
.play-shop-park-chip:active {
	transform: scale(0.96);
}
.play-shop-park-chip .chip-emoji {
	font-size: 1rem;
	line-height: 1;
}
.play-shop-park-chip.is-active {
	color: var(--shop-accent);
	border-color: color-mix(in srgb, var(--shop-accent) 60%, transparent);
	background: color-mix(in srgb, var(--shop-accent) 14%, transparent);
	box-shadow: 0 0 14px color-mix(in srgb, var(--shop-accent) 22%, transparent);
}

/* ── Shopkeeper NPC ──────────────────────────────────────────────────────── */
.play-shop-npc {
	--npc-accent: var(--shop-accent);
	position: relative;
	display: flex;
	gap: 0.8rem;
	align-items: flex-start;
	padding: 0.9rem 1rem;
	border-radius: 12px;
	background: color-mix(in srgb, var(--npc-accent) 9%, rgba(0, 0, 0, 0.34));
	border: 1px solid color-mix(in srgb, var(--npc-accent) 30%, transparent);
}
.play-shop-npc-avatar {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 3.2rem;
	height: 3.2rem;
	border-radius: 12px;
	font-size: 1.8rem;
	line-height: 1;
	background: color-mix(in srgb, var(--npc-accent) 16%, transparent);
	border: 1px solid color-mix(in srgb, var(--npc-accent) 42%, transparent);
	box-shadow: 0 0 20px color-mix(in srgb, var(--npc-accent) 28%, transparent);
}
.play-shop-npc-identity {
	min-width: 0;
	flex: 1 1 auto;
}
.play-shop-npc-name {
	margin: 0;
	font-size: 1rem;
	font-weight: 800;
	line-height: 1.2;
	color: var(--npc-accent);
}
.play-shop-npc-name small {
	font-weight: 500;
	color: var(--text-muted);
}
.play-shop-npc-sub {
	margin: 0.12rem 0 0;
	font-size: 0.78rem;
	font-style: italic;
	color: var(--text-muted);
}
.play-shop-npc-quote {
	margin: 0.55rem 0 0;
	padding: 0.55rem 0.75rem;
	border-radius: 0 8px 8px 0;
	border-left: 3px solid var(--npc-accent);
	background: rgba(255, 255, 255, 0.04);
	color: var(--text);
	font-size: 0.92rem;
	line-height: 1.5;
}
/* The keeper's line crossfades in when they react to a purchase (routes/shop.js
   swaps the text + toggles .is-reacting), then restores the standing greeting. */
.play-shop-npc-quote.is-reacting {
	animation: play-shop-quote-react 0.3s ease-out;
}
@keyframes play-shop-quote-react {
	from {
		opacity: 0.25;
		transform: translateY(3px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}
@media (prefers-reduced-motion: reduce) {
	.play-shop-npc-quote.is-reacting {
		animation: none;
	}
}

/* ── Today's Pick (always gold — it's the "deal") ────────────────────────── */
.play-shop-featured {
	display: flex;
	gap: 0.5rem;
	align-items: baseline;
	flex-wrap: wrap;
	padding: 0.6rem 0.8rem;
	border-radius: 10px;
	/* Opaque dark base + gold wash so the deal banner POPS and stays readable over the
	   painted room backdrop (a transparent gradient blended into the scene). */
	background: linear-gradient(
		100deg,
		color-mix(in srgb, var(--gold) 26%, rgba(14, 11, 7, 0.92)),
		rgba(14, 11, 7, 0.88)
	);
	border: 1px solid color-mix(in srgb, var(--gold) 50%, transparent);
	box-shadow: 0 3px 16px rgba(0, 0, 0, 0.42);
}
.play-shop-featured-tag {
	font-size: 0.78rem;
	font-weight: 800;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--gold);
	white-space: nowrap;
}
.play-shop-featured-text {
	color: var(--text);
	font-size: 0.9rem;
}

/* ── Item grid (shop slots) ──────────────────────────────────────────────── */
.play-shop-grid {
	display: grid;
	gap: 0.6rem;
	grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.play-shop-cat {
	grid-column: 1 / -1;
	margin: 0.35rem 0 -0.1rem;
	font-size: 0.7rem;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--shop-accent) 70%, var(--text-muted));
}
.play-shop-item {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	padding: 0.8rem 0.85rem;
	border-radius: 12px;
	border: 1px solid var(--border);
	background: var(--shop-card);
	overflow: hidden;
	transition: border-color 0.18s ease, transform 0.12s ease,
		box-shadow 0.18s ease;
}
.play-shop-item:hover {
	transform: translateY(-2px);
	border-color: color-mix(in srgb, var(--shop-accent) 45%, transparent);
	box-shadow: 0 0 18px color-mix(in srgb, var(--shop-accent) 12%, transparent);
}
.play-shop-item.is-featured {
	border-color: color-mix(in srgb, var(--gold) 55%, transparent);
	box-shadow:
		0 0 0 1px color-mix(in srgb, var(--gold) 22%, transparent),
		0 0 22px color-mix(in srgb, var(--gold) 16%, transparent);
}
.play-shop-item.is-owned {
	opacity: 0.6;
}
/* "Not yet yours" — a calm, dimmed locked state, NOT an alarming retail red. The
   "🔒 N short" status label (is-short) carries the signal, so it isn't color-only. */
.play-shop-item.is-unaffordable {
	opacity: 0.9;
}
.play-shop-item.is-unaffordable .play-shop-item-cost {
	opacity: 0.6;
}
.play-shop-item.is-unaffordable .play-action-btn {
	opacity: 0.5;
}
.play-shop-item-status.is-short {
	color: var(--text-muted);
	font-weight: 700;
}
.play-shop-item-name {
	font-size: 0.95rem;
	font-weight: 700;
	line-height: 1.25;
	color: #fff;
}
.play-shop-item-cost {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	align-self: flex-start;
	padding: 0.2rem 0.55rem;
	border-radius: 999px;
	background: rgba(241, 196, 15, 0.1);
	border: 1px solid rgba(241, 196, 15, 0.3);
	color: var(--gold);
	font-weight: 800;
	font-size: 0.85rem;
	font-variant-numeric: tabular-nums;
}
.play-shop-item-cost.is-sale {
	gap: 0.35rem;
	border-color: color-mix(in srgb, var(--shop-accent, var(--gold)) 50%, transparent);
}
.play-shop-cost-was {
	color: var(--text-muted);
	font-weight: 600;
	font-size: 0.78em;
	text-decoration: line-through;
}
.play-shop-sale-pct {
	color: var(--shop-accent, var(--gold));
	font-weight: 800;
	font-size: 0.72em;
}
.play-shop-item-desc {
	flex: 1 1 auto;
	color: var(--text-muted);
	font-size: 0.82rem;
	line-height: 1.45;
}
.play-shop-item-foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	margin-top: 0.1rem;
}
.play-shop-item-status {
	font-size: 0.74rem;
	color: var(--text-muted);
}
.play-shop-item-status.is-owned {
	color: #2ecc71;
	font-weight: 700;
}
/* One-shot "stamp on" of the Owned badge right after a purchase: routes/shop.js
   adds .play-shop-stamp to the just-bought card's badge, then clears it. */
.play-shop-item-status.is-owned.play-shop-stamp {
	animation: play-shop-stamp 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.4);
	transform-origin: left center;
}
@keyframes play-shop-stamp {
	0% {
		transform: scale(1.8) rotate(-8deg);
		opacity: 0;
	}
	55% {
		transform: scale(0.92) rotate(2deg);
		opacity: 1;
	}
	100% {
		transform: scale(1) rotate(0);
		opacity: 1;
	}
}
@media (prefers-reduced-motion: reduce) {
	.play-shop-item-status.is-owned.play-shop-stamp {
		animation: none;
	}
}
.play-shop-item .play-action-btn {
	width: auto;
	min-width: 4.5rem; /* comfortable tap width (height handled in play-polish) */
	padding-inline: 1.05rem;
	margin-left: auto;
}
.play-shop-ribbon {
	position: absolute;
	top: 0.95rem;
	right: -1.85rem;
	width: 6.6rem;
	padding: 0.14rem 0;
	text-align: center;
	transform: rotate(45deg);
	background: var(--gold);
	color: #1a1206;
	font-size: 0.58rem;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}

/* ── Your Bag ────────────────────────────────────────────────────────────── */
.play-shop-bag-title {
	margin-bottom: 0.4rem;
	font-size: 0.7rem;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--shop-accent) 70%, var(--text-muted));
}
.play-shop-bag-row {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}
.play-shop-bag-chip {
	display: inline-flex;
	gap: 0.35rem;
	align-items: center;
	padding: 0.25rem 0.6rem;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid var(--border);
	font-size: 0.82rem;
	color: var(--text);
}
.play-shop-bag-chip b {
	color: var(--gold);
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
	.play-shop {
		padding: 0.7rem;
	}
	.play-shop-grid {
		grid-template-columns: 1fr;
	}
	.play-shop-npc-avatar {
		width: 2.8rem;
		height: 2.8rem;
		font-size: 1.5rem;
	}
	.play-shop-npc {
		padding: 0.75rem 0.8rem;
	}
}

/* ============================================================================
   WoW-style storefront layout — left park sidebar + topbar + content.
   Dark/gold play theme (not an ornate reskin) so it matches the rest of /play.
   ============================================================================ */
.play-shop--wow {
	padding: 0;
	gap: 0;
	/* Fill the hosting panel body so the topbar/sidebar can stay put while only
	   the item area scrolls. overflow:hidden zeroes the flex min-size, so without
	   the flex:1 + min-height:0 below it would shrink and CLIP the items. */
	flex: 1 1 auto;
	min-height: 0;
	overflow: hidden;
}
.play-shop--wow .play-shop-topbar {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	flex-wrap: wrap;
	flex: 0 0 auto;
	padding: 0.6rem 0.75rem;
	border-bottom: 1px solid var(--border);
	background: rgba(0, 0, 0, 0.22);
}
.play-shop--wow .play-shop-topbar .play-shop-tabs {
	flex: 0 0 auto;
}
.play-shop--wow .play-shop-topbar .play-shop-tab {
	flex: 0 0 auto;
}
.play-shop-topbar-right {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin-left: auto;
}
.play-shop--wow .play-shop-topbar-right .rpg-wallet {
	margin: 0;
}

.play-shop-body {
	display: grid;
	/* minmax(0, 1fr) (not 1fr) + min-width:0 keep the content column from blowing
	   out to its children's min-content width — without these the inner item grid
	   balloons far past the window and gets clipped on the right. */
	grid-template-columns: 11rem minmax(0, 1fr);
	/* Fill the shop card; the columns stretch to full height (default align), the
	   sidebar stays fixed and the content column scrolls on its own. */
	flex: 1 1 auto;
	min-width: 0;
	min-height: 0;
}
.play-shop-sidebar {
	padding: 0.55rem;
	border-right: 1px solid var(--border);
	background: rgba(0, 0, 0, 0.18);
	min-height: 0;
	overflow-y: auto;
}
.play-shop--wow .play-shop-sidebar .play-shop-parks {
	flex-direction: column;
	overflow: visible;
	gap: 0.3rem;
	margin: 0;
	padding: 0;
	scroll-snap-type: none;
}
.play-shop--wow .play-shop-sidebar .play-shop-park-chip {
	width: 100%;
	justify-content: flex-start;
	align-items: flex-start;
	border-radius: 8px;
	padding: 0.5rem 0.65rem;
	/* Let long park names ("Islands of Adventure") wrap instead of truncating. */
	white-space: normal;
	line-height: 1.25;
	text-align: left;
}
.play-shop--wow .play-shop-sidebar .play-shop-park-chip .chip-emoji {
	margin-top: 0.05rem;
}
.play-shop-content,
.play-shop-content--full {
	padding: 0.85rem;
	min-width: 0;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	-webkit-overflow-scrolling: touch;
}
.play-shop--wow .play-shop-grid {
	min-width: 0;
}
.play-shop--wow .play-shop-sidebar {
	min-width: 0;
}
.play-shop-content--full {
	flex: 1 1 auto;
}

@media (max-width: 720px) {
	/* Mobile uses ONE reliable scroll container — the panel body — instead of a
	   nested, grid-row-constrained inner scroll. That nested scroll computes fine
	   in desktop engines but mobile Safari often fails to make it scrollable, so
	   .play-shop--wow's overflow:hidden then clips the list with no way to scroll.
	   Here the whole shop flows at content height and the panel body scrolls it;
	   the topbar sticks so the gold balance and search stay put. */
	.play-shop--wow {
		flex: 0 0 auto;
		overflow: visible;
	}
	.play-shop--wow .play-shop-topbar {
		position: sticky;
		top: 0;
		z-index: 3;
		/* Opaque while it floats over scrolling items. */
		background: #14151b;
	}
	.play-shop-body {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: auto auto;
		min-height: 0;
	}
	.play-shop-content,
	.play-shop-content--full {
		overflow: visible;
		min-height: 0;
	}
	.play-shop-sidebar {
		border-right: none;
		border-bottom: 1px solid var(--border);
		padding: 0.5rem 0.55rem;
		overflow-y: visible;
	}
	.play-shop--wow .play-shop-sidebar .play-shop-parks {
		flex-direction: row;
		overflow-x: auto;
		scroll-snap-type: x proximity;
	}
	.play-shop--wow .play-shop-sidebar .play-shop-park-chip {
		width: auto;
		white-space: nowrap;
	}
	.play-shop-topbar-right {
		width: 100%;
		margin-left: 0;
	}
}

/* ============================================================================
   In a screen-shell ROOM (shop-storefront-conversion.md Phase 1): the Emporium is
   opened via TPQScreenShell.openRoom, NOT a hub-panel modal. The room stage
   (.tpq-room-stagebody) is itself the scroll container, so the shop must FLOW at
   content height — the desktop inner-scroll mode (overflow:hidden + flex:1) needs a
   fixed-height flex host the stage doesn't provide, and would clip without this.
   We also drop the shop's own gradient so the painted room backdrop shows through;
   the npc header + item cards keep their own backgrounds for local readability.
   (The legacy hub-panel modal CSS that lived here is gone — when tpq_room_off=1 the
   shop falls back to a normal full-screen hub panel, like every other panel.)
   ============================================================================ */
.tpq-room[data-room-tab="interior"] {
	--room-hue: rgba(40, 30, 16, 0.32); /* warm emporium tint over shop_interior.png */
}
/* ── Phase 3: fast-travel rail. The room's ribbon rail IS the resort switcher, so
   the in-body park sidebar is retired here. The painted backdrop is shared across
   parks (real per-park art can drop in later); the per-park scrim hue + the
   swapping clerk + the catalog give each storefront its own identity. ── */
.tpq-room[data-room="shop"] .tpq-room-backdrop {
	background: url("/assets/screen-art/screens/shop_interior.png") center / cover no-repeat;
}
.tpq-room[data-room="shop"] .play-shop-sidebar {
	display: none;
}
.tpq-room[data-room="shop"] .play-shop-body {
	grid-template-columns: minmax(0, 1fr);
}
.tpq-room[data-room="shop"][data-room-tab="mk"] { --room-hue: rgba(64, 48, 14, 0.34); }
.tpq-room[data-room="shop"][data-room-tab="epcot"] { --room-hue: rgba(20, 44, 74, 0.36); }
.tpq-room[data-room="shop"][data-room-tab="hs"] { --room-hue: rgba(70, 22, 18, 0.34); }
.tpq-room[data-room="shop"][data-room-tab="ak"] { --room-hue: rgba(24, 52, 26, 0.34); }
.tpq-room[data-room="shop"][data-room-tab="usf"] { --room-hue: rgba(22, 30, 70, 0.36); }
.tpq-room[data-room="shop"][data-room-tab="ioa"] { --room-hue: rgba(70, 44, 14, 0.34); }
.tpq-room[data-room="shop"][data-room-tab="epu"] { --room-hue: rgba(40, 22, 74, 0.38); }
.tpq-room .play-shop,
.tpq-room .play-shop--wow {
	flex: 0 0 auto;
	overflow: visible;
	background: transparent;
	padding: 0;
	/* The room stage fills the screen; keep the STOREFRONT a centered column so the
	   painted store frames it on wide monitors instead of cards sprawling edge-to-edge. */
	width: 100%;
	max-width: 1120px;
	margin-inline: auto;
}
.tpq-room .play-shop-body {
	min-height: 0;
}
.tpq-room .play-shop-content,
.tpq-room .play-shop-content--full,
.tpq-room .play-shop-sidebar {
	overflow: visible;
	min-height: 0;
}

/* ============================================================================
   Phase 2 — diorama dressing (shop-storefront-conversion.md). Added by JS as
   .play-shop--scene (kill switch: localStorage tpq_shop_scene_off=1 removes it).
   The keeper reads as a present character; goods sit in recessed shelf slots.
   ============================================================================ */
/* ── Shopkeeper presence: a larger bust + a rounded speech bubble ──────────── */
.play-shop--scene .play-shop-npc {
	align-items: center;
	gap: 1rem;
	padding: 1rem 1.1rem;
}
.play-shop--scene .play-shop-npc-avatar {
	width: 6rem;
	height: 6rem;
	border-radius: 14px;
}
.play-shop--scene .play-shop-npc-emoji {
	font-size: 2.6rem;
}
.play-shop--scene .play-shop-npc-name {
	font-size: 1.12rem;
}
.play-shop--scene .play-shop-npc-quote {
	border-left: 1px solid color-mix(in srgb, var(--npc-accent) 26%, transparent);
	border-radius: 12px;
	background: color-mix(in srgb, var(--npc-accent) 9%, rgba(6, 7, 12, 0.62));
}
@media (max-width: 480px) {
	.play-shop--scene .play-shop-npc-avatar {
		width: 4.6rem;
		height: 4.6rem;
	}
	.play-shop--scene .play-shop-npc-emoji {
		font-size: 2rem;
	}
}
/* Keeper nod on a purchase/reaction (routes/shop.js nodKeeper). The compound
   selector out-specifies idleMicro's breathing while it plays. */
.play-shop-npc-avatar.play-shop-nod {
	animation: play-shop-nod 0.5s ease;
}
@keyframes play-shop-nod {
	0% {
		transform: translateY(0) rotate(0);
	}
	30% {
		transform: translateY(4px) scale(0.97) rotate(-2deg);
	}
	65% {
		transform: translateY(-2px) scale(1.02) rotate(1deg);
	}
	100% {
		transform: none;
	}
}
@media (prefers-reduced-motion: reduce) {
	.play-shop-npc-avatar.play-shop-nod {
		animation: none;
	}
}

/* ── Goods sit IN recessed shelf slots, not flat on a gradient. The gold "shelf
   lip" goes on every card; the recessed inset shadow skips the featured card so its
   gold "Pick" ring survives. Grid-scoped (0,3,0) so it beats .is-featured/:hover. ── */
.play-shop--scene .play-shop-grid .play-shop-item {
	background:
		linear-gradient(180deg, rgba(255, 255, 255, 0.045), transparent 38%),
		var(--shop-card);
	border-bottom: 2px solid color-mix(in srgb, var(--shop-accent) 42%, transparent);
}
.play-shop--scene .play-shop-grid .play-shop-item:not(.is-featured) {
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.06),
		inset 0 -14px 20px -14px rgba(0, 0, 0, 0.65);
}

/* ── Your purse: gold visible while browsing; a −cost floats off it on a buy ── */
.play-shop-purse {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	width: fit-content;
	margin: 0 0 0.6rem auto; /* right-aligned at the top of the content */
	padding: 0.3rem 0.75rem;
	border-radius: 999px;
	background: rgba(241, 196, 15, 0.1);
	border: 1px solid rgba(241, 196, 15, 0.32);
	color: var(--gold);
	font-weight: 800;
	font-size: 0.92rem;
	font-variant-numeric: tabular-nums;
}
.play-shop-purse-coin {
	font-size: 0.95rem;
	line-height: 1;
}

/* ── Floating purchase toast ─────────────────────────────────────────────────
   Fixed, self-dismissing feedback for Buy actions. Sits above the mobile action
   bar and above the desktop store window (z-index 1300), so it's always visible. */
.play-shop-toast {
	position: fixed;
	left: 50%;
	bottom: calc(4.75rem + var(--play-safe-bottom, 0px));
	transform: translate(-50%, 0.75rem);
	z-index: 1400;
	max-width: min(92vw, 26rem);
	padding: 0.6rem 1.15rem;
	border-radius: 999px;
	font-weight: 800;
	font-size: 0.9rem;
	line-height: 1.3;
	text-align: center;
	box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.22s ease, transform 0.22s ease;
}
.play-shop-toast.is-show {
	opacity: 1;
	transform: translate(-50%, 0);
}
.play-shop-toast.is-ok {
	background: linear-gradient(180deg, #1c7a48, #155f38);
	color: #eafff3;
	border: 1px solid rgba(46, 204, 113, 0.6);
}
.play-shop-toast.is-err {
	background: linear-gradient(180deg, #8c2f26, #6f241d);
	color: #ffe9e6;
	border: 1px solid rgba(231, 76, 60, 0.6);
}
@media (prefers-reduced-motion: reduce) {
	.play-shop-toast {
		transition: opacity 0.22s ease;
		transform: translate(-50%, 0);
	}
}

/* V2 shopkeeper portrait (visual-identity.md §4.2) — fills the avatar tile; when the
   img 404s it removes itself (onerror) and the emoji underneath shows as before. */
.play-shop-npc-avatar {
	position: relative;
	overflow: hidden;
}
.play-shop-npc-art {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	image-rendering: auto; /* portrait bust downscaled from large art — smooth, not jagged (see crest note) */
	border-radius: inherit;
}
/* The portrait is matte-cut (transparent background), so the emoji fallback
   shows THROUGH it unless we hide it once the art loads (has-art). */
.play-shop-npc-emoji {
	display: inline-flex;
}
.play-shop-npc-avatar.has-art .play-shop-npc-emoji {
	display: none;
}
