/**
 * Tribal Order Trading Post — core marketplace surface
 * =============================================================================
 * ART DIRECTION — "The Vault Ledger", transaction chamber
 *
 * Extends the catalog's obsidian-and-gold codex into the logged-in marketplace.
 * Same Oswald/Barlow pairing, same relic-frame instinct — the Trading Post is a
 * back room of the same archive, where the deals are struck.
 *
 *   Signature  THE CUT CORNER. Every binding action (buy, accept, send, commit)
 *              is a solid gold button with one chamfered corner — a card frame
 *              with the corner clipped, the mark of a card leaving a collection.
 *              Navigation and secondary moves stay sharp-cornered hairline
 *              ghosts. Cut corner = commitment, hairline = movement; the shape
 *              system reads before the label does.
 *   Plates     Document panels (payment, condition notes, shipping) carry gold
 *              corner brackets — notarized paperwork in the ledger.
 *   Motion     One orchestrated entrance per page: the eyebrow rule draws, the
 *              title rises, tabs cascade, tiles stagger in. Hovers charge (lift
 *              + hairline brighten + soft bloom); presses land. transform and
 *              opacity only; full prefers-reduced-motion fallback.
 *   Texture    Film grain + a faint gold dawn at the top edge, so the black is
 *              never flat.
 *
 * WHY THE TOKENS ARE REDECLARED HERE
 * database.css only loads on pages carrying the catalog shortcode. The Trading
 * Post page does not carry it, so inheriting these custom properties would
 * leave every one undefined. Values are kept identical to database.css on
 * purpose; change them in both places or neither. ONE deliberate exception:
 * --tov-text-3xl is a clamp() here where the catalog holds a flat 3.25rem
 * (CHANGELOG 0.8.3) — the Post's masthead has to survive a 320px column and
 * the catalog's never gets one. Any OTHER divergence is drift, not a decision.
 *
 * THEME DEFENSE
 * The host theme styles bare <a>/<button> through descendant selectors (the
 * catalog's controls were turned pink once; the theme's .tovt-prose underlines
 * every anchor inside it). Every property a host theme is known to attack —
 * color, background, border, text-decoration, font — is asserted at .tov-mkt
 * scope with !important on the shared controls, mirroring database.css's
 * documented approach. Layout properties stay clean.
 * =============================================================================
 */

.tov-mkt {
	/* Native form controls (select menus, scrollbars, autofill tints) follow
	   the UA scheme, not our tokens — without this a gift-form select pops a
	   white system menu over obsidian. tov-tour.css already knew; the app the
	   tour mounts over did not. Inherits to every control inside the shell. */
	color-scheme: dark;

	/* Surfaces */
	--tov-bg: #0a0a0b;
	--tov-bg-2: #0d0d0f;
	--tov-surface: #151517;
	--tov-surface-2: #1b1b1f;
	--tov-surface-3: #232329;

	/* Gold */
	--tov-gold: #d4a24e;
	--tov-gold-bright: #ecc677;
	--tov-gold-deep: #8a6a2f;
	--tov-gold-ink: #14100c;
	--tov-line: rgba(212, 162, 78, 0.18);
	--tov-line-strong: rgba(212, 162, 78, 0.55);
	--tov-focus: #ecc677;

	/* Text */
	/* #f4f1ea, not #f2efe9 — the two-digit slip was drift, not a decision. It is
	   the catalog/theme/sheet value, and messaging's --tov-msg-other-edge is
	   rgba(244, 241, 234, .12), i.e. derived from this exact ink. */
	--tov-text: #f4f1ea;
	--tov-text-muted: #a19d95;
	--tov-text-dim: #857f75;

	/* Rarity */
	--tov-legendary: #d4a24e;
	--tov-epic: #a978d9;
	--tov-rare: #b145c4;
	/* Carried over from database.css so the set is whole. Nothing in the Post
	   paints it yet; a missing token is how a module ends up hardcoding one. */
	--tov-uncommon: #5fb37a;
	--tov-common: #ffffff;

	/* Status — marketplace-specific, added to the token set rather than
	   hardcoded per component so a status recolor is one edit. */
	--tov-success: #5fb37a;
	--tov-danger: #d9634e;
	/* The catalog spells this role --tov-warning (database.css, #e0a458). This
	   file's consumers are all on --tov-warn, so the name stays — but do not add
	   a THIRD spelling, and do not assume the two hexes match. They do not. */
	--tov-warn: #d8a657;
	--tov-status-active: var(--tov-success);
	/* Muted, not dim: badges sit on their own 10% tinted plate (see the
	   color-mix block), and dim measured ~4.1:1 there at 11px/600 — under the
	   4.5:1 small-text floor. Same correction marketplace-trades.css already
	   made for withdrawn/expired; the word on the badge is the differentiator,
	   not the depth of the grey. */
	--tov-status-paused: var(--tov-text-muted);
	--tov-status-completed: var(--tov-gold);
	--tov-status-cancelled: var(--tov-danger);
	/* Attention — the notification pips ("3 deals waiting on you"). Red, not
	   gold: on a surface whose resting state is already gold on dark, a gold
	   count reads as decoration, and these numbers exist to interrupt. NOT
	   --tov-danger, which is a light text tone for dark plates; this pair is a
	   solid plate + its ink. #fff6f0 on #cf2f21 measures ~4.8:1 (11px/700 is
	   small text, so the 4.5:1 floor applies); the plate itself clears 3:1
	   against both the page and the raised surfaces. */
	--tov-alert: #cf2f21;
	--tov-alert-ink: #fff6f0;

	/* Type — full scale, so no module has to patch a missing step locally. */
	--tov-font-display: "Oswald", "Bebas Neue", "Arial Narrow", sans-serif;
	--tov-font-body: "Barlow", "Segoe UI", system-ui, -apple-system, sans-serif;
	--tov-text-xs: 0.6875rem;
	--tov-text-sm: 0.8125rem;
	--tov-text-base: 0.9375rem;
	--tov-text-lg: 1.125rem;
	--tov-text-xl: 1.5rem;
	--tov-text-2xl: 2.25rem;
	/* The one intentional divergence from database.css — see the header. */
	--tov-text-3xl: clamp(2.4rem, 6vw, 3.6rem);

	/* Space + shape */
	--tov-space-1: 4px;
	--tov-space-2: 8px;
	--tov-space-3: 12px;
	--tov-space-4: 16px;
	--tov-space-5: 24px;
	--tov-space-6: 32px;
	--tov-space-8: 48px;
	--tov-r-sm: 2px;
	--tov-r-md: 5px;
	--tov-r-lg: 9px;
	--tov-r-pill: 999px;
	--tov-shadow-md: 0 10px 30px -14px rgba(0, 0, 0, 0.9);
	--tov-shadow-lg: 0 24px 60px -20px rgba(0, 0, 0, 0.95);
	--tov-charge: 0 0 0 1px var(--tov-line-strong),
		0 18px 40px -18px rgba(0, 0, 0, 0.9),
		0 0 26px -6px rgba(212, 162, 78, 0.4);

	/* The signature chamfer — one corner clipped off a committing control. */
	--tov-cut: 9px;

	/* Motion */
	--tov-dur-fast: 120ms;
	--tov-dur-base: 220ms;
	--tov-dur-slow: 420ms;
	--tov-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
	--tov-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

	position: relative;
	color: var(--tov-text);
	font-family: var(--tov-font-body);
	font-size: var(--tov-text-base);
	line-height: 1.55;
	max-width: 1280px;
	margin-inline: auto;
	padding: var(--tov-space-5) var(--tov-space-4) var(--tov-space-8);
}

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

/* Texture: gold dawn at the top edge + film grain, matching the catalog and the
 * theme chrome. Both layers are pointer-inert and cheap (no repaint on scroll). */
.tov-mkt::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background:
		radial-gradient(110% 60% at 50% -8%, rgba(212, 162, 78, 0.06), transparent 55%),
		radial-gradient(100% 100% at 50% 130%, rgba(0, 0, 0, 0.5), transparent 60%);
}

.tov-mkt::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	opacity: 0.35;
	mix-blend-mode: overlay;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

.tov-mkt > * {
	position: relative;
	z-index: 1;
}

/* ---------------------------------------------------------------- keyframes */

@keyframes tov-mkt-rise {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes tov-mkt-draw {
	from { transform: scaleX(0); }
	to { transform: scaleX(1); }
}

@keyframes tov-mkt-spin {
	to { transform: rotate(360deg); }
}

@keyframes tov-mkt-pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(236, 198, 119, 0.45); }
	50% { box-shadow: 0 0 0 6px rgba(236, 198, 119, 0); }
}

/* ---------------------------------------------------------------- masthead */

/* Mirrors .tov-db__head — one archive, one voice: gold dashed eyebrow,
   condensed display title with the gold accent word, meta hanging off the
   baseline on the right. The entrance is the page's one orchestrated sequence:
   rule draws, title rises, meta and tabs follow. */
.tov-mkt__masthead {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--tov-space-4);
	padding-bottom: var(--tov-space-4);
	border-bottom: 1px solid var(--tov-line);
}

.tov-mkt__eyebrow {
	display: flex;
	align-items: center;
	gap: var(--tov-space-2);
	margin: 0 0 var(--tov-space-1);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xs);
	font-weight: 500;
	letter-spacing: 0.32em;
	text-transform: uppercase;
	color: var(--tov-gold);
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) both;
}

.tov-mkt__eyebrow::before {
	content: "";
	width: 26px;
	height: 1px;
	background: linear-gradient(90deg, var(--tov-gold), transparent);
	transform-origin: left center;
	animation: tov-mkt-draw var(--tov-dur-slow) var(--tov-ease-out) both;
}

.tov-mkt__title {
	margin: 0;
	font-family: var(--tov-font-display);
	font-weight: 700;
	font-size: var(--tov-text-3xl);
	line-height: 0.95;
	letter-spacing: 0.01em;
	text-transform: uppercase;
	color: var(--tov-text);
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) 60ms both;
}

.tov-mkt__title em {
	font-style: normal;
	color: var(--tov-gold);
}

.tov-mkt__masthead-meta {
	display: flex;
	align-items: baseline;
	gap: var(--tov-space-3);
	padding-bottom: var(--tov-space-1);
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) 120ms both;
}

.tov-mkt__whoami {
	margin: 0;
	font-size: var(--tov-text-sm);
	color: var(--tov-text-dim);
}

