:root {
  /* Cardz Center house style — every screen uses this.
     Rebrand v4: black and neon blue, per the user's request for "ดำและ
     สีฟ้านีออนสะท้อนแสง" -- replacing v3's black-and-emerald.

     Neon is light seen against dark, so the ground goes darker than it was
     (#03060a, near black) and the accent goes bright and saturated rather
     than deep. --primary is a cyan-leaning electric blue: on a black
     ground it reads as lit rather than painted, which is the whole point
     of the brief. --primary-dark is NOT simply a darker blue -- it is
     pushed toward indigo so the gradients on buttons and the topbar shift
     hue as well as lightness, which is what makes a surface look like it
     is catching light instead of fading out.

     --card-bg/--card-bg-2 and --bg/--card-bg stay close in lightness so
     the gradients used throughout this file read as a sheen, not a seam.

     --success is deliberately NOT the accent. On a blue-accented site a
     blue "price up" would be indistinguishable from every button, so it
     stays green (hue ~155) and --danger stays red: a number moving up or
     down must never be read as branding. The same goes for --info, which
     is nudged toward violet so an information panel does not disappear
     into the brand colour. */
  --primary: #22d3ff;
  --primary-dark: #0b7fd4;
  --primary-light: rgba(34,211,255,0.16);
  --ink: #e8f4fb;
  --ink-soft: #8ba6bd;
  --border: #17364d;
  --bg: #03060a;
  --card-bg: #0a1622;
  --card-bg-2: #11263a;
  --success: #2fe08a;
  --success-bg: rgba(47,224,138,0.14);
  --warn: #ffc247;
  --warn-bg: rgba(255,194,71,0.14);
  --info: #8f9dff;
  --info-bg: rgba(143,157,255,0.14);
  --purple: #c792ff;
  --purple-bg: rgba(199,146,255,0.16);
  --danger: #ff5470;
  /* The neon itself: a halo reused wherever something should look lit
     rather than filled. Defined once so "how bright is the glow" is one
     decision, not thirty. */
  --glow: 0 0 12px rgba(34,211,255,0.45);
  --glow-soft: 0 0 18px rgba(34,211,255,0.22);
  --radius: 12px;
  --nav-h: 60px;
  --header-h: 56px;
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* The browser's own rule for this is `[hidden] { display: none }`, which any
   class setting `display: flex` or `display: block` silently beats -- and
   then everything the page hides with the `hidden` attribute stays on
   screen. That is exactly what put the scan result sheet and the "reading
   the photo" overlay on top of the camera the moment the page opened. */
[hidden] { display: none !important; }
html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans Thai", Helvetica, Arial, sans-serif;
  -webkit-tap-highlight-color: transparent;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }
img { max-width: 100%; display: block; }

.app-shell {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  /* A soft vignette rather than one flat fill -- the "gradient play" the
     rebrand asked for, visible behind every screen's own surfaces. */
  background: radial-gradient(120% 70% at 50% 0%, var(--card-bg) 0%, var(--bg) 60%);
  padding-bottom: calc(var(--nav-h) + 12px);
  position: relative;
}

/* ---------- Top header ---------- */
.topbar {
  position: sticky; top: 0; z-index: 20;
  height: var(--header-h);
  background: linear-gradient(180deg, var(--card-bg-2), var(--card-bg));
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
  padding: 0 14px;
}
.topbar .brand {
  font-weight: 800; font-size: 18px; color: var(--primary);
  white-space: nowrap;
}
.topbar .spacer { flex: 1; }
/* Shared baseline for every {{ icon(...) }} svg so it sits on the text
   baseline like a glyph would, wherever it's dropped into a line of text,
   a button, or a badge -- instead of each call site guessing its own
   vertical-align. */
.icon { display: inline-block; vertical-align: -0.2em; flex-shrink: 0; }
.icon-btn {
  position: relative;
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; background: transparent; border: none; cursor: pointer;
}
.icon-btn .badge {
  position: absolute; top: 0; right: 0;
  background: var(--primary); color: #fff;
  font-size: 10px; font-weight: 700;
  border-radius: 999px; min-width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 3px;
}

/* ---------- Bottom nav ---------- */
.bottom-nav {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 480px;
  height: var(--nav-h);
  background: var(--card-bg);
  border-top: 1px solid var(--border);
  display: flex;
  z-index: 30;
  box-shadow: 0 -2px 10px rgba(0,0,0,0.04);
}
.bottom-nav a {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; font-size: 9.5px; color: var(--ink-soft); white-space: nowrap; padding: 0 2px;
}
.bottom-nav a.active { color: var(--primary); font-weight: 700; }
.bottom-nav .nav-icon { font-size: 18px; }
.bottom-nav .fab {
  margin-top: -18px;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--primary); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; box-shadow: 0 4px 10px rgba(224,57,62,0.4);
}

/* ---------- Flash messages ---------- */
.flash-wrap { padding: 10px 14px 0; }
.flash {
  padding: 10px 12px; border-radius: var(--radius);
  font-size: 13.5px; margin-bottom: 8px;
}
.flash.success { background: var(--success-bg); color: var(--success); }
.flash.error { background: var(--primary-light); color: var(--primary); }

.page { padding: 12px 14px; }
.page-title { font-size: 20px; font-weight: 800; margin: 4px 0 12px; }
.section-title { font-size: 15px; font-weight: 700; margin: 18px 0 8px; color: var(--ink); }
.muted { color: var(--ink-soft); }
.small { font-size: 12.5px; }

/* ---------- Search / filters ---------- */
.search-bar {
  display: flex; gap: 8px; padding: 10px 14px; background: var(--card-bg);
  border-bottom: 1px solid var(--border);
}
.search-bar input[type="text"], .search-bar input[type="search"] {
  flex: 1; border: 1px solid var(--border); border-radius: 999px;
  padding: 9px 14px; font-size: 14px; background: var(--bg);
}
.filter-toggle {
  border: 1px solid var(--border); background: var(--card-bg);
  border-radius: 999px; padding: 9px 14px; font-size: 13px; white-space: nowrap;
}
.chip-row { display: flex; gap: 8px; overflow-x: auto; padding: 10px 14px; background: var(--card-bg); }
.chip-row::-webkit-scrollbar { display: none; }
.chip {
  border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px;
  font-size: 13px; white-space: nowrap; background: var(--card-bg); color: var(--ink-soft);
}
.chip.active { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); border-color: var(--primary); color: #fff; font-weight: 600; }

details.filters { background: var(--card-bg); border-bottom: 1px solid var(--border); }
details.filters summary { padding: 10px 14px; font-size: 13px; color: var(--ink-soft); cursor: pointer; list-style: none; }
details.filters summary::-webkit-details-marker { display: none; }
.filters-form { padding: 4px 14px 14px; display: grid; gap: 10px; }
.filters-form .row { display: flex; gap: 8px; }
.filters-form select, .filters-form input {
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font-size: 13px; width: 100%; background: var(--card-bg-2); color: var(--ink);
}

/* ---------- Listing grid / cards ---------- */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 12px 14px; }
.listing-card {
  background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column;
}
.listing-card .thumb {
  width: 100%; aspect-ratio: 1/1; background: var(--card-bg-2) url('data:image/svg+xml;utf8,') center/cover;
  display: flex; align-items: center; justify-content: center; color: var(--ink-soft); font-size: 12px; overflow: hidden;
}
.listing-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
/* A card scan is portrait; cropping it to a square cuts the art and the
   number off, so checklist art is shown whole inside the tile. */
.listing-card .thumb.card-art img { object-fit: contain; padding: 6px; }
.listing-card .body { padding: 8px 10px 10px; }
.listing-card .title { font-size: 13px; font-weight: 600; line-height: 1.3; height: 34px; overflow: hidden; }
.listing-card .price { font-size: 15px; font-weight: 800; color: var(--ink); margin-top: 4px; }
.listing-card .meta { font-size: 11px; color: var(--ink-soft); margin-top: 2px; display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.badge-tag {
  display: inline-block; font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 4px;
  background: var(--info-bg); color: var(--info);
}
.badge-sold {
  position: absolute; inset: 0; background: rgba(0,0,0,0.5); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px;
}
.thumb-wrap { position: relative; }

.empty-state { text-align: center; padding: 50px 20px; color: var(--ink-soft); }
.empty-state .emoji { font-size: 40px; margin-bottom: 10px; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: 999px; padding: 12px 18px; font-size: 14.5px; font-weight: 700;
  border: none; cursor: pointer; width: 100%;
}
.btn-primary { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); color: #fff; }
.btn-primary:active { background: var(--primary-dark); }
.btn-outline { background: transparent; color: var(--primary); border: 1.5px solid var(--primary); }
.btn-secondary { background: var(--card-bg-2); color: var(--ink); border: 1px solid var(--border); }
.btn-ghost { background: transparent; color: var(--ink-soft); border: 1px solid var(--border); }
.btn-sm { padding: 8px 14px; font-size: 13px; width: auto; }
.btn-block-row { display: flex; gap: 8px; }
.btn-block-row .btn { flex: 1; }
.btn:disabled { opacity: 0.5; }

/* ---------- Forms ---------- */
.form-group { margin-bottom: 14px; }
label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--ink); }
input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="tel"], input[type="search"], textarea, select {
  width: 100%; border: 1px solid var(--border); border-radius: 10px;
  padding: 11px 12px; font-size: 14.5px; background: var(--card-bg-2); color: var(--ink);
}
textarea { resize: vertical; min-height: 80px; font-family: inherit; }
.checkbox-row { display: flex; align-items: center; gap: 8px; }
.checkbox-row input { width: auto; }
.hint { font-size: 11.5px; color: var(--ink-soft); margin-top: 4px; }
.file-input-wrap { border: 1.5px dashed var(--border); border-radius: 10px; padding: 16px; text-align: center; color: var(--ink-soft); font-size: 13px; }

/* ---------- Cards / panels ---------- */
.panel { background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; margin-bottom: 12px; }
.row-between { display: flex; justify-content: space-between; align-items: center; }
.stack { display: flex; flex-direction: column; gap: 10px; }

/* ---------- Auth ---------- */
.auth-wrap { padding: 40px 20px; }
.auth-logo { text-align: center; font-size: 26px; font-weight: 900; color: var(--primary); margin-bottom: 24px; }
.auth-switch { text-align: center; margin-top: 16px; font-size: 13.5px; color: var(--ink-soft); }

