/* ── Site-wide mobile polish ─────────────────────────────────────────────
 * Loaded after every page-specific stylesheet so the rules below win on
 * equal specificity. Scope is intentionally narrow: cross-cutting iOS
 * Safari / mobile-Chrome platform quirks that bite every page. Per-page
 * mobile layout still lives in each page's own stylesheet.
 */

/* Tap-highlight + 300ms delay. Coarse-pointer media query keeps these off
 * desktop, where tap-highlight is irrelevant and touch-action would
 * suppress double-click-to-zoom in some contexts. */
@media (hover: none) and (pointer: coarse) {
	a,
	button,
	[role='button'],
	summary,
	input[type='submit'],
	input[type='button'],
	input[type='reset'] {
		-webkit-tap-highlight-color: transparent;
		touch-action: manipulation;
	}
	label,
	select,
	input[type='checkbox'],
	input[type='radio'] {
		-webkit-tap-highlight-color: transparent;
	}
}

/* Horizontal-scroll guard. A few px of off-by-one overflow on one child
 * shouldn't give the whole page a horizontal scrollbar on a phone.
 * overflow-x: clip is safer than overflow: hidden because it does not
 * also clamp vertical scrolling — and unlike hidden it cannot create a
 * new scroll container that breaks position: sticky higher in the tree. */
@media (max-width: 768px) {
	html,
	body {
		overflow-x: clip;
	}
}

/* iOS Safari zooms the viewport on focus when an input's computed
 * font-size is < 16px. Bump unstyled inputs/textareas/selects so that
 * tapping a search/email field doesn't punt the layout sideways. Pages
 * that intentionally use small inputs use class selectors with higher
 * specificity, so designed sizes still win where they matter. */
@media (max-width: 768px) {
	input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='color']),
	textarea,
	select {
		font-size: max(16px, 1em);
	}
}

/* Reusable safe-area utility for any fixed-bottom UI that doesn't already
 * handle the iPhone home indicator. Apply via class — no automatic
 * targeting, so existing layouts are untouched. */
@supports (padding: env(safe-area-inset-bottom)) {
	.mobile-safe-bottom {
		padding-bottom: env(safe-area-inset-bottom);
	}
	.mobile-safe-top {
		padding-top: env(safe-area-inset-top);
	}
}

/* ── Home-page specific mobile polish ──────────────────────────────────
 * Fixes that span across home.css but are best kept here
 * so the load order guarantees they win on equal-specificity conflicts.
 */

@media (max-width: 768px) {
	/* Chapter rail navigation dots — only useful on wide viewports. */
	.h-chapter-rail {
		display: none !important;
	}

	/* Ghost model loads a full GLB at opacity 0.1 — invisible on mobile,
	   pure bandwidth waste. The layer div still occupies its z-index slot. */
	.h-ghost-model {
		display: none !important;
	}

	/* Hero: on phones the sticky/margin-bottom trick (used for the parallax
	   text pin) causes a big blank gap.  The media query in home.css already
	   resets it to relative but misses some padding edge-cases. */
	.h-hero-text {
		padding-top: 1.5rem;
		padding-bottom: 2rem;
	}

	/* Title size: clamp already handles it but add a hard cap so it never
	   wraps oddly on 320-360px screens. */
	.h-title {
		font-size: clamp(2.6rem, 11vw, 4rem);
		letter-spacing: -0.03em;
	}

	.h-act-title {
		font-size: clamp(2rem, 8.5vw, 3.2rem);
	}

	/* Subtitle / lede: tighten line-height slightly on narrow screens */
	.h-subtitle {
		font-size: 1rem;
		line-height: 1.5;
	}

	.h-act-lede {
		font-size: 1rem;
		line-height: 1.5;
	}

	/* CTA row: stack on very small phones */
	.h-cta-row {
		gap: 0.65rem;
	}

	.h-btn-primary,
	.h-btn-ghost {
		min-height: 48px;
		padding: 0.9rem 1.4rem;
		font-size: 0.92rem;
	}

	/* Standards list: allow 2-per-line on tiny screens */
	.h-standards {
		gap: 0.5rem 0.9rem;
		font-size: 0.62rem;
	}

	/* Pillars: already single-column via home.css, add breathing room */
	.h-pillars {
		padding: 3rem 1.25rem;
	}

	.h-pillar p {
		font-size: 0.9rem;
	}

	/* Bento section */
	.h-bento-section {
		padding: 3rem 1rem;
	}

	.h-bento-body {
		padding: 1rem 1.2rem;
	}

	/* Dev section code block: allow horizontal scroll without breaking layout */
	.h-dev-pre {
		font-size: 0.74rem;
	}

	/* Final CTA section */
	.h-cta-section {
		padding: 3.5rem 1.25rem;
	}

	.h-cta-section h2 {
		font-size: clamp(2rem, 9vw, 3.2rem);
	}

	.h-cta-section p {
		font-size: 1rem;
	}

	.h-cta-row-center {
		flex-direction: column;
		align-items: stretch;
	}

	.h-cta-row-center .h-btn-primary,
	.h-cta-row-center .h-btn-ghost {
		text-align: center;
		justify-content: center;
	}

	/* Footer */
	.h-footer-horizon {
		padding: 2.5rem 1.25rem 1.25rem !important;
	}

	.h-footer-watermark {
		font-size: clamp(5rem, 18vw, 10rem);
	}
}