/* Shown only until a member has picked their own handle. */
.tov-mkt__whoami-cta {
	margin: 2px 0 0;
	font-size: var(--tov-text-sm);
}

.tov-mkt__whoami-cta a {
	color: var(--tov-gold);
}

.tov-mkt__handle {
	color: var(--tov-text-muted);
	font-weight: 600;
	letter-spacing: 0.02em;
}

/* The sign-out form participates in the meta row as if it were its button. */
.tov-mkt__signout {
	display: contents;
}

/* --------------------------------------------------------------------- nav */

.tov-mkt__nav {
	display: flex;
	flex-wrap: wrap;
	gap: var(--tov-space-1);
	margin: var(--tov-space-4) 0 var(--tov-space-5);
	border-bottom: 1px solid var(--tov-line);
}

.tov-mkt__tab {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: var(--tov-space-2);
	padding: var(--tov-space-3) var(--tov-space-4);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none !important;
	color: var(--tov-text-dim);
	animation: tov-mkt-rise var(--tov-dur-base) var(--tov-ease-out) both;
	transition: color var(--tov-dur-fast) var(--tov-ease-out);
}

/* Tabs cascade in behind the title, 40ms apart. Capped at eight; anything
   later simply arrives with the eighth. */
.tov-mkt__tab:nth-child(1) { animation-delay: 140ms; }
.tov-mkt__tab:nth-child(2) { animation-delay: 180ms; }
.tov-mkt__tab:nth-child(3) { animation-delay: 220ms; }
.tov-mkt__tab:nth-child(4) { animation-delay: 260ms; }
.tov-mkt__tab:nth-child(5) { animation-delay: 300ms; }
.tov-mkt__tab:nth-child(6) { animation-delay: 340ms; }
.tov-mkt__tab:nth-child(7) { animation-delay: 380ms; }
.tov-mkt__tab:nth-child(n+8) { animation-delay: 420ms; }

/* The underline is its own element so it can draw in rather than pop. */
.tov-mkt__tab::after {
	content: "";
	position: absolute;
	left: var(--tov-space-4);
	right: var(--tov-space-4);
	bottom: -1px;
	height: 2px;
	background: var(--tov-gold);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--tov-dur-base) var(--tov-ease-out);
}

.tov-mkt__tab:hover,
.tov-mkt__tab:focus-visible {
	color: var(--tov-gold-bright);
}

.tov-mkt__tab:hover::after {
	transform: scaleX(0.55);
}

.tov-mkt__tab.is-current {
	color: var(--tov-gold);
}

.tov-mkt__tab.is-current::after {
	transform: scaleX(1);
}

/* Alert red, not gold (owner call, 2026-08-28): a count that means "waiting on
   you" has to stand out from across the page, and gold is this surface's
   resting color. The token pair carries the contrast math. */
.tov-mkt__pip {
	min-width: 1.4em;
	padding: 1px 6px;
	border-radius: var(--tov-r-pill);
	background: var(--tov-alert);
	color: var(--tov-alert-ink);
	font-family: var(--tov-font-body);
	font-size: var(--tov-text-xs); /* same 0.6875rem, said in the scale's words */
	font-weight: 700;
	letter-spacing: 0;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

/* The routed view rises as one block after the chrome settles. */
.tov-mkt__body {
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) 160ms both;
}

/* ------------------------------------------------------------------- grids */

.tov-mkt__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--tov-space-5);
}

/* Tiles stagger up as the grid arrives — same rhythm as the catalog. Capped at
   twelve so a 60-listing page is not a 3-second parade. */
.tov-mkt__grid > * {
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) both;
}

.tov-mkt__grid > *:nth-child(1) { animation-delay: 40ms; }
.tov-mkt__grid > *:nth-child(2) { animation-delay: 80ms; }
.tov-mkt__grid > *:nth-child(3) { animation-delay: 120ms; }
.tov-mkt__grid > *:nth-child(4) { animation-delay: 160ms; }
.tov-mkt__grid > *:nth-child(5) { animation-delay: 200ms; }
.tov-mkt__grid > *:nth-child(6) { animation-delay: 240ms; }
.tov-mkt__grid > *:nth-child(7) { animation-delay: 280ms; }
.tov-mkt__grid > *:nth-child(8) { animation-delay: 320ms; }
.tov-mkt__grid > *:nth-child(9) { animation-delay: 360ms; }
.tov-mkt__grid > *:nth-child(10) { animation-delay: 400ms; }
.tov-mkt__grid > *:nth-child(11) { animation-delay: 440ms; }
.tov-mkt__grid > *:nth-child(n+12) { animation-delay: 480ms; }

.tov-mkt__card {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-3);
}

.tov-mkt__card-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tov-space-2);
}

.tov-mkt__card-meta {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--tov-space-2);
	font-size: var(--tov-text-sm);
}

.tov-mkt__seller {
	color: var(--tov-text-dim);
}

.tov-mkt__price {
	font-family: var(--tov-font-display);
	font-weight: 600;
	color: var(--tov-gold);
	letter-spacing: 0.04em;
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- relic tiles */

.tov-mkt__tile {
	--tov-mkt-accent: var(--tov-gold);
	position: relative;
	background: linear-gradient(180deg, var(--tov-surface) 0%, var(--tov-bg-2) 100%);
	border: 1px solid var(--tov-line);
	border-top: 2px solid var(--tov-mkt-accent);
	border-radius: var(--tov-r-sm);
	padding: var(--tov-space-3);
	box-shadow: var(--tov-shadow-md);
	transition: border-color var(--tov-dur-base) var(--tov-ease-out),
		box-shadow var(--tov-dur-base) var(--tov-ease-out),
		transform var(--tov-dur-base) var(--tov-ease-out);
}

/* The hover charge: lift, hairline brightens, soft gold bloom — the same
   "relic waking up" the catalog tiles have. :focus-within gets the identical
   state, not a lesser one: every tile wraps a real link, so a keyboard user was
   tabbing through a plate that never acknowledged them while a mouse user got
   the whole performance. */
.tov-mkt__tile:hover,
.tov-mkt__tile:focus-within {
	border-color: var(--tov-line-strong);
	box-shadow: var(--tov-charge);
	transform: translateY(-3px);
}

/* The bloom in the tile's OWN rarity. --tov-mkt-accent is already set inline per
   tile (TOV_Listings::card_tile_html) and already paints the top edge, so a Rare
   tile can wake up violet and a Legendary one gold instead of every relic
   glowing the same house gold.
   Guarded rather than layered as a second declaration in the rule above: the
   value carries var(), so on a browser without color-mix() it would not fall
   back to --tov-charge — it would be invalid at computed-value time and compute
   to `none`, i.e. no bloom at all. @supports keeps the flat gold charge as the
   real fallback. Same reasoning as the badge plate further down. */
@supports (box-shadow: 0 0 1px color-mix(in srgb, red 55%, transparent)) {
	.tov-mkt__tile:hover,
	.tov-mkt__tile:focus-within {
		box-shadow: 0 0 0 1px var(--tov-line-strong),
			0 18px 40px -18px rgba(0, 0, 0, 0.9),
			0 0 26px -6px color-mix(in srgb, var(--tov-mkt-accent, var(--tov-gold)) 55%, transparent);
	}
}

/* The art box is wrapped so the pips can overlay it as a SIBLING of the link
   rather than a child — anything inside an anchor is absorbed into that link's
   accessible name, and this one is named after the card, not after its season.
   The wrapper doubles as the pips' query container. One tile renders at 206px in
   a deal column, 196px in the browse grid, 88px in a trade grid and 72px in a
   message header; the strip has to size itself against the TILE, and a viewport
   media query cannot tell those four apart. Emitted only by the catalogued
   branch of TOV_Listings::card_tile_html(), which is what keeps the scrim and
   the pips off the un-catalogued plate below without a :not() to maintain. */
.tov-mkt__tile-frame {
	position: relative;
	container-type: inline-size;
}

.tov-mkt__tile-art {
	/* Positioned for the scrim it now carries; the plate variant inherits this
	   harmlessly, having no ::after of its own. */
	position: relative;
	display: block;
	aspect-ratio: 3 / 4;
	overflow: hidden;
	background: var(--tov-bg);
	border: 1px solid var(--tov-line);
}

.tov-mkt__tile-art img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--tov-dur-slow) var(--tov-ease-out);
}

.tov-mkt__tile:hover .tov-mkt__tile-art img {
	transform: scale(1.03);
}

/* The un-catalogued plate. Deliberately reads as a deliberate state, not as a
   loading failure — the card is real, the catalog entry simply is not made. */
.tov-mkt__tile-art--plate {
	display: grid;
	place-items: center;
	padding: var(--tov-space-4);
	background:
		repeating-linear-gradient(
			135deg,
			transparent 0 6px,
			rgba(212, 162, 78, 0.05) 6px 12px
		),
		var(--tov-bg);
	color: var(--tov-text-dim);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	text-align: center;
}

/* ------------------------------------------------------------------ pips
 *
 * The catalog's tile vocabulary (`.tov-card__pips` / `.tov-pip` in
 * database.css), ported. Over there a card is a decorated relic; here the SAME
 * card was an anonymous thumbnail wearing a 2px coloured edge, so a Hero looked
 * exactly like a common at the one moment a buyer is deciding. Same marks, same
 * arrangement, two renames deep:
 *
 *   NOT `.tov-pip` — database.css can be enqueued on the same page as this file
 *   and that class is already spoken for over there.
 *   NOT `.tov-mkt__pip` either, which is the obvious translation and is ALREADY
 *   TAKEN, up in the nav block: it is the gold count badge on the hub's tabs,
 *   and inheriting min-width/text-align/tabular-nums off a numeral badge is not
 *   a bug anyone would find quickly. These join the `tile-` family instead,
 *   beside --art/--name/--meta/--frame, which is what they belong to anyway.
 */

/* Scrim, so a pip over white card art is still a pip. database.css states this
   gradient in percentages because a catalog tile is always 232px wide; these
   stops are LENGTHS because this tile is anywhere from 206px down to 72px, and
   44px of cover is two rows of pips at every one of those sizes where a
   percentage is two rows at one of them. No bottom band: the catalog's grounds
   art that bleeds to the panel edge, and this art box is already ruled off by a
   hairline border of its own. Same ink as the catalog's. */
.tov-mkt__tile-frame .tov-mkt__tile-art::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(
		180deg,
		rgba(0, 0, 0, 0.55) 0,
		rgba(0, 0, 0, 0.3) 44px,
		transparent 88px
	);
}