/* ---------- Detail page ---------- */
.gallery { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; background: #000; }
.gallery img { width: 100%; aspect-ratio: 1/1; object-fit: contain; scroll-snap-align: start; flex-shrink: 0; background: #111; }
.gallery .no-image { width: 100%; aspect-ratio: 1/1; display: flex; align-items: center; justify-content: center; color: var(--ink-soft); background: var(--card-bg-2); }
.detail-header { padding: 14px; background: linear-gradient(180deg, var(--card-bg-2), var(--card-bg)); border-bottom: 8px solid var(--bg); }
.detail-price { font-size: 24px; font-weight: 900; }
.detail-title { font-size: 16px; font-weight: 700; margin: 6px 0; }
.tag-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 8px 0; }
.seller-card { display: flex; align-items: center; gap: 10px; padding: 14px; background: linear-gradient(180deg, var(--card-bg-2), var(--card-bg)); border-bottom: 8px solid var(--bg); }
.avatar {
  width: 42px; height: 42px; border-radius: 50%; background: var(--primary-light); color: var(--primary);
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px; flex-shrink: 0;
}
.stars { color: #f5a623; font-size: 13px; }
.sticky-buy-bar {
  /* Sits directly above the global bottom-nav rather than on top of it --
     both used to be pinned to bottom:0, so the nav (z-index 30) painted
     over this bar and silently swallowed every tap meant for Buy/Offer. */
  position: fixed; bottom: var(--nav-h); left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 480px; background: var(--card-bg); border-top: 1px solid var(--border);
  padding: 10px 14px; display: flex; gap: 8px; z-index: 31;
}

.desc-text { white-space: pre-wrap; font-size: 14px; line-height: 1.5; }
.desc-text.clamped { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.desc-toggle { background: none; border: none; color: var(--primary); font-weight: 700; font-size: 13px; padding: 8px 0 0; cursor: pointer; }

/* A "Make offer" panel that only opens when tapped -- keeps the button
   stack from turning into a form by default. */
.offer-box summary { list-style: none; }
.offer-box summary::-webkit-details-marker { display: none; }
.offer-box summary::marker { content: ""; }
.offer-form { display: flex; flex-direction: column; gap: 8px; padding: 12px 2px 2px; }
.offer-form input[type="number"], .offer-form input[type="text"] {
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  font-size: 14px; background: var(--card-bg-2); color: var(--ink);
}

/* ---------- Chat ---------- */
.thread-list-item { display: flex; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); background: var(--card-bg); }
.thread-list-item .thumb-sm { width: 48px; height: 48px; border-radius: 8px; overflow: hidden; background: var(--card-bg-2); flex-shrink: 0; }
.thread-list-item .thumb-sm img { width: 100%; height: 100%; object-fit: cover; }
.thread-list-item .info { flex: 1; min-width: 0; }
.thread-list-item .name-row { display: flex; justify-content: space-between; font-size: 13.5px; font-weight: 700; }
.thread-list-item .last-msg { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.unread-dot { background: var(--primary); color: #fff; font-size: 10px; border-radius: 999px; min-width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; padding: 0 4px; }

.chat-context { display: flex; gap: 10px; align-items: center; padding: 10px 14px; background: var(--primary-light); border-bottom: 1px solid var(--border); }
.chat-context img { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; }
.chat-messages { padding: 14px; display: flex; flex-direction: column; gap: 10px; min-height: 50vh; }
.msg-row { display: flex; }
.msg-row.mine { justify-content: flex-end; }
.msg-bubble { max-width: 75%; padding: 9px 13px; border-radius: 16px; font-size: 14px; }
.msg-row.mine .msg-bubble { background: var(--primary); color: #fff; border-bottom-right-radius: 4px; }
.msg-row.theirs .msg-bubble { background: var(--card-bg-2); border: 1px solid var(--border); border-bottom-left-radius: 4px; }
.msg-offer { font-weight: 800; margin-bottom: 2px; }
.msg-time { font-size: 10px; color: var(--ink-soft); margin-top: 3px; }
.chat-input-bar {
  /* Same fix as .sticky-buy-bar: stack above the bottom-nav instead of
     underneath it, so the offer/send button actually receives the tap. */
  position: fixed; bottom: var(--nav-h); left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 480px; background: var(--card-bg); border-top: 1px solid var(--border);
  padding: 8px 10px; display: flex; gap: 8px; align-items: center; z-index: 31;
}
.chat-input-bar input[type="text"] { flex: 1; border-radius: 999px; }
.chat-input-bar button { border-radius: 999px; padding: 10px 16px; background: var(--primary); color: #fff; border: none; font-weight: 700; }

/* ---------- Order status ---------- */
.status-badge { display: inline-block; padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.status-pending_payment { background: var(--warn-bg); color: var(--warn); }
.status-paid { background: var(--info-bg); color: var(--info); }
.status-shipped { background: var(--purple-bg); color: var(--purple); }
.status-delivered { background: var(--success-bg); color: var(--success); }
.status-cancelled { background: var(--card-bg-2); color: var(--ink-soft); }

.order-card { background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin-bottom: 10px; }
.order-item-row { display: flex; justify-content: space-between; font-size: 13.5px; padding: 4px 0; }

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.stat-box { background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; text-align: center; }
.stat-box .num { font-size: 22px; font-weight: 900; color: var(--primary); }
.stat-box .label { font-size: 12px; color: var(--ink-soft); margin-top: 2px; }

.rating-picker { display: flex; gap: 6px; font-size: 30px; }
.rating-picker input { display: none; }
.rating-picker label { cursor: pointer; color: #494c55; margin: 0; }
.rating-picker input:checked ~ label,
.rating-picker label:hover, .rating-picker label:hover ~ label { color: #f5a623; }
.rating-picker { flex-direction: row-reverse; justify-content: flex-end; }

.review-item { border-bottom: 1px solid var(--border); padding: 10px 0; }
.review-item:last-child { border-bottom: none; }

hr.divider { border: none; border-top: 1px solid var(--border); margin: 12px 0; }

.pagination { display: flex; justify-content: center; gap: 6px; padding: 16px 0; }
.pagination a, .pagination span { padding: 8px 13px; border-radius: 8px; border: 1px solid var(--border); font-size: 13px; background: var(--card-bg-2); color: var(--ink); }
.pagination .current { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); color: #fff; border-color: var(--primary); }

@media (min-width: 481px) {
  .app-shell { border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
}

/* ---------- Home page: horizontal sections ---------- */
.home-banner {
  margin: 12px 14px; padding: 16px; border-radius: var(--radius); color: #fff;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
}
.home-banner .btn { background: #fff; color: var(--primary); }
.section-row { display: flex; justify-content: space-between; align-items: baseline; padding: 0 14px; }
.section-row a { font-size: 12.5px; color: var(--primary); font-weight: 700; white-space: nowrap; }
.hscroll { display: flex; gap: 10px; overflow-x: auto; padding: 4px 14px 14px; scroll-snap-type: x proximity; }
.hscroll::-webkit-scrollbar { display: none; }
.hscroll-card { flex: 0 0 138px; scroll-snap-align: start; }
.hscroll-card .listing-card { height: 100%; }

/* ---------- Portfolio ---------- */
.portfolio-summary { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 8px; }

/* ---------- Portfolio value chart (dark, premium hero card) ---------- */
.portfolio-hero {
  /* Rebrand v3: same near-black-to-emerald sheen as the rest of the site's
     surfaces, radiating from the top-left like light catching a fold of
     dark velvet fabric. */
  background: radial-gradient(120% 140% at 15% 0%, #123a55 0%, #0a1622 55%, #03060a 100%);
  border-radius: 18px; padding: 18px 16px 8px; margin: 12px 14px 14px; color: var(--ink);
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
}
.ph-label { font-size: 12px; color: var(--ink-soft); font-weight: 600; letter-spacing: 0.2px; }
.ph-total { font-size: 28px; font-weight: 900; margin-top: 4px; color: var(--ink); letter-spacing: -0.3px; }
.ph-delta { font-size: 12.5px; font-weight: 700; margin-top: 4px; }
.ph-delta.up { color: var(--success); }
.ph-delta.down { color: #e5484d; }
.ph-delta.muted { color: #6f8578; font-weight: 500; }
.ph-chart-wrap { margin: 14px -4px 0; }
.ph-chart-svg { width: 100%; height: 150px; display: block; }
.ph-chart-empty {
  padding: 30px 10px; text-align: center; font-size: 12.5px; color: var(--ink-soft); line-height: 1.6;
}
.ph-range-tabs { display: flex; gap: 6px; padding: 4px 4px 14px; }
.ph-range-tabs button {
  flex: 1; background: rgba(232,244,251,0.06); border: 1px solid rgba(232,244,251,0.1);
  color: var(--ink-soft); font-size: 11.5px; font-weight: 700; padding: 7px 0; border-radius: 8px; cursor: pointer;
}
.ph-range-tabs button.active { background: var(--primary-light); border-color: rgba(34,211,255,0.4); color: var(--primary); }
.ph-most-valuable { border-top: 1px solid rgba(232,244,251,0.1); padding: 12px 4px 14px; }
.ph-mv-title { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.4px; }
.ph-mv-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; font-size: 13px; }
.ph-mv-row .ph-mv-name { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70%; }
.ph-mv-row .ph-mv-value { color: var(--success); font-weight: 700; }

/* ---------- Social feed ---------- */
.social-tabs { display: flex; background: var(--card-bg); border-bottom: 1px solid var(--border); position: sticky; top: var(--header-h); z-index: 15; }
.social-tabs a { flex: 1; text-align: center; padding: 12px; font-size: 13.5px; color: var(--ink-soft); border-bottom: 2px solid transparent; }
.social-tabs a.active { color: var(--primary); font-weight: 700; border-color: var(--primary); }
.composer { background: var(--card-bg); border-bottom: 8px solid var(--bg); padding: 12px 14px; }
.composer textarea { min-height: 56px; }
.post-card { background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin: 0 14px 12px; }
.post-head { display: flex; align-items: center; gap: 8px; }
.post-head .who { flex: 1; min-width: 0; }
.post-head .name { font-weight: 700; font-size: 13.5px; display: flex; align-items: center; gap: 6px; }
.post-head .time { font-size: 11px; color: var(--ink-soft); }
/* Follow, sized for a header rather than for a form. The old button was a
   full .btn -- as tall as the avatar beside it, and with a second button
   next to it the header outweighed the post underneath. */
.post-follow {
  flex: 0 0 auto; padding: 4px 11px; border-radius: 999px; cursor: pointer;
  font-size: 11.5px; font-weight: 700; line-height: 1.5; white-space: nowrap;
  background: none; border: 1px solid var(--primary); color: var(--primary);
}
.post-follow:active { transform: scale(0.96); }
/* Already following: present, but no longer asking to be pressed. */
.post-follow.on { border-color: var(--border); color: var(--ink-soft); }
.post-follow.danger { border-color: var(--border); color: var(--danger); }

/* A tapped photo opens full size. Feed images are cropped to a tidy height,
   so a card's text is usually cut off -- this is where it can be read. */
.photo-view {
  position: fixed; inset: 0; z-index: 90; display: flex;
  align-items: center; justify-content: center; padding: 16px;
  background: #000000ee; cursor: zoom-out;
}
.photo-view img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 8px;
}
.photo-view-close {
  position: absolute; top: calc(env(safe-area-inset-top, 0px) + 12px); right: 14px;
  width: 40px; height: 40px; border-radius: 999px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: #ffffff26; border: 1px solid #ffffff30; color: #fff;
}
.post-image img { cursor: zoom-in; }
.post-body { font-size: 13.5px; margin: 8px 0; white-space: pre-wrap; }
.post-image { border-radius: 8px; overflow: hidden; margin-bottom: 8px; }
.post-image img { width: 100%; max-height: 320px; object-fit: cover; }
.post-actions { display: flex; gap: 16px; font-size: 12.5px; color: var(--ink-soft); border-top: 1px solid var(--border); padding-top: 8px; margin-top: 4px; }
.post-actions button { background: none; border: none; padding: 0; font-size: 12.5px; color: var(--ink-soft); cursor: pointer; }
.post-actions button.liked { color: var(--primary); font-weight: 700; }
.comment-item { font-size: 12.5px; padding: 3px 0; }
.comment-item strong { margin-right: 5px; }

/* ---------- Search: category quick-filter grid ---------- */
.category-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 4px 14px 14px; }
.category-tile {
  position: relative; min-height: 96px; border-radius: 16px; padding: 14px;
  color: #fff; display: flex; flex-direction: column; justify-content: flex-end;
  overflow: hidden; box-shadow: 0 2px 6px rgba(0,0,0,0.08);
  background-size: cover; background-position: center;
}
.category-tile.has-image::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.65) 100%);
}
.category-tile.has-image .name, .category-tile.has-image .count { position: relative; z-index: 1; text-shadow: 0 1px 3px rgba(0,0,0,0.5); }
.category-tile .emoji { position: absolute; top: 10px; right: 10px; font-size: 26px; opacity: 0.85; }
.category-tile .name { font-weight: 800; font-size: 14px; line-height: 1.25; }
.category-tile .count { font-size: 11.5px; opacity: 0.9; margin-top: 2px; }
.category-grid-all {
  grid-column: 1 / -1; display: flex; align-items: center; justify-content: center;
  padding: 12px; border-radius: 12px; border: 1.5px dashed var(--border); color: var(--ink-soft);
  font-size: 13px; font-weight: 700;
}

/* ---------- Show Sets (official set checklists) ---------- */
.sets-lang-tabs { display: flex; gap: 8px; padding: 10px 14px; background: var(--card-bg); border-bottom: 1px solid var(--border); }
.sets-lang-tabs a {
  flex: 1; text-align: center; padding: 9px 0; border-radius: 999px; font-size: 13px; font-weight: 700;
  color: var(--ink-soft); border: 1.5px solid var(--border);
}
.sets-lang-tabs a.active { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); border-color: var(--primary); color: #fff; }
.set-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 14px; }
.set-tile {
  background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column;
}
.set-tile .cover {
  width: 100%; aspect-ratio: 3/2; background: var(--card-bg-2);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  font-size: 13px; font-weight: 800; color: var(--ink-soft); text-align: center; padding: 8px;
}
/* contain, not cover: a set's logo or a portrait card was being cropped to
   a 3:2 box, which cut the top and bottom off every tile. */
.set-tile .cover img { width: 100%; height: 100%; object-fit: contain; padding: 10px; }
/* Magic's set symbols come from Scryfall as single-colour black SVGs, which
   would be invisible on this dark tile. Pokemon's logos are full-colour
   PNGs and must not be touched, so this keys on the file type. */
.set-tile .cover img[src$=".svg"] { filter: invert(1); opacity: 0.92; padding: 18px; }
/* Last resort: no picture loaded at all, so the tile spells the set out.
   The old rule left this at the 13px muted grey of a caption, which is how
   a grid of sets ended up looking like a grid of empty boxes with a code
   in the corner. The set's NAME, big enough to read at arm's length. */
.set-tile .cover.cover-text {
  font-size: 17px; line-height: 1.25; color: var(--ink); padding: 12px;
  background: linear-gradient(135deg, var(--card-bg-2), var(--card-bg));
  word-break: break-word;
}
.set-tile .body { padding: 10px; }
.set-tile .set-name { font-size: 13px; font-weight: 700; line-height: 1.3; height: 34px; overflow: hidden; }
.set-tile .set-meta { font-size: 11px; color: var(--ink-soft); margin-top: 3px; }
.set-tile .set-progress { font-size: 11.5px; font-weight: 700; color: var(--ink); margin-top: 8px; }
.set-progress-bar { height: 5px; border-radius: 3px; background: var(--card-bg-2); margin-top: 5px; overflow: hidden; }
.set-progress-bar > span { display: block; height: 100%; background: var(--success); border-radius: 3px; }
.set-tile .set-value { font-size: 12.5px; font-weight: 800; color: var(--primary); margin-top: 6px; }

.checklist-header { padding: 16px 14px; background: linear-gradient(180deg, var(--card-bg-2), var(--card-bg)); border-bottom: 8px solid var(--bg); }
.checklist-header .set-title { font-size: 18px; font-weight: 800; }
.checklist-header .set-sub { font-size: 12.5px; color: var(--ink-soft); margin-top: 3px; }
.checklist-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--border);
}
.checklist-row .card-thumb {
  width: 44px; height: 61px; flex-shrink: 0; border-radius: 4px; overflow: hidden;
  background: var(--border); display: block;
}
.checklist-row .card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.checklist-row .num { font-size: 11.5px; color: var(--ink-soft); width: 62px; flex-shrink: 0; }
.checklist-row .info { flex: 1; min-width: 0; }
.checklist-row .name { font-size: 13.5px; font-weight: 600; }
.checklist-row .rarity { font-size: 11px; color: var(--ink-soft); margin-top: 1px; }
.checklist-row.owned { background: var(--success-bg); }
.checklist-row .owned-badge { font-size: 11.5px; font-weight: 700; color: var(--success); white-space: nowrap; }
.checklist-row .add-link { font-size: 11.5px; font-weight: 700; color: var(--primary); white-space: nowrap; }
.checklist-empty { text-align: center; padding: 50px 20px; color: var(--ink-soft); font-size: 13px; line-height: 1.7; }

/* ---------- Card tiles (checklist + movers, one shared look) ---------- */
.card-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; padding: 12px 14px 20px;
}
.card-tile {
  position: relative; display: flex; flex-direction: column;
  background: linear-gradient(155deg, var(--card-bg-2), var(--card-bg) 65%); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.card-tile.owned { border-color: var(--success); }
.card-tile .tile-rank {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px;
  background: rgba(0,0,0,0.66); color: #fff;
  font-size: 11px; font-weight: 800; line-height: 20px; text-align: center;
}
.card-tile .tile-img {
  position: relative; aspect-ratio: 5 / 7; background: var(--border);
  display: flex; align-items: center; justify-content: center;
}
.card-tile .tile-img img { width: 100%; height: 100%; object-fit: contain; display: block; }
.card-tile .tile-img-fallback {
  display: none; font-size: 12px; font-weight: 700; color: var(--ink-soft);
}
.card-tile .tile-img.no-img .tile-img-fallback { display: block; }
.card-tile .tile-body { padding: 9px 10px 10px; display: flex; flex-direction: column; gap: 2px; }
.card-tile .tile-name {
  display: block; font-size: 13px; font-weight: 700; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* The Japanese-printing marker after a card's English name. Small and
   quiet: it is a note about which printing this is, not a heading. */
.card-tile .tile-jp, .card-title .tile-jp {
  font-size: 9.5px; font-weight: 800; letter-spacing: .04em;
  vertical-align: 2px; padding: 1px 4px; border-radius: 4px;
  background: var(--chip-bg, rgba(127, 127, 127, .18));
  color: var(--ink-soft);
}
.card-title .tile-jp { font-size: 12px; vertical-align: 4px; }
.card-tile .tile-set {
  font-size: 11px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-tile .tile-meta { font-size: 11px; color: var(--ink-soft); }
.card-tile .tile-price { font-size: 15px; font-weight: 800; margin-top: 5px; }
.card-tile .tile-price.muted { color: var(--ink-soft); font-weight: 700; }
.card-tile .tile-change { font-size: 11.5px; font-weight: 700; }
.card-tile .tile-change.up { color: var(--success); }
.card-tile .tile-change.down { color: #e5484d; }
.card-tile .tile-change.flat { color: var(--ink-soft); font-weight: 600; }
.card-tile .tile-range { font-size: 10.5px; color: var(--ink-soft); margin-top: 1px; }
.card-tile .tile-sold { font-size: 11px; font-weight: 700; color: var(--primary); margin-top: 3px; }
.card-tile .tile-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 7px;
}
.card-tile .tile-qty { font-size: 11.5px; color: var(--ink-soft); font-weight: 600; }
.card-tile .tile-add {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  border: 1.5px solid var(--primary); color: var(--primary);
  font-size: 19px; font-weight: 700; line-height: 26px; text-align: center;
}

.card-tile .tile-watch-form { position: absolute; top: 4px; right: 4px; z-index: 2; margin: 0; }
.card-tile .tile-watch {
  width: 28px; height: 28px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(0,0,0,0.55); color: #fff; font-size: 15px; line-height: 28px;
  padding: 0; text-align: center;
}
.card-tile .tile-watch.on { color: var(--warn); }

/* ---------- Single card detail ---------- */
.card-hero {
  position: relative; padding: 22px 14px 18px; display: flex; justify-content: center;
  background: var(--card-bg-2); overflow: hidden;
}
/* the card's own art, blurred, as the backdrop */
.card-hero::before {
  content: ""; position: absolute; inset: -40px;
  background-image: var(--art); background-size: cover; background-position: center;
  filter: blur(38px) saturate(1.3); opacity: 0.5;
}
.card-hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(10,11,13,0.15), var(--bg));
}
.card-hero .hero-art { position: relative; z-index: 1; }
.card-hero img {
  max-height: 360px; width: auto; border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.55);
}
.card-hero.no-img { padding: 0; }
.card-hero.no-img::before, .card-hero.no-img::after { display: none; }
.hero-back {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(0,0,0,0.5); color: #fff;
  font-size: 22px; line-height: 32px; text-align: center;
}
.card-title { font-size: 19px; font-weight: 800; line-height: 1.25; }
/* The card's name in its own language, directly under the English one.
   Smaller and lighter so it reads as the same card said twice, not as a
   second fact competing with the first. */
.card-title-alt {
  font-size: 15px; font-weight: 600; line-height: 1.3;
  color: var(--muted); margin-top: 2px;
}
.sold-jump { width: 100%; margin-top: 12px; }
.span-tabs {
  display: flex; gap: 6px; margin-top: 10px; justify-content: center;
}
.span-tabs a {
  flex: 1; text-align: center; padding: 7px 0; border-radius: 999px;
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  border: 1px solid var(--border);
}
.span-tabs a.active { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.spark-empty { padding: 18px 4px; line-height: 1.7; text-align: center; }

/* Range tabs under the collection-value chart on the home page */
.pv-spans { display: flex; gap: 4px; margin-top: 12px; justify-content: center; }
.pv-spans a {
  flex: 1; text-align: center; padding: 8px 0; border-radius: 999px;
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
}
.pv-spans a.active { background: var(--ink); color: var(--bg); }
.qty-row {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; font-size: 13.5px;
}
.qty-controls { display: flex; align-items: center; gap: 12px; }
.qty-controls form { margin: 0; }
.qty-btn {
  width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
  border: 1.5px solid var(--border); background: var(--card-bg-2);
  color: var(--ink); font-size: 19px; line-height: 30px; padding: 0;
}
.qty-btn.add { border-color: var(--primary); color: var(--primary); }
.qty-btn:disabled { opacity: 0.35; }
.qty-value { min-width: 26px; text-align: center; font-size: 16px; font-weight: 800; }
.hero-watch {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; cursor: pointer;
  border: 1px solid var(--border); background: var(--card-bg-2); color: var(--ink-soft);
  font-size: 18px; line-height: 34px; padding: 0;
}
.hero-watch.on { color: var(--warn); border-color: var(--warn); }
.detail-block {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px; margin-top: 12px;
}
.detail-label { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); }
.detail-price { font-size: 26px; font-weight: 800; margin-top: 2px; }
.detail-change { font-size: 13px; font-weight: 800; }
.detail-change.up { color: var(--success); }
.detail-change.down { color: #e5484d; }
.detail-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px;
}
.detail-row:last-child { border-bottom: none; }

/* Price chart: axis text and gridlines live inside the SVG, so they are
   styled here rather than inline. */
.chart-head { display: flex; align-items: baseline; gap: 10px; margin: 8px 0 2px; }
.chart-now { font-size: 20px; font-weight: 800; letter-spacing: -0.4px; }
.chart-delta { font-size: 12.5px; font-weight: 700; }
.chart-delta.up { color: var(--success); }
.chart-delta.down { color: #e5484d; }
.spark .grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; }
.spark .axis { fill: var(--ink-soft); font-size: 8px; }

/* Price points: label and source on the left, the figure on the right. */
.pp-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.pp-row:last-child { border-bottom: none; }
.pp-label { font-size: 12.5px; min-width: 0; }
.pp-source { display: block; font-size: 10.5px; color: var(--ink-soft); margin-top: 2px; }
.pp-value { font-size: 14px; font-weight: 700; white-space: nowrap; }
.pp-row.strong .pp-value { font-size: 17px; color: var(--primary); }

/* Three-month snapshot: a small grid of figures. */
.snap-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; margin-top: 8px;
  background: var(--border); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.snap-cell { background: var(--card-bg); padding: 9px 10px; }
.snap-label { font-size: 10.5px; color: var(--ink-soft); }
.snap-value { font-size: 14px; font-weight: 700; margin-top: 2px; }
.snap-value.up { color: var(--success); }
.snap-value.down { color: #e5484d; }

/* Card facts straight from the publisher: label on the left, value wrapping
   freely on the right, because an attack's text is a paragraph. */
.fact-list { margin: 8px 0 0; }
.fact {
  display: grid; grid-template-columns: 96px 1fr; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--border);
}
.fact:last-child { border-bottom: none; }
.fact dt { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); padding-top: 1px; }
.fact dd {
  margin: 0; font-size: 13px; color: var(--ink); line-height: 1.5;
  white-space: pre-line; overflow-wrap: anywhere;
}

/* Outbound shop links. */
.shop-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 0; border-bottom: 1px solid var(--border);
  color: var(--ink); text-decoration: none;
}
.shop-row:last-of-type { border-bottom: none; }
.shop-site {
  flex-shrink: 0; min-width: 78px; font-size: 12px; font-weight: 700;
  color: var(--ink); letter-spacing: 0.2px;
}
.shop-label { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink-soft); }
.shop-price { flex-shrink: 0; font-size: 14px; color: var(--primary); }
.shop-go { flex-shrink: 0; font-size: 15px; color: var(--primary); }
.spark { width: 100%; height: 90px; margin: 8px 0 4px; display: block; }

/* ---------- Sort / filter controls ---------- */
.card-controls { padding: 0 14px 8px; }
.cc-panel {
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius);
}
.cc-panel > summary {
  padding: 10px 12px; font-size: 13px; font-weight: 700; cursor: pointer;
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.cc-panel > summary::-webkit-details-marker { display: none; }
.cc-count { font-size: 11.5px; font-weight: 600; color: var(--ink-soft); }
.cc-form { padding: 2px 12px 12px; display: grid; gap: 10px; }
.cc-group-title { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); margin-bottom: 4px; }
.cc-form select {
  width: 100%; padding: 9px 10px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--card-bg-2); color: var(--ink);
}
/* Camera button beside the search field. */
/* Camera button: a flex item inside .search-bar, sized like the search
   button next to it. Never absolutely positioned -- that put it outside the
   bar entirely on a phone. */
