/* TradeBinder — application styles */

/* Fonts (self-hosted woff2, served by WhiteNoise; preloaded in base.html) ---- */
@font-face {
  font-family: "Cinzel"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/cinzel-v26-latin-600.bd1fede05376.woff2") format("woff2");
}
@font-face {
  font-family: "Cinzel"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../fonts/cinzel-v26-latin-700.82175d611596.woff2") format("woff2");
}
@font-face {
  font-family: "Source Sans 3"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/source-sans-3-v19-latin-regular.27ab01c4cb50.woff2") format("woff2");
}
@font-face {
  font-family: "Source Sans 3"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/source-sans-3-v19-latin-600.9a35cba76eda.woff2") format("woff2");
}
@font-face {
  font-family: "Source Sans 3"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../fonts/source-sans-3-v19-latin-700.9b13bd3653e3.woff2") format("woff2");
}

/* Single dark theme — "dark TCG premium": warm near-black, gold & parchment. */
:root {
  color-scheme: dark;
  --bg: #131009;
  --surface: #1e1812;
  --surface-2: #292117;
  --surface-3: #0e0b07;
  --text: #e7dfd0;
  --muted: #a49786;
  --border: #3d2c18;
  --border-strong: #5a4426;
  --gold: #ecbe6e;
  --gold-bright: #f7d795;
  --gold-deep: #b98f47;
  --gold-faint: rgba(236, 190, 110, .12);
  --oxblood: #531e18;
  --oxblood-bright: #7a2e24;
  --primary: #ecbe6e;
  --primary-hover: #f7d795;
  --primary-contrast: #201505;
  --success: #86c28b;
  --success-bg: rgba(134, 194, 139, .12);
  --warning: #e0aa52;
  --warning-bg: rgba(224, 170, 82, .13);
  --danger: #e2745f;
  --danger-bg: rgba(226, 116, 95, .13);
  --radius: 10px;
  --radius-sm: 7px;
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .35);
  --ring: 0 0 0 3px rgba(236, 190, 110, .28);
  --font-display: "Cinzel", "Times New Roman", serif;
}

* { box-sizing: border-box; }

body {
  font-family: "Source Sans 3", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  margin: 0;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--gold); text-decoration: none; }
a:hover { text-decoration: underline; color: var(--gold-bright); }

h1 { font-family: var(--font-display); font-weight: 700; font-size: 1.55rem; margin: 0 0 .25rem; letter-spacing: .01em; color: var(--gold); }
h2 { font-family: var(--font-display); font-weight: 600; font-size: 1.1rem; margin: 1.5rem 0 .75rem; letter-spacing: .02em; color: var(--gold-deep); }
h3 { font-size: .95rem; margin: 0 0 .5rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }

/* Inline SVG icons (symbols defined in base.html) */
.icon { width: 1em; height: 1em; vertical-align: -.13em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* Layout ------------------------------------------------------------------ */
/* 68rem: wide enough that the search-results rows (one-line add controls) fit
   without the horizontal scrollbar; .table-scroll stays as the narrow-window
   fallback. */
.container { max-width: 68rem; margin: 0 auto; padding: 1.5rem 1.25rem 4rem; }

/* Top nav ----------------------------------------------------------------- */
.topnav {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: 1.25rem;
  padding: .7rem 1.25rem;
  background: color-mix(in srgb, var(--surface-3) 90%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 var(--gold-faint);
}
.topnav .brand {
  font-family: var(--font-display); font-weight: 700; font-size: 1rem;
  letter-spacing: .06em; color: var(--gold);
  display: inline-flex; align-items: center; gap: .45rem;
}
.topnav .brand .icon { width: 1.15em; height: 1.15em; stroke: var(--gold-deep); }
.topnav .brand:hover { text-decoration: none; color: var(--gold-bright); }
.topnav .spacer { flex: 1; }
.topnav a:not(.brand) {
  color: var(--muted); font-weight: 600; padding: .3rem .1rem;
  border-bottom: 2px solid transparent;
}
.topnav a:not(.brand):hover { color: var(--gold-bright); text-decoration: none; }
.topnav a[aria-current="page"] { color: var(--gold); border-bottom-color: var(--gold-deep); }
.topnav .who { color: var(--muted); font-size: .9rem; }
@media (max-width: 40rem) {
  .topnav { flex-wrap: wrap; gap: .4rem .9rem; row-gap: .15rem; padding: .55rem .9rem; }
  .topnav .who { display: none; }  /* email crowds phones; Log out still shows */
}

/* Buttons ----------------------------------------------------------------- */
.btn, button {
  font: inherit; font-weight: 600;
  padding: .45rem .9rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  cursor: pointer; display: inline-flex; align-items: center; gap: .35rem;
  transition: background .12s, border-color .12s, transform .04s;
}
.btn:hover, button:hover { background: var(--surface-2); border-color: var(--border-strong); text-decoration: none; }
.btn:active, button:active { transform: translateY(1px); }
.btn:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; box-shadow: var(--ring); border-color: var(--primary);
}
.btn-primary, button.btn-primary {
  background: var(--primary); border-color: var(--primary); color: var(--primary-contrast);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25);
}
.btn-primary:hover, button.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
.btn-danger:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }
.btn-sm { padding: .25rem .55rem; font-size: .82rem; }
button:disabled { opacity: .5; cursor: not-allowed; }
.linkbtn { background: none; border: none; padding: 0; color: var(--muted); font: inherit; font-weight: 500; }
.linkbtn:hover { background: none; color: var(--text); text-decoration: underline; }

/* Panels & sections ------------------------------------------------------- */
.panel {
  background: var(--surface); border: 1px solid var(--border);
  border-top-color: var(--border-strong);
  border-radius: var(--radius); padding: 1.1rem 1.25rem; box-shadow: var(--shadow);
  margin-bottom: 1.25rem;
}
.page-actions { display: flex; gap: 1rem; margin: .25rem 0 1.5rem; font-weight: 500; flex-wrap: wrap; }
.toolbar { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.muted, .helptext { color: var(--muted); font-size: .88rem; }
.errorlist { color: var(--danger); list-style: none; padding: 0; margin: .5rem 0; }

/* Inputs ------------------------------------------------------------------ */
input[type=text], input[type=email], input[type=password], input[type=search],
input[type=number], input[type=file], select, textarea {
  font: inherit; color: var(--text); background: var(--surface-3);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .45rem .6rem;
}
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--muted) 75%, transparent); }
textarea { width: 100%; }
.search-input {
  width: 100%; max-width: 32rem; padding: .6rem .8rem; font-size: 1rem;
}
.form p { margin: .6rem 0; display: flex; flex-wrap: wrap; gap: .25rem .6rem; align-items: center; }
.form label { min-width: 8rem; color: var(--muted); font-weight: 500; }