/* pointer-events is load-bearing here, not housekeeping: the strip lies across
   the top of the art and the whole art box is one link, so without it the top
   corner of every tile in the marketplace would quietly stop being clickable.
   flex-wrap is the safety valve — where three labels will not fit on one line
   the rarity pip drops to a second row and stays right-aligned, which is the
   same arrangement one line down rather than a squeeze. */
.tov-mkt__tile-pips {
	position: absolute;
	inset: var(--tov-space-2) var(--tov-space-2) auto;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--tov-space-2);
	pointer-events: none;
}

/* The catalog sets its pips at 10px over a 232px tile; the browse grid's art box
   here is 196px and every other surface is smaller, so the strip comes down one
   step to hold the same proportion rather than the same pixels. */
.tov-mkt__tile-pip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 3px 7px;
	font-family: var(--tov-font-display);
	font-weight: 600;
	font-size: 9px;
	line-height: 1;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--tov-text);
	/* The literal first: this plate is what makes a pip legible over bright art,
	   so it is the one value here that must never fail to a transparent box. The
	   color-mix restates it through the token and wins wherever it is supported.
	   The white hairline below keeps its literal — a highlight is not a rarity,
	   and --tov-common is the common-rarity token, not a name for white. */
	background: rgba(10, 10, 11, 0.72);
	background: color-mix(in srgb, var(--tov-bg) 72%, transparent);
	backdrop-filter: blur(4px);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: var(--tov-r-pill);
}

/* Season speaks gold, as it does in the catalog — the registry's own voice. */
.tov-mkt__tile-pip--season {
	color: var(--tov-gold-bright);
}

/* Rarity is pushed to the far edge; season and Hero stay left.
   --tov-mkt-accent is already set inline per tile and already paints the top
   border, so the dot and this hairline are the same rarity as the edge by
   construction — there is no second source of truth to drift. Where color-mix is
   missing the border-color falls to currentColor, i.e. the rarity at full
   strength: louder than intended, never wrong. */
.tov-mkt__tile-pip--rarity {
	margin-left: auto;
	color: var(--tov-mkt-accent, var(--tov-common));
	border-color: color-mix(in srgb, var(--tov-mkt-accent, var(--tov-common)) 45%, transparent);
}

.tov-mkt__tile-pip-dot {
	flex: 0 0 auto;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--tov-mkt-accent, var(--tov-common));
	box-shadow: 0 0 6px var(--tov-mkt-accent, transparent);
	transition: box-shadow var(--tov-dur-base) var(--tov-ease-out);
}

/* THE POINT OF THE WHOLE CHANGE. A Hero is the crown of the registry and the
   one thing a buyer pays a premium for, and the marketplace never said so
   anywhere — not on the grid, not in a deal, not in a trade. Filled gold plate,
   dark ink, crown: pixel-for-pixel the catalog's mark, so a collector who
   learned it there is not taught it twice. The ink is --tov-gold-ink rather than
   the catalog's --tov-bg because the Post has a token made for exactly this
   (dark type on a gold plate) and every button already wears it. */
.tov-mkt__tile-pip--hero {
	color: var(--tov-gold-ink);
	background: linear-gradient(135deg, var(--tov-gold-bright), var(--tov-gold));
	border-color: transparent;
	/* No @supports guard, unlike the tile bloom above: if color-mix is missing
	   this glow simply does not paint, and a solid gold plate with a crown on it
	   was never the ambiguous part. */
	box-shadow: 0 0 12px -2px color-mix(in srgb, var(--tov-gold) 60%, transparent);
}

.tov-mkt__tile-pip--hero .tov-crown {
	flex: 0 0 auto;
	width: 1.15em;
	height: 1.15em;
	margin: -1px 0;
}

/* The pips wake with the tile. Only the dot changes, and only its bloom — the
   same charge the frame gets, in the tile's own rarity. :focus-within is matched
   to :hover for the reason given at the tile rule: the art box is a real link
   and a keyboard user gets the whole performance too. */
.tov-mkt__tile:hover .tov-mkt__tile-pip-dot,
.tov-mkt__tile:focus-within .tov-mkt__tile-pip-dot {
	box-shadow: 0 0 11px 1px var(--tov-mkt-accent, transparent);
}

/* Below ~190px of art there is no room for three labels: the trade grids go down
   to 88px and the message header's thumbnail to 72px. The LABELS go, the MARKS
   stay — a season, a crown and a rarity dot still read Season 3 / Hero /
   Legendary at a glance, which was always the job. Clipped rather than
   display:none, so the Hero label is still announced; .tov-visually-hidden is a
   class and a container query cannot add one, so the pattern is inlined. */
@container (max-width: 190px) {
	.tov-mkt__tile-pips {
		inset: 5px 5px auto;
		gap: 4px;
	}

	.tov-mkt__tile-pip {
		gap: 0;
		padding: 3px 4px;
		letter-spacing: 0.06em;
	}

	.tov-mkt__tile-pip-label {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}
}

.tov-mkt__tile-name {
	margin: var(--tov-space-3) 0 0;
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-lg);
	font-weight: 600;
	line-height: 1.15;
	color: var(--tov-text);
}

.tov-mkt__tile-meta {
	margin: var(--tov-space-1) 0 0;
	font-size: var(--tov-text-sm);
	color: var(--tov-text-muted);
}

.tov-mkt__tile-since {
	margin: 2px 0 0;
	font-size: var(--tov-text-xs, 0.75rem);
	color: var(--tov-text-muted);
	letter-spacing: 0.02em;
}

.tov-mkt__tile--unlinked {
	opacity: 0.92;
}

/* ----------------------------------------------------------------- buttons */

/* THE COMPONENT EVERY MODULE BORROWS — and the one the host theme keeps
 * reaching for. Selectors are scoped `.tov-mkt .tov-mkt__btn` and the contested
 * properties carry !important so no `.tovt-prose a`, `.page-content button` or
 * page-builder kit rule can restyle a control mid-row. <a> and <button> render
 * to the pixel alike: identical box, identical line-height, identical states.
 *
 * Grammar:  (default)   solid gold, chamfered corner, glint on hover — the ONE
 *                       committing action of a view.
 *           --ghost     hairline box — secondary moves and navigation.
 *           --danger    hairline in the danger tone — destructive moves.
 *           --quiet     borderless text control — tertiary actions.
 *           --lg        the money CTA (Buy / Reserve) sizes up.
 *           .is-busy    in-flight: inert with a small working ring.
 */
.tov-mkt .tov-mkt__btn {
	position: relative;
	overflow: hidden;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--tov-space-2);
	padding: var(--tov-space-2) var(--tov-space-4);
	min-height: 44px;
	font-family: var(--tov-font-display) !important;
	font-size: var(--tov-text-sm) !important;
	font-weight: 600 !important;
	line-height: 1.25 !important;
	letter-spacing: 0.1em !important;
	text-transform: uppercase !important;
	text-decoration: none !important;
	text-align: center;
	cursor: pointer;
	color: var(--tov-gold-ink) !important;
	background: var(--tov-gold) !important;
	border: 1px solid var(--tov-gold) !important;
	border-radius: var(--tov-r-sm);
	margin: 0;
	/* The cut corner — the signature of a binding action. */
	clip-path: polygon(0 0, calc(100% - var(--tov-cut)) 0, 100% var(--tov-cut), 100% 100%, 0 100%);
	/* Engraved label. */
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.22);
	transition: background var(--tov-dur-fast) var(--tov-ease-out),
		color var(--tov-dur-fast) var(--tov-ease-out),
		border-color var(--tov-dur-fast) var(--tov-ease-out),
		transform var(--tov-dur-fast) var(--tov-ease-out),
		box-shadow var(--tov-dur-base) var(--tov-ease-out);
}

/* The glint: a light edge that sweeps the face of a solid button on hover.
   Painted on its own layer, transform-only, and removed for reduced motion. */
.tov-mkt .tov-mkt__btn::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(
		105deg,
		transparent 42%,
		rgba(255, 255, 255, 0.34) 50%,
		transparent 58%
	);
	transform: translateX(-130%);
}

.tov-mkt .tov-mkt__btn:hover::after,
.tov-mkt .tov-mkt__btn:focus-visible::after {
	transform: translateX(130%);
	transition: transform 620ms var(--tov-ease-out);
}

.tov-mkt .tov-mkt__btn:hover,
.tov-mkt .tov-mkt__btn:focus-visible {
	background: var(--tov-gold-bright) !important;
	border-color: var(--tov-gold-bright) !important;
	color: var(--tov-gold-ink) !important;
	box-shadow: 0 0 22px -6px rgba(212, 162, 78, 0.55);
}

/* Presses land: the button seats itself, the bloom tightens. */
.tov-mkt .tov-mkt__btn:active {
	transform: translateY(1px);
	box-shadow: 0 0 10px -6px rgba(212, 162, 78, 0.55);
}

/* Links can be visited; a committed action must not change clothes over it. */
.tov-mkt a.tov-mkt__btn:visited {
	color: var(--tov-gold-ink) !important;
}

/* The money CTA — larger plate, larger cut, the loudest thing on its page. */
.tov-mkt .tov-mkt__btn--lg {
	--tov-cut: 12px;
	min-height: 52px;
	padding: var(--tov-space-3) var(--tov-space-5);
	font-size: var(--tov-text-base) !important;
	letter-spacing: 0.12em !important;
}

/* Ghost — hairline box, sharp corners, no glint. Movement, not commitment. */
.tov-mkt .tov-mkt__btn--ghost {
	background: transparent !important;
	color: var(--tov-gold) !important;
	border-color: var(--tov-line-strong) !important;
	clip-path: none;
	text-shadow: none;
}

.tov-mkt .tov-mkt__btn--ghost::after {
	content: none;
}

.tov-mkt .tov-mkt__btn--ghost:hover,
.tov-mkt .tov-mkt__btn--ghost:focus-visible {
	background: rgba(212, 162, 78, 0.08) !important;
	color: var(--tov-gold-bright) !important;
	border-color: var(--tov-gold) !important;
	box-shadow: none;
}

.tov-mkt a.tov-mkt__btn--ghost:visited {
	color: var(--tov-gold) !important;
}

/* Danger — the ghost's grammar in the warning tone. Destruction is secondary
   by design; nothing destructive gets a solid plate. */