/* Very small phones (≤ 380px) — tighten further */
@media (max-width: 380px) {
	.h-title {
		font-size: clamp(2.2rem, 12vw, 3rem);
	}

	.h-cta-row {
		flex-direction: column;
		align-items: stretch;
	}

	.h-btn-primary,
	.h-btn-ghost {
		width: 100%;
		text-align: center;
		justify-content: center;
	}
}

/* ── Safe-area insets for fixed/sticky UI ──────────────────────────────
 * Applied globally so every page benefits. Modals and drawers that sit
 * at the viewport edge need padding-bottom to clear the iPhone home
 * indicator and Android navigation bar.
 */
@supports (padding: env(safe-area-inset-bottom)) {
	/* Modals anchored to full viewport height */
	.modal-content,
	.plugin-modal,
	.avatar-modal-side,
	.auth-form-wrap {
		padding-bottom: max(24px, env(safe-area-inset-bottom));
	}

	/* Toast / snackbar that sits at bottom-center */
	.agent-deploy-toast,
	.status-toast,
	.toast {
		bottom: max(1.5rem, calc(env(safe-area-inset-bottom) + 1rem));
	}

	/* Sticky bottom nav / tab bars */
	.nav-bottom,
	.bottom-bar,
	.mobile-tab-bar {
		padding-bottom: env(safe-area-inset-bottom);
	}

	/* Auth shell on very small iPhones */
	@media (max-width: 860px) {
		body:has(.shell) {
			padding-bottom: env(safe-area-inset-bottom);
		}
	}
}

/* ── 360px — very small Android phones ────────────────────────────────
 * Galaxy A series, Moto G, etc. sit at 360px.
 */
@media (max-width: 360px) {
	/* Marketplace: force single column so cards don't shrink below usable size */
	.market-grid {
		grid-template-columns: 1fr !important;
	}

	/* Create page: full-bleed cards */
	.card-grid {
		grid-template-columns: 1fr !important;
		max-width: none !important;
		padding: 0;
	}

	/* Auth: let the avatar panel compress more */
	.panel {
		min-height: 160px !important;
	}
	.agent-avatar {
		width: 140px !important;
		height: 140px !important;
	}

	/* Nav: shrink wordmark gap */
	.wordmark-logo {
		width: 18px;
		height: 18px;
	}
}

/* ── PWA standalone mode ────────────────────────────────────────────────
 * When installed as a PWA (no browser chrome), compensate for the absence
 * of the browser status bar and adjust top-anchored sticky headers.
 */