.scan-btn {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; font-size: 19px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  text-decoration: none; line-height: 1;
}
.scan-btn:active { background: var(--border); }

/* The camera offered as a whole row rather than an icon: on the add-a-card
   screen there is space to say what it does, and it is the faster way in of
   the two the page offers. Sized so the icon reads as a shutter, not as a
   bullet point. */
.scan-cta {
  display: flex; align-items: center; gap: 12px;
  padding: 14px; margin-bottom: 14px;
  border-radius: 14px; text-decoration: none;
  background: var(--info-bg); border: 1px solid var(--info);
  color: inherit;
}
.scan-cta:active { filter: brightness(1.08); }
.scan-cta-icon {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  font-size: 21px; line-height: 1;
  background: var(--primary); color: #fff;
}
.scan-cta-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.scan-cta-text strong { font-size: 15px; font-weight: 800; }
.scan-cta-text .small { color: var(--muted); line-height: 1.5; }
.scan-cta-go { flex: 0 0 auto; font-size: 22px; color: var(--muted); }
.search-bar { align-items: center; }
.search-bar .filter-toggle { flex: 0 0 auto; }

/* Graded panel on a card page */
.grade-part { margin-top: 14px; }
.grade-part:first-of-type { margin-top: 8px; }
.grade-part-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  font-size: 13px; font-weight: 700; color: var(--ink-soft); margin-bottom: 6px;
}
.grade-src {
  padding: 8px 0 8px 10px; border-left: 3px solid var(--border);
  margin-bottom: 6px;
}
.grade-src.on { border-left-color: var(--success); }
.grade-src-name { font-size: 13.5px; font-weight: 700; }
.grade-dot {
  font-size: 11.5px; font-weight: 600; color: var(--ink-soft);
  margin-left: 6px;
}
.grade-src.on .grade-dot { color: var(--success); }