.tov-mkt .tov-mkt__btn--danger {
	background: transparent !important;
	color: var(--tov-danger) !important;
	border-color: rgba(217, 99, 78, 0.5) !important;
	clip-path: none;
	text-shadow: none;
}

.tov-mkt .tov-mkt__btn--danger::after {
	content: none;
}

.tov-mkt .tov-mkt__btn--danger:hover,
.tov-mkt .tov-mkt__btn--danger:focus-visible {
	background: rgba(217, 99, 78, 0.12) !important;
	color: var(--tov-danger) !important;
	border-color: var(--tov-danger) !important;
	box-shadow: none;
}

.tov-mkt a.tov-mkt__btn--danger:visited {
	color: var(--tov-danger) !important;
}

/* Quiet — a text control that still meets the 44px target. */
.tov-mkt .tov-mkt__btn--quiet {
	background: transparent !important;
	color: var(--tov-text-muted) !important;
	border-color: transparent !important;
	clip-path: none;
	text-shadow: none;
}

.tov-mkt .tov-mkt__btn--quiet::after {
	content: none;
}

.tov-mkt .tov-mkt__btn--quiet:hover,
.tov-mkt .tov-mkt__btn--quiet:focus-visible {
	background: transparent !important;
	color: var(--tov-gold-bright) !important;
	border-color: transparent !important;
	box-shadow: none;
}

/* THE FOCUS RING, drawn INSIDE the clip. clip-path clips everything the
   element paints — outline and outer box-shadow included — so the global
   2px-offset ring and the gold bloom never rendered on the solid plate: the
   only surviving cue was gold-to-brighter-gold at 1.42:1, a WCAG 2.4.7 miss
   on the primary CTA of every screen. A dark ring in the engraved ink
   (11.6:1 on gold-bright) rides inside the polygon, and its trimmed
   top-right corner echoes the chamfer instead of fighting it. */
.tov-mkt .tov-mkt__btn:focus-visible {
	outline: 2px solid var(--tov-gold-ink);
	outline-offset: -5px;
}

/* The un-clipped variants keep the house outer ring. */
.tov-mkt .tov-mkt__btn--ghost:focus-visible,
.tov-mkt .tov-mkt__btn--danger:focus-visible,
.tov-mkt .tov-mkt__btn--quiet:focus-visible {
	outline: 2px solid var(--tov-focus);
	outline-offset: 2px;
}

.tov-mkt .tov-mkt__btn[disabled],
.tov-mkt .tov-mkt__btn[aria-disabled="true"] {
	opacity: 0.45;
	cursor: not-allowed;
	transform: none;
	box-shadow: none;
}

.tov-mkt .tov-mkt__btn[disabled]::after,
.tov-mkt .tov-mkt__btn[aria-disabled="true"]::after {
	content: none;
}

/* In-flight: inert, with a small working ring where the gap is. Add .is-busy
   from any submit handler; the control keeps its width so the row holds. */
.tov-mkt .tov-mkt__btn.is-busy {
	pointer-events: none;
	opacity: 0.75;
}

.tov-mkt .tov-mkt__btn.is-busy::before {
	content: "";
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
	border: 2px solid rgba(20, 16, 12, 0.3);
	border-top-color: currentColor;
	border-radius: 50%;
	animation: tov-mkt-spin 700ms linear infinite;
}

.tov-mkt :focus-visible {
	outline: 2px solid var(--tov-focus);
	outline-offset: 2px;
}

/* Forms that exist only to carry a nonce and a button dissolve into their
 * parent: the button itself becomes the flex item, so a row of mixed <a> and
 * <form><button> children aligns to the pixel. */
.tov-mkt__inline-form {
	display: contents;
}

/* ------------------------------------------------------------------ pager */

/* Newer / older, quiet ghosts around a small state line. Only renders when a
   second page exists, so the common single-page case is untouched. */
.tov-mkt__pager {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--tov-space-3);
	margin-top: var(--tov-space-5);
}

.tov-mkt__pager-state {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

/* ------------------------------------------------------------------ badges */

.tov-mkt__badge {
	display: inline-flex;
	align-items: center;
	padding: 2px var(--tov-space-2);
	border: 1px solid currentColor;
	border-radius: var(--tov-r-pill);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xs); /* same 0.6875rem, said in the scale's words */
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

/* Where color-mix is available the badge sits on a tinted plate of its own
   tone; where it is not, the hairline pill above already reads. */
@supports (background: color-mix(in srgb, red 10%, transparent)) {
	.tov-mkt__badge {
		background: color-mix(in srgb, currentColor 10%, transparent);
		border-color: color-mix(in srgb, currentColor 45%, transparent);
	}
}

.tov-mkt__badge--active { color: var(--tov-status-active); }
.tov-mkt__badge--paused { color: var(--tov-status-paused); }
.tov-mkt__badge--completed { color: var(--tov-status-completed); }
.tov-mkt__badge--cancelled { color: var(--tov-status-cancelled); }
.tov-mkt__badge--listed { color: var(--tov-gold); }
.tov-mkt__badge--muted { color: var(--tov-text-muted); }

/* ----------------------------------------------------------------- notices */

.tov-mkt__notice {
	padding: var(--tov-space-3) var(--tov-space-4);
	margin-bottom: var(--tov-space-4);
	border-left: 3px solid var(--tov-gold);
	background: var(--tov-surface);
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
	animation: tov-mkt-rise var(--tov-dur-base) var(--tov-ease-out) both;
}

.tov-mkt__notice--ok { border-left-color: var(--tov-success); }
.tov-mkt__notice--warn { border-left-color: var(--tov-warn); }
.tov-mkt__notice--error { border-left-color: var(--tov-danger); }

.tov-mkt__empty {
	padding: var(--tov-space-8) var(--tov-space-4);
	text-align: center;
	border: 1px dashed var(--tov-line);
	border-radius: var(--tov-r-md);
	background:
		radial-gradient(80% 90% at 50% 0%, rgba(212, 162, 78, 0.04), transparent 60%),
		var(--tov-bg-2);
}

.tov-mkt__empty-head {
	margin: 0 0 var(--tov-space-2);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-lg);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

.tov-mkt__empty-body {
	margin: 0 0 var(--tov-space-4);
	color: var(--tov-text-dim);
	font-size: var(--tov-text-sm);
}

.tov-mkt__hint {
	font-size: var(--tov-text-sm);
	color: var(--tov-text-dim);
	margin: var(--tov-space-2) 0 0;
}

/* ------------------------------------------------------------------- forms */

.tov-mkt__form-layout {
	display: grid;
	grid-template-columns: minmax(200px, 280px) 1fr;
	gap: var(--tov-space-6);
	align-items: start;
}

.tov-mkt__form {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-4);
	/* .tov-mkt is 1280px wide, and an uncapped form inherited every pixel of it:
	   the Payment & Shipping screen rendered a "Venmo handle" input ~1240px long.
	   34rem is the measure the document plates already use. */
	max-width: 34rem;
}

/* Two plates side by side once there is room for both at that measure. Scoped by
   :has() to forms that actually hold two — the create-listing form has a single
   fieldset and must stay a stack, or it would sit next to a dead column. Same
   progressive-enhancement bargain .tov-pick makes in the trades sheet: a browser
   without :has() keeps the capped single column, which is correct, only taller.
   Collapsed again at 860px with the rest of the two-column layouts. */
.tov-mkt__form:has(.tov-mkt__fieldset ~ .tov-mkt__fieldset) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: start;
	/* Two 34rem columns and the gap between them — each plate keeps the measure
	   it would have had alone. */
	max-width: calc(34rem * 2 + var(--tov-space-4));
}

/* Everything that is not a plate — the Save button, a trailing hint — spans. */
.tov-mkt__form:has(.tov-mkt__fieldset ~ .tov-mkt__fieldset) > :not(.tov-mkt__fieldset) {
	grid-column: 1 / -1;
}

/* A fieldset here holds a postal address or a payment handle, which is exactly
   the notarized-paperwork the document plates elsewhere are for — this was the
   only sensitive surface in the Post without the treatment. Same four corner
   gradients as .tov-listing__note below. The radius drops to --tov-r-sm with it:
   a square bracket pinned to a 5px-rounded corner reads as a printing error. The
   legend clears the 14px bracket arm on its own — browsers indent it past the
   fieldset's padding-inline, which is 16px here. */
.tov-mkt__fieldset {
	background:
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 14px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 1px 14px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 14px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 1px 14px,
		var(--tov-surface);
	background-repeat: no-repeat;
	border: 1px solid var(--tov-line);
	border-radius: var(--tov-r-sm);
	padding: var(--tov-space-4);
	margin: 0;
}

.tov-mkt__fieldset legend {
	padding: 0 var(--tov-space-2);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-gold);
}

.tov-mkt__radio {
	display: flex;
	align-items: center;
	gap: var(--tov-space-3);
	padding: var(--tov-space-2) 0;
	cursor: pointer;
	min-height: 44px;
}

.tov-mkt__field {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-2);
}

.tov-mkt__field label {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

/* Inputs are asserted against host-theme descendant selectors the same way the
 * catalog's are — the whole control set, one focus story. */
.tov-mkt input[type="text"],
.tov-mkt input[type="email"],
.tov-mkt input[type="number"],
.tov-mkt input[type="file"],
.tov-mkt select,
.tov-mkt textarea {
	width: 100%;
	padding: var(--tov-space-3);
	background: var(--tov-bg) !important;
	color: var(--tov-text) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-sm);
	font-family: var(--tov-font-body) !important;
	font-size: var(--tov-text-base);
	text-transform: none;
	letter-spacing: normal;
	transition: border-color var(--tov-dur-fast) var(--tov-ease-out),
		box-shadow var(--tov-dur-fast) var(--tov-ease-out);
}