@media (display-mode: standalone) {
	/* Give the topmost sticky header extra top padding for the status bar area */
	header:first-of-type,
	.nav-top,
	.market-topbar,
	.agent-page-header {
		padding-top: max(0.75rem, env(safe-area-inset-top));
	}

	/* Bottom of scrollable main content — clear the home indicator */
	main,
	.stage,
	.market-main {
		padding-bottom: max(2rem, calc(env(safe-area-inset-bottom) + 1rem));
	}

	/* Hide browser-specific UI hints that don't apply in standalone */
	.h-scroll-hint {
		display: none;
	}
}

/* ── Marketplace mobile polish ─────────────────────────────────────────
 * Supplements marketplace.css at breakpoints it doesn't cover.
 */
@media (max-width: 480px) {
	/* Modal: full-screen bottom sheet on phones */
	.avatar-modal {
		position: fixed !important;
		inset: 0 !important;
		max-height: 100dvh !important;
		border-radius: 0 !important;
		grid-template-columns: 1fr !important;
		grid-template-rows: 48vw 1fr !important;
	}

	.avatar-modal-side {
		max-height: none;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
	}

	/* Topbar: stack filter row below search on very narrow screens */
	.market-filter-chips {
		gap: 6px;
	}
	.market-filter-chip {
		font-size: 0.72rem;
		padding: 5px 10px;
	}
}

/* ── Create page mobile polish ─────────────────────────────────────────
 */
@media (max-width: 700px) {
	/* Upload drop zone: increase height so it's easier to tap */
	.upload-zone,
	[class*='drop-zone'] {
		min-height: 140px;
	}

	/* Card CTAs: full tap width */
	.create-card {
		-webkit-tap-highlight-color: transparent;
	}
}

/* ── Auth / login mobile polish ────────────────────────────────────────
 */
@media (max-width: 480px) {
	/* Sign-in form: use full available height */
	.shell {
		border-radius: 0;
		min-height: 100dvh;
	}

	/* Wallet connect button row: stack if too many */
	.wallet-list,
	.wallet-grid {
		grid-template-columns: 1fr !important;
	}
}

/* ── Scroll behaviour ──────────────────────────────────────────────────
 * Smooth momentum scroll on iOS for overflow containers.
 */
@media (hover: none) and (pointer: coarse) {
	[style*='overflow: auto'],
	[style*='overflow-y: auto'],
	[style*='overflow-y: scroll'],
	.scrollable,
	.avatar-modal-side,
	.market-main,
	.agent-chat-history {
		-webkit-overflow-scrolling: touch;
		scroll-behavior: smooth;
	}
}

/* ── Tap-target floor (touch only) ─────────────────────────────────────
 * Loaded last, so these win over page CSS on equal specificity. Gated on
 * pointer type (not viewport width) because a 768px+ tablet is still
 * touch-only and needs the same 44px floor — and desktop mouse visuals
 * must stay untouched. Scope is the controls the cross-page audit flagged
 * below 44px at 320/768: search/sort fields, marketplace + agents filter
 * controls, the dashboard/login form, and the onboarding pill.
 */
@media (hover: none) and (pointer: coarse) {
	/* Primary text fields & selects — comfortable height + 16px font (the
	   font rule above already prevents iOS focus-zoom). */
	#market-search,
	#ag-search,
	#skills-search,
	.market-sort,
	#ag-sort,
	#skills-sort {
		min-height: 44px;
	}

	/* Buttons that drive search/filter/auth flows. */
	.mkt-wallet-btn,
	.market-theme-cta,
	#skills-loadmore,
	.privy-row-btn,
	.privy-chain-btn,
	.onchain-toggle-btn,
	.card-see3d {
		min-height: 44px;
	}

	/* Square icon buttons need width too, not just height. */
	.password-toggle,
	.card-star {
		min-width: 44px;
		min-height: 44px;
	}

	/* Filter chips/segments: full 44px hit height with breathing room
	   between neighbours so dense rows stay easy to tap. */
	.market-chip,
	.market-cat-chip,
	.market-filter-chip {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.market-filter-chips,
	.market-cats {
		gap: 8px;
	}

	/* "On-chain only" style inline checkbox rows — give the whole label a
	   44px hit area and enlarge the box itself from its 13px default. */
	label:has(> #ag-onchain),
	label:has(> #remember) {
		min-height: 44px;
	}
	#ag-onchain,
	#remember {
		width: 18px;
		height: 18px;
	}
}