/* ---------------- Home: collection value ---------------- */
.home-top { display: flex; justify-content: flex-end; padding: 8px 14px 0; }
.lang-switch {
  display: inline-flex; border: 1px solid var(--border); border-radius: 999px;
  overflow: hidden; background: var(--card-bg);
}
.lang-switch a {
  padding: 6px 12px; font-size: 11.5px; font-weight: 700; color: var(--ink-soft);
  white-space: nowrap;
}
.lang-switch a.active { background: var(--primary); color: #fff; }

.pv { padding: 14px 14px 6px; }
.pv-label { font-size: 13px; font-weight: 700; color: var(--ink-soft); }
.pv-total { font-size: 34px; font-weight: 800; letter-spacing: -0.5px; margin-top: 2px; }
.pv-delta { font-size: 13.5px; font-weight: 700; margin-top: 2px; }
.pv-delta.up, .mv-change.up { color: var(--success); }
.pv-delta.down, .mv-change.down { color: #e5484d; }
.pv-chart { width: 100%; height: 130px; display: block; margin-top: 10px; }
.pv-axis {
  display: flex; justify-content: space-between;
  font-size: 10.5px; color: var(--ink-soft); margin-top: 2px;
}
.pv-note { font-size: 11.5px; color: var(--ink-soft); line-height: 1.7; margin-top: 6px; }

.panel-card {
  margin: 10px 14px; padding: 12px 14px; border-radius: var(--radius);
  background: var(--card-bg); border: 1px solid var(--border);
}
.empty-inline { padding: 10px 0 4px; }
.ei-title { font-size: 14.5px; font-weight: 700; }

.mv-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 0;
  border-top: 1px solid var(--border); color: inherit;
}
.mv-row:first-of-type { border-top: 0; }
.mv-art {
  flex: 0 0 auto; width: 42px; height: 58px; border-radius: 6px; overflow: hidden;
  background: var(--card-bg-2); display: flex; align-items: center; justify-content: center;
  font-size: 20px;
}
.mv-art img { width: 100%; height: 100%; object-fit: cover; }
.mv-body { flex: 1; min-width: 0; }
.mv-name {
  font-size: 14px; font-weight: 700; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.mv-sub { font-size: 11.5px; color: var(--ink-soft); margin-top: 1px; }
.mv-right { text-align: right; flex-shrink: 0; }
.mv-value { font-size: 15px; font-weight: 800; white-space: nowrap; }
.mv-change { font-size: 11.5px; font-weight: 700; white-space: nowrap; margin-top: 1px; }
/* How long the move took, under the figure. Small on purpose -- it is the
   caveat on the number above it, not a number of its own. */
.mv-days { font-size: 10px; color: var(--ink-soft); white-space: nowrap; margin-top: 1px; }

/* ---------------- Scan: viewfinder ---------------- */
.scan-stage {
  position: fixed; inset: 0; background: #000; z-index: 60;
  overflow: hidden;
}
.scan-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.scan-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; align-items: center; gap: 10px;
  padding: calc(env(safe-area-inset-top, 0px) + 10px) 14px 10px;
  background: linear-gradient(#000c, #0000);
}
.scan-top-title { flex: 1; text-align: center; color: #fff; font-weight: 700; font-size: 15px; }
.scan-round {
  width: 44px; height: 44px; flex: 0 0 auto; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; color: #fff; text-decoration: none;
  background: #ffffff26; border: 1px solid #ffffff30; cursor: pointer;
}
.scan-round.scan-ghost { background: none; border-color: transparent; }

/* Card-shaped guide: 63x88mm, the real proportions of a trading card. */
.scan-guide {
  position: absolute; z-index: 2;
  left: 50%; top: 50%; transform: translate(-50%, -54%);
  width: min(78vw, 340px); aspect-ratio: 63 / 88;
  border-radius: 12px; box-shadow: 0 0 0 100vmax #00000073;
}
.scan-guide .c {
  position: absolute; width: 26px; height: 26px;
  border: 3px solid #fff; border-radius: 3px;
}
.scan-guide .tl { top: -2px; left: -2px; border-right: 0; border-bottom: 0; }
.scan-guide .tr { top: -2px; right: -2px; border-left: 0; border-bottom: 0; }
.scan-guide .bl { bottom: -2px; left: -2px; border-right: 0; border-top: 0; }
.scan-guide .br { bottom: -2px; right: -2px; border-left: 0; border-top: 0; }

.scan-hint {
  position: absolute; z-index: 3; left: 14px; right: 14px; bottom: 140px;
  text-align: center; color: #fff; font-size: 13.5px; line-height: 1.7;
  text-shadow: 0 1px 6px #000;
}
.scan-warn {
  position: absolute; z-index: 3; left: 14px; right: 14px; top: 78px;
  padding: 10px 12px; border-radius: 12px; font-size: 12.5px; line-height: 1.7;
  background: #000000b3; color: #ffd28a; border: 1px solid #ffffff2e;
}
.scan-fallback {
  position: absolute; inset: 0; z-index: 1; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: var(--bg);
}
.scan-fallback-inner { text-align: center; max-width: 300px; }

.scan-bottom {
  position: absolute; z-index: 3; left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
  display: flex; align-items: center; justify-content: space-around;
  padding: 0 24px;
}
.scan-shutter {
  width: 74px; height: 74px; border-radius: 999px; cursor: pointer;
  background: #fff; border: 5px solid #ffffff5c; box-shadow: 0 4px 18px #0009;
}
.scan-shutter:active { transform: scale(0.94); }
.scan-shutter:disabled { opacity: 0.45; }

.scan-busy {
  position: absolute; inset: 0; z-index: 5; display: flex;
  flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  background: #000000c4; color: #fff; font-size: 14px; font-weight: 600;
}
.scan-spinner {
  width: 34px; height: 34px; border-radius: 999px;
  border: 3px solid #ffffff33; border-top-color: #fff;
  animation: scan-spin 0.8s linear infinite;
}
@keyframes scan-spin { to { transform: rotate(360deg); } }

/* ---------------- Scan: the review screen ----------------
   The whole pile, laid out, before any of it is filed. A full-screen layer
   over the viewfinder rather than a separate page: the pile only exists in
   this browser, so navigating away is where it stops existing. */
.review-stage {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column; background: var(--bg);
}
.review-top {
  flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
  padding: calc(env(safe-area-inset-top, 0px) + 12px) 14px 12px;
  border-bottom: 1px solid var(--border);
}
.review-list { flex: 1 1 auto; overflow-y: auto; padding: 12px 14px 4px; }
.review-row {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 11px; margin-bottom: 9px; border-radius: 12px;
  background: var(--card-bg); border: 1px solid var(--border);
}
.review-art {
  flex: 0 0 auto; width: 54px; height: 75px; border-radius: 6px;
  overflow: hidden; background: var(--card-bg-2); color: var(--ink-soft);
  display: flex; align-items: center; justify-content: center;
}
.review-art img { width: 100%; height: 100%; object-fit: cover; }
.review-body { flex: 1 1 auto; min-width: 0; }
.review-name { font-weight: 700; font-size: 14px; line-height: 1.35; }
.review-set { margin-bottom: 6px; }
.review-fact {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 12px; line-height: 1.9;
}
.review-fact span { color: var(--ink-soft); }
.review-fact strong { color: var(--primary); font-weight: 600; text-align: right; }
.review-price { margin-top: 5px; font-size: 13px; font-weight: 800; }
.review-edit {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: 1px solid var(--border); color: var(--ink-soft);
}
.review-foot {
  flex: 0 0 auto; padding: 12px 14px calc(env(safe-area-inset-bottom, 0px) + 14px);
  border-top: 1px solid var(--border); background: var(--card-bg);
}
.review-total {
  text-align: center; font-size: 13.5px; font-weight: 700;
  color: var(--ink-soft); margin-bottom: 10px; line-height: 1.6;
}
.review-foot .btn { width: 100%; }

/* Only up while the browser has no camera answer on file. Sits above the
   hint line so it does not cover the frame guide. */
.scan-perm {
  position: absolute; z-index: 3; left: 12px; right: 12px;
  top: calc(env(safe-area-inset-top, 0px) + 72px);
  padding: 10px 12px; border-radius: 12px;
  background: #0a1622e0; border: 1px solid var(--border);
  color: var(--ink-soft); font-size: 11.5px; line-height: 1.65;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* ---------------- Scan: the pile scanned so far ----------------
   Sits above the shutter so a whole box can be photographed in one pass:
   each card looks itself up while the next one is being taken, and the
   strip is where the answers land. Horizontal, because the viewfinder is
   the point of the screen and this must not take it over. */
.scan-queue {
  position: absolute; z-index: 3; left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 104px);
  padding: 0 12px;
}
.scan-queue-strip {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 6px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.scan-queue-strip::-webkit-scrollbar { display: none; }
.scan-queue-total {
  text-align: right; padding: 0 4px; font-weight: 800; font-size: 14px;
  color: var(--primary); text-shadow: 0 1px 6px #000c;
}
.scan-queue-total:empty { display: none; }

.qcard {
  position: relative; flex: 0 0 auto; width: 208px; max-width: 72vw;
  display: flex; align-items: center; gap: 9px; text-align: left;
  padding: 7px 9px; border-radius: 12px; cursor: pointer;
  background: #0a1622d9; border: 1px solid #ffffff2e; color: var(--ink);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.qcard:active { transform: scale(0.98); }
.qcard-thumb {
  flex: 0 0 auto; width: 34px; height: 47px; border-radius: 5px;
  overflow: hidden; background: #0006; display: flex;
  align-items: center; justify-content: center; color: var(--ink-soft);
}
.qcard-thumb img { width: 100%; height: 100%; object-fit: cover; }
.qcard-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.qcard-title {
  font-size: 12.5px; font-weight: 700; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.qcard-sub, .qcard-price {
  font-size: 11px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.qcard-sub { color: var(--ink-soft); }
.qcard-price { color: var(--primary); font-weight: 700; }
.qcard-none .qcard-title, .qcard-error .qcard-title { color: var(--ink-soft); }
.qcard-none .qcard-sub { color: var(--primary); }
.qcard-error { border-color: var(--danger); }
.qcard.is-added { border-color: var(--success); }
.qcard-tick {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; border-radius: 999px;
  background: var(--success); color: #03060a;
  font-size: 12px; font-weight: 900; line-height: 20px; text-align: center;
}
.qcard-spin {
  position: absolute; right: 9px; top: 50%; margin-top: -8px;
  width: 16px; height: 16px; border-radius: 999px;
  border: 2px solid #ffffff2e; border-top-color: var(--primary);
  animation: scan-spin 0.8s linear infinite;
}

/* The shutter no longer opens a sheet, so the shot itself has to be
   visible: one frame of white over the viewfinder. */
.scan-stage.flash::after {
  content: ""; position: absolute; inset: 0; z-index: 4;
  background: #fff; opacity: 0.55; pointer-events: none;
}
/* The way out of a continuous pass. It only grows a label once there is
   something to go and look at -- a "done" button over an empty queue is
   an invitation to leave before starting. */
.scan-done-label { display: none; }
.scan-round.is-done {
  width: auto; padding: 0 14px; gap: 6px;
  border-color: var(--primary); color: var(--primary);
}
.scan-round.is-done .scan-done-label {
  display: inline; font-size: 12.5px; font-weight: 700; white-space: nowrap;
}

/* ---------------- Scan: result sheet ---------------- */
body.sheet-open { overflow: hidden; }
.sheet-wrap { position: fixed; inset: 0; z-index: 70; display: flex; align-items: flex-end; }
.sheet-backdrop { position: absolute; inset: 0; background: #000000a8; }
.sheet {
  position: relative; width: 100%; max-height: 92vh;
  display: flex; flex-direction: column;
  background: var(--bg); border-radius: 20px 20px 0 0;
  border-top: 1px solid var(--border);
  animation: sheet-up 0.22s ease-out;
}
@keyframes sheet-up { from { transform: translateY(22px); opacity: 0.4; } }
.sheet-grip {
  width: 42px; height: 4px; border-radius: 999px; background: var(--border);
  margin: 9px auto 4px;
}
.sheet-title { text-align: center; font-weight: 700; font-size: 15px; padding-bottom: 8px; }
.sheet-body { overflow-y: auto; padding: 4px 14px 8px; -webkit-overflow-scrolling: touch; }
.sheet-label { font-size: 13px; font-weight: 700; color: var(--ink-soft); margin: 12px 0 6px; }
.sheet-actions {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px calc(env(safe-area-inset-bottom, 0px) + 12px);
  border-top: 1px solid var(--border); background: var(--card-bg);
}
.sheet-actions .btn { flex: 1; margin: 0; }
.sheet-actions .scan-round { background: var(--card-bg-2); border-color: var(--border); color: var(--ink); }
.sheet-msg { margin-top: 12px; padding: 10px 12px; border-radius: 12px; font-size: 13px; line-height: 1.6; }
.sheet-msg.ok { background: var(--success-bg); color: var(--success); }
.sheet-msg.bad { background: var(--warn-bg); color: var(--warn); }
.msg-actions { display: flex; gap: 8px; margin-top: 10px; }
.msg-actions a, .msg-actions button {
  flex: 1; text-align: center; padding: 9px 8px; border-radius: 10px;
  font-size: 12.5px; font-weight: 700; cursor: pointer;
  background: var(--card-bg); border: 1px solid var(--border); color: var(--ink);
}

.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.compare-cell { text-align: center; }
.compare-cell img, .compare-cell #match-img-wrap {
  width: 100%; height: 168px; object-fit: contain;
  border-radius: 12px; background: var(--card-bg-2); border: 1px solid var(--border);
}
#match-img-wrap { display: flex; align-items: center; justify-content: center; overflow: hidden; }
#match-img-wrap img { height: 100%; border: 0; }
.compare-cap { font-size: 12.5px; font-weight: 700; color: var(--ink-soft); margin-top: 6px; }

.match-strip { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.match-strip::-webkit-scrollbar { display: none; }
.match-thumb {
  flex: 0 0 auto; width: 74px; height: 104px; padding: 0; cursor: pointer;
  border-radius: 10px; overflow: hidden; background: var(--card-bg-2);
  border: 2px solid transparent; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px;
  font-size: 22px; color: var(--ink-soft); text-decoration: none;
}
.match-thumb img { width: 100%; height: 100%; object-fit: cover; }
.match-thumb.active { border-color: var(--primary); }
.match-thumb.manual { border: 2px dashed var(--border); }
.match-thumb.manual small { font-size: 10.5px; }

.pick-head { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; margin-top: 12px; }
.pick-name { font-size: 17px; font-weight: 800; line-height: 1.35; }
.pick-price { font-size: 21px; font-weight: 800; }
.pick-actions { display: flex; gap: 8px; margin-top: 12px; }
.pick-actions .btn { flex: 1; width: auto; margin: 0; padding: 9px 8px; font-size: 12.5px; }

.grade-chips { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.grade-chips::-webkit-scrollbar { display: none; }
.grade-chip {
  flex: 0 0 auto; padding: 9px 16px; border-radius: 10px; cursor: pointer;
  font-size: 13px; font-weight: 700; white-space: nowrap;
  background: var(--card-bg-2); border: 1.5px solid var(--border); color: var(--ink-soft);
}
.grade-chip.active { border-color: var(--primary); color: var(--primary); }

/* Price for the grade selected on the scan sheet */
.quote {
  margin-top: 10px; padding: 10px 12px; border-radius: 12px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  font-size: 13px;
}
.quote.empty { color: var(--ink-soft); }
.quote-head { font-size: 12px; font-weight: 700; color: var(--ink-soft); margin-bottom: 6px; }
.quote-note { line-height: 1.7; }
.quote-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 0; border-top: 1px solid var(--border); text-decoration: none; color: inherit;
}
.quote-row:first-of-type { border-top: 0; }
.quote-left { min-width: 0; }
.quote-title { font-weight: 700; font-size: 13px; }
.quote-sub { font-size: 11.5px; color: var(--ink-soft); line-height: 1.55; margin-top: 1px; }
.quote-value { font-size: 16px; font-weight: 800; white-space: nowrap; }

.pick-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.pick-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pick-field > span { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); }
.pick-field select, .pick-field input {
  width: 100%; padding: 10px 11px; font-size: 14px;
  border-radius: 10px; border: 1px solid var(--border);
  background: var(--card-bg); color: var(--ink);
}

/* Scan page (fallback tile) */
.scan-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 34px 18px; text-align: center; cursor: pointer;
  border: 2px dashed var(--border); border-radius: var(--radius);
  background: var(--card-bg);
}
.scan-icon { font-size: 34px; }
.scan-label { font-size: 14.5px; font-weight: 700; }
.scan-preview {
  width: 100%; max-height: 320px; object-fit: contain; margin-top: 12px;
  border-radius: var(--radius); border: 1px solid var(--border); background: var(--card-bg-2);
}

.probe-raw {
  margin: 8px 0 0; padding: 10px; max-height: 260px; overflow: auto;
  background: var(--card-bg-2); border: 1px solid var(--border); border-radius: 8px;
  font-size: 10.5px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
  color: var(--ink-soft);
}
.auto-panel {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px; margin-bottom: 14px;
}
.auto-title { font-size: 13.5px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.auto-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--ink-soft); flex-shrink: 0;
}
.auto-dot.on { background: var(--success); box-shadow: 0 0 0 3px var(--success-bg); }
.cc-input {
  width: 100%; padding: 9px 10px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--card-bg-2); color: var(--ink);
}
.cc-range { display: flex; align-items: center; gap: 8px; }
.cc-range input {
  flex: 1; min-width: 0; padding: 9px 10px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--card-bg-2); color: var(--ink);
}
.cc-range span { font-size: 12.5px; color: var(--ink-soft); }
.cc-hint { font-size: 11px; color: var(--ink-soft); margin-top: 5px; }
.cc-check { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.cc-check input { width: 17px; height: 17px; }
.cc-actions { display: flex; gap: 8px; }
.cc-actions .btn { flex: 1; }

/* ---------- Biggest price movers heading ---------- */
.movers-head { padding: 22px 14px 8px; border-top: 1px solid var(--border); margin-top: 14px; }
.movers-title { font-size: 15px; font-weight: 800; margin-bottom: 3px; }
.movers-empty { padding: 4px 14px 24px; line-height: 1.7; }

/* ---------- Admin panel ---------- */
.admin-tabs { display: flex; gap: 8px; overflow-x: auto; padding: 10px 14px; background: var(--card-bg); border-bottom: 1px solid var(--border); }
.admin-tabs a { flex-shrink: 0; padding: 8px 14px; border-radius: 999px; border: 1.5px solid var(--border); font-size: 13px; font-weight: 600; color: var(--ink-soft); }
.admin-tabs a.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.admin-row { display: flex; align-items: center; gap: 10px; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin-bottom: 8px; }
.admin-row .info { flex: 1; min-width: 0; }
.admin-row .title { font-weight: 700; font-size: 13.5px; }
.admin-row .sub { font-size: 11.5px; color: var(--ink-soft); margin-top: 2px; }
/* Import panel: one block per game, so twenty-odd sources read as eight
   short groups instead of one long undifferentiated list. */
.imp-game { margin-bottom: 16px; }
.imp-game-name {
  font-size: 12px; font-weight: 800; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ink-soft);
  padding: 0 2px 6px; border-bottom: 1px solid var(--border); margin-bottom: 8px;
}
.imp-row { padding: 10px 12px; }
/* nowrap, so a long source name gets an ellipsis rather than pushing the
   row onto two lines and breaking the even rhythm of the list. */
.imp-row .title { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; min-width: 0; }
/* What each source is for, said once as a tag rather than buried in a
   sentence under every row. */
.imp-kind {
  font-size: 10px; font-weight: 800; padding: 2px 7px; border-radius: 999px;
  letter-spacing: 0.02em; white-space: nowrap;
}
.imp-kind-list { background: var(--info-bg); color: var(--info); }
.imp-kind-price { background: var(--success-bg); color: var(--success); }
.imp-kind-extra { background: var(--card-bg-2); color: var(--ink-soft); }
.imp-lang {
  font-size: 10px; font-weight: 800; color: var(--ink-soft);
  border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px;
}
/* Delete-and-rebuild. It should not look like the row above it: this one
   removes rows that collections and listings point at. */
/* Game picker + file picker + button. Wraps to one per line on a phone,
   where three controls will not sit side by side. */
.upload-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.upload-row .input { flex: 1 1 180px; min-width: 0; }
.upload-row .btn { flex: 0 0 auto; }
/* The three ordered steps at the top of the import page. The page had
   grown into a wall of buttons; this is the part that is actually a
   sequence, so it reads as one. */
.setup-steps {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 12px; margin-bottom: 14px;
}
.setup-steps .step {
  border-top: 1px solid var(--border); padding: 12px 0 10px;
}
.setup-steps .step:first-of-type { border-top: 0; padding-top: 0; }
.step-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.step-no {
  font-size: 10px; font-weight: 800; letter-spacing: .04em;
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px;
  color: var(--ink-soft); white-space: nowrap;
}
.step-danger .step-no { color: var(--danger); border-color: var(--danger); }
.step-name { font-weight: 700; font-size: 13.5px; }
.step-note { margin: 6px 0 9px; line-height: 1.65; }
/* Wraps to as many rows as it needs on a phone. */
.step-buttons { display: flex; flex-wrap: wrap; gap: 6px; }
.step-buttons .btn { flex: 0 0 auto; }
.imp-row.imp-danger { border-color: var(--danger); }
.imp-danger-actions { display: flex; gap: 6px; align-items: center; }
.btn.imp-force {
  color: var(--danger); border-color: var(--danger); background: transparent;
  font-weight: 700;
}
.imp-lang-danger { color: var(--danger); border-color: var(--danger); }
.btn.btn-danger {
  background: var(--danger); border-color: var(--danger); color: #fff;
  font-weight: 700;
}
.btn.btn-danger:disabled { opacity: .5; }
.imp-source {
  font-weight: 600; font-size: 12.5px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.imp-steps { font-size: 11px; font-weight: 600; color: var(--ink-soft); }
/* The two sources behind a language, stacked so each stays on its own
   line however long the host names are. */
.imp-sources { display: flex; flex-direction: column; gap: 3px; margin-top: 5px; }
.imp-sources > span { display: flex; align-items: center; gap: 6px; min-width: 0; }
.imp-none { color: var(--ink-soft); font-style: italic; }
.imp-advanced { margin-top: 6px; }
.imp-advanced > summary {
  cursor: pointer; font-size: 12px; font-weight: 700; color: var(--ink-soft);
  padding: 8px 2px;
}
.imp-advanced .admin-row { background: transparent; }
.color-dot { width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0; border: 1px solid rgba(255,255,255,0.15); }
.admin-inline-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.admin-inline-form input[type="text"], .admin-inline-form input[type="number"] {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; font-size: 13px;
}
.admin-inline-form input[type="number"] { width: 60px; }
.admin-inline-form input[type="color"] { width: 34px; height: 34px; padding: 2px; border: 1px solid var(--border); border-radius: 8px; }
.badge-suspended { background: var(--primary-light); color: var(--primary); }
.badge-admin { background: var(--purple-bg); color: var(--purple); }
.admin-cat-thumb { width: 34px; height: 34px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
.admin-file-input { font-size: 11.5px; max-width: 130px; }

/* Data-coverage report in the admin screen */
.cov-row { padding: 10px 0; border-top: 1px solid var(--border); }
.cov-row:first-of-type { border-top: 0; }
.cov-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.cov-name { font-size: 13.5px; font-weight: 700; }
.cov-bars { display: grid; gap: 4px; margin-top: 6px; }
.cov-bar { display: flex; align-items: center; gap: 8px; }
.cov-label { font-size: 11.5px; color: var(--ink-soft); width: 30px; flex: 0 0 auto; }
.cov-track {
  flex: 1; height: 7px; border-radius: 4px; background: var(--card-bg-2); overflow: hidden;
}
.cov-track > i { display: block; height: 100%; background: var(--success); }
.cov-track > i.warn { background: var(--warn); }
.cov-pct { font-size: 11.5px; font-weight: 700; width: 46px; text-align: right; flex: 0 0 auto; }

/* --- A listing's photographs -------------------------------------------
   The seller's own pictures are the evidence a buyer judges the card by,
   so they get real estate: a scrollable strip of thumbnails with a live
   count, and a cover chooser that shows both candidates side by side. */
.photo-actions { display: flex; gap: 8px; }
.photo-actions .btn { flex: 1; }
.photo-strip {
  display: flex; gap: 8px; overflow-x: auto; padding: 10px 0 2px;
  -webkit-overflow-scrolling: touch;
}
.photo-strip:empty { padding: 0; }
.photo-thumb {
  position: relative; flex: 0 0 76px; width: 76px; height: 76px;
  border-radius: 10px; overflow: hidden; background: var(--card-bg-2);
}
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-del {
  position: absolute; top: 2px; right: 2px; width: 22px; height: 22px;
  border: 0; border-radius: 50%; cursor: pointer; line-height: 1;
  background: rgba(0, 0, 0, .62); color: #fff; font-size: 12px;
}
.photo-count { font-size: 12px; margin-top: 4px; }
.photo-count.short { color: var(--danger); font-weight: 700; }
.photo-count.ok { color: var(--success, #2fe08a); }
.reuse-thumb {
  width: 34px; height: 34px; border-radius: 7px; object-fit: cover; display: block;
}

.cover-pick { display: flex; gap: 10px; }
.cover-opt { flex: 1; cursor: pointer; }
.cover-opt input { position: absolute; opacity: 0; pointer-events: none; }
.cover-box {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px; border: 2px solid var(--border); border-radius: 12px;
}
.cover-opt input:checked + .cover-box {
  border-color: var(--accent); background: var(--card-bg-2);
}
.cover-art {
  width: 100%; height: 92px; display: flex; align-items: center;
  justify-content: center; font-size: 26px;
}
.cover-art img { max-width: 100%; max-height: 92px; object-fit: contain; }

/* The catalogue picture, wherever it is shown to a buyer. It is the
   publisher's artwork -- identical for every copy of the card in the
   world -- so it never appears without saying so. */
.official-note {
  display: block; margin-top: 6px; padding: 6px 9px; border-radius: 8px;
  font-size: 11.5px; line-height: 1.5;
  background: var(--warn-bg, rgba(200, 150, 0, .12));
  color: var(--text-muted, inherit);
}

/* --- Scan results on the selling form ---------------------------------
   Each hit is a whole button: the picture, what it is, and what it is
   worth, so the seller picks the right printing by looking rather than by
   reading a row of text. */
.scan-hit {
  display: flex; gap: 10px; align-items: center; width: 100%;
  padding: 8px; margin-bottom: 6px; cursor: pointer; text-align: left;
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 10px; color: inherit; font: inherit;
}
.scan-hit:last-child { margin-bottom: 0; }
.scan-hit:active { border-color: var(--accent); }
.scan-hit img, .scan-hit-blank {
  flex: 0 0 44px; width: 44px; height: 60px; border-radius: 6px;
  object-fit: cover; display: flex; align-items: center;
  justify-content: center; background: var(--card-bg);
}
.scan-hit-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.scan-hit-text strong,
.scan-hit-text span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Order history, shown to buyer, seller and admin alike ------------ */
.hist-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--border); color: inherit; text-decoration: none;
}
.hist-row:last-child { border-bottom: 0; }
.hist-main { flex: 1; min-width: 0; }
.hist-main .t {
  font-weight: 600; font-size: 13.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hist-amount { font-weight: 700; white-space: nowrap; }
.hist-totals {
  display: flex; gap: 8px; margin: 6px 0 10px; flex-wrap: wrap;
}
.hist-stat {
  flex: 1; min-width: 92px; padding: 8px 10px; border-radius: 10px;
  background: var(--card-bg-2);
}
.hist-stat .n { font-weight: 800; font-size: 16px; }

/* --- Community: header, comment sheet, notifications -------------------
   The community has its own header because chat and notifications belong
   to it, not to every page on the site. */
.social-top {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px 8px;
}
.social-title { font-size: 19px; font-weight: 800; flex: 1; }
.social-icons { display: flex; gap: 6px; }
/* Scoped to this header: the top bar has its own .icon-btn and must not
   be restyled from under it. */
.social-top .icon-btn {
  position: relative; width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; cursor: pointer; text-decoration: none; color: inherit;
  background: var(--card-bg-2); border: 1px solid var(--border);
}
.icon-dot {
  position: absolute; top: -3px; right: -3px; min-width: 17px; height: 17px;
  padding: 0 4px; border-radius: 999px; background: var(--primary);
  color: #fff; font-size: 10px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}

/* Comments are read and written here, not spilled down the feed. */
.post-comment-btn { text-decoration: none; color: inherit; cursor: pointer; }
.sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 14px 10px; border-bottom: 1px solid var(--border);
}
.sheet-close {
  border: 0; background: none; color: var(--ink-soft);
  font-size: 16px; cursor: pointer; padding: 2px 6px;
}
.sheet-empty { padding: 26px 4px; text-align: center; color: var(--ink-soft); font-size: 13px; }
.sheet-foot {
  display: flex; gap: 8px; align-items: center;
  padding: 10px 14px calc(env(safe-area-inset-bottom, 0px) + 12px);
  border-top: 1px solid var(--border); background: var(--card-bg);
}
.sheet-foot input[type="text"] { flex: 1; padding: 9px 11px; font-size: 13px; }
.sheet-foot .btn { margin: 0; }
#comment-sheet .sheet { min-height: 46vh; }
#comment-sheet .sheet-body { flex: 1; }
.comment-item { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; padding: 7px 0; }
.comment-item + .comment-item { border-top: 1px solid var(--border); }
.comment-item strong { font-size: 12.5px; }
.comment-item > span { font-size: 13px; line-height: 1.55; flex: 1 1 100%; }
.comment-time { font-size: 11px; color: var(--ink-soft); flex: 0 0 auto !important; }

.notif-row {
  display: flex; gap: 10px; align-items: flex-start; padding: 11px 12px;
  border-radius: 12px; text-decoration: none; color: inherit;
  border: 1px solid var(--border); margin-bottom: 8px; background: var(--card-bg);
}
.notif-row.unseen { background: var(--info-bg, var(--card-bg-2)); border-color: var(--primary); }
.notif-icon { font-size: 17px; line-height: 1.3; }
.notif-text { flex: 1; font-size: 13.5px; line-height: 1.6; min-width: 0; }
.notif-quote { display: block; color: var(--ink-soft); font-size: 12.5px; }
.notif-time { display: block; color: var(--ink-soft); font-size: 11.5px; margin-top: 2px; }
.notif-thumb { flex: 0 0 42px; width: 42px; height: 42px; border-radius: 8px; overflow: hidden; }
.notif-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- The account page ---------------------------------------------------
   Cover, avatar, the four totals, segmented tabs and real switches. */
.acct-cover {
  position: relative; height: 96px;
  background: linear-gradient(135deg, var(--card-bg-2), var(--card-bg));
  background-size: cover; background-position: center;
}
.acct-lang { position: absolute; top: 10px; right: 12px; display: flex; gap: 6px; }
.lang-chip {
  padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 700;
  text-decoration: none; color: var(--ink); background: #00000066;
  border: 1px solid var(--border); backdrop-filter: blur(4px);
}
.lang-chip.on { background: var(--primary); color: #fff; border-color: var(--primary); }

/* Only the avatar rides up over the cover. The name and email sit below
   it on a clean background -- text half over a photograph is unreadable,
   and it was clipping the name. */
.acct-head { display: flex; gap: 12px; align-items: flex-start; padding: 0 14px 10px; }
.acct-head .acct-avatar { margin-top: -32px; }
.acct-avatar {
  position: relative; flex: 0 0 72px; width: 72px; height: 72px; border-radius: 50%;
  overflow: hidden; cursor: pointer; display: flex; align-items: center;
  justify-content: center; font-size: 26px; font-weight: 800;
  background: var(--card-bg-2); border: 3px solid var(--bg);
}
.acct-avatar img { width: 100%; height: 100%; object-fit: cover; }
.acct-avatar-edit {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 2px 0;
  font-size: 9.5px; font-weight: 700; text-align: center;
  background: #000000b0; color: #fff;
}
.acct-who { flex: 1; min-width: 0; padding-top: 8px; }
.acct-name { font-size: 18px; font-weight: 800; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.acct-handle { font-size: 13.5px; color: var(--primary); font-weight: 600; }
.acct-pencil { text-decoration: none; font-size: 12px; }

.acct-stats { display: flex; gap: 4px; padding: 4px 14px 10px; }
.acct-stats > div {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 0;
}
.acct-stats .label { font-size: 11px; color: var(--ink-soft); white-space: nowrap; }
.acct-stats .num {
  font-size: 14.5px; font-weight: 800; color: var(--primary);
  overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.acct-stats.flat { padding: 4px 0 0; }
.acct-actions { display: flex; gap: 8px; padding: 0 14px 12px; }
.acct-actions .btn { flex: 1; margin: 0; }

.seg-tabs {
  display: flex; gap: 2px; margin: 0 14px 4px; padding: 3px;
  background: var(--card-bg-2); border-radius: 999px;
}
.seg-tabs a {
  flex: 1; text-align: center; padding: 9px 4px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; color: var(--ink-soft); text-decoration: none;
}
.seg-tabs a.active { background: var(--card-bg); color: var(--ink); font-weight: 800; }

.perf-row { padding: 10px 0; border-bottom: 1px solid var(--border); }
.perf-row:last-of-type { border-bottom: 0; }

/* Top rising / Top falling -- an underline tab pair, colored so the tab
   itself hints which direction it holds before a single row is read. */
.mover-tabs {
  display: flex; gap: 18px; padding: 4px 14px 0; border-bottom: 1px solid var(--border);
}
.mover-tabs a {
  display: flex; align-items: center; gap: 5px; padding: 8px 2px 10px;
  font-size: 14px; font-weight: 700; color: var(--ink-soft);
  border-bottom: 2.5px solid transparent; margin-bottom: -1px;
}
.mover-tabs a.active.up { color: var(--success); border-bottom-color: var(--success); }
.mover-tabs a.active.down { color: #e5484d; border-bottom-color: #e5484d; }
.perf-label { font-size: 13px; font-weight: 700; }
.perf-value { font-size: 21px; font-weight: 800; margin: 2px 0 3px; }
.perf-value.up { color: var(--success, #2fe08a); }
.perf-value.down { color: var(--danger); }

/* A switch that looks like a switch, built from a checkbox so it posts
   with the form and needs no script. */
.switch-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 0;
  border-bottom: 1px solid var(--border); cursor: pointer;
}
.switch-row:last-of-type { border-bottom: 0; }
.switch-row > span:first-child { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.switch-label { font-size: 13.5px; font-weight: 600; }
.switch-row input { position: absolute; opacity: 0; pointer-events: none; }
.switch {
  flex: 0 0 44px; width: 44px; height: 26px; border-radius: 999px;
  background: var(--border); position: relative; transition: background .15s;
}
.switch::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 50%; background: #fff; transition: transform .15s;
}
.switch-row input:checked ~ .switch { background: var(--primary); }
.switch-row input:checked ~ .switch::after { transform: translateX(18px); }

.share-row { display: flex; gap: 8px; margin-top: 10px; }
.share-row input { flex: 1; min-width: 0; font-size: 12px; padding: 8px 10px; }
.share-row .btn { margin: 0; white-space: nowrap; }

/* Collection layout, driven by the switches in account settings. */
.pf-list { display: flex; flex-direction: column; gap: 8px; padding: 0 14px; }
.pf-list .listing-card { display: flex; gap: 10px; align-items: center; padding: 8px; }
.pf-list .thumb { flex: 0 0 54px; width: 54px; height: 74px; }
.pf-list .body { flex: 1; min-width: 0; padding: 0; }
/* A graded copy drawn as the slab it lives in. Only ever applied to a row
   that stands for one grade -- a stacked row can hold several. */
.thumb.slab {
  padding: 9px 7px 7px; border-radius: 7px;
  background: var(--card-bg-2);
  box-shadow: inset 0 0 0 2px #ffffff26, 0 1px 4px #0006;
  position: relative;
}
.thumb.slab::before {
  content: ''; position: absolute; top: 3px; left: 12%; right: 12%; height: 3px;
  border-radius: 2px; background: #ffffff40;
}
.thumb.slab img { border-radius: 3px; }

/* --- Light theme --------------------------------------------------------
   The dark palette above is the default and stays the house style. A
   reader who asked for light in their settings gets these tokens instead;
   "ตามเครื่อง" (system) applies them only when the device asks for light.
   Only the colours are redefined -- every rule above keeps working. */
:root[data-theme="light"] {
  color-scheme: light;
  --ink: #16181d;
  --ink-soft: #5f6673;
  --border: #e2e5ea;
  --bg: #f6f7f9;
  --card-bg: #ffffff;
  --card-bg-2: #eef0f4;
  --primary: #0072a3;
  --primary-dark: #005b84;
  --primary-light: rgba(0, 114, 163, 0.10);
  --success-bg: rgba(13, 122, 74, 0.12);
  --success: #0d7a4a;
  --warn: #9a6b00;
  --warn-bg: rgba(255, 194, 71, 0.20);
  --info: #4a54c9;
  --info-bg: rgba(143, 157, 255, 0.16);
  --purple: #7a43c9;
  --purple-bg: rgba(199, 146, 255, 0.20);
  --danger: #c62841;
  --glow: none;
  --glow-soft: none;
}
@media (prefers-color-scheme: light) {
  :root[data-theme="system"] {
    color-scheme: light;
    --ink: #16181d;
    --ink-soft: #5f6673;
    --border: #e2e5ea;
    --bg: #f6f7f9;
    --card-bg: #ffffff;
    --card-bg-2: #eef0f4;
    --primary: #0072a3;
    --primary-dark: #005b84;
    --primary-light: rgba(0, 114, 163, 0.10);
    --success-bg: rgba(13, 122, 74, 0.12);
    --success: #0d7a4a;
    --warn: #9a6b00;
    --warn-bg: rgba(255, 194, 71, 0.20);
    --info: #4a54c9;
    --info-bg: rgba(143, 157, 255, 0.16);
    --purple: #7a43c9;
    --purple-bg: rgba(199, 146, 255, 0.20);
    --danger: #c62841;
    --glow: none;
    --glow-soft: none;
  }
}
/* The light theme's own header bar: a dark-on-dark topbar over a light
   page would be the one thing that gives away a half-done theme. */
:root[data-theme="light"] .lang-chip,
:root[data-theme="system"] .lang-chip { background: #ffffffcc; }

/* A chip holding a hidden radio should look chosen the moment it is
   tapped, not only after the form is saved and the page comes back. */
.chip:has(input[type="radio"]:checked),
.chip:has(input[type="checkbox"]:checked) {
  border-color: var(--primary); color: var(--primary); font-weight: 700;
}

/* A reply inside a support thread. Indented and tinted so a conversation
   reads as a conversation rather than one long block of text. */
.support-reply {
  margin: 6px 0 0 10px; padding: 7px 10px; border-radius: 8px;
  background: var(--card-bg-2); border-left: 2px solid var(--border);
  font-size: 12px; line-height: 1.6; white-space: pre-wrap;
}
.support-reply.from-admin { border-left-color: var(--primary); }

/* A support conversation in the message inbox. It has no card photo to
   show, so the thumbnail slot carries an icon instead of sitting empty. */
.thumb-sm.support-thumb {
  display: flex; align-items: center; justify-content: center;
  background: var(--card-bg-2); color: var(--primary);
}
.thumb-sm.support-thumb svg { width: 18px; height: 18px; }

/* The PromptPay QR on a payment page. Centred, on white regardless of
   theme -- a scanner needs the light modules to actually be light, and a
   dark-mode page would otherwise invert it into something unreadable. */
.pay-qr {
  display: flex; justify-content: center; padding: 12px;
  background: #fff; border-radius: 12px; margin: 8px 0 10px;
}
.pay-qr svg { width: 100%; max-width: 260px; height: auto; }

/* A formal legal notice, in a frame that scrolls.

   It is long because it is the thing being consented to, and it should
   stay long -- but a page that has to be scrolled past three screens of
   clauses before the first form field appears is a page people give up
   on. So the document scrolls inside its own box and the form stays
   within reach underneath. */
.legal-notice {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px 4px 8px 14px; margin-bottom: 14px;
}
.legal-head { padding-right: 10px; padding-bottom: 10px; }
.legal-title {
  font-size: 15px; font-weight: 800; line-height: 1.45; text-align: center;
}
.legal-subtitle {
  font-size: 11.5px; color: var(--ink-soft); text-align: center;
  margin-top: 2px;
}
.legal-body {
  max-height: 44vh; min-height: 200px; overflow-y: auto;
  padding: 12px 10px 4px 0; border-top: 1px solid var(--border);
  /* A hint that there is more below: the last line fades out at the
     bottom edge instead of being cut off mid-stroke. */
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
  overscroll-behavior: contain;
}
.legal-body:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.legal-scrollhint { text-align: center; padding: 4px 10px 0 0; font-size: 11px; }
.legal-party {
  font-size: 12px; line-height: 1.7; padding-bottom: 10px;
  border-bottom: 1px solid var(--border); margin-bottom: 12px;
}
.legal-preamble {
  font-size: 12.5px; line-height: 1.75; margin: 0 0 12px;
  text-indent: 1.5em; text-align: justify;
}
.legal-clauses {
  margin: 0; padding-left: 20px; font-size: 12.5px; line-height: 1.75;
}
.legal-clauses > li { margin-bottom: 12px; }
.legal-clauses > li:last-child { margin-bottom: 0; }
.legal-clauses > li > div:last-child { text-align: justify; }
.legal-clause-head { font-weight: 800; margin-bottom: 2px; }

/* The consent tick. Deliberately a large, obvious target with the text
   beside it, not a checkbox squeezed into a line of small print. */
.consent-row {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px; margin: 4px 0 14px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 10px; cursor: pointer; line-height: 1.7; text-align: justify;
}
.consent-row input[type="checkbox"] {
  width: 20px; height: 20px; margin: 1px 0 0; flex: 0 0 auto;
  accent-color: var(--primary);
}

/* Choosing between a saved delivery address and a new one. Two large
   tappable rows rather than a pair of small radios in a line, because
   this is a decision made with a thumb on a phone. */
.addr-choice { margin-bottom: 12px; }
.addr-opt {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 12px; margin-bottom: 6px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 10px; cursor: pointer;
}
.addr-opt:has(input:checked) { border-color: var(--primary); }
.addr-opt input[type="radio"] {
  width: 18px; height: 18px; margin: 1px 0 0; flex: 0 0 auto;
  accent-color: var(--primary);
}
.addr-hidden { display: none; }

/* --- The public shop page ----------------------------------------------
   Built to answer, in order: who is this seller, what do they sell, and
   what did the last buyers think. The header carries the trust numbers,
   the tabs keep the stock grid from scrolling past the reviews, and the
   filter bar sticks so a long grid can still be narrowed with one thumb. */
.shop-cover {
  position: relative; height: 104px;
  background-size: cover; background-position: center;
  background-repeat: no-repeat;
  border-bottom: 1px solid var(--border);
}
/* The ready-made covers, used when the seller has uploaded no picture.
   Set as a background-IMAGE, not a background shorthand, so an uploaded
   photo in the style attribute replaces the gradient cleanly instead of
   fighting it. */
.shop-cover.theme-emerald {
  background-image:
    radial-gradient(120% 140% at 15% 0%, rgba(14,131,88,0.5), transparent 62%),
    linear-gradient(135deg, #17342a, #0b1712);
}
.shop-cover.theme-midnight {
  background-image:
    radial-gradient(120% 140% at 80% 0%, rgba(91,157,255,0.34), transparent 60%),
    linear-gradient(135deg, #14203a, #070c16);
}
.shop-cover.theme-ember {
  background-image:
    radial-gradient(120% 140% at 20% 10%, rgba(255,138,60,0.36), transparent 62%),
    linear-gradient(135deg, #35190f, #150a06);
}
.shop-cover.theme-violet {
  background-image:
    radial-gradient(120% 140% at 75% 0%, rgba(184,146,255,0.36), transparent 60%),
    linear-gradient(135deg, #271a3d, #100a1a);
}
.shop-cover.theme-ocean {
  background-image:
    radial-gradient(120% 140% at 10% 0%, rgba(56,189,208,0.34), transparent 62%),
    linear-gradient(135deg, #102c33, #061316);
}
.shop-cover.theme-gold {
  background-image:
    radial-gradient(120% 140% at 30% 0%, rgba(255,194,71,0.34), transparent 62%),
    linear-gradient(135deg, #332a12, #151107);
}
.shop-flag {
  position: absolute; left: 12px; bottom: 8px; display: flex; gap: 5px;
  align-items: center; padding: 4px 10px; border-radius: 999px;
  font-size: 11.5px; font-weight: 700;
  background: var(--warn-bg); color: var(--warn);
}
.shop-cover-edit {
  position: absolute; right: 10px; top: 10px; display: flex; gap: 5px;
  align-items: center; padding: 5px 11px; border-radius: 999px;
  font-size: 12px; font-weight: 700; color: var(--ink);
  background: #000000a6; border: 1px solid var(--border);
  backdrop-filter: blur(4px);
}
.shop-cover-edit svg { width: 14px; height: 14px; }
.shop-head { display: flex; gap: 12px; align-items: flex-start; padding: 0 14px 8px; }
/* The avatar has to be POSITIONED, not merely pulled up with a negative
   margin. .shop-cover above it is position:relative, and a positioned
   element paints over its non-positioned siblings whatever the source
   order -- which is what was slicing the top off the shop's logo. */
.shop-avatar {
  position: relative; z-index: 2;
  flex: 0 0 72px; width: 72px; height: 72px; border-radius: 18px;
  margin-top: -30px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 800; color: var(--ink);
  background: linear-gradient(135deg, var(--card-bg-2), var(--card-bg));
  border: 3px solid var(--bg);
  box-shadow: 0 4px 14px #00000066;
}
.shop-avatar img { width: 100%; height: 100%; object-fit: cover; }
.shop-who { flex: 1; min-width: 0; padding-top: 8px; }
.shop-name { font-size: 18px; font-weight: 800; line-height: 1.3; }
.shop-sub { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 2px; }

.shop-stats { display: flex; padding: 2px 14px 10px; }
.shop-stats > div {
  flex: 1; min-width: 0; text-align: center;
  border-right: 1px solid var(--border);
}
.shop-stats > div:last-child { border-right: 0; }
.shop-stats .num { font-size: 16px; font-weight: 800; color: var(--primary); }
.shop-stats .label { font-size: 11px; color: var(--ink-soft); margin-top: 1px; }
.shop-actions { display: flex; gap: 8px; padding: 0 14px 10px; }

.shop-tabs { margin-bottom: 8px; }
.seg-count {
  display: inline-block; min-width: 17px; padding: 0 4px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; line-height: 16px;
  background: var(--primary-light); color: var(--primary);
}
.seg-tabs a.active .seg-count { background: var(--primary); color: #fff; }

/* The filter bar sticks under the header: on a shop with sixty cards the
   category chips are needed at the bottom of the grid, not only the top. */
.shop-filters {
  position: sticky; top: var(--header-h); z-index: 14;
  background: var(--bg); border-bottom: 1px solid var(--border);
  padding-top: 6px;
}
.shop-search { position: relative; margin: 0 14px 8px; }
/* Direct child only. A bare `.shop-search svg` also caught the clear
   button's own icon, re-positioning it 11px from ITS box and pushing the
   whole page sideways on a phone whenever a search was active. */
.shop-search > svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--ink-soft); pointer-events: none;
}
.shop-search input {
  width: 100%; padding: 10px 36px; border-radius: 999px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  color: var(--ink); font-size: 14px; font-family: inherit;
}
.shop-search input:focus { outline: none; border-color: var(--primary); }
.shop-search input::-webkit-search-cancel-button { display: none; }
.shop-search-clear {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  display: flex; color: var(--ink-soft);
}
.shop-search-clear svg { width: 16px; height: 16px; }
.shop-cats { background: transparent; padding-top: 0; padding-bottom: 8px; }
.chip-n { opacity: 0.65; font-size: 11px; }
.shop-sortbar {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 14px 8px;
}
.shop-sort { display: flex; align-items: center; gap: 5px; color: var(--ink-soft); }
.shop-sort svg { width: 15px; height: 15px; }
.shop-sort select {
  background: var(--card-bg-2); color: var(--ink); font-family: inherit;
  border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 10px; font-size: 12.5px; max-width: 55vw;
}

.kv-row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.kv-row:last-child { border-bottom: 0; }

/* The feedback summary: one big number, then the shape of the ratings
   behind it. The bars matter -- 90% from ten reviews and 90% from four
   hundred are not the same claim. */
.fb-summary { display: flex; gap: 16px; align-items: center; }
.fb-score { text-align: center; flex: 0 0 auto; }
.fb-pct { font-size: 30px; font-weight: 800; color: var(--primary); line-height: 1.1; }
.fb-bars { flex: 1; min-width: 0; }
.fb-bar-row { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
.fb-bar-label {
  flex: 0 0 auto; display: flex; align-items: center; gap: 2px;
  font-size: 11.5px; color: var(--ink-soft);
}
.fb-bar-label svg { width: 11px; height: 11px; color: #f5a623; }
.fb-bar {
  flex: 1; height: 6px; border-radius: 999px;
  background: var(--card-bg-2); overflow: hidden;
}
.fb-bar i { display: block; height: 100%; background: var(--primary); border-radius: 999px; }
.fb-bar-n { flex: 0 0 24px; text-align: right; }

/* --- The watchlist tab on the collection page ---------------------------
   Watched listings reuse the marketplace tile, because they ARE
   marketplace items. Watched catalogue cards are rows instead: what
   matters about them is the price and which way it moved, and a row can
   show both without the picture pushing them off screen. */
.listing-card.wl-gone { opacity: 0.55; }
.listing-card.wl-gone .thumb { position: relative; }
.wl-badge {
  position: absolute; left: 6px; top: 6px; padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; background: #000000b8; color: var(--ink);
  border: 1px solid var(--border);
}
.wl-list { padding: 0 14px; }
.wl-row {
  display: flex; gap: 10px; align-items: center;
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.wl-row:last-child { border-bottom: 0; }
.wl-thumb {
  flex: 0 0 46px; width: 46px; height: 64px; border-radius: 6px; overflow: hidden;
  background: var(--card-bg-2); display: flex; align-items: center;
  justify-content: center; color: var(--ink-soft);
}
.wl-thumb img { width: 100%; height: 100%; object-fit: cover; }
.wl-body { flex: 1; min-width: 0; }
.wl-name {
  display: block; font-size: 14px; font-weight: 700; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wl-price { font-size: 15px; font-weight: 800; margin-top: 2px; }
.wl-delta { font-size: 11.5px; font-weight: 700; margin-left: 4px; }
.wl-delta.up { color: var(--success); }
.wl-delta.down { color: #e5484d; }
.wl-star button {
  background: none; border: 0; padding: 6px; cursor: pointer; color: #f5a623;
}
.wl-star svg { width: 20px; height: 20px; }
/* The star on a watched listing is gold like every other star on the
   site, so "tap this to un-watch" reads the same in both halves of the
   watchlist rather than looking like an unrelated grey button. */
.wl-unstar { color: #f5a623; padding-left: 10px; padding-right: 10px; }
.wl-unstar svg { width: 18px; height: 18px; }

/* --- The shop appearance page ------------------------------------------
   The preview is the real storefront header at the real size, so what the
   seller is choosing is what buyers get, not an approximation of it. */
.appearance-preview {
  margin: 0 -14px 16px; border-bottom: 1px solid var(--border);
  padding-bottom: 2px;
}
.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.theme-swatch {
  position: relative; display: flex; align-items: flex-end; justify-content: center;
  height: 58px; border-radius: 10px; cursor: pointer; overflow: hidden;
  border: 2px solid var(--border); background-size: cover; background-position: center;
}
.theme-swatch input { position: absolute; opacity: 0; pointer-events: none; }
.theme-swatch:has(input:checked) { border-color: var(--primary); }
.theme-swatch:has(input:checked)::after {
  content: "✓"; position: absolute; top: 4px; right: 6px;
  font-size: 12px; font-weight: 800; color: #fff;
  text-shadow: 0 1px 3px #000;
}
.theme-name {
  width: 100%; text-align: center; padding: 3px 2px;
  font-size: 11px; font-weight: 700; color: var(--ink);
  background: #000000a0;
}
.theme-swatch.theme-emerald { background-image: radial-gradient(120% 140% at 15% 0%, rgba(14,131,88,0.5), transparent 62%), linear-gradient(135deg, #17342a, #0b1712); }
.theme-swatch.theme-midnight { background-image: radial-gradient(120% 140% at 80% 0%, rgba(91,157,255,0.34), transparent 60%), linear-gradient(135deg, #14203a, #070c16); }
.theme-swatch.theme-ember { background-image: radial-gradient(120% 140% at 20% 10%, rgba(255,138,60,0.36), transparent 62%), linear-gradient(135deg, #35190f, #150a06); }
.theme-swatch.theme-violet { background-image: radial-gradient(120% 140% at 75% 0%, rgba(184,146,255,0.36), transparent 60%), linear-gradient(135deg, #271a3d, #100a1a); }
.theme-swatch.theme-ocean { background-image: radial-gradient(120% 140% at 10% 0%, rgba(56,189,208,0.34), transparent 62%), linear-gradient(135deg, #102c33, #061316); }
.theme-swatch.theme-gold { background-image: radial-gradient(120% 140% at 30% 0%, rgba(255,194,71,0.34), transparent 62%), linear-gradient(135deg, #332a12, #151107); }

/* --- The buyer's purchases list ----------------------------------------
   Led by the picture and the name of the thing bought, because that is
   what a buyer recognises -- an order number is how the database thinks
   about it, not how they do. */
.purchase-row {
  padding: 14px 0; border-bottom: 1px solid var(--border);
}
.purchase-row:last-of-type { border-bottom: 0; }
.purchase-top { display: flex; gap: 12px; }
.purchase-thumb {
  flex: 0 0 74px; width: 74px; height: 74px; border-radius: 10px;
  overflow: hidden; background: var(--card-bg-2);
  display: flex; align-items: center; justify-content: center; color: var(--ink-soft);
}
.purchase-thumb img { width: 100%; height: 100%; object-fit: cover; }
.purchase-body { flex: 1; min-width: 0; }
.purchase-state {
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink-soft); text-transform: uppercase; margin-bottom: 2px;
}
.purchase-state.tracked { color: var(--success); }
.purchase-title {
  display: block; font-size: 14.5px; font-weight: 700; line-height: 1.35;
  color: var(--ink);
}
.purchase-price { font-size: 16px; font-weight: 800; margin-top: 3px; }
.purchase-meta { margin-top: 1px; }
.purchase-actions { display: flex; gap: 8px; margin-top: 10px; }
.purchase-actions .btn { flex: 1; margin: 0; }

/* --- The tracking page -------------------------------------------------
   Five stages, one of which this site cannot answer for itself. That one
   is drawn the same as the others but says plainly that the courier holds
   the answer, rather than inventing a scan nobody made. */
.track-head-row { display: flex; gap: 12px; }
.track-thumb {
  flex: 0 0 64px; width: 64px; height: 64px; border-radius: 10px;
  overflow: hidden; background: var(--card-bg-2);
  display: flex; align-items: center; justify-content: center; color: var(--ink-soft);
}
.track-thumb img { width: 100%; height: 100%; object-fit: cover; }
.track-status {
  font-size: 11.5px; font-weight: 800; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--primary); margin-bottom: 2px;
}
.track-item { font-size: 15px; font-weight: 700; line-height: 1.35; }

.track-number-row { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.track-number {
  flex: 1; min-width: 0; padding: 9px 12px; border-radius: 10px;
  background: var(--card-bg-2); border: 1px solid var(--border);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px; font-weight: 700; letter-spacing: 0.04em;
  overflow-x: auto; white-space: nowrap;
}
.track-copy { flex: 0 0 auto; width: auto; margin: 0; padding: 9px 14px; }

.track-steps { margin: 16px 0 4px; padding: 0 4px; }
.track-step { display: flex; gap: 12px; position: relative; padding-bottom: 22px; }
.track-step:last-child { padding-bottom: 0; }
/* The connector is drawn on the step, not between them, so the last one
   has no dangling tail. */
.track-step::before {
  content: ""; position: absolute; left: 10px; top: 22px; bottom: 0;
  width: 2px; background: var(--border);
}
.track-step:last-child::before { display: none; }
.track-step.done::before { background: var(--primary); }
.track-dot {
  flex: 0 0 22px; width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--border); background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  color: #fff; position: relative; z-index: 1;
}
.track-dot svg { width: 12px; height: 12px; }
.track-step.done .track-dot { background: var(--primary); border-color: var(--primary); }
.track-step.current .track-dot {
  border-color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-light);
}
.track-step-body { padding-top: 1px; }
.track-step-label { font-size: 14px; font-weight: 600; color: var(--ink-soft); }
.track-step.done .track-step-label { color: var(--ink); font-weight: 700; }
.track-step.current .track-step-label { color: var(--primary); font-weight: 800; }

.track-event {
  display: flex; gap: 12px; padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.track-event:last-child { border-bottom: 0; }
.track-event-when { flex: 0 0 74px; line-height: 1.45; }
.track-event-what { flex: 1; min-width: 0; }

/* --- Collection tile actions -------------------------------------------
   Three small buttons that wrap as a row, not three full-width ones. The
   old layout gave each `flex: 1`, so "ดูข้อมูล" and "ลงขาย" broke onto
   two lines inside a 180px tile and stood twice as tall as "ลบ". */
.pf-actions {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px;
}
.pf-actions .btn,
.pf-actions form {
  width: auto; margin: 0; flex: 0 0 auto;
}
.pf-actions .btn {
  padding: 6px 11px; font-size: 12px; line-height: 1.2;
  white-space: nowrap; border-radius: 8px;
}
.pf-line { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pf-pencil { display: inline-flex; color: var(--primary); padding: 2px; flex: 0 0 auto; }
.pf-pencil svg { width: 15px; height: 15px; }

/* --- Copies held, on a card's own page ---------------------------------
   One row per copy, because a played copy and a slabbed one are different
   objects -- and each row leads back to the form that described it. */
.owned-list { margin-top: 10px; border-top: 1px solid var(--border); }
.owned-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.owned-row:last-child { border-bottom: 0; }
.owned-what { flex: 1; min-width: 0; }
.owned-edit {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  color: var(--primary); font-weight: 700; white-space: nowrap;
}
.owned-edit svg { width: 14px; height: 14px; }

/* The card being edited, at the top of the portfolio edit form. */
.pf-edit-head { display: flex; gap: 12px; align-items: flex-start; }
.pf-edit-thumb {
  flex: 0 0 56px; width: 56px; height: 78px; border-radius: 8px;
  overflow: hidden; background: var(--card-bg-2);
  display: flex; align-items: center; justify-content: center; color: var(--ink-soft);
}
.pf-edit-thumb img { width: 100%; height: 100%; object-fit: cover; }

/* --- The neon, applied ---------------------------------------------------
   Neon is light, not paint: what makes the brief work is a halo spilling
   onto the dark ground around a bright element, not a brighter fill. So
   the glow goes on the few things that should read as lit -- the
   wordmark, primary buttons, the active tab, the floating action -- and
   nowhere else. A page where everything glows has no focus at all, and
   the halo is switched off entirely in light mode, where it would only
   read as a smudge (see --glow: none there).

   These rules come last so they win over the earlier definitions without
   editing each one in place. */
.topbar .brand {
  text-shadow: 0 0 14px rgba(34,211,255,0.55), 0 0 3px rgba(34,211,255,0.35);
  letter-spacing: 0.01em;
}
:root[data-theme="light"] .topbar .brand,
:root[data-theme="system"] .topbar .brand { text-shadow: none; }

.btn-primary { box-shadow: var(--glow); }
.btn-primary:active { box-shadow: none; }
.btn-outline { box-shadow: var(--glow-soft); }

.bottom-nav a.active { text-shadow: 0 0 10px rgba(34,211,255,0.5); }
.bottom-nav .fab { box-shadow: 0 0 16px rgba(34,211,255,0.55); }

/* A thin lit edge along the top of the bottom bar and the bottom of the
   header, so the two chrome bars read as backlit panels rather than as
   flat blocks sitting on the page. */
.topbar { border-bottom: 1px solid var(--border); box-shadow: 0 1px 0 rgba(34,211,255,0.12); }
.bottom-nav { box-shadow: 0 -1px 0 rgba(34,211,255,0.14); }
:root[data-theme="light"] .topbar,
:root[data-theme="system"] .topbar,
:root[data-theme="light"] .bottom-nav,
:root[data-theme="system"] .bottom-nav { box-shadow: none; }

/* The chosen chip and the active segment, lit the same way. */
.chip.active { box-shadow: var(--glow-soft); }
.seg-tabs a.active { box-shadow: 0 0 10px rgba(34,211,255,0.18); }
:root[data-theme="light"] .chip.active,
:root[data-theme="system"] .chip.active,
:root[data-theme="light"] .seg-tabs a.active,
:root[data-theme="system"] .seg-tabs a.active { box-shadow: none; }

/* A focused field should show where the cursor is without a browser
   outline that ignores the palette. */
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}

/* The shop cover that matches the new house style, and the default for
   any shop that has not chosen one. "emerald" stays available -- shops
   that picked it keep it rather than being redecorated overnight. */
.shop-cover.theme-neon {
  background-image:
    radial-gradient(120% 140% at 15% 0%, rgba(34,211,255,0.42), transparent 62%),
    linear-gradient(135deg, #0d2f4a, #050d16);
}
.theme-swatch.theme-neon {
  background-image:
    radial-gradient(120% 140% at 15% 0%, rgba(34,211,255,0.42), transparent 62%),
    linear-gradient(135deg, #0d2f4a, #050d16);
}

/* Two names side by side, for the one comparison the verification review
   exists to make: is the payout account in the name on the ID card? */
.name-compare {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin: 8px 0; padding: 10px;
  background: var(--card-bg-2); border: 1px solid var(--border); border-radius: 10px;
  word-break: break-word;
}

/* Offers on the cart page, where they moved to from their own header icon. */
.offer-line {
  display: flex; align-items: center; gap: 10px; justify-content: space-between;
  padding: 11px 13px; margin-bottom: 8px; border-radius: 12px;
  background: var(--card-bg); border: 1px solid var(--border);
  color: inherit; text-decoration: none;
}
.offer-line-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.offer-line-name {
  font-size: 13.5px; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- The import page's price-freshness panel ---------------------------
   First thing on the page now: setting a game up happens once, keeping its
   prices current happens every day, and the daily one used to be three
   clicks down inside two folded panels. */
.price-state {
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px; margin-bottom: 14px;
}
.price-state.off { border-color: var(--warn, #d29922); }
.fresh-bar {
  height: 8px; border-radius: 999px; background: var(--border);
  margin-top: 12px; overflow: hidden;
}
.fresh-bar span {
  display: block; height: 100%; border-radius: 999px;
  background: var(--primary); transition: width .3s;
}
.fresh-set {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border);
}
.fresh-set .input { width: auto; flex: 0 0 auto; }

/* A set's name in the language it was printed in, under the English one. */
.set-name-alt {
  font-size: 11px; color: var(--muted); line-height: 1.35;
  margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.set-title-alt {
  font-size: 14px; font-weight: 600; color: var(--muted);
  line-height: 1.4; margin-top: 2px;
}

/* --- Where each game's prices come from, and its own update button --- */
.game-prices {
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px; margin-bottom: 14px;
}
.game-price-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0; border-top: 1px solid var(--border);
}
.game-price-row:first-of-type { border-top: 0; }
.gp-main { flex: 1; min-width: 0; }
.gp-name { font-size: 14px; font-weight: 700; display: flex; gap: 8px;
           align-items: baseline; flex-wrap: wrap; }
.gp-src { margin-top: 4px; display: flex; gap: 6px; flex-wrap: wrap; }
.gp-tag {
  background: var(--border); border-radius: 999px;
  padding: 2px 8px; font-size: 11px; white-space: nowrap;
}
.gp-tag.gp-none { background: transparent; border: 1px dashed var(--border); }
.gp-feed { margin-top: 4px; line-height: 1.6; }

/* --- The three flagship games, before the folded list of every game --- */
.featured-games {
  background: var(--card-bg-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px; margin-bottom: 14px;
}
.featured-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}
.featured-game-card {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px;
}
/* Reuses .game-prices' own row/tag rules for the collapsed "other games"
   list -- only the outer element becomes a <details>, same padding
   convention as .setup-steps above (a <details class="cc-panel X"> pairs
   the panel's own padding with the summary's, which is how that one
   already renders on this page). */
details.game-prices { padding: 14px; }
/* The two per-game buttons, stacked rather than crammed side by side on a
   narrow row. */
.gp-actions { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.gp-actions .btn { width: 100%; white-space: nowrap; }

/* ---------- Inside the iPhone app ---------- */
/* The web page runs edge to edge in the app: no Safari chrome sits between
   it and the glass, so the notch covers the top of the header and the home
   bar sits on top of the tab bar. `viewport-fit=cover` in base.html is what
   makes env(safe-area-inset-*) report real numbers; these rules spend them.
   Everything here is scoped to data-native="1", which the server sets only
   when the request carries the app's user agent -- a browser is untouched. */
:root[data-native="1"] .topbar {
  height: calc(var(--header-h) + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
}
:root[data-native="1"] .bottom-nav {
  height: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
:root[data-native="1"] .app-shell {
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px) + 12px);
}
/* The buy bar and the chat box stack on top of the tab bar, so when the tab
   bar grows they have to move up by exactly the same amount or the nav
   swallows their taps -- the bug that put them above bottom:0 originally. */
:root[data-native="1"] .sticky-buy-bar,
:root[data-native="1"] .chat-input-bar {
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
}
/* Sheets are already handled: .sheet-actions and .sheet-foot have paid for
   the home bar since they were written, unscoped, which is right -- a sheet
   covers the whole glass in a browser too. Adding a second inset here would
   pad them twice. */
/* Long-pressing a link in a browser offers "copy"; in the app it offers
   nothing and just interrupts a scroll, so it is turned off for chrome and
   left on for text the reader might actually want to select. */
:root[data-native="1"] .topbar,
:root[data-native="1"] .bottom-nav {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