.tov-mkt input[type="text"]:focus,
.tov-mkt input[type="email"]:focus,
.tov-mkt input[type="number"]:focus,
.tov-mkt select:focus,
.tov-mkt textarea:focus {
	outline: none;
	border-color: var(--tov-gold) !important;
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

/* THE INVALID STATE — the exact inverse of the gold focus ring above: same 3px
 * halo, same geometry, the danger tone. There was no field-level error state
 * anywhere in the Post; server-side validation printed one page-level notice and
 * left every input looking fine, so a member with five inputs on the Payment &
 * Shipping screen had to guess which one the notice meant.
 *
 * aria-invalid is the hook rather than a class because it is the attribute the
 * PHP has to emit for assistive tech regardless — one source of truth, and the
 * styling cannot drift out of sync with what a screen reader announces.
 *
 * STATUS (v0.16.0): deliberately FORWARD-BUILT — no PHP emits aria-invalid or
 * .tov-mkt__field-error yet; server validation still reports one page-level
 * notice per the flash pattern. Wiring per-field errors means re-rendering
 * forms with field state across the redirect, a design change, not a patch.
 * This block is the landing zone for that pass, not evidence it happened.
 *
 * WHY THE SELECTOR LIST IS SPELLED OUT. The control rules above assert
 * `border: ... !important` from `.tov-mkt input[type="text"]` and friends, which
 * outweighs a bare `.tov-mkt [aria-invalid="true"]` — the error ring would have
 * lost to the very rules it has to override, silently. So each control type is
 * named, the way the focus rules above name them. :not([disabled]) is not a
 * specificity trick for its own sake: a control the member cannot edit has no
 * business flagging itself, and it buys the margin to also outrank the trade
 * composer's own !important control block in marketplace-trades.css.
 * The leading generic selector catches anything not in the enumerated set — a
 * radio group, a fieldset — where nothing is competing. */
.tov-mkt [aria-invalid="true"],
.tov-mkt input[type="text"][aria-invalid="true"]:not([disabled]),
.tov-mkt input[type="email"][aria-invalid="true"]:not([disabled]),
.tov-mkt input[type="number"][aria-invalid="true"]:not([disabled]),
.tov-mkt input[type="file"][aria-invalid="true"]:not([disabled]),
.tov-mkt select[aria-invalid="true"]:not([disabled]),
.tov-mkt textarea[aria-invalid="true"]:not([disabled]) {
	border-color: var(--tov-danger) !important;
	box-shadow: 0 0 0 3px rgba(217, 99, 78, 0.18);
}

/* Focusing a bad field must not clear the mark — the error outranks the focus
   tone, because it is the thing still needing a fix. The ring only tightens. */
.tov-mkt [aria-invalid="true"]:focus,
.tov-mkt [aria-invalid="true"]:focus-visible,
.tov-mkt input[type="text"][aria-invalid="true"]:not([disabled]):focus,
.tov-mkt input[type="email"][aria-invalid="true"]:not([disabled]):focus,
.tov-mkt input[type="number"][aria-invalid="true"]:not([disabled]):focus,
.tov-mkt input[type="file"][aria-invalid="true"]:not([disabled]):focus-visible,
.tov-mkt select[aria-invalid="true"]:not([disabled]):focus,
.tov-mkt textarea[aria-invalid="true"]:not([disabled]):focus {
	border-color: var(--tov-danger) !important;
	box-shadow: 0 0 0 3px rgba(217, 99, 78, 0.32);
}

/* The sentence the page-level notice used to carry alone, said at the field it
   is about. Sits inside .tov-mkt__field, which is already a column stack, so it
   lands under the label and its input with the stack's own gap. --tov-danger is
   5.5:1 on --tov-bg and 5.1:1 on --tov-surface: AA at this size on either. */
.tov-mkt__field-error {
	margin: 0;
	font-size: var(--tov-text-sm);
	line-height: 1.4;
	color: var(--tov-danger);
}

.tov-mkt textarea {
	resize: vertical;
	min-height: 90px;
}

/* The field box above themes input[type=file] like any other control, but
 * background/border/color on the input itself cannot reach the browser's
 * OWN "Choose File" button chrome — that is a replaced-content widget, not
 * text the input paints. Left alone it stays a native grey/white pill no
 * matter what the input around it looks like. ::file-selector-button (the
 * standard hook, plus the WebKit alias older Safari needs) is the only way
 * to actually reach it. Styled as a ghost control on purpose: choosing a
 * file is not a commitment, so it stays hairline/sharp-cornered — the
 * Upload button next to it is what carries the one cut corner. */
.tov-mkt input[type="file"]::file-selector-button,
.tov-mkt input[type="file"]::-webkit-file-upload-button {
	margin: 0 var(--tov-space-3) 0 0;
	padding: var(--tov-space-2) var(--tov-space-3);
	min-height: 36px;
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xs);
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--tov-gold) !important;
	background: transparent !important;
	border: 1px solid var(--tov-line-strong) !important;
	border-radius: var(--tov-r-sm);
	cursor: pointer;
	transition: background var(--tov-dur-fast) var(--tov-ease-out),
		color var(--tov-dur-fast) var(--tov-ease-out),
		border-color var(--tov-dur-fast) var(--tov-ease-out);
}

.tov-mkt input[type="file"]:hover::file-selector-button,
.tov-mkt input[type="file"]:hover::-webkit-file-upload-button {
	background: rgba(212, 162, 78, 0.08) !important;
	color: var(--tov-gold-bright) !important;
	border-color: var(--tov-gold) !important;
}

.tov-mkt input[type="file"]:focus-visible {
	outline: none;
	border-color: var(--tov-gold) !important;
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

/* --------------------------------------------------------- single listing */

.tov-listing {
	display: grid;
	grid-template-columns: minmax(240px, 380px) 1fr;
	gap: var(--tov-space-6);
	align-items: start;
}

/* The two columns arrive as one composed entrance: art first, dossier after. */
.tov-listing__art {
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) both;
}

.tov-listing__detail {
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) 100ms both;
}

.tov-listing__status {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tov-space-3);
	margin: 0 0 var(--tov-space-3);
}

.tov-listing__type {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-text-dim);
}

.tov-listing__owner {
	margin: 0 0 var(--tov-space-4);
	color: var(--tov-text-muted);
}

/* The asking price is the page's fact of record: display-large, tabular,
   with a faint bloom — and underlined by its own gold hairline. */
.tov-listing__price {
	position: relative;
	margin: 0 0 var(--tov-space-5);
	padding-bottom: var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-2xl);
	font-weight: 600;
	color: var(--tov-gold);
	letter-spacing: 0.02em;
	font-variant-numeric: tabular-nums;
	text-shadow: 0 0 24px rgba(212, 162, 78, 0.35);
}

.tov-listing__price::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 64px;
	height: 1px;
	background: linear-gradient(90deg, var(--tov-gold), transparent);
}

/* Compact circulation spectrum — the catalog's branded data-viz, on the
   listing, so the number that justifies the price is not on another page. */
.tov-mkt-circ {
	margin: 0 0 var(--tov-space-5);
	padding: var(--tov-space-3) var(--tov-space-4);
	background: var(--tov-bg-2);
	border: 1px solid var(--tov-line);
	border-radius: var(--tov-r-md);
}

.tov-mkt-circ__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--tov-space-3);
	margin-bottom: var(--tov-space-2);
}

.tov-mkt-circ__label {
	font-family: var(--tov-font-display);
	font-weight: 600;
	font-size: var(--tov-text-sm);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

.tov-mkt-circ__pop {
	font-family: var(--tov-font-display);
	font-weight: 700;
	font-size: var(--tov-text-xl);
	line-height: 1;
	color: var(--tov-gold);
	font-variant-numeric: tabular-nums;
}

.tov-mkt-circ__headline {
	margin: 0 0 var(--tov-space-3);
	font-size: var(--tov-text-sm);
	line-height: 1.4;
	color: var(--tov-text-muted);
}

.tov-mkt-circ__headline b {
	color: var(--tov-gold);
	font-weight: 700;
}

.tov-mkt-circ__track {
	position: relative;
	height: 8px;
	border-radius: var(--tov-r-pill);
	background:
		linear-gradient(90deg,
			color-mix(in srgb, var(--tov-gold) 45%, transparent),
			var(--tov-surface-3) 60%);
	border: 1px solid var(--tov-line);
}

.tov-mkt-circ__fill {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	width: var(--tov-circ-pct, 50%);
	border-radius: var(--tov-r-pill) 0 0 var(--tov-r-pill);
	background: linear-gradient(90deg, color-mix(in srgb, var(--tov-gold) 70%, transparent), var(--tov-gold));
}

.tov-mkt-circ__marker {
	position: absolute;
	top: 50%;
	width: 15px;
	height: 15px;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: var(--tov-text);
	border: 3px solid var(--tov-gold);
	box-shadow: 0 0 0 3px var(--tov-bg-2), 0 0 14px -1px color-mix(in srgb, var(--tov-gold) 55%, transparent);
}

.tov-listing__note h2,
.tov-listing__handles h2,
.tov-photos__title {
	margin: 0 0 var(--tov-space-2);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--tov-gold);
}

/* Document plates — the notarized-paperwork panels. Gold corner brackets top-
   left and bottom-right, painted as two background gradients pinned to the
   corners; no extra markup, no layout cost. Also the photo slots below —
   a copy's front/back photos are exactly this kind of notarized evidence. */
.tov-listing__note,
.tov-listing__handles,
.tov-photos__slot {
	position: relative;
	padding: var(--tov-space-4);
	margin-bottom: var(--tov-space-4);
	background:
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 14px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 1px 14px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 14px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 1px 14px,
		var(--tov-surface);
	background-repeat: no-repeat;
	border: 1px solid var(--tov-line);
	border-radius: var(--tov-r-sm);
}

/* Payment handles are shown as inert, selectable text. They are never
   linkified: this is the exact spot where a member is about to send money to a
   stranger, and a clickable destination is the cheapest phishing vector there
   is. Monospace so an ambiguous character can be read accurately. */
.tov-listing__handles-text {
	margin: 0;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: var(--tov-text-sm);
	color: var(--tov-text);
	white-space: pre-wrap;
	word-break: break-word;
	user-select: all;
}

/* The sealed state of the payment panel: the handles exist, but this viewer
   has not committed. Reads as a deliberate seal, not missing data. */
.tov-listing__handles-sealed {
	margin: 0;
	padding: var(--tov-space-2) var(--tov-space-3);
	border: 1px dashed var(--tov-line-strong);
	border-radius: var(--tov-r-sm);
	background: repeating-linear-gradient(
			135deg,
			transparent 0 6px,
			rgba(212, 162, 78, 0.04) 6px 12px
		),
		var(--tov-bg-2);
	font-size: var(--tov-text-sm);
	color: var(--tov-text-muted);
}

/* The decision row. Mixed <a> and <form><button> children all center to one
   rail; the money CTA is the tallest thing standing and the rest hold rank. */
.tov-listing__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tov-space-3);
	margin-top: var(--tov-space-5);
	padding-top: var(--tov-space-4);
	border-top: 1px solid var(--tov-line);
}