/* Tables ------------------------------------------------------------------ */
/* On phones the tables keep their natural width and swipe inside this wrapper
   instead of crushing their columns (or panning the whole page). */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 44rem) {
  .table-scroll > .data-table { min-width: 42rem; }   /* read-only rows: 6–8 text columns fit the one canvas */
}
.data-table { width: 100%; border-collapse: collapse; }
.data-table thead th {
  text-align: left; font-size: .74rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--gold-deep); font-weight: 700; padding: .5rem .6rem; border-bottom: 1px solid var(--border);
}
.data-table tbody td { padding: .55rem .6rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tbody tr:hover { background: var(--surface-2); }
.data-table .actions { white-space: nowrap; text-align: right; }
.num { font-variant-numeric: tabular-nums; }

/* Fixed-layout tables ----------------------------------------------------- */
/* Fixed column widths (set via <colgroup>) so an out-of-band row refresh
   can't re-balance the table — nothing shifts horizontally. */
.data-table--fixed { table-layout: fixed; }
.data-table--fixed td, .data-table--fixed th { overflow: hidden; text-overflow: ellipsis; }
.field-error { color: var(--danger); font-size: .8rem; margin-top: .25rem; }

/* Badges ------------------------------------------------------------------ */
.badge {
  display: inline-block; padding: .12rem .5rem; border-radius: 999px;
  font-size: .76rem; font-weight: 600; border: 1px solid var(--border); color: var(--muted);
}
.badge--mutual { color: var(--success); background: var(--success-bg); border-color: transparent; }
.badge--ok { color: var(--success); background: var(--success-bg); border-color: transparent; }
.badge--warn { color: var(--warning); background: var(--warning-bg); border-color: transparent; }
.badge--err { color: var(--danger); background: var(--danger-bg); border-color: transparent; }

/* Search results ---------------------------------------------------------- */
.results { list-style: none; padding: 0; margin: .75rem 0 0; max-width: 42rem; }
.results li { border-bottom: 1px solid var(--border); padding: .5rem 0; }
.result-form { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.result-form .grow { flex: 1; min-width: 12rem; }
/* Fixed-width controls so dropdown vs fixed-language rows align cleanly. */
.result-form .finish-sel { width: 9rem; }
.result-form .lang-cell { display: inline-flex; align-items: center; justify-content: center; min-width: 3.75rem; }
.result-form .lang-cell select { width: 100%; }
.result-form .qty { width: 4rem; }

/* Messages ---------------------------------------------------------------- */
.messages { list-style: none; padding: 0; margin: 0 0 1.25rem; }
.messages li {
  padding: .6rem .85rem; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; margin-bottom: .5rem;
  background: var(--success-bg); color: var(--success); font-weight: 500;
  border-left: 3px solid var(--success);
}
.messages li.error { background: var(--danger-bg); color: var(--danger); border-left-color: var(--danger); }

/* Matches ----------------------------------------------------------------- */
.match-grid { display: flex; gap: 2rem; flex-wrap: wrap; padding: .25rem 1rem 1rem; }
.match-col { flex: 1; min-width: 16rem; }
.match-list { list-style: none; margin: .25rem 0 0; padding: 0; }
.match-list li {
  display: flex; gap: .6rem; align-items: flex-start;
  padding: .5rem 0; border-bottom: 1px solid var(--border);
}
.match-list li:last-child { border-bottom: none; }
.match-list li > span { display: flex; flex-direction: column; gap: .05rem; font-size: .9rem; }
.match-qty { color: var(--gold-deep); font-size: .82rem; font-weight: 600; }

/* Empty state ------------------------------------------------------------- */
.empty { color: var(--muted); padding: 1rem .25rem; }

/* Code/format help -------------------------------------------------------- */
pre.help { background: var(--surface-2); padding: .8rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border); overflow-x: auto; font-size: .85rem; }
code { background: var(--surface-2); padding: .05rem .3rem; border-radius: 4px; font-size: .9em; }

/* Pitch badge (FAB: 1=red, 2=yellow, 3=blue) ------------------------------ */
.pitch {
  display: inline-block; min-width: 1.15rem; text-align: center;
  padding: .02rem .32rem; border-radius: 5px; font-size: .72rem; font-weight: 800;
  color: #fff; vertical-align: middle;
}
.pitch--1 { background: #cf4c3c; }
.pitch--2 { background: #c9941a; }
.pitch--3 { background: #3d7dc9; }
.cardno { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Set list ---------------------------------------------------------------- */
.set-list { columns: 2; column-gap: 2rem; max-width: 52rem; padding-left: 1.1rem; }
@media (max-width: 40rem) { .set-list { columns: 1; } }
.set-list li { margin: .15rem 0; break-inside: avoid; }

/* Catalogue search (ported look from fab-collection-ui) -------------------- */
.htmx-indicator { opacity: 0; transition: opacity .15s; margin-left: .5rem; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }

/* Label stays in its own column; the chips wrap to the right of it. */
.chip-group { display: flex; gap: .4rem; align-items: flex-start; margin-top: .6rem; }
.chip-group .chips { display: flex; flex-wrap: wrap; gap: .4rem; flex: 1; }
.chip-label { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; min-width: 5.2rem; flex: none; padding-top: .3rem; }
@media (max-width: 40rem) {
  /* Phones: label above full-width chips — halves the chip rows. */
  .chip-group { flex-direction: column; gap: .3rem; }
  .chip-label { padding-top: 0; }
}
.filter-chip { position: relative; display: inline-flex; align-items: center; cursor: pointer; }
.filter-chip input { position: absolute; opacity: 0; pointer-events: none; }
.filter-chip span {
  display: inline-block; padding: .22rem .6rem; border-radius: 999px; font-size: .82rem;
  border: 1px solid var(--border); background: var(--surface); color: var(--muted);
  transition: background .12s, color .12s, border-color .12s;
}
.filter-chip:hover span { background: var(--surface-2); }
.filter-chip input:checked + span {
  background: var(--primary); border-color: var(--primary);
  color: var(--primary-contrast); font-weight: 600;
}
.filter-chip input:focus-visible + span { box-shadow: var(--ring); }

/* Grouped results */
details.cardgroup {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); margin: .5rem 0; box-shadow: var(--shadow);
}
details.cardgroup > summary {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .7rem 1rem; cursor: pointer; list-style: none; user-select: none;
}
details.cardgroup > summary::-webkit-details-marker { display: none; }
.group-thumb {
  width: 34px; height: 48px; border-radius: 3px; object-fit: cover; flex: none;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .5); border: 1px solid var(--border);
}
.group-thumb--none {
  display: inline-block;
  background: linear-gradient(150deg, var(--oxblood) 0%, var(--surface-3) 85%);
}
details.cardgroup > summary::after {
  content: "▸"; margin-left: auto; color: var(--gold-deep); font-size: .85rem;
  transition: transform .15s;
}
details.cardgroup > summary:hover { background: var(--surface-2); border-radius: var(--radius); }
details.cardgroup > summary > strong {
  font-family: var(--font-display); font-weight: 600; font-size: .92rem; letter-spacing: .02em;
}
details.cardgroup[open] > summary::after { transform: rotate(90deg); }
details.cardgroup[open] { border-color: var(--gold-deep); }
details.cardgroup[open] > summary:hover { border-radius: var(--radius) var(--radius) 0 0; }
.cardgroup-table { margin: 0 0 .25rem; }
.cardgroup-table td { font-size: .9rem; }
/* Long set names clamp with an ellipsis (full name in the title tooltip) so the
   row stays one line; the add-a-copy controls likewise never wrap. */
.cardgroup-table .set-cell {
  max-width: 13rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Flat (card-# sorted) results share the grouped view's chrome: same gilded box,
   and each row carries the summary-style thumbnail + Cinzel name. */
.flat-results {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  margin: .5rem 0; padding: .35rem .5rem;
}
/* Flat rows stack the set (muted) under the card name in one cell — one fewer
   column, so the add-a-copy controls stay on screen without horizontal scroll. */
.flat-name { max-width: 17rem; }
.flat-name-wrap { display: flex; align-items: center; gap: .55rem; }
.flat-name-wrap .group-thumb { flex: none; }
.flat-name-stack { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.flat-name-stack > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flat-name strong {
  font-family: var(--font-display); font-weight: 600; font-size: .92rem;
  letter-spacing: .02em;
}
.flat-set { font-size: .8rem; }

/* Rarity badges (palette from the old app) */
.rarity-badge {
  display: inline-block; padding: .1rem .5rem; border-radius: 5px;
  font-size: .74rem; font-weight: 700; color: #fff; white-space: nowrap;
}
.rarity-common { background: #64748b; }
.rarity-rare { background: #06b6d4; }
.rarity-super-rare { background: #3b62d9; }
.rarity-majestic { background: #db2777; }
.rarity-legendary { background: #f97316; }
.rarity-fabled { background: #dc2626; }
.rarity-marvel { background: #0aa173; }
.rarity-promo { background: #7c3aed; }
.rarity-promo-marvel { background: #6d3fd1; }
.rarity-gold { background: #facc15; color: #201505; }
.rarity-gold-marvel { background: #f59e0b; }
.rarity-token { background: #14b8a6; }
.rarity-basic { background: #94a3b8; color: #201505; }

/* Pitch row tints (translucent — work in light & dark) */
.pitch-row-1 { background: rgba(239, 68, 68, .07); }
.pitch-row-2 { background: rgba(234, 179, 8, .09); }
.pitch-row-3 { background: rgba(59, 130, 246, .08); }

/* Empty / prompt state */
.empty-state { text-align: center; padding: 3.5rem 1rem; color: var(--muted); }
.empty-state-icon { font-size: 2.6rem; margin-bottom: .6rem; color: var(--gold-deep); }
.empty-state-icon .icon { width: 1.2em; height: 1.2em; stroke-width: 1.2; }
.empty-state-title {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.1rem; color: var(--text);
}

/* Hover card-image previews (hotlinked from the official CDN) ----------------
   position:fixed keeps the popover unclippable; the small script in base.html
   places it next to the hovered link, clamped inside the viewport. Without JS
   these offsets pin it centre-right as a fallback. */
.card-preview {
  display: none; position: fixed; z-index: 40;
  top: 50%; right: 1.25rem; transform: translateY(-50%);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: .4rem; box-shadow: var(--shadow);
}
.card-preview:empty { display: none !important; }  /* nothing to show pre-fetch */
@media (hover: hover) { td.preview-anchor:hover .card-preview { display: block; } }  /* a tap is not a hover: never on phones */
td.preview-anchor .cell-clip {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-preview-imgs { display: flex; gap: .4rem; }
.card-preview-imgs img {
  width: 240px; height: auto; display: block; border-radius: 10px;
  aspect-ratio: 376 / 526;  /* card faces' CDN dimensions — sizes the popover pre-load */
}
/* Sideways/split cards (Burn Up||Shock) ship as portrait scans meant to be read
   landscape — rotate them. 240px-wide portrait ≈ 336px tall → rotated box 336×240. */
.card-preview-imgs.horizontal { position: relative; width: 336px; height: 240px; }
.card-preview-imgs.horizontal img {
  width: 240px; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%) rotate(90deg);
}
/* A few CDN scans are rotated the opposite way (MISROTATED_SCANS in cardnums.py). */
.card-preview-imgs.horizontal.flip img { transform: translate(-50%, -50%) rotate(-90deg); }
/* Popover with no loadable image (missing CDN file) — hidden by the base.html script. */
.card-preview.preview-broken { display: none !important; }
/* Two-faced printings (double-sided Marvels): one face at a time, turned over
   with a button — the pair side by side overflowed the sheet's face column and
   the phone's sheet. .faces turns in 3D; the back face sits behind the front. */
.card-preview-imgs.two-faced { display: block; width: fit-content; position: relative; perspective: 900px; }
.two-faced .faces { display: block; position: relative; transform-style: preserve-3d; transition: transform .45s ease; }
.two-faced .face-front, .two-faced .face-back { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.two-faced .face-front { transform: rotateY(0deg); }   /* WebKit honours backface-visibility only on a transformed element */
.two-faced .face-back { position: absolute; inset: 0; transform: rotateY(180deg); }
.two-faced.turned .faces { transform: rotateY(180deg); }
.face-turn {
  position: absolute; right: .45rem; bottom: .45rem; z-index: 2;
  width: 2.3rem; height: 2.3rem; padding: 0; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.15rem; line-height: 1;
  background: rgba(0, 0, 0, .62); color: #fff; border: 1px solid rgba(255, 255, 255, .45); box-shadow: none; cursor: pointer;
}
.face-turn:hover { background: rgba(0, 0, 0, .82); }
.face-turn:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
/* A sideways two-faced printing (Mistcloak Gully // Inner Chi, the one such
   card): keep .horizontal's rotated 336×240 box with both faces centred in it
   (the .horizontal img rule has the higher specificity, so each face is said
   again here), and compose the back's turn INTO its rotation — the parent's
   rotateY(180) and the back's cancel, leaving rotate(90), so the turned back
   reads the same way up as the front; .flip scans mirror to -90. */
.card-preview-imgs.horizontal.two-faced { width: 336px; }
.card-preview-imgs.horizontal.two-faced .faces { width: 336px; height: 240px; }
.card-preview-imgs.horizontal.two-faced .face-back { inset: auto; left: 50%; top: 50%; transform: translate(-50%, -50%) rotateY(180deg) rotate(90deg); }
.card-preview-imgs.horizontal.flip.two-faced .face-back { transform: translate(-50%, -50%) rotateY(180deg) rotate(-90deg); }
/* In the sheet's face column (15rem) a sideways card is scaled to fit: its
   rotated 336×240 box reached 80px into the sections beside it — over the
   title, the summary and the add box. 240 wide → scans 171px, box 240×171. */
.sheet-face .card-preview-imgs.horizontal,
.sheet-face .card-preview-imgs.horizontal.two-faced,
.sheet-face .card-preview-imgs.horizontal.two-faced .faces { width: 240px; height: 171px; }
.sheet-face .card-preview-imgs.horizontal img { width: 171px; }
/* The hover popover has room: both faces side by side, no button. A sideways
   pair keeps its box and shows the front (the sheet has the turn button). */
.card-preview .two-faced { display: flex; width: auto; perspective: none; }
.card-preview .two-faced .faces { display: flex; gap: .4rem; transform: none; }
.card-preview .two-faced .face-back { position: static; transform: none; }
.card-preview .horizontal.two-faced { display: block; width: 336px; }
.card-preview .horizontal.two-faced .faces { display: block; width: 336px; height: 240px; }
.card-preview .horizontal.two-faced .face-back { position: absolute; transform: translate(-50%, -50%) rotateY(180deg) rotate(90deg); }
.card-preview .face-turn { display: none; }
/* Foil shine (cardvault-style): a gradient layered over the scan with
   mix-blend-mode color-dodge, masked to a soft spotlight. --fx/--fy are unitless
   0–100 cursor coordinates set by base.html; without JS it sits at the centre. */
.card-preview-imgs.foil {
  position: relative;
  transform: perspective(900px)
    rotateY(calc((var(--fx, 50) - 50) * 0.1deg))
    rotateX(calc((50 - var(--fy, 50)) * 0.1deg));
  transition: transform .15s ease-out;
}
.foil-shine {
  position: absolute; inset: 0; border-radius: 10px; pointer-events: none;
  mix-blend-mode: color-dodge; opacity: .75;
  background-size: 220% 220%;
  background-position: calc(var(--fx, 50) * 1%) calc(var(--fy, 50) * 1%);
  -webkit-mask-image: radial-gradient(circle at calc(var(--fx, 50) * 1%) calc(var(--fy, 50) * 1%),
      rgba(255, 255, 255, .9) 12%, rgba(255, 255, 255, 0) 55%);
  mask-image: radial-gradient(circle at calc(var(--fx, 50) * 1%) calc(var(--fy, 50) * 1%),
      rgba(255, 255, 255, .9) 12%, rgba(255, 255, 255, 0) 55%);
}
.foil--rainbow .foil-shine {
  background-image: repeating-linear-gradient(130deg,
    hsla(283, 49%, 60%, 1), hsla(2, 74%, 59%, 1), hsla(75, 60%, 50%, .7),
    hsla(93, 56%, 52%, 1), hsla(176, 38%, 50%, 1), hsla(228, 100%, 77%, 1),
    hsla(283, 49%, 61%, 1));
}
.foil--cold .foil-shine {
  opacity: .55;
  background-image: repeating-linear-gradient(130deg,
    hsla(210, 15%, 65%, 1), hsla(200, 30%, 85%, 1), hsla(220, 10%, 55%, .8),
    hsla(190, 25%, 80%, 1), hsla(210, 15%, 65%, 1));
}
.foil--gold .foil-shine {
  opacity: .55;
  background-image: repeating-linear-gradient(130deg,
    hsla(40, 65%, 55%, 1), hsla(48, 90%, 75%, 1), hsla(35, 50%, 45%, .8),
    hsla(45, 85%, 70%, 1), hsla(40, 65%, 55%, 1));
}
.trade-cell { white-space: nowrap; }
.trade-cell .muted { font-size: .8rem; }
/* "Got [n] ✓" / "Traded [n] ✓" read as one labeled phrase, not two stray
   number boxes (owner: which qty box is which?). */
.count-action { display: inline-flex; gap: .3rem; align-items: center; white-space: nowrap; }
.count-action[hidden] { display: none; }  /* the two-step reveal; the class's display would beat the attribute */
button[hidden], .btn[hidden] { display: none; }  /* Got… / Traded… hide once their row is revealed */
/* Per-finish owned breakdown next to the Search page's owned count. */
.owned-breakdown { font-size: .76rem; white-space: nowrap; }

/* Binder grid view (?view=grid) --------------------------------------------- */
.view-toggle { display: inline-flex; margin-left: auto; }
.view-toggle .btn { border-radius: 0; margin-left: -1px; }
.view-toggle .btn:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); margin-left: 0; }
.view-toggle .btn:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.view-toggle .btn.active {
  background: var(--gold-faint); color: var(--gold); border-color: var(--border-strong);
  position: relative; z-index: 1;
}
.binder-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 1rem; padding: 1.1rem; margin-top: 1rem;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
}
.card-tile {
  position: relative; display: block; border-radius: 8px;
  transition: transform .12s ease-out, box-shadow .12s ease-out;
}
.card-tile img, .card-tile-back {
  display: block; width: 100%; aspect-ratio: 376 / 526; border-radius: 8px;
  border: 1px solid var(--border); object-fit: cover;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}
.card-tile:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, .55), 0 0 0 1px var(--gold-deep);
  text-decoration: none;
}
.card-tile-back {
  background: linear-gradient(150deg, var(--oxblood) 0%, var(--surface-3) 90%);
  display: flex; align-items: center; justify-content: center; text-align: center;
  padding: .75rem;
}
.card-tile-name {
  font-family: var(--font-display); font-weight: 600; font-size: .85rem;
  color: var(--gold-deep); line-height: 1.3; overflow-wrap: anywhere;
}
.tile-qty {
  position: absolute; right: .4rem; bottom: .45rem;
  background: rgba(14, 11, 7, .88); color: var(--gold);
  font-size: .78rem; font-weight: 700; font-variant-numeric: tabular-nums;
  padding: .05rem .45rem; border-radius: 999px; border: 1px solid var(--border-strong);
  /* All cards' "12 · 8 St · 2 RF · 1 CF" stays one line inside the tile (the sheet has the whole breakdown). */
  white-space: nowrap; max-width: calc(100% - .8rem); overflow: hidden; text-overflow: ellipsis;
}
.tile-price {
  position: absolute; left: .4rem; top: .45rem;
  background: rgba(14, 11, 7, .88); color: var(--text);
  font-size: .72rem; font-weight: 600; font-variant-numeric: tabular-nums;
  padding: .05rem .4rem; border-radius: 999px; border: 1px solid var(--border-strong);
}
.tile-dots { position: absolute; right: .45rem; top: .45rem; display: flex; gap: .3rem; }
.tile-dot {
  width: .62rem; height: .62rem; border-radius: 50%;
  border: 1px solid rgba(14, 11, 7, .8); box-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}
.tile-dot--trade { background: var(--success); }
.tile-dot--want { background: #e0669a; }
/* All cards: a card you own nothing of is dimmed; ♡/⇄ signals inline. */
.card-tile--unowned img, .card-tile--unowned .card-tile-back { filter: brightness(.55); }
.card-tile--unowned:hover img, .card-tile--unowned:hover .card-tile-back { filter: brightness(.8); }
.sig { font-size: .85em; }
.sig--trade { color: var(--success); }
.sig--want { color: #e0669a; }
.tile-chip {
  position: absolute; left: .4rem; bottom: .45rem; max-width: calc(100% - 3.4rem);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: rgba(14, 11, 7, .88); color: var(--gold-bright);
  font-size: .72rem; font-weight: 600;
  padding: .05rem .45rem; border-radius: 999px; border: 1px solid var(--gold-deep);
}
.tile-dot--foil {
  background: conic-gradient(#c96ee0, #e05a52, #a4c94a, #52b8a4, #7d95e8, #c96ee0);
}

/* Friends --------------------------------------------------------------------- */
.friend-list { list-style: none; padding: 0; margin: 0 0 1.5rem; }
.friend-list li {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .65rem .9rem; margin: .4rem 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.friend-list .friend-name { font-weight: 600; }
.friend-list .friend-actions { margin-left: auto; display: flex; gap: .4rem; align-items: center; }

/* Auth entrance & landing --------------------------------------------------- */
body.auth-page {
  background:
    radial-gradient(60rem 40rem at 50% -10rem, color-mix(in srgb, var(--oxblood) 55%, transparent), transparent 70%),
    var(--bg);
  min-height: 100vh;
}
.auth-card {
  max-width: 26rem; margin: 9vh auto 0;
  border-top: 2px solid var(--gold-deep);
  padding: 1.6rem 1.75rem 1.25rem;
}
.auth-card h1 { margin-bottom: .1rem; }
.auth-card .form label { min-width: 100%; margin-bottom: -.25rem; }
.auth-card .form input { width: 100%; }
.auth-submit { width: 100%; justify-content: center; padding: .6rem; }
.auth-foot { border-top: 1px solid var(--border); padding-top: .8rem; margin-bottom: 0; }

.hero { display: flex; gap: 3rem; align-items: center; padding: 3rem 0 1rem; flex-wrap: wrap; }
.hero-copy { flex: 1; min-width: 18rem; }
.hero-copy h1 { font-size: 2.1rem; line-height: 1.2; }
.hero-copy p { max-width: 34rem; font-size: 1.05rem; }
.hero-fan { position: relative; width: 21rem; height: 17rem; flex: none; margin: 0 auto; }
.hero-fan img {
  position: absolute; width: 11rem; aspect-ratio: 376 / 526; border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .6);
  border: 1px solid var(--border-strong);
}
.hero-fan img:nth-child(1) { left: 0; top: 2.2rem; transform: rotate(-9deg); }
.hero-fan img:nth-child(2) { left: 5rem; top: .6rem; z-index: 1; }
.hero-fan img:nth-child(3) { left: 10rem; top: 2.2rem; transform: rotate(9deg); }

.home-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 1rem; margin-top: 1.25rem; }
.home-tile { display: flex; flex-direction: column; gap: .15rem; margin: 0; }
.home-tile:hover { text-decoration: none; border-color: var(--gold-deep); }
.home-tile .icon { width: 1.6rem; height: 1.6rem; stroke: var(--gold-deep); margin-bottom: .35rem; }
.home-tile-title {
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
  letter-spacing: .02em; color: var(--gold);
}

/* Set filter box + its clear button (see binder/_set_filter.html). */
/* One clear affordance per field: the native search-cancel ✕ is hidden
   app-wide (it doubled up with ours and doesn't exist on iOS anyway). */
input[type="search"]::-webkit-search-cancel-button { display: none; }

.set-filter { display: inline-flex; gap: .35rem; align-items: center; position: relative; }
.set-filter input { padding-right: 2.2rem; }
.set-filter .set-clear {
  position: absolute; right: .3rem; top: 50%; transform: translateY(-50%);
  background: none; border: none; box-shadow: none;
  color: var(--muted); font-size: 1rem; line-height: 1; padding: .3rem .5rem; cursor: pointer;
}
.set-filter .set-clear:hover { color: var(--text); background: none; border: none; }
/* Pressed: keep the centring. The global button:active nudge (translateY(1px),
   .btn rules above) outranks the class's own transform, and without this the
   ✕ dropped half its height under the pointer on mousedown — a press near its
   top released over the input and never became a click. */
.set-filter .set-clear:active, .q-clear:active { transform: translateY(calc(-50% + 1px)); }
/* The ✕s appear only when there's something to clear (mirrors native behavior). */
.set-filter input:placeholder-shown ~ .set-clear,
.find-box input:placeholder-shown ~ .q-clear { display: none; }
/* Our filterable dropdown replacing <datalist> (invisible on iOS — it only
   feeds the keyboard suggestion bar there). */
.set-suggest {
  position: absolute; top: calc(100% + .3rem); left: 0; z-index: 40;
  min-width: 100%; max-width: 22rem; max-height: 14rem; overflow-y: auto;
  /* Touch-scrollable: momentum scrolling, vertical pans stay in the list
     instead of chaining to (or panning) the page. */
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain; touch-action: pan-y;
  margin: 0; padding: .25rem; list-style: none;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
}
.set-suggest li {
  padding: .4rem .6rem; border-radius: var(--radius-sm);
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.set-suggest li:hover, .set-suggest li.active { background: var(--surface-3); }

/* Collapsible "More filters" row (class/talent/type/cost/format dropdowns). */
.more-filters { margin-top: .6rem; }
.more-toggle { color: var(--muted); }
.more-toggle::after { content: " ▾"; font-size: .8em; }
.more-toggle[aria-expanded="true"]::after { content: " ▴"; }
.more-dot {
  display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--primary); vertical-align: middle; margin-left: .15rem;
}
.more-panel { margin-top: .5rem; }
/* The hidden attribute's UA display:none loses to the author .toolbar
   display:flex rule — restate it so the collapse actually collapses. */
.more-panel[hidden] { display: none; }

/* Main search box with the clear-everything ✕ tucked inside its right edge. */
.find-box { position: relative; display: inline-block; width: 100%; max-width: 32rem; vertical-align: middle; }
.find-box .search-input { max-width: none; padding-right: 2.4rem; }
.q-clear {
  position: absolute; right: .3rem; top: 50%; transform: translateY(-50%);
  background: none; border: none; box-shadow: none;
  color: var(--muted); font-size: 1rem; line-height: 1; padding: .3rem .5rem; cursor: pointer;
}
.q-clear:hover { color: var(--text); background: none; border: none; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Decks -------------------------------------------------------------------- */
.deck-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr)); gap: .8rem; }
.deck-card { display: flex; gap: .8rem; align-items: center; text-decoration: none; color: inherit; }
.deck-card:hover { border-color: var(--primary); }
.deck-card-body { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.deck-meta { display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; margin-top: .2rem; }
.deck-hero-thumb { width: 48px; height: 67px; border-radius: 4px; object-fit: cover; flex: none; }
.deck-header { display: flex; gap: .9rem; align-items: center; flex-wrap: wrap; margin-bottom: .6rem; }
.deck-header-body { flex: 1 1 16rem; min-width: 0; }
.deck-tabs { display: flex; gap: .25rem; margin: .4rem 0 1rem; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.deck-tabs a { padding: .45rem .8rem; color: var(--muted); text-decoration: none; border-bottom: 2px solid transparent; }
.deck-tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--primary); }
.deck-status { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: center; }
.deck-counts { display: flex; flex-wrap: wrap; gap: .35rem; align-items: baseline; }
.deck-issues { flex-basis: 100%; margin: .2rem 0 0; padding-left: 1.2rem; }
.deck-issue--error { color: var(--danger); }
.deck-issue--warning { color: var(--warning); }
.pitch-bar { display: flex; flex-direction: column; gap: .2rem; min-width: 11rem; flex: 0 0 auto; }
.pitch-bar-row { display: flex; align-items: center; gap: .4rem; }
.pitch-bar-track { flex: 1; height: .55rem; background: var(--surface-3); border-radius: 999px; overflow: hidden; }
.pitch-bar-fill { display: block; height: 100%; border-radius: 999px; }
.pitch-bar-fill--1 { background: #cf4c3c; }
.pitch-bar-fill--2 { background: #c9941a; }
.pitch-bar-fill--3 { background: #3d7dc9; }
/* Deck editor (fabrary-style): pool (left) + deck (right); stacks on narrow screens. */
.deck-editor { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
@media (max-width: 60rem) { .deck-editor { grid-template-columns: minmax(0, 1fr); } }
.deck-editor-pool, .deck-editor-deck { min-width: 0; }
.pool-filters { margin-bottom: .8rem; }
.pool-chips { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.chip-sep { width: 1px; height: 1.3rem; background: var(--border); margin: 0 .2rem; }
.pitch-dots { letter-spacing: -.05em; font-size: .9em; line-height: 1; }
/* Pitch chips carry their colour (owner: "should be color coded"). */
.filter-chip--pitch-1 > span { color: #e0604f; border-color: #cf4c3c; background: rgba(207, 76, 60, .12); }
.filter-chip--pitch-2 > span { color: #dba627; border-color: #c9941a; background: rgba(201, 148, 26, .14); }
.filter-chip--pitch-3 > span { color: #6a9fdd; border-color: #3d7dc9; background: rgba(61, 125, 201, .14); }
.filter-chip--pitch-1 input:checked + span { background: #cf4c3c; color: #fff; border-color: #cf4c3c; }
.filter-chip--pitch-2 input:checked + span { background: #c9941a; color: #1a1408; border-color: #c9941a; }
.filter-chip--pitch-3 input:checked + span { background: #3d7dc9; color: #fff; border-color: #3d7dc9; }
.filter-chip > span .pitch-dots { color: inherit; }
.pool-search { margin-top: .6rem; }
.pool-filter-panel .more-panel { margin-top: .6rem; padding-top: .6rem; border-top: 1px solid var(--border); }
.stat-filter { display: inline-flex; align-items: center; gap: .25rem; }
.stat-filter-label { font-size: .78rem; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.stat-filter select { width: auto; padding-right: 1.6rem; }
.stat-filter input[type=number] { width: 4.2rem; }
.pool-search .find-box { flex: 1 1 9rem; }
/* The idle "searching…" indicator takes no room (htmx only fades it), so the
   sort, Filters and Grid | List stay on the search's row. */
.pool-search .htmx-indicator { display: none; }
.pool-filters.htmx-request .pool-search .htmx-indicator { display: inline; }
.deck-total { margin: .2rem 0 .4rem; }
.deck-section-title { margin: .8rem 0 .4rem; font-size: 1.05rem; }
.deck-notes { margin-bottom: .8rem; }
/* Card tiles: the card image, in the editor with fabrary's [0..N] buttons
   underneath at ~98px wide (the Cards tab keeps its larger tiles). */
.deck-tiles {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(8.4rem, 1fr));
  gap: .55rem; padding: .6rem; margin: 0 0 .4rem;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
}
.deck-tiles--extras { grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); }
.deck-editor .deck-tiles, .deck-editor .deck-tiles--extras { grid-template-columns: repeat(auto-fill, minmax(6.2rem, 1fr)); gap: .7rem .5rem; }
.deck-tile { min-width: 0; }
.deck-tile-img { position: relative; display: block; border-radius: 8px; }
.deck-tile-img img, .deck-tile-img .card-tile-back {
  display: block; width: 100%; aspect-ratio: 376 / 526; border-radius: 8px;
  border: 1px solid var(--border); object-fit: cover; box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}
.deck-tile-img:hover img { box-shadow: 0 6px 16px rgba(0, 0, 0, .55), 0 0 0 1px var(--gold-deep); }
.deck-tile--illegal .deck-tile-img img { opacity: .45; }
/* Fabrary's quantity buttons [0..max]: the current count pressed, counts the
   shared deck + inventory limit can't reach disabled. The same group renders
   in list rows, under grid tiles and in the deck pane. */
.deck-tile { position: relative; }
.qty { display: inline-flex; gap: 2px; vertical-align: middle; }
.qty button {
  width: 1.45rem; height: 1.45rem; min-width: 0; padding: 0; border-radius: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--bg); color: var(--muted);
  font-size: .76rem; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; box-shadow: none;
}
.qty button:hover { background: var(--surface-2); border-color: var(--border-strong); color: var(--text); }
.qty button[aria-pressed="true"] { background: var(--primary); border-color: var(--primary); color: var(--primary-contrast); font-weight: 700; }
.qty button:disabled, .qty button:disabled:hover { opacity: .35; cursor: default; background: var(--bg); border-color: var(--border); color: var(--muted); }
.qty button:focus-visible, .own-badge:focus-visible, .print-btn:focus-visible { outline: none; box-shadow: var(--ring); border-color: var(--primary); }
/* One zone for the page: the right-hand group (list) follows data-col, the
   pool tiles' strip (grid) data-strip; the other groups are rendered but hidden.
   The first cell renders every zone's group for phones; desktops show its deck group. */
.deck-editor .qty-cell--main .qty:not([data-zone="deck"]) { display: none; }
.deck-editor .qty-head--main .zone-label:not([data-zone="deck"]) { display: none; }
.deck-editor .row-in[data-zone="deck"] { display: none; }        /* the deck group itself is in view */
.strip-head.strip-head--list { display: none; }       /* the list's copy: phones only (below) */
.deck-editor[data-col="inventory"] .qty-cell--col .qty[data-zone="maybe"],
.deck-editor[data-col="maybe"] .qty-cell--col .qty[data-zone="inventory"],
.deck-editor[data-col="inventory"] .row-in[data-zone="inventory"],
.deck-editor[data-col="maybe"] .row-in[data-zone="maybe"],
.deck-editor[data-strip="deck"] .tile-strip--pool .qty:not([data-zone="deck"]),
.deck-editor[data-strip="inventory"] .tile-strip--pool .qty:not([data-zone="inventory"]),
.deck-editor[data-strip="maybe"] .tile-strip--pool .qty:not([data-zone="maybe"]) { display: none; }
.col-select, .strip-select {
  width: auto; min-height: 0; padding: .15rem 1.4rem .15rem .4rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--gold-deep);
}
.strip-head { margin: 0 0 .4rem; display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.strip-head select { text-transform: none; letter-spacing: 0; font-size: .82rem; }
.pool-sort { width: auto; font-size: .82rem; padding: .35rem 1.6rem .35rem .5rem; }
@media (hover: none) { .col-select, .strip-select, .pool-sort { font-size: 16px; letter-spacing: 0; text-transform: none; } }   /* the iOS zoom floor, like every control */
/* The owned badge is a link into the Binder's card sheet. */
.own-badge {
  display: inline-flex; align-items: center; min-height: 0; text-decoration: none;
  font: inherit; font-size: .76rem; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.4;
  padding: .05rem .5rem; border-radius: 999px; border: 1px solid var(--border-strong);
  background: rgba(14, 11, 7, .88); color: var(--muted); cursor: pointer; white-space: nowrap; box-shadow: none;
}
.own-badge:hover { border-color: var(--gold); text-decoration: none; background: rgba(14, 11, 7, .88); }
.deck-tile .own-badge { position: absolute; right: .35rem; top: .4rem; z-index: 2; }
.deck-tile .tile-in { top: auto; bottom: .4rem; }     /* the in-deck badge takes the art's lower corner: no collision with the owned badge */
.tile-strip { display: flex; justify-content: center; margin-top: .3rem; }
.deck-hero-row { display: flex; align-items: center; gap: .5rem; padding: .3rem .4rem .5rem; margin-bottom: .2rem; border-bottom: 1px solid var(--border); }
.deck-hero-row .row-thumb { width: 24px; height: 34px; border-radius: 3px; object-fit: cover; }
.deck-hero-name { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.deck-hero-name .row-sub { font-size: .76rem; }
.deck-hero-row .own-badge.tile-own { position: static; }
/* Desktops: the deck pane sticks and scrolls on its own, so the pool and the
   deck scroll independently (decision 7). The pane's inner #deck-pane is what
   out-of-band swaps replace, so the section keeps its scroll position. */
.pane-switch { display: none; }
@media (min-width: 60.01rem) {
  .deck-editor-deck { position: sticky; top: calc(var(--topnav-h, 3.8rem) + .5rem); max-height: calc(100vh - var(--topnav-h, 3.8rem) - 1rem); overflow-y: auto; overscroll-behavior: contain; }
}
/* Phones (≤60rem: the panes stack): a Pool | Deck switch under the status
   strip shows one pane; it sticks under the top bar (--topnav-h from edit.html). */
@media (max-width: 60rem) {
  .pane-switch {
    display: flex; position: sticky; top: var(--topnav-h, 0px); z-index: 9;
    background: var(--bg); padding: .4rem 0; margin: 0 0 .5rem;
  }
  .pane-switch .btn { flex: 1; min-height: 2.75rem; border-radius: 0; margin-left: -1px; font-size: .95rem; }
  .pane-switch .btn:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); margin-left: 0; }
  .pane-switch .btn:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
  .pane-switch .btn[aria-pressed="true"] { background: var(--gold-faint); color: var(--gold); border-color: var(--border-strong); position: relative; z-index: 1; }
  .deck-editor[data-show="pool"] .deck-editor-deck, .deck-editor[data-show="deck"] .deck-editor-pool { display: none; }
}
/* Narrow screens (≤44rem): one button group per row — the strip dropdown's
   zone in the pool, Arena and Deck tables, the section's own zone in the
   Inventory and Maybe tables — no thumbnails, tiles three across. */
@media (max-width: 44rem) {
  .table-scroll > .deck-edit-table { min-width: 0; }   /* its own width, not the read-only tables' 42rem canvas */
  .strip-head.strip-head--list { display: flex; }
  .deck-edit-table[data-zone="pool"] .qty-cell--col, .deck-edit-table[data-zone="deck"] .qty-cell--col,
  .deck-edit-table[data-zone="pool"] .qty-head--col, .deck-edit-table[data-zone="deck"] .qty-head--col,
  .deck-edit-table[data-zone="inventory"] .qty-cell--main, .deck-edit-table[data-zone="maybe"] .qty-cell--main,
  .deck-edit-table[data-zone="inventory"] .qty-head:not(.qty-head--col), .deck-edit-table[data-zone="maybe"] .qty-head:not(.qty-head--col) { display: none; }
  .deck-editor .qty-cell--main .qty { display: none; }
  .deck-editor[data-strip="deck"] .qty-cell--main .qty[data-zone="deck"],
  .deck-editor[data-strip="inventory"] .qty-cell--main .qty[data-zone="inventory"],
  .deck-editor[data-strip="maybe"] .qty-cell--main .qty[data-zone="maybe"] { display: inline-flex; }
  /* The deck pane's Arena / Deck rows keep the main-deck group (the strip
     dropdown lives in the other pane). */
  .deck-editor[data-strip] .deck-editor-deck .qty-cell--main .qty { display: none; }
  .deck-editor[data-strip] .deck-editor-deck .qty-cell--main .qty[data-zone="deck"] { display: inline-flex; }
  /* The pool's header names the zone the strip set; the deck pane's says Deck. */
  .deck-editor-pool .qty-head--main .zone-label { display: none; }
  .deck-editor[data-strip="deck"] .deck-editor-pool .qty-head--main .zone-label[data-zone="deck"],
  .deck-editor[data-strip="inventory"] .deck-editor-pool .qty-head--main .zone-label[data-zone="inventory"],
  .deck-editor[data-strip="maybe"] .deck-editor-pool .qty-head--main .zone-label[data-zone="maybe"] { display: inline; }
  /* A pool row says where its copies are for every zone whose group is hidden. */
  .deck-editor[data-col] .row-in[data-zone] { display: inline-block; }
  .deck-editor[data-strip="deck"] .row-in[data-zone="deck"],
  .deck-editor[data-strip="inventory"] .row-in[data-zone="inventory"],
  .deck-editor[data-strip="maybe"] .row-in[data-zone="maybe"] { display: none; }
  .deck-edit-row .row-thumb { display: none; }
  .deck-edit-table thead th, .deck-edit-table tbody td { padding: .3rem .25rem; }
  .deck-edit-table .qty button { width: 1.65rem; }   /* narrower (the height stays 30px) so the name keeps ~160px */
  .deck-editor .deck-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem .3rem; padding: .35rem; }
  .tile-strip .qty { gap: 1px; }
  .tile-strip .qty button { width: 1.5rem; }     /* four fit a 107px tile; the height stays touch-sized */
}
#pool { scroll-margin-top: calc(var(--topnav-h, 0px) + 4rem); }   /* a paged pool scrolls in under the bar and the switch */
/* Touch screens: 44px rows, bigger buttons, a tile strip that still fits. */
@media (hover: none) {
  .qty button { width: 1.9rem; height: 1.9rem; font-size: .85rem; }
  .deck-editor .print-btn { width: 1.9rem; height: 1.9rem; }
  .deck-tile { --strip-h: 1.9rem; }
  .tile-strip .qty button { width: 1.55rem; }
  .own-badge { min-height: 1.7rem; }
  .deck-edit-table tbody td { padding-top: .4rem; padding-bottom: .4rem; }
  .deck-editor .pager .btn { min-height: 2.75rem; padding: .5rem 1rem; }
}
/* Fabrary's printing button (deck rows, deck tiles, the hero row): opens the
   printing picker. */
.print-btn {
  width: 1.5rem; height: 1.5rem; min-width: 0; padding: 0; border-radius: 50%; flex: none;
  border: 1px solid var(--border); background: var(--bg); color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center; box-shadow: none;
}
.print-btn:hover { border-color: var(--gold-deep); color: var(--gold); background: var(--bg); }
.deck-edit-table .print-cell { width: 1%; padding-left: 0; }
.deck-tile .print-btn { position: absolute; left: .35rem; bottom: calc(var(--strip-h, 1.45rem) + .7rem); z-index: 2; }
.deck-tile .tile-chip { left: auto; right: .35rem; }          /* the legality chip keeps clear of the printing button and the in-deck badge */
/* The printing picker: one card per exact printing. */
.printing-grid {
  list-style: none; margin: .4rem 0 0; padding: .15rem;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: .6rem;
  max-height: 60vh; overflow: auto;
}
.printing-card {
  display: flex; flex-direction: column; gap: .25rem; min-width: 0; padding: .5rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-3);
}
.printing-card--current { border-color: var(--gold-deep); box-shadow: 0 0 0 1px var(--gold-deep); }
.printing-card-img { display: block; width: 5rem; aspect-ratio: 376 / 526; object-fit: cover; border-radius: 6px; align-self: center; }
.printing-card-set { font-size: .86rem; line-height: 1.25; }
.printing-card-sub { font-size: .76rem; }
.printing-card-line { display: flex; justify-content: space-between; gap: .4rem; font-size: .8rem; }
.printing-card .btn-sm, .printing-card-listed { align-self: flex-start; margin-top: .15rem; }
.deck-tile--editable .deck-tile-img img { transition: filter .12s; }
.deck-tile--editable:hover .deck-tile-img img { filter: brightness(.8); }
.tile-in {
  position: absolute; left: .4rem; top: .45rem;
  background: rgba(14, 11, 7, .88); color: var(--gold);
  font-size: .7rem; font-weight: 700; font-variant-numeric: tabular-nums;
  padding: .05rem .45rem; border-radius: 999px; border: 1px solid var(--border-strong);
}
/* Owned / needed on deck tiles: unowned cards grey out, short ones dim. */
.tile-own {
  position: absolute; right: .4rem; top: .45rem;
  background: rgba(14, 11, 7, .88); font-size: .7rem; font-weight: 700; font-variant-numeric: tabular-nums;
  padding: .05rem .45rem; border-radius: 999px; border: 1px solid var(--border-strong);
}
.tile-own--ok { color: var(--success); }
.tile-own--short { color: var(--warning); border-color: var(--warning); }
.tile-own--none { color: var(--danger); border-color: var(--danger); }
.deck-tile--unowned .deck-tile-img img { filter: grayscale(1) brightness(.5); }
.deck-tile--short .deck-tile-img img { filter: brightness(.7); }
.deck-edit-row--unowned .row-thumb { filter: grayscale(1) brightness(.5); }
.deck-edit-row--unowned .cell-clip a { color: var(--muted); }
.deck-edit-table .tile-own { position: static; }
/* Card dialog (click a card): preview + printings. */
.card-dialog { display: flex; gap: 1rem; align-items: flex-start; flex-wrap: wrap; }
.card-dialog-preview { flex: 0 0 auto; min-width: 240px; min-height: 336px; }
.card-dialog-preview .card-preview-imgs { gap: .6rem; }
.card-dialog-info { flex: 1 1 18rem; min-width: 0; }
.card-dialog-title { margin: 0; }
.card-dialog-meta { margin: .2rem 0 .6rem; }
.card-dialog-h { margin: .4rem 0 .3rem; font-size: .95rem; }
.printing-list { list-style: none; margin: 0; padding: 0; max-height: 50vh; overflow: auto; }
.printing-more { margin-top: .5rem; }
.printing-more > summary { cursor: pointer; list-style: revert; }
.printing { display: flex; align-items: center; gap: .5rem; padding: .35rem .4rem; border-top: 1px solid var(--border); }
.printing--current { background: var(--gold-faint); }
.printing-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.printing-sub { font-size: .76rem; }
.printing-owned { color: var(--success); font-weight: 600; }
.dialog-short { color: var(--warning); font-weight: 600; }
.card-dialog-foot { margin: .6rem 0 0; font-size: .85rem; }
/* The card sheet dialog (click a card). Desktop: a centred dialog; phones
   (≤44rem): a bottom sheet sized to the visible viewport (base.html sets
   --vv-h from visualViewport so the keypad shrinks it), page scroll locked. */
.card-lightbox {
  border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 0;
  background: var(--surface); color: var(--text); width: min(94vw, 52rem); max-height: 92vh;
  box-shadow: 0 30px 80px rgba(0,0,0,.8); overflow: hidden;
}
.card-lightbox::backdrop { background: rgba(0, 0, 0, .7); }
.card-lightbox .card-preview-imgs:not(.horizontal) img { width: min(80vw, 15rem); }
.lightbox-bar { display: flex; justify-content: flex-end; align-items: center; gap: .4rem; padding: .35rem .5rem 0; }
.card-lightbox:not(.has-focus) .lightbox-done { display: none; }  /* `button { display: inline-flex }` ties a bare class */
.lightbox-close { background: none; border: none; box-shadow: none; color: var(--muted); font-size: 1.1rem; padding: .3rem .55rem; cursor: pointer; }
.lightbox-body { padding: 0 1rem 1rem; max-height: calc(92vh - 2.6rem); overflow-y: auto; overscroll-behavior: contain; }
html.sheet-open { overflow: hidden; }
html.sheet-open body { position: fixed; width: 100%; }
@media (max-width: 44rem) {
  .card-lightbox {
    position: fixed; inset: auto 0 0 0; margin: 0; width: 100%; max-width: 100%;
    max-height: var(--vv-h, 92dvh); border-radius: 16px 16px 0 0; border-bottom: none;
  }
  .card-lightbox .lightbox-body { max-height: calc(var(--vv-h, 92dvh) - 2.6rem); min-height: 40vh; }
  /* Keypad up (iOS shrinks the visual viewport, not the layout viewport the
     sheet is anchored to — its bottom half would sit behind the keys): pin the
     sheet to the visible area instead. --vv-top / --vv-h track visualViewport. */
  html.keypad .card-lightbox { top: var(--vv-top, 0); bottom: auto; height: var(--vv-h, 92dvh); border-radius: 0; }
  html.keypad .card-lightbox .lightbox-body { min-height: 0; }
  .card-lightbox::backdrop { touch-action: none; }
}
/* Sheet layout */
.card-sheet { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: 1rem; align-items: start; }
@media (max-width: 44rem) { .card-sheet { grid-template-columns: 1fr; gap: .6rem; } }
.sheet-face { min-height: 8rem; }
.sheet-face .card-preview-imgs { gap: .6rem; }
@media (max-width: 44rem) { .sheet-face .card-preview-imgs:not(.horizontal) img { width: min(60vw, 12rem); } .sheet-side { display: flex; justify-content: center; } }
.sheet-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.sheet-title { margin: 0; font-size: 1.25rem; }
.sheet-pitches { display: inline-flex; gap: .25rem; }
.sheet-pitches a { text-decoration: none; }
.sheet-summary { margin: .2rem 0 .4rem; font-size: .95rem; }
.sheet-status { min-height: 1.2em; margin-bottom: .3rem; }
.sheet-sec { border-top: 1px solid var(--border); padding-top: .5rem; margin-top: .5rem; }
.sheet-sec-title { margin: 0 0 .3rem; font-size: 1rem; }
.sheet-h { margin: .6rem 0 .3rem; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.printing-more > summary.sheet-h { cursor: pointer; }
.sheet-tabs { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); overflow: hidden; background: var(--surface-3); margin: .2rem 0 .6rem; }
.sheet-tab { appearance: none; border: 0; border-right: 1px solid var(--border); border-radius: 0; box-shadow: none; background: transparent; color: var(--muted); font: inherit; font-weight: 600; min-height: 2.75rem; padding: .4rem .3rem; display: inline-flex; gap: .3rem; align-items: center; justify-content: center; cursor: pointer; }
.sheet-tab:last-child { border-right: 0; }
.sheet-tab:hover { background: var(--surface-2); }
.sheet-tab[aria-selected="true"] { background: var(--surface-2); color: var(--text); box-shadow: inset 0 -2px 0 var(--gold); }
.sheet-tab:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.sheet-tab .sheet-tab-n { font-weight: 400; font-variant-numeric: tabular-nums; }
.sheet-addbox { padding: .55rem .6rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface-2); display: flex; flex-direction: column; gap: .45rem; }
.sheet-addbox.htmx-request { opacity: .6; }
.sheet-addbox.htmx-request .sheet-add-form, .sheet-addbox.htmx-request .sheet-printing { pointer-events: none; }  /* the old form never posts mid-swap */
.sheet-field .sheet-printing-one { font-size: 1rem; color: var(--text); }
.sheet-field { display: flex; flex-direction: column; gap: .2rem; font-size: .8rem; color: var(--muted); }
.sheet-field select.sheet-printing { width: 100%; min-height: 2.75rem; font-size: 1rem; color: var(--text); }
.sheet-addbox .sheet-owned { font-size: .85rem; }
.sheet-add-form { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin-top: .1rem; }
.sheet-add-form .sheet-add-actions { display: flex; gap: .4rem; flex: 1 0 100%; }
.sheet-add-form .sheet-add-actions button { flex: 1; min-height: 2.75rem; }
.sheet-add-form select, .sheet-add-form input.qty { min-height: 2.5rem; }
.sheet-add-form input.qty { width: 4.5rem; }
.sheet-block { padding: .45rem .55rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); margin-bottom: .4rem; }
.sheet-block.htmx-request .sheet-block-ctl { pointer-events: none; opacity: .6; }
.sheet-block-id { display: flex; align-items: flex-start; gap: .4rem; font-size: .92rem; }
.sheet-block-id .row-thumb { flex: none; width: 24px; height: 34px; border-radius: 3px; object-fit: cover; }
.sheet-block-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; flex: 1; }
.sheet-block.revealing .sheet-count input { pointer-events: none; opacity: .6; }  /* Traded…/Got… open: one live box */
.sheet-block-sub { font-size: .82rem; }
.sheet-block-ctl { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin-top: .4rem; }
.sheet-block-ctl .btn-sm, .sheet-block-ctl .btn { min-height: 2.5rem; }
.sheet-block-ctl .count-action { flex-wrap: wrap; }
.sheet-count { display: inline-flex; align-items: center; gap: .3rem; font-size: .85rem; }
.sheet-count input.qty, .count-action input.qty { width: 4.2rem; min-height: 2.5rem; padding: .2rem .3rem; }
.sheet-right { margin-left: auto; }
.sheet-edit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: .4rem .6rem; margin-top: .4rem; font-size: .85rem; }
.sheet-edit-grid label { display: flex; flex-direction: column; gap: .15rem; }
.sheet-edit-grid .sheet-edit-wide { grid-column: 1 / -1; }
.sheet-edit-grid input, .sheet-edit-grid select { min-height: 2.5rem; }
.sheet-empty { margin: 0 0 .3rem; }
.group-thumb-btn { background: none; border: none; padding: 0; margin: 0; cursor: pointer; line-height: 0; box-shadow: none; }
.group-thumb-btn:hover { background: none; }
.card-sheet-page { max-width: 60rem; }
@media (hover: none) { .sheet-esc { display: none; } }
/* List view rows: [deck qty] · card · own · [column qty]. The card cell takes
   what the fixed cells leave and clips its text (width: 100% + max-width: 0 is
   the auto-layout idiom that lets an ellipsis shrink a nowrap cell instead of
   widening the table past its pane). The selectors match .data-table's own
   (thead th / tbody td), so these paddings win by order. */
.deck-edit-table thead th, .deck-edit-table tbody td { padding: .3rem .4rem; }
.deck-edit-table .qty-cell, .deck-edit-table .own-cell { width: 1%; white-space: nowrap; }
.deck-edit-table td.preview-anchor { width: 100%; max-width: 0; }
.deck-edit-table .own-cell { text-align: center; }
.deck-edit-table .qty-head--col { white-space: nowrap; }
.deck-edit-table .row-in { font-size: .68rem; padding: 0 .4rem; vertical-align: middle; }
.deck-edit-row .row-thumb { width: 24px; height: 34px; border-radius: 3px; object-fit: cover; vertical-align: middle; margin-right: .35rem; }
.deck-edit-row .row-sub { display: block; font-size: .76rem; line-height: 1.2; }
.deck-edit-row--illegal .cell-clip a { color: var(--muted); }

/* Touch devices: iOS Safari auto-zooms the page when a control with text
   under 16px gets focus — in the sheet that also shrinks the visual viewport
   the sheet is sized to, which is disorienting. Floor every text control at
   16px (the tables' .9rem cells and the sheet's .85rem count labels would
   otherwise pass a smaller size down through `font: inherit`). Same
   specificity as the base control rule above, later in the file, so it wins. */
@media (hover: none) {
  input[type=text], input[type=email], input[type=password], input[type=search],
  input[type=number], select, textarea { font-size: max(16px, 1em); }
}

/* The unified Binder page (One Binder PR 4) ------------------------------- */
.hub-head { display: flex; align-items: baseline; gap: 1rem 1.5rem; flex-wrap: wrap; }
.hub-head h1 { margin-right: auto; }
.hub-head .page-actions { margin: .25rem 0 1rem; }
.scope-pills { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .6rem; }
.scope-pill { position: relative; display: inline-flex; cursor: pointer; }
.scope-pill input { position: absolute; opacity: 0; pointer-events: none; }
.scope-pill > span {
  display: inline-flex; align-items: center; gap: .35rem; padding: .4rem .85rem; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--muted); font-weight: 600;
  transition: background .12s, color .12s, border-color .12s;
}
.scope-pill:hover > span { background: var(--surface-2); }
.scope-pill input:checked + span { background: var(--primary); border-color: var(--primary); color: var(--primary-contrast); }
.scope-pill input:focus-visible + span { box-shadow: var(--ring); }
.scope-pill .pill-count { display: inline; padding: 0; border: 0; background: none; color: inherit; font-variant-numeric: tabular-nums; font-weight: 500; opacity: .8; }
.view-toggle[hidden] { display: none; }
.scope-tools { margin-top: .6rem; }
.pager { margin: .6rem 0; align-items: baseline; }
.htmx-indicator.stale { color: var(--gold); }  /* shown via an inline opacity: htmx injects its own indicator rules */
.active-filters .badge { margin-right: .25rem; }

/* The Binder page's phone furniture (design §4) ---------------------------
   Desktop first: the strip, tool row and filter panel are plain inline rows;
   below 44rem the strip is the only sticky element, the tool row wraps, and
   the filter panel / actions menu become bottom sheets (JS-gated: html.js). */
.pill-short, .cnt-short { display: none; }
.tool-row { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-top: .6rem; }
.set-filter--hub input { width: 16rem; }
.filters-open, .actions-open { display: none; }   /* phone + JS only (below) */
.filters-dot { display: inline-block; width: .5rem; height: .5rem; border-radius: 50%; background: var(--gold); margin-left: .4rem; }
.filters-dot[hidden] { display: none; }
.active-filters { display: none; }
.filter-panel { display: contents; }
.filter-panel-head { display: none; }
.filter-panel-foot { display: flex; gap: .5rem; margin-top: .6rem; }
.filter-panel-foot .filters-close { display: none; }
.hint { font-size: .8rem; color: var(--muted); margin: .3rem 0 0; }
.scope-actions .actions-head { display: none; }
.status-banner:empty { display: none; }
.status-close { display: none; }
.card-tile { -webkit-touch-callout: none; }
.tile-details { display: none; }
@media (hover: none) {
  /* A group's summary opens the sheet (no inline rows on touch screens): a
     chevron instead of the accordion marker. */
  body.hub .cardgroup > summary, .cardgroup > summary[data-dialog-touch] { list-style: none; }
  body.hub .cardgroup > summary::-webkit-details-marker, .cardgroup > summary[data-dialog-touch]::-webkit-details-marker { display: none; }
  body.hub .cardgroup > summary::after, .cardgroup > summary[data-dialog-touch]::after { content: "›"; margin-left: auto; color: var(--muted); font-size: 1.3rem; line-height: 1; }
  /* Only tiles that carry the strip (the owner's views) lift their badges. */
  .card-tile:has(.tile-details) .tile-qty, .card-tile:has(.tile-details) .tile-chip { bottom: calc(2.75rem + .45rem); }
  .tile-details {
    display: block; text-align: center; min-height: 2.75rem; line-height: 2.75rem; font-size: .85rem;
    color: var(--muted); background: var(--surface); border: 1px solid var(--border); border-top: none;
    border-radius: 0 0 8px 8px; margin-top: -8px; padding-top: 8px;
  }
}
.edition-badge {
  font-size: .68rem; padding: 0 .3rem; border: 1px solid var(--border-strong); border-radius: 4px;
  color: var(--muted); vertical-align: middle; letter-spacing: .02em;
}
.share-link { display: flex; flex-direction: column; gap: .4rem; }
.share-link-row { display: flex; gap: .4rem; }
.share-link-row input { flex: 1; min-width: 0; font-size: .85rem; }
.last-status { display: block; font-size: .82rem; margin-top: .2rem; }

@media (max-width: 44rem) {
  body.hub .topnav { position: static; }
  body.hub .container { padding-top: .6rem; }
  /* The header's box stays (the ⋯ sheet lives in it); only the title goes. */
  body.hub .hub-head { display: contents; }
  body.hub .hub-head h1 { display: none; }
  /* The form is no box on phones: the strip's containing block is then the
     container, which holds #results — so the strip stays put while the
     results scroll (a sticky box is clamped to its parent). */
  body.hub .find-form.panel { display: contents; }
  .hub-strip {
    position: sticky; top: 0; z-index: 9; margin: 0 -1.25rem; padding: .5rem 1.25rem .45rem;
    background: color-mix(in srgb, var(--bg) 94%, transparent); backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--border);
  }
  .hub-strip .find-box { max-width: none; }
  .hub-strip .search-input { min-height: 2.75rem; }
  .hub-strip .htmx-indicator { position: absolute; right: 2.6rem; top: .8rem; margin: 0; font-size: .78rem; pointer-events: none; }
  .hub-strip { position: sticky; }
  .scope-pills { flex-wrap: nowrap; gap: .3rem; margin-top: .45rem; }
  .scope-pill { flex: 1 1 auto; min-width: 0; }
  .scope-pill > span { width: 100%; justify-content: center; padding: .45rem .3rem; font-size: .8rem; gap: .25rem; min-height: 2.25rem; white-space: nowrap; }
  .pill-long, .cnt-long { display: none; }
  .pill-short, .cnt-short { display: inline; }
  .tool-row { margin-top: .6rem; }
  .set-filter--hub { width: 100%; }
  .set-filter--hub input { width: 100%; min-height: 2.75rem; }
  html.js .filters-open, html.js .actions-open { display: inline-flex; min-height: 2.75rem; }
  .tool-row { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: .7rem .8rem; margin-top: .6rem; }
  .tool-row select { min-height: 2.75rem; flex: 1 1 auto; min-width: 0; max-width: 12rem; }
  .tool-row .view-toggle { margin-left: 0; }
  .tool-row .view-toggle .btn { min-height: 2.75rem; }
  .hub-search { display: none; }                 /* the keyboard's Search key submits */
  .active-filters { display: flex; flex-wrap: wrap; gap: .35rem; width: 100%; }
  .active-filters:empty { display: none; }
  .active-filter { font-size: .78rem; padding: .25rem .6rem; border-radius: 999px; min-height: 2rem; }
  html.js .filter-panel {
    display: flex; flex-direction: column; position: fixed; inset: auto 0 0 0; z-index: 30;
    max-height: var(--vv-h, 92dvh); background: var(--surface); border-top: 1px solid var(--border-strong);
    border-radius: 16px 16px 0 0; box-shadow: 0 -20px 60px rgba(0, 0, 0, .6);
    transform: translateY(105%); transition: transform .2s ease-out; visibility: hidden;
  }
  html.js .filter-panel.open { transform: none; visibility: visible; }
  html.js .filter-panel-head { display: flex; justify-content: space-between; align-items: center; padding: .6rem .6rem .2rem 1rem; touch-action: none; }
  .filter-panel-body { overflow-y: auto; overscroll-behavior: contain; padding: 0 1rem .4rem; flex: 1 1 auto; touch-action: pan-y; }
  .filter-panel-body .chip-group { flex-direction: column; gap: .3rem; }
  .filter-panel-body .filter-chip span { min-height: 2.25rem; display: inline-flex; align-items: center; }
  .filter-panel-body select { min-height: 2.75rem; }
  html.js .filter-panel-foot { padding: .6rem 1rem calc(.6rem + env(safe-area-inset-bottom)); justify-content: space-between; border-top: 1px solid var(--border); margin: 0; touch-action: none; }
  .filter-panel-foot .btn, .filter-panel-foot button { min-height: 2.75rem; }
  html.js .filter-panel-foot .filters-close { display: inline-flex; }
  html.js .scope-actions {
    display: none; position: fixed; inset: auto 0 0 0; z-index: 30; flex-direction: column; gap: .1rem; margin: 0;
    background: var(--surface); border-top: 1px solid var(--border-strong); border-radius: 16px 16px 0 0;
    padding: .4rem 1rem calc(.8rem + env(safe-area-inset-bottom)); box-shadow: 0 -20px 60px rgba(0, 0, 0, .6);
  }
  html.js .scope-actions.open { display: flex; }
  html.js .scope-actions .actions-head { display: flex; justify-content: space-between; align-items: center; }
  .scope-actions > a { min-height: 2.75rem; display: flex; align-items: center; }
  .share-link { width: 100%; }
  .share-link-row input, .share-link .btn-sm { min-height: 2.75rem; }
  /* The empty state's own filter list duplicates the strip's chips here. */
  html.js .empty-state .active-filters-list { display: none; }
  .status-banner {
    position: fixed; top: var(--strip-h, 6rem); left: .6rem; right: .6rem; z-index: 20; display: none;
    background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    padding: .55rem 2.3rem .55rem .75rem; box-shadow: 0 8px 24px rgba(0, 0, 0, .5); color: var(--text);
  }
  .status-banner.show { display: block; }
  .status-close { display: block; position: absolute; right: .25rem; top: .3rem; background: none; border: none; box-shadow: none; padding: .2rem .5rem; color: var(--muted); }
}

/* A phone's first All-cards visit (nothing chosen, nothing remembered): the
   undecided table stays out of sight until the grid the page asks for lands
   (hub.html clears the marker when that round trip ends). */
@media (max-width: 44rem) {
  html.js form#find:has(#view-toggle[data-view-undecided]) ~ #results { display: none; }
}

/* Decks · Stats tab */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); gap: .8rem; margin-bottom: .8rem; }
.stats-panel { margin-bottom: .8rem; }
.stats-panel .deck-section-title { margin-top: 0; }
.stats-sub { margin: .8rem 0 .3rem; font-size: .95rem; color: var(--muted); }
.stats-table tbody td { padding: .3rem .4rem; }
.stats-table td.num, .stats-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.stats-hand thead th, .stats-hand tbody td { padding: .3rem .45rem; }
@media (max-width: 44rem) { .table-scroll > .stats-hand { min-width: 0; } }   /* its natural width, not the card tables' canvas */
.stats-note { font-size: .82rem; margin: .4rem 0 0; }
.stats-calc { margin-top: .8rem; gap: .5rem .8rem; align-items: center; flex-wrap: wrap; }
.stats-calc label { display: inline-flex; align-items: center; gap: .3rem; }
.stats-calc input.qty { width: 4.4rem; }
.stats-calc-result { margin-left: auto; }

/* Decks · Collection panel (PR D) */
.deck-collection-head { display: flex; flex-wrap: wrap; gap: .2rem 1rem; align-items: baseline; }
.deck-collection-head .deck-section-title { margin: 0; }
.deck-collection-sum { margin: 0; }
.deck-collection-warn { margin: .5rem 0 0; }
.deck-missing tbody td { padding: .3rem .45rem; }
.deck-missing td.num, .deck-missing th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.deck-missing td.num .muted { white-space: normal; }
@media (max-width: 44rem) { .table-scroll > .deck-missing { min-width: 0; } }   /* its natural width, not the card tables' canvas */
.deck-collection-actions { margin-top: .6rem; gap: .5rem .8rem; align-items: center; flex-wrap: wrap; }
.deck-collection-line .deck-issue--warning { color: var(--warning, #d9a441); }