/* ── Tap-target floor, round 2 (touch only) ────────────────────────────
 * Every selector below was measured under 44x44 CSS px on a real Pixel 5
 * by `npm run audit:mobile-touch` (scripts/mobile-touch-audit.mjs); the
 * sizes in the comments are that run's measured boxes. Grouped by the
 * surface they came from so the next audit run can be traced back here.
 *
 * The technique is deliberately uniform: raise the box to a 44px floor and
 * centre the existing content inside it with inline-flex, so nothing moves
 * visually except the hit area growing. Gated on pointer type rather than
 * viewport width because a large tablet is still finger-driven, and a
 * desktop mouse must keep the designed compact sizing.
 */
@media (hover: none) and (pointer: coarse) {
	/* Skip links. Injected by /nav.js on every page and hand-written on a
	   few; they are the first focusable element, so a keyboard-plus-touch
	   user lands on them first. Measured 157x36, 152x40, 127x41, 393x26. */
	.nav-skip,
	.skip-link {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* Shared footer. Present on most pages. Measured: the NVIDIA badge at
	   24x44 (too narrow, not too short) and the community button at 145x41. */
	.h-footer-nvidia {
		min-width: 44px;
		justify-content: center;
	}
	.h-footer-community-btn {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* Docs shell. The sidebar is the single densest control list on the
	   site: 271 links measured at 267x30, stacked, with no gap between hit
	   areas. Raising the floor also separates neighbours. */
	.sidebar-link {
		min-height: 44px;
		display: flex;
		align-items: center;
	}
	.docs-pagetools-btn,
	.docs-pagetools-caret,
	.docs-logo,
	.docs-world-link {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.docs-pagetools-caret {
		min-width: 44px;
		justify-content: center;
	}

	/* /launches. Each launch row carries a strip of 29px actions plus a
	   37x10 tip button, which is the smallest control measured anywhere. */
	.lx-action,
	.lx-agent-row,
	.twc-make,
	.mp-tick {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.lx-agent-row,
	.mp-tick {
		display: flex;
	}
	.lx-action-watch {
		min-width: 44px;
		justify-content: center;
	}
	/* The wallet pill's identity run carries the popover handler, so the pill is a
	   real target; the run stretches through the pill's padding to match it. */
	span.twc {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* Home page. Avatar picker tiles (32x32), animation/emote chips (50x24),
	   the advent topic links (152x33) and the section CTAs (111x41). */
	.pg-avatar-item {
		min-width: 44px;
		min-height: 44px;
	}
	.pg-anim,
	.pg-chip,
	.hp-btn,
	.adv-topic,
	.har-cta-link,
	.wyg-card-link {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /forge. Showcase card actions and the generation-mode tabs. */
	.showcase-vote,
	.showcase-remix,
	.showcase-cat-badge,
	.fq-connect-btn {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	#tab-text,
	#tab-image,
	#tab-sketch {
		min-height: 44px;
	}

	/* /play. The community picker, its name field, and the intro reopener. */
	.cc-card-holders,
	.cc-nav-brand,
	.cc-adventure,
	.cc-gallery-btn,
	.pi-reopen {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.cc-nav-toggle {
		min-width: 44px;
		min-height: 44px;
	}
	.cc-name-input {
		min-height: 44px;
	}

	/* /marketplace. Card title links (289x32) and the disclosure banner. */
	.card-profile-link,
	.tws-disc-cta {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.tws-disc-x {
		min-width: 44px;
		min-height: 44px;
	}

	/* /markets. Watchlist stars are the smallest tap target on the page. */
	.nw-star {
		min-width: 44px;
		min-height: 44px;
	}
	.mkt-more {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /changelog filter pills. */
	.cl-filter {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /walk. Share/copy row plus the standard button kit at mobile size. */
	.wl-copy-btn {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.btn {
		min-height: 44px;
	}

	/* /irl. Consent, calibration and bottom-sheet controls all sat at 32-43px. */
	.irl-consent-btn,
	.irl-sheet-btn,
	.irl-sheet-report,
	.irl-ob-learn,
	.tws-es-btn {
		min-height: 44px;
	}
	.irl-cal-step {
		min-width: 44px;
		min-height: 44px;
	}
	#irl-cal-save,
	#irl-cal-cancel {
		min-height: 44px;
	}
	/* Checkbox inputs default to 13-16px; the label row carries the hit area
	   and the box itself grows to a thumb-sized 22px. */
	#irl-consent-dontshow {
		width: 22px;
		height: 22px;
	}

	/* Auth / dashboard form. Fields measured 42px, the submit 41px. */
	#email,
	#password,
	#privy-email-input,
	#submit,
	.brand,
	.panel-brand,
	.forgot {
		min-height: 44px;
	}
	.brand,
	.panel-brand,
	.forgot {
		display: inline-flex;
		align-items: center;
	}
}

/* ── Canvas scroll posture ─────────────────────────────────────────────
 * A canvas with `touch-action: auto` that also calls preventDefault in a
 * pointer handler makes orbit gestures fight page scroll; one with
 * `touch-action: none` inside a scrolling page swallows the swipe outright.
 * Every canvas below is a decorative or preview surface embedded in a page
 * the user still has to scroll, so vertical panning belongs to the page and
 * horizontal drag belongs to the canvas.
 *
 * Full-screen application canvases (#kx-canvas on /play, #irl-canvas on
 * /irl) are deliberately absent: they own the whole viewport, there is
 * nothing to scroll behind them, and `touch-action: none` is correct there.
 */
#footer-bot-canvas,
.walk-companion-canvas,
.walk-preview-canvas,
#drop-canvas,
#lx-field,
#avatar-canvas,
#walk-minimap,
.mocap-waveform {
	touch-action: pan-y;
}

/* ── Safe-area insets for the bars the audit found unprotected ─────────
 * Each of these is fixed or sticky, hugs the bottom edge, and had no rule
 * mentioning safe-area-inset applying to it, so on an iPhone its last row
 * of controls sits under the home indicator.
 *
 * Each rule keeps the bar's own designed bottom padding as the floor (the
 * value the audit measured) and only grows past it on a device that
 * actually reports an inset, so nothing shifts on a phone without one.
 */
@supports (padding: env(safe-area-inset-bottom)) {
	.lx-toolbar {
		padding-bottom: max(6px, env(safe-area-inset-bottom));
	}
	.irl-bottom {
		padding-bottom: max(14px, env(safe-area-inset-bottom));
	}
	#irl-caption-panel,
	#irl-error-sheet,
	#irl-mypins-sheet,
	#irl-agents-sheet {
		padding-bottom: max(36px, env(safe-area-inset-bottom));
	}
	#irl-calibrate-panel {
		padding-bottom: max(18px, env(safe-area-inset-bottom));
	}
}

/* ── /marketplace card controls on touch ──────────────────────────────
 * The card grid is deliberately dense on desktop (hover reveals the compose
 * CTA, the heart is a 16px glyph, tags are 18px pills). Under a thumb every
 * one of those was below the 44px floor: 1358 of 1735 targets on the page.
 * Each rule below grows the tappable box to 44px in its smaller dimension
 * while the painted visual stays the size the card was designed around:
 * transparent borders with `background-clip: padding-box` extend the box
 * without extending the pill, and negative margins hand the extra height
 * back so the card layout does not shift. Selectors repeat the page's own
 * specificity because pages/marketplace.html styles the same controls with
 * three-class selectors and this sheet only wins on a tie.
 */
@media (hover: none) and (pointer: coarse) {
	/* Title link: the inline stylesheet floors it at 32px with a
	   three-class selector, so match that specificity. */
	.market-card-avatar .title-row .title.card-profile-link,
	.market-card-agent .title.card-profile-link,
	.market-grid .card-profile-link {
		min-height: 44px;
		line-height: 1.3;
		display: flex;
		align-items: center;
	}

	/* Heart: 17x21 glyph. The title row is already 44px tall, so the box
	   grows sideways into a square centred on the glyph. */
	.market-card-avatar .title-row .card-heart,
	.card-heart {
		min-width: 44px;
		min-height: 44px;
		margin-top: 0;
		padding: 0;
		display: inline-grid;
		place-items: center;
	}

	/* Author: a 19px name in the byline. */
	.market-card-avatar .byline .card-author,
	a.card-author {
		display: inline-flex;
		align-items: center;
		min-width: 44px;
		min-height: 44px;
		margin: -13px 0;
	}

	/* Tag pills: 18px tall. Vertical transparent border grows the box to
	   44px, background-clip keeps the pill at its painted size, and the
	   negative margin keeps the wrap rows where they were. */
	.market-card-avatar .card-tags .tag-pill,
	.market-grid button.tag-pill {
		box-sizing: border-box;
		min-height: 44px;
		min-width: 44px;
		border-color: transparent;
		border-width: 13px 1px;
		background-clip: padding-box;
		/* The pill's 1px outline moves from the (now transparent) border to
		   an inset shadow, which paints at the padding-box edge. */
		box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
		margin: -13px 0;
		position: relative;
		z-index: 1;
	}
	.market-card-avatar .card-tags .tag-pill:active,
	.market-card-avatar .card-tags .tag-pill:focus-visible {
		box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4);
		border-color: transparent;
	}

	/* Compose CTA: hidden until hover on desktop, which a touch screen never
	   fires, so it is both visible and tappable here. */
	.market-card-avatar .footer .compose-cta {
		color: #a5b4fc;
		background: rgba(99, 102, 241, 0.15);
		border-color: rgba(99, 102, 241, 0.3);
		pointer-events: auto;
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding: 0 10px;
	}
	.market-card-avatar .footer .compose-cta:active {
		background: rgba(99, 102, 241, 0.25);
	}
	.market-card-avatar .footer .compose-cta:focus-visible {
		outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color, #fff);
		outline-offset: var(--focus-ring-offset, 2px);
	}

	/* Hero actions (287x37), slide dots (38x32: a 4px bar inside invisible
	   padding, so grow the padding), the "All" chip (43px wide) and the
	   leaderboard link (113x19). */
	.market-hero-cta,
	.market-hero-secondary,
	a.market-hero-secondary {
		min-height: 44px;
	}
	.market-hero-dots button,
	.market-hero-dot {
		padding: 20px 9px;
	}
	.market-chip {
		min-width: 44px;
		min-height: 44px;
	}
	.mkt-top-see-all {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
	.tws-disc-x {
		width: 44px;
		height: 44px;
	}
}

/* ── Tap-target floor, round 3 (touch only) ────────────────────────────
 * Measured by `npm run audit:mobile-touch` on a real Pixel 5 against
 * production on 2026-09-08; every size in a comment below is that run's
 * measured box. Same technique as round 2: raise the box to a 44px floor
 * and centre the existing content in it, gated on pointer type so a
 * desktop mouse keeps the designed compact sizing.
 *
 * The largest single finding of that run is not in this block, because it
 * was not a missing rule: 392 of the site's 584 stylesheet-bearing pages
 * never loaded this file at all. Everything under public/ is copied to
 * dist/ verbatim and bypassed the injector in vite.config.js, so /docs
 * (296 sidebar links at 267x30), /changelog and /ar were measuring rules
 * that had already been written for them. The post-build sweep in
 * vite.config.js's `mobile-ergonomics` plugin closes that.
 */
@media (hover: none) and (pointer: coarse) {
	/* Shared site footer link columns. 29 links measured at 165x20 on the
	   home page, stacked 9px apart in a grid that goes two-up at 460px, so
	   the hit areas were both short and adjacent. */
	.foot-col a {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* Home hero forge bar and its example chips: the site's primary call to
	   action. Input 186x36, submit 110x38, tries 101x27. */
	.hero-forge-input,
	.hero-forge-go,
	.hero-try {
		min-height: 44px;
	}
	.hero-try,
	.hero-forge-go {
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* Home mini-forge dock. Prompt 140x35, prompt chips 110x27, the enhance
	   icon 30x30, Forge 81x37, the options disclosure 96x26. */
	.hf-prompt,
	.hf-chip,
	.hf-forge-btn,
	.hf-opts-toggle {
		min-height: 44px;
	}
	.hf-chip,
	.hf-forge-btn,
	.hf-opts-toggle {
		display: inline-flex;
		align-items: center;
	}
	.hf-icon-mini {
		min-width: 44px;
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* Home partner strip (88x21 wordmarks), the embed playground's format
	   tabs and toolbar (52x25, 59x27, 26x26), the animation bar's stop
	   button (14x14, the smallest control measured anywhere in the run) and
	   the community-forge header controls (64x28, 151x40, 120x39). */
	.press-logo,
	.pg-tab,
	.pg-copy,
	.hcf-tab,
	.hcf-cta,
	.hcf-more,
	.hero-chip {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.pg-color-trigger,
	.wyg-anim-stop {
		min-width: 44px;
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* /markets. Every row's name cell is one 225x24 link inside a 49px cell,
	   so the link fills its cell rather than floating in the middle of it,
	   and the whole row becomes the target. News headlines are 19-39px. */
	td.name-cell > a {
		min-height: 44px;
		display: flex;
		align-items: center;
	}
	.nw-title a {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* The walk companion's own controls: 22x22, 22x22 and 20x21, floating
	   over whatever page summoned it. Its dismiss, avatar-swap, transition and
	   narration buttons are the same 22x22 and were missing from this list. */
	.walk-companion-trail,
	.walk-companion-c2w,
	.walk-companion-feedback,
	.walk-companion-close,
	.walk-companion-swap,
	.walk-companion-narrate {
		min-width: 44px;
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* /coin. Market rows (104x22 and 103x17 pair links), the chart range
	   segments (49x27) and the header pills (87x36). */
	.cv-mkt-x,
	.cv-mkt-pair,
	.cv-range-btn,
	.cv-pill {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.cv-mkt-pair {
		display: flex;
	}

	/* /ar. Mode chips 165x29, the brand link 98x19, the back-to-top 81x15. */
	.chip,
	a.brand,
	a.top {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /forge showcase. Round 2 gave these a height floor and they are still
	   too NARROW: the vote button measured 43x44 and the view-all link
	   25x48, both one axis short. The sort segments (61x22) and the refresh
	   icon (26x26) were missed entirely. */
	.showcase-vote,
	.showcase-view-all,
	.showcase-refresh {
		min-width: 44px;
		justify-content: center;
	}
	.showcase-sort-btn,
	.showcase-view-all {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.showcase-refresh {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /news is its own standalone shell: a 26px topbar nav and a 165x42
	   subscribe button. */
	header.topbar nav a,
	a.subscribe {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /changelog filter chips (28px) and /irl's onboarding link (142x32). */
	.cl-filter,
	.irl-ob-learn {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* Consent and preference checkboxes. A 22x22 box is a miss on a thumb;
	   giving the surrounding label the floor makes the whole row tappable,
	   which is what a checkbox row should have been all along. */
	label:has(> #irl-consent-dontshow) {
		min-height: 44px;
		display: flex;
		align-items: center;
	}

	/* Buttons that measured 43px on one axis are not a rounding artefact to
	   wave through: a 43px box IS under the floor. Pin them to 44. */
	.tws-disc-cta,
	.tws-es-btn {
		min-height: 44px;
	}
}

/* ── Tap-target floor, round 4 (touch only) ────────────────────────────
 * The residue of the 2026-09-08 run, re-measured against a local production
 * build once rounds 1-3 and the delivery fix above were in place. Two
 * shapes dominate it, and both are worth recognising because neither is
 * "we forgot a rule":
 *
 *   - One axis short. A control that already carries a height floor can
 *     still be 23px wide (a two-letter wordmark, an icon-only action).
 *     `min-height` alone never catches those, so these get `min-width`.
 *   - A component that declares its own floor BELOW 44. `min-height` beats
 *     `height`, so a page that sets a height loses to this file; a page
 *     that sets its own `min-height: 32px` in a runtime-injected <style>
 *     wins on equal specificity and later order. Those are fixed where they
 *     are declared instead of being fought from here (see
 *     src/irl/onboarding.js), which is why they are not in this list.
 */
@media (hover: none) and (pointer: coarse) {
	/* Home: partner wordmarks measured 23x44 and 28x44, the contract-address
	   copy button 353x26, and the floating brand chip 34x34 (public/brand.js
	   sizes it explicitly under 560px). */
	.press-logo {
		min-width: 44px;
		justify-content: center;
	}
	.foot-ca {
		min-height: 44px;
	}
	.brand-mark-chip {
		min-width: 44px;
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* /forge BYOK key field, 296x39. */
	.byok-input {
		min-height: 44px;
	}

	/* /news topbar links reach the height floor and stop at 38px wide. */
	header.topbar nav a {
		min-width: 44px;
		justify-content: center;
	}

	/* /coin: breadcrumbs (38x22), the narrow chart ranges (37x44 and 40x44)
	   and the copy-contract button (38x19). */
	.cv-crumbs a,
	.cv-contract button {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.cv-range-btn {
		min-width: 44px;
		justify-content: center;
	}

	/* /walk's skip link, 201x36. */
	.h-skip-link {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /play lobby: the identity disclosure and its field (both 315x40), the
	   feed sort segments (40px) and the footer links (43x44, 40x44). */
	.cc-id-toggle,
	.cc-sort,
	.cc-avatar-custom input {
		min-height: 44px;
	}
	.cc-foot-links a {
		min-width: 44px;
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* /launches: the hero CTAs (39px), the pulse-strip label (14px), the
	   network toggle (28px) and the oracle filter (27px); plus the two
	   round-2 controls that were short on the OTHER axis, 37x43 and 43x57. */
	.lx-btn,
	.lx-pulse-label,
	.lx-net-btn,
	.lx-of-btn {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.twc-make,
	.lx-action-watch,
	.lx-of-btn,
	.lx-net-btn {
		min-width: 44px;
		justify-content: center;
	}

	/* Docs shell: the world link is 35px wide, the header CTA 58x30, and the
	   sidebar search field 247x36. */
	.docs-world-link {
		min-width: 44px;
		justify-content: center;
	}
	.docs-header-right .btn-primary,
	.sidebar-search input {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
	.sidebar-search input {
		display: block;
	}

	/* /coin breadcrumbs and the copy-contract button reach the height floor and
	   stop at 38px wide. */
	.cv-crumbs a,
	.cv-contract button {
		min-width: 44px;
		justify-content: center;
	}

	/* /launches explore nav: 21px underlined links in a row of their own. */
	.lx-explore-link {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}

	/* /forge's two holder notes. Both paragraphs are flex containers, so the
	   link inside each is a standalone box rather than a word in a sentence
	   (which is why the WCAG 2.5.8 inline exception does not cover it), and
	   both measured 15px tall. */
	.fq-holder-note a,
	.fq-perk-line a {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
	}
}