/* The way back sits under the decision row, quiet, with the ledger arrow. */
.tov-mkt__backline {
	margin: var(--tov-space-4) 0 0;
	font-size: var(--tov-text-sm);
}

.tov-mkt__backline a {
	display: inline-flex;
	align-items: center;
	gap: var(--tov-space-2);
	min-height: 44px;
	color: var(--tov-text-muted) !important;
	text-decoration: none !important;
	transition: color var(--tov-dur-fast) var(--tov-ease-out);
}

.tov-mkt__backline a::before {
	content: "\2190";
	color: var(--tov-gold);
	transition: transform var(--tov-dur-fast) var(--tov-ease-out);
}

.tov-mkt__backline a:hover,
.tov-mkt__backline a:focus-visible {
	color: var(--tov-text) !important;
}

.tov-mkt__backline a:hover::before {
	transform: translateX(-3px);
}

/* ------------------------------------------------------------------ photos */

.tov-photos {
	margin-top: var(--tov-space-5);
}

/* Stacked, not side-by-side. This panel lives in .tov-listing__art, capped at
   240–380px so the art column stays thumbnail-scale next to the wide detail
   column — a 2-up grid in that width left each slot ~150–180px, too narrow
   for the native file control (or an uploaded photo) to read well at any
   viewport. Full plate width for both is worth the extra vertical scroll. */
.tov-photos__slots {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--tov-space-4);
	margin-top: var(--tov-space-4);
}

/* Layout only — background/border/padding/corner-brackets come from the
   shared document-plate rule above so this matches the condition-notes
   plate exactly. margin-bottom is reset because these sit in a grid row,
   not a stack; .tov-photos__slots' own gap/margin-top do that job. */
.tov-photos__slot {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-3);
	margin-bottom: 0;
}

.tov-photos__slot form {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-3);
}

.tov-photos__slot-label {
	margin: 0 0 var(--tov-space-2);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

.tov-photos__image img {
	width: 100%;
	height: auto;
	display: block;
	border: 1px solid var(--tov-line);
	border-radius: var(--tov-r-sm);
}

.tov-photos__empty {
	margin: 0;
	font-size: var(--tov-text-sm);
	color: var(--tov-text-dim);
}

/* ---------------------------------------------------------------- sign-in */

.tov-mkt--auth {
	max-width: 460px;
}

/* The door of the archive: the auth card carries the document brackets too —
   signing in is signing the ledger. */
.tov-auth {
	padding: var(--tov-space-6);
	background:
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 18px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) top left / 1px 18px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 18px 1px,
		linear-gradient(var(--tov-line-strong), var(--tov-line-strong)) bottom right / 1px 18px,
		linear-gradient(180deg, var(--tov-surface) 0%, var(--tov-bg-2) 100%);
	background-repeat: no-repeat;
	border: 1px solid var(--tov-line);
	border-top: 2px solid var(--tov-gold);
	border-radius: var(--tov-r-sm);
	box-shadow: var(--tov-shadow-lg);
	animation: tov-mkt-rise var(--tov-dur-slow) var(--tov-ease-out) both;
}

.tov-auth__eyebrow {
	margin: 0 0 var(--tov-space-2);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--tov-gold);
}

.tov-auth__title {
	margin: 0 0 var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-2xl);
	font-weight: 600;
	line-height: 1.1;
	color: var(--tov-text);
}

.tov-auth__lede {
	margin: 0 0 var(--tov-space-5);
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
}

/* The first-timer's orientation line under the sign-in form. Quieter than the
   lede on purpose: a returning member's eye should slide straight past it. */
.tov-auth__footnote {
	margin: var(--tov-space-5) 0 0;
	padding-top: var(--tov-space-4);
	border-top: 1px solid var(--tov-line);
	color: var(--tov-text-dim);
	font-size: var(--tov-text-sm);
	line-height: 1.55;
}

.tov-auth__form {
	display: flex;
	flex-direction: column;
	gap: var(--tov-space-3);
}

.tov-auth__label {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-text-muted);
}

.tov-auth__input {
	width: 100%;
	padding: var(--tov-space-3);
	background: var(--tov-bg) !important;
	color: var(--tov-text) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-sm);
	font-family: var(--tov-font-body) !important;
	font-size: var(--tov-text-base);
	transition: border-color var(--tov-dur-fast) var(--tov-ease-out),
		box-shadow var(--tov-dur-fast) var(--tov-ease-out);
}

.tov-auth__input:focus {
	outline: none;
	border-color: var(--tov-gold) !important;
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

/* The multiline sibling of .tov-auth__input — shipping addresses, gift notes.
   Same material, same focus story; resize is vertical-only so a drag cannot
   break the column. */
.tov-mkt__textarea {
	width: 100%;
	padding: var(--tov-space-3);
	background: var(--tov-bg) !important;
	color: var(--tov-text) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-sm);
	font-family: var(--tov-font-body) !important;
	font-size: var(--tov-text-base);
	line-height: 1.5;
	resize: vertical;
	min-height: 2.75rem;
}

.tov-mkt__textarea:focus-visible {
	outline: none;
	border-color: var(--tov-gold) !important;
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

.tov-mkt input[type="text"]::placeholder,
.tov-mkt input[type="email"]::placeholder,
.tov-mkt input[type="number"]::placeholder,
.tov-mkt textarea::placeholder,
.tov-mkt__textarea::placeholder {
	color: var(--tov-text-muted);
	opacity: 1;
}

/* A one-time code is read digit by digit off a phone and typed here — wide
   tracking and a monospace face make a transcription error visible. Written
   at input[type="text"] strength: the base control rules are (0,2,1) and
   silently beat the old bare-class (0,1,0) version at every width — the
   whole treatment shipped as dead code and the field rendered as 15px
   body-face. Specificity decides between two !important font-families, so
   the monospace needs the win on that axis too. */
.tov-mkt input[type="text"].tov-auth__input--code {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
	font-size: 1.5rem;
	letter-spacing: 0.35em;
	text-align: center;
}

.tov-auth__resend {
	margin-top: var(--tov-space-4);
	text-align: center;
}

.tov-auth__link {
	background: none !important;
	border: 0 !important;
	/* House 44px target: text sits small, the hit box does not. */
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	padding: var(--tov-space-2);
	color: var(--tov-text-dim) !important;
	font-family: var(--tov-font-body) !important;
	font-size: var(--tov-text-sm) !important;
	letter-spacing: normal !important;
	text-transform: none !important;
	text-decoration: underline !important;
	text-underline-offset: 2px;
	cursor: pointer;
}

.tov-auth__link:hover,
.tov-auth__link:focus-visible {
	color: var(--tov-gold-bright) !important;
}

/* ---------------------------------------------------------------- utility */

/* Verbatim from database.css / sheet.css. It belongs here for the same reason
   the tokens do: database.css only loads on catalog pages, so on the Trading
   Post this class would otherwise resolve to nothing and every label written for
   a screen reader alone would render on the page in full. Deliberately unscoped,
   matching the other two copies — changing it means changing all three. */
.tov-visually-hidden {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ------------------------------------------------------------- responsive */

@media (max-width: 860px) {
	.tov-listing,
	.tov-mkt__form-layout {
		grid-template-columns: 1fr;
	}

	/* 16px is a hard threshold: mobile Safari auto-zooms the page whenever a
	   focused control computes below it, and header.php sets initial-scale=1
	   with no maximum-scale to suppress that. It does not zoom back out on
	   blur, so every form in the flow compounds it.

	   Stated at the SAME specificity as the base control rules — a media
	   query adds none, and the previous bare-class list (0,1,0) lost the
	   cascade to those (0,2,1)/(0,1,1) rules at every width, shipping this
	   entire block as a no-op while its comment claimed victory. Element
	   selectors also cover the unclassed trade-composer controls. The OTP
	   field stays exempt through its own higher-specificity 1.5rem. */
	.tov-mkt input[type="text"],
	.tov-mkt input[type="email"],
	.tov-mkt input[type="number"],
	.tov-mkt input[type="file"],
	.tov-mkt select,
	.tov-mkt textarea {
		font-size: 16px;
	}

	/* Below the fold the two document plates stack, and the form drops back to
	   the single-column measure it holds everywhere else. */
	.tov-mkt__form:has(.tov-mkt__fieldset ~ .tov-mkt__fieldset) {
		grid-template-columns: 1fr;
		max-width: 34rem;
	}
}

@media (max-width: 560px) {
	.tov-mkt {
		padding: var(--tov-space-4) var(--tov-space-3) var(--tov-space-6);
	}

	.tov-mkt__grid {
		grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
		gap: var(--tov-space-4);
	}

	.tov-mkt__nav {
		gap: 0;
	}

	.tov-mkt__tab {
		padding: var(--tov-space-3) var(--tov-space-3);
	}

	/* Decision row goes full-width, stacked: every action a thumb-sized bar. */
	.tov-listing__actions {
		align-items: stretch;
		flex-direction: column;
	}

	.tov-listing__actions .tov-mkt__btn {
		width: 100%;
	}
}

/* ------------------------------------------------ hang-right bug tab */

/* Lives in wp_footer, outside .tov-mkt, so it carries its own tokens. */
.tov-bug {
	--tov-bg: #0a0a0b;
	--tov-bg-2: #0d0d0f;
	--tov-gold: #d4a24e;
	--tov-gold-bright: #ecc677;
	--tov-gold-ink: #14100c;
	--tov-line: rgba(212, 162, 78, 0.18);
	--tov-line-strong: rgba(212, 162, 78, 0.55);
	--tov-text: #f4f1ea;
	--tov-text-muted: #a19d95;
	--tov-text-dim: #857f75;
	--tov-cut: 9px;
	--tov-dur-base: 220ms;
	--tov-ease-out: cubic-bezier(0.22, 1, 0.36, 1);

	position: fixed;
	right: 0;
	top: 38%;
	z-index: 50;
	display: flex;
	flex-direction: row-reverse;
	align-items: stretch;
	color: var(--tov-text);
	font-family: "Barlow", "Segoe UI", Arial, Helvetica, sans-serif;
	font-size: 14px;
	line-height: 1.45;
}

.tov-bug > summary {
	list-style: none;
}

.tov-bug > summary::-webkit-details-marker {
	display: none;
}

.tov-bug__tab {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8px;
	width: 44px;
	min-height: 112px;
	padding: 12px 0;
	background: var(--tov-bg-2);
	color: var(--tov-gold);
	border: 1px solid var(--tov-line-strong);
	border-right: 0;
	cursor: pointer;
	writing-mode: vertical-rl;
	transform: rotate(180deg);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	font-family: "Oswald", "Arial Narrow", Arial, Helvetica, sans-serif;
	font-size: 11px;
	font-weight: 600;
}

.tov-bug__tab:hover,
.tov-bug__tab:focus-visible {
	color: var(--tov-gold-bright);
	background: #151517;
}

.tov-bug__icon {
	display: flex;
	transform: rotate(180deg);
}

.tov-bug[open] .tov-bug__tab {
	border-color: var(--tov-gold);
}

.tov-bug__plate {
	width: min(20rem, calc(100vw - 56px));
	padding: 16px 16px 18px;
	background: var(--tov-bg-2);
	border: 1px solid #31281a;
	border-right: 0;
	border-top: 3px solid var(--tov-gold);
	box-shadow: -18px 12px 40px -18px rgba(0, 0, 0, 0.85);
}

.tov-bug__kicker {
	margin: 0 0 4px;
	font-family: "Oswald", "Arial Narrow", Arial, Helvetica, sans-serif;
	font-size: 10px;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--tov-gold);
}

.tov-bug__title {
	margin: 0 0 8px;
	font-family: "Oswald", "Arial Narrow", Arial, Helvetica, sans-serif;
	font-size: 22px;
	font-weight: 500;
	letter-spacing: 0.03em;
	color: var(--tov-text);
}

.tov-bug__ok {
	margin: 0;
	color: var(--tov-gold-bright);
	font-size: 14px;
}

.tov-bug__lede {
	margin: 0 0 12px;
	font-size: 13px;
	line-height: 1.5;
	color: var(--tov-text-muted);
}

.tov-bug__body {
	display: block;
	width: 100%;
	margin: 0 0 12px;
	padding: 10px;
	min-height: 8rem;
	background: var(--tov-bg);
	color: var(--tov-text);
	border: 1px solid var(--tov-line);
	border-radius: 2px;
	font: inherit;
	resize: vertical;
}

.tov-bug__body:focus-visible {
	outline: none;
	border-color: var(--tov-gold);
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

.tov-bug__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 18px;
	background: var(--tov-gold);
	color: var(--tov-gold-ink);
	border: 1px solid #ecc677;
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--tov-cut)), calc(100% - var(--tov-cut)) 100%, 0 100%);
	font-family: "Oswald", "Arial Narrow", Arial, Helvetica, sans-serif;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	cursor: pointer;
}

.tov-bug__submit:hover,
.tov-bug__submit:focus-visible {
	background: var(--tov-gold-bright);
}

@media (max-width: 560px) {
	.tov-bug {
		top: auto;
		bottom: 18%;
	}
}

/* -------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
	.tov-mkt *,
	.tov-mkt *::before,
	.tov-mkt *::after {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
		animation-delay: 0ms !important;
		animation-iteration-count: 1 !important;
	}

	.tov-mkt__tile:hover,
	.tov-mkt__tile:focus-within,
	.tov-mkt__tile:hover .tov-mkt__tile-art img,
	.tov-mkt .tov-mkt__btn:active {
		transform: none;
	}

	/* The pips are deliberately NOT in the list above, and that is the whole
	   note: this list exists for states that end somewhere other than where they
	   started, which the blanket rule cannot undo. The pips' one transition is
	   the rarity dot's bloom — it moves nothing and ends on a glow, the blanket
	   rule already flattens the fade, and zeroing it outright would take a rarity
	   cue away from the very people this block protects. */

	.tov-mkt .tov-mkt__btn::after {
		content: none;
	}
}

/* ==========================================================================
   Claim / registration page ([tribal_card_claim]) — the vault's front door
   for a scanned QR code. Composes the Vault Ledger grammar: one framed plate,
   registration ticks, gold kicker. No animation — nothing here to reduce.
   ========================================================================== */

.tov-claim {
	max-width: 34rem;
	margin: 0 auto;
	padding: var(--tov-space-5) var(--tov-space-3);
}

.tov-claim__frame {
	position: relative;
	border: 1px solid var(--tov-line-strong);
	padding: var(--tov-space-5) var(--tov-space-4);
	background:
		linear-gradient(180deg, rgba(212, 162, 78, 0.05), transparent 30%),
		var(--tov-bg-raised, rgba(255, 255, 255, 0.02));
}

/* Corner registration ticks, same motif as the reliquary frame. */
.tov-claim__frame::before,
.tov-claim__frame::after {
	content: "";
	position: absolute;
	width: 14px;
	height: 14px;
	border: 1px solid var(--tov-gold);
	pointer-events: none;
}

.tov-claim__frame::before {
	top: 6px;
	left: 6px;
	border-width: 1px 0 0 1px;
}

.tov-claim__frame::after {
	bottom: 6px;
	right: 6px;
	border-width: 0 1px 1px 0;
}

.tov-claim__kicker {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--tov-gold);
	margin: 0 0 var(--tov-space-2);
}

.tov-claim__title {
	font-family: var(--tov-font-display);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--tov-text);
	margin: 0 0 var(--tov-space-4);
}

.tov-claim__lede,
.tov-claim__fineprint {
	color: var(--tov-text-muted);
	margin: var(--tov-space-3) 0;
}

.tov-claim__fineprint {
	font-size: var(--tov-text-sm);
	border-top: 1px solid var(--tov-line);
	padding-top: var(--tov-space-3);
}

.tov-claim__card {
	border: 1px solid var(--tov-line);
	border-left: 2px solid var(--tov-gold);
	padding: var(--tov-space-3) var(--tov-space-4);
	margin: var(--tov-space-3) 0;
}

.tov-claim__card-label {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-text-dim);
	margin: 0;
}

.tov-claim__card-name {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xl);
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--tov-gold);
	margin: var(--tov-space-1, 0.25rem) 0 0;
}

.tov-claim__card-season {
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
	margin: var(--tov-space-1, 0.25rem) 0 0;
}

/* Who the card is about to belong to. Deliberately the loudest thing on a
   signed-in claim: it is the only fact on the page the member has to agree
   with, and the one there is no undoing afterwards. */
.tov-claim__who {
	border: 1px solid var(--tov-line);
	border-left: 2px solid var(--tov-gold);
	padding: var(--tov-space-3) var(--tov-space-4);
	margin: var(--tov-space-3) 0;
}

.tov-claim__who-label {
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-text-dim);
	margin: 0;
}

.tov-claim__who-value {
	color: var(--tov-text);
	/* An email address is the one string here that must survive a narrow phone
	   without reflowing the frame — most scans arrive on one. */
	overflow-wrap: anywhere;
	margin: var(--tov-space-1, 0.25rem) 0 0;
}

/* The register-for-someone-else disclosure. Quiet on purpose. */
.tov-claim__alt summary {
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
	cursor: pointer;
}

.tov-claim__form {
	display: grid;
	gap: var(--tov-space-2);
	margin-top: var(--tov-space-3);
}

.tov-claim__form .tov-mkt__btn {
	justify-self: start;
	margin-top: var(--tov-space-2);
}

/* Honeypot: visually gone, still in the accessibility tree of exactly nobody. */
.tov-claim__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.tov-claim__actions {
	margin-top: var(--tov-space-4);
}

/* ==========================================================================
   Magic-link sign-in: after an email is requested, the job is "go click the
   link". The typed-code fallback stays in a closed disclosure.
   ========================================================================== */

.tov-auth__check-mail {
	margin: 0 0 var(--tov-space-6);
	padding: var(--tov-space-5) var(--tov-space-4);
	text-align: center;
	border: 1px solid var(--tov-line-strong);
	border-radius: var(--tov-r-sm);
	background:
		radial-gradient(80% 90% at 50% 0%, rgba(212, 162, 78, 0.12), transparent 62%),
		var(--tov-surface);
}

.tov-auth__check-mail-kicker {
	margin: 0 0 var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-sm);
	font-weight: 600;
	letter-spacing: 0.28em;
	text-transform: uppercase;
	color: var(--tov-gold);
}

.tov-auth__check-mail-action {
	margin: 0 0 var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xl);
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0.02em;
	color: var(--tov-text);
}

.tov-auth__check-mail-note {
	margin: 0;
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
	line-height: 1.5;
}

.tov-auth__alt {
	margin-top: var(--tov-space-3);
	border-top: 1px solid var(--tov-line);
	padding-top: var(--tov-space-3);
}

.tov-auth__alt > summary {
	cursor: pointer;
	color: var(--tov-text-muted);
	font-size: var(--tov-text-sm);
	font-family: var(--tov-font-display);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	list-style-position: inside;
}

.tov-auth__alt > summary:hover,
.tov-auth__alt > summary:focus-visible {
	color: var(--tov-gold);
}

.tov-auth__alt[open] > summary {
	margin-bottom: var(--tov-space-3);
}

/* ==========================================================================
   Confirm dialog — the ceremony before an irreversible POST
   ==========================================================================
   Replaces the browser's confirm() popup on forms carrying data-tov-confirm
   (marketplace.js). The <dialog> is appended INSIDE `.tov-mkt`, so every token
   arrives by inheritance — the top layer ignores DOM stacking, so nesting
   costs nothing and saves this file from restating the palette the way
   tov-tour.css must. Selectors are `.tov-mkt .tov-confirm…` so the buttons
   inside compose the real `.tov-mkt .tov-mkt__btn` grammar, cut corner and all.

   The reduced-motion blanket above (`.tov-mkt *`) already flattens the
   entrance rise. The ::backdrop is deliberately static — a backdrop is not an
   element of `.tov-mkt` and no blanket rule can reach it, so it gets nothing
   that would need flattening. Its color is a literal, not a token, for the
   same reason: custom-property inheritance into ::backdrop is not dependable
   across the browsers this must serve. Value = tov-tour.css's scrim. */

.tov-mkt .tov-confirm {
	width: min(92vw, 30rem);
	max-height: 85vh;
	overflow: auto;
	margin: auto;
	padding: 0;
	border: 1px solid var(--tov-line-strong);
	/* The gold top edge every raised plate in the Ledger wears. */
	border-top: 2px solid var(--tov-gold);
	border-radius: var(--tov-r-md);
	background: linear-gradient(180deg, var(--tov-surface) 0%, var(--tov-bg-2) 100%);
	color: var(--tov-text);
	box-shadow: var(--tov-shadow-lg);
}

.tov-mkt .tov-confirm[open] {
	animation: tov-mkt-rise var(--tov-dur-base) var(--tov-ease-out) both;
}

.tov-confirm::backdrop {
	background: rgba(6, 6, 8, 0.74);
}

/* Padding lives on the inner wrapper, not the dialog: a click anywhere inside
   the plate must target a child, so that marketplace.js can read a click whose
   target is the <dialog> itself as a backdrop click. */
.tov-mkt .tov-confirm__inner {
	padding: var(--tov-space-5) var(--tov-space-5) var(--tov-space-4);
}

.tov-mkt .tov-confirm__title {
	margin: 0 0 var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-xl);
	font-weight: 500;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	line-height: 1.2;
	color: var(--tov-text);
}

.tov-mkt .tov-confirm__body {
	margin: 0 0 var(--tov-space-5);
	font-size: var(--tov-text-base);
	line-height: 1.55;
	color: var(--tov-text-muted);
}

.tov-mkt .tov-confirm__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: var(--tov-space-2);
}

/* On a phone the two choices stack full-width, committing action on top —
   same convention as the listing actions rail. */
@media (max-width: 480px) {
	.tov-mkt .tov-confirm__actions {
		flex-direction: column-reverse;
		align-items: stretch;
	}
}

/* ==========================================================================
   Grid search / sort / filters — same chrome as the Card Database
   ========================================================================== */

.tov-mkt__toolbar {
	display: flex;
	flex-wrap: wrap;
	gap: var(--tov-space-3);
	margin-bottom: var(--tov-space-3);
}

.tov-mkt__filter-count {
	margin: 0 0 var(--tov-space-4);
	font-size: var(--tov-text-sm);
	color: var(--tov-text-dim);
	letter-spacing: 0.04em;
}

.tov-mkt .tov-search {
	position: relative;
	flex: 1 1 320px;
	min-width: 0;
}

.tov-mkt .tov-search__icon {
	position: absolute;
	top: 50%;
	left: 16px;
	width: 17px;
	height: 17px;
	transform: translateY(-50%);
	color: var(--tov-text-dim);
	pointer-events: none;
}

.tov-mkt .tov-search__input {
	width: 100%;
	height: 52px;
	padding: 0 44px 0 44px;
	font-family: var(--tov-font-body) !important;
	font-size: var(--tov-text-base) !important;
	color: var(--tov-text) !important;
	background: var(--tov-surface) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-md);
}

.tov-mkt .tov-search__input:focus,
.tov-mkt .tov-search__input:focus-visible {
	outline: none;
	border-color: var(--tov-gold) !important;
	box-shadow: 0 0 0 3px rgba(212, 162, 78, 0.18);
}

.tov-mkt .tov-search__clear {
	position: absolute;
	top: 50%;
	right: 8px;
	display: none;
	place-items: center;
	width: 30px;
	height: 30px;
	padding: 0;
	transform: translateY(-50%);
	color: var(--tov-text-muted);
	background: transparent !important;
	border: 0 !important;
	cursor: pointer;
}

.tov-mkt .tov-search.is-filled .tov-search__clear {
	display: grid;
}

.tov-mkt .tov-sort {
	position: relative;
	display: inline-flex;
	align-items: center;
	height: 52px;
}

.tov-mkt .tov-sort__icon {
	position: absolute;
	top: 50%;
	left: 16px;
	transform: translateY(-50%);
	color: var(--tov-text-dim);
	pointer-events: none;
}

.tov-mkt .tov-sort::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 17px;
	width: 7px;
	height: 7px;
	margin-top: -5px;
	border-right: 2px solid var(--tov-text-dim);
	border-bottom: 2px solid var(--tov-text-dim);
	transform: rotate(45deg);
	pointer-events: none;
}

.tov-mkt .tov-sort__select {
	height: 52px;
	padding: 0 34px 0 40px;
	appearance: none;
	font-family: var(--tov-font-display) !important;
	font-weight: 500;
	font-size: var(--tov-text-sm) !important;
	letter-spacing: 0.04em;
	color: var(--tov-text) !important;
	background: var(--tov-surface) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-md);
	cursor: pointer;
}

.tov-mkt .tov-filters__trigger {
	display: inline-flex;
	align-items: center;
	gap: var(--tov-space-2);
	height: 52px;
	padding: 0 var(--tov-space-4);
	font-family: var(--tov-font-display) !important;
	font-weight: 500;
	font-size: var(--tov-text-sm) !important;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--tov-text) !important;
	background: var(--tov-surface) !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-md);
	cursor: pointer;
}

.tov-mkt .tov-filters__trigger[aria-expanded="true"] {
	border-color: var(--tov-gold) !important;
	color: var(--tov-gold) !important;
}

.tov-mkt .tov-filters__trigger svg {
	width: 16px;
	height: 16px;
}

.tov-mkt .tov-filters__badge {
	display: none;
	place-items: center;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	font-size: var(--tov-text-xs);
	color: var(--tov-bg);
	background: var(--tov-gold);
	border-radius: var(--tov-r-pill);
}

.tov-mkt .tov-filters__trigger.has-active .tov-filters__badge {
	display: grid;
}

.tov-mkt .tov-filters__panel {
	overflow: hidden;
	max-height: 0;
	opacity: 0;
	margin-bottom: 0;
	border: 1px solid transparent;
	border-radius: var(--tov-r-lg);
	background: linear-gradient(180deg, var(--tov-surface-2), var(--tov-surface));
	transition: max-height var(--tov-dur-slow) var(--tov-ease-out),
		opacity var(--tov-dur-base) var(--tov-ease-out),
		margin-bottom var(--tov-dur-slow) var(--tov-ease-out),
		border-color var(--tov-dur-slow) var(--tov-ease-out);
}

.tov-mkt .tov-filters__panel.is-open {
	max-height: 4000px;
	opacity: 1;
	margin-bottom: var(--tov-space-5);
	border-color: var(--tov-line);
}

.tov-mkt .tov-filters__inner {
	padding: var(--tov-space-5);
}

.tov-mkt .tov-filters__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: var(--tov-space-5) var(--tov-space-6);
}

.tov-mkt .tov-facet {
	border: 0;
	margin: 0;
	padding: 0;
	min-width: 0;
}

.tov-mkt .tov-facet__legend {
	display: flex;
	align-items: center;
	gap: var(--tov-space-2);
	width: 100%;
	padding: 0 0 var(--tov-space-3);
	margin-bottom: var(--tov-space-3);
	font-family: var(--tov-font-display);
	font-weight: 600;
	font-size: var(--tov-text-xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--tov-gold);
	border-bottom: 1px solid var(--tov-line);
}

.tov-mkt .tov-facet__n {
	margin-left: auto;
	font-weight: 400;
	color: var(--tov-text-dim);
}

.tov-mkt .tov-facet__options {
	display: flex;
	flex-direction: column;
	gap: 2px;
	max-height: 216px;
	overflow-y: auto;
}

.tov-mkt .tov-opt {
	display: flex;
	align-items: center;
	gap: var(--tov-space-3);
	padding: 7px 9px;
	min-height: 40px;
	font-size: var(--tov-text-sm);
	color: var(--tov-text-muted);
	border-radius: var(--tov-r-sm);
	cursor: pointer;
}

.tov-mkt .tov-opt input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.tov-mkt .tov-opt__box {
	position: relative;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	border: 1px solid var(--tov-line-strong);
	border-radius: var(--tov-r-sm);
	background: var(--tov-bg);
}

.tov-mkt .tov-opt__box::after {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	width: 5px;
	height: 9px;
	border: solid var(--tov-bg);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) translate(-1px, -1px) scale(0);
}

.tov-mkt .tov-opt input:checked ~ .tov-opt__box {
	background: var(--tov-gold);
	border-color: var(--tov-gold);
}

.tov-mkt .tov-opt input:checked ~ .tov-opt__box::after {
	transform: rotate(45deg) translate(-1px, -1px) scale(1);
}

.tov-mkt .tov-opt__label {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tov-mkt .tov-opt__count {
	flex: 0 0 auto;
	font-size: var(--tov-text-xs);
	color: var(--tov-text-dim);
}

.tov-mkt .tov-filters__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tov-space-2);
	margin-top: var(--tov-space-5);
	padding-top: var(--tov-space-4);
	border-top: 1px solid var(--tov-line);
}

.tov-mkt .tov-filters__foot-label {
	font-size: var(--tov-text-xs);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--tov-text-dim);
}

.tov-mkt .tov-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 6px 5px 11px;
	font-size: var(--tov-text-xs);
	color: var(--tov-text);
	background: var(--tov-surface-3);
	border: 1px solid var(--tov-line);
	border-radius: var(--tov-r-pill);
}

.tov-mkt .tov-chip__tax {
	color: var(--tov-gold);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 10px;
}

.tov-mkt .tov-chip__x {
	display: grid;
	place-items: center;
	width: 18px;
	height: 18px;
	color: var(--tov-text-muted);
	background: transparent !important;
	border: 0 !important;
	cursor: pointer;
}

.tov-mkt .tov-reset {
	margin-left: auto;
	padding: 6px 12px;
	font-size: var(--tov-text-xs);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--tov-text-muted) !important;
	background: transparent !important;
	border: 1px solid var(--tov-line) !important;
	border-radius: var(--tov-r-pill);
	cursor: pointer;
}

.tov-mkt .tov-reset:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}

.tov-mkt__card.is-hidden {
	display: none !important;
}

.tov-mkt__filter-empty {
	display: none;
	flex-direction: column;
	align-items: center;
	gap: var(--tov-space-4);
	text-align: center;
	padding: var(--tov-space-8) var(--tov-space-4);
}

.tov-mkt__filter.is-empty .tov-mkt__grid {
	display: none;
}

.tov-mkt__filter.is-empty .tov-mkt__filter-empty {
	display: flex;
}

.tov-mkt .tov-empty__title {
	margin: 0;
	font-family: var(--tov-font-display);
	font-size: var(--tov-text-lg);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--tov-text);
}

.tov-mkt .tov-empty__text {
	margin: 0;
	max-width: 36em;
	color: var(--tov-text-muted);
}

.tov-mkt .tov-empty__reset {
	min-height: 44px;
	padding: 0 var(--tov-space-4);
	font-family: var(--tov-font-display) !important;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tov-gold) !important;
	background: transparent !important;
	border: 1px solid var(--tov-line-strong) !important;
	border-radius: var(--tov-r-md);
	cursor: pointer;
}
