/* Exor Games buylist (public/buylist.js) — 2026-09-11 redesign.
   Colours come from the theme's --xg-* tokens where it runs inside
   exorgames.com (xg-dark.css redefines them under html[data-xg-theme="dark"]),
   with light fallbacks for the standalone test page, which follows the
   system for dark. Layout: a search toolbar, one card per printing with an
   aligned offers grid (condition · cash · credit · action), and the list
   panel — a sticky column on desktop, a bottom sheet on phones. */
.xg-buylist {
  --bl-bg: var(--xg-bg, #f5f6f7);
  --bl-surface: var(--xg-surface, #ffffff);
  --bl-surface-2: var(--xg-bg, #f5f6f7);
  --bl-ink: var(--xg-ink, #171b1d);
  --bl-text: var(--xg-text, #3d454b);
  --bl-muted: var(--xg-muted, #707a83);
  --bl-line: rgba(128, 140, 150, 0.22);
  --bl-line-strong: rgba(128, 140, 150, 0.4);
  --bl-accent: #0d7a5f;
  --bl-accent-soft: rgba(13, 122, 95, 0.1);
  --bl-accent-ink: #ffffff;
  --bl-danger: #b42318;
  --bl-shadow: 0 1px 2px rgba(16, 24, 40, 0.05), 0 8px 24px -12px rgba(16, 24, 40, 0.18);
  --bl-radius: 16px;
  --bl-card-radius: 5% / 3.6%;
  box-sizing: border-box;
  max-width: 1180px;
  margin: 0 auto;
  padding: 10px 20px 64px;
  color: var(--bl-text);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
.xg-buylist *, .xg-buylist *::before, .xg-buylist *::after { box-sizing: border-box; }
html[data-xg-theme="dark"] .xg-buylist { --bl-accent: #2fbf95; --bl-accent-soft: rgba(47, 191, 149, 0.14); --bl-accent-ink: #0b1a15; --bl-danger: #ff7b6b; --bl-line: rgba(160, 175, 185, 0.18); --bl-line-strong: rgba(160, 175, 185, 0.34); --bl-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 28px -12px rgba(0, 0, 0, 0.6); }
html[data-xg-theme="dark"] .xg-buylist .bl__seticon { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  .xg-buylist--standalone { --bl-bg: #111517; --bl-surface: #181d20; --bl-surface-2: #111517; --bl-ink: #eef2f4; --bl-text: #c3ccd1; --bl-muted: #8a969d; --bl-accent: #2fbf95; --bl-accent-soft: rgba(47, 191, 149, 0.14); --bl-accent-ink: #0b1a15; --bl-danger: #ff7b6b; --bl-line: rgba(160, 175, 185, 0.18); --bl-line-strong: rgba(160, 175, 185, 0.34); }
  .xg-buylist--standalone .bl__seticon { filter: invert(1); }
}
.xg-buylist [hidden] { display: none !important; }
.xg-buylist button, .xg-buylist input, .xg-buylist select { font-family: inherit; }
.xg-buylist :focus-visible { outline: 2px solid var(--bl-accent); outline-offset: 2px; }

/* logged out */
.xg-buylist__loading { text-align: center; color: var(--bl-muted); }
.xg-buylist__login { max-width: 520px; margin: 0 auto; padding: 32px 24px; text-align: center; background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius); box-shadow: var(--bl-shadow); }
.xg-buylist__login h2 { margin: 0 0 6px; font-size: 22px; color: var(--bl-ink); }
.xg-buylist__login p { margin: 0 0 18px; }
.xg-buylist__btn { display: inline-block; padding: 12px 22px; border-radius: 999px; background: var(--bl-accent); color: var(--bl-accent-ink) !important; font-weight: 700; text-decoration: none !important; }
.xg-buylist__link { display: inline-block; margin-left: 14px; color: var(--bl-muted); }

/* ---- layout ------------------------------------------------------- */
.bl { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 24px; align-items: start; }

/* ---- search toolbar ----------------------------------------------- */
.bl__bar { display: grid; grid-template-columns: 200px minmax(0, 1.4fr) minmax(0, 1fr) auto; gap: 8px; margin: 0; padding: 10px; background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius); box-shadow: var(--bl-shadow); }
.bl__input, .bl__select { min-width: 0; width: 100%; height: 46px; margin: 0; padding: 0 14px; font: inherit; font-size: 16px; line-height: 1.3; border: 1px solid var(--bl-line-strong); border-radius: 12px; background: var(--bl-surface-2); color: var(--bl-ink); box-shadow: none; -webkit-appearance: none; appearance: none; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.bl__input::placeholder { color: var(--bl-muted); opacity: 1; }
.bl__input:focus, .bl__select:focus { border-color: var(--bl-accent); box-shadow: 0 0 0 3px var(--bl-accent-soft); outline: none; }
.bl__select { padding-right: 36px; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1.5l5 5 5-5' fill='none' stroke='%23707a83' stroke-width='1.8' stroke-linecap='round'/></svg>"); background-repeat: no-repeat; background-position: right 14px center; font-weight: 600; }
.bl__input[type="search"] { -webkit-appearance: none; }
.bl__input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
.bl__setwrap { position: relative; display: flex; min-width: 0; }
.bl__input--set { flex: 1; }
.bl__setwrap .bl__seticon--pick { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; pointer-events: none; }
.bl__setwrap .bl__seticon--pick:not([hidden]) + .bl__input--set { padding-left: 40px; }
.bl__btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; margin: 0; padding: 0 18px; height: 46px; font: inherit; font-size: 15px; font-weight: 700; line-height: 1; border: 1px solid var(--bl-line-strong); border-radius: 12px; background: var(--bl-surface); color: var(--bl-ink); cursor: pointer; white-space: nowrap; transition: background 0.15s ease, border-color 0.15s ease, transform 0.08s ease; }
.bl__btn:hover { border-color: var(--bl-accent); }
.bl__btn:active { transform: translateY(1px); }
.bl__btn:disabled { opacity: 0.45; cursor: default; transform: none; }
.bl__btn--primary { background: var(--bl-accent); color: var(--bl-accent-ink); border-color: transparent; }
.bl__btn--primary:hover { filter: brightness(1.06); border-color: transparent; }
.bl__muted { color: var(--bl-muted); }
.bl__status { min-height: 20px; font-size: 13.5px; margin: 12px 2px 10px; }
.bl__chip { display: inline-block; margin: 6px 6px 0 0; padding: 6px 12px; border: 1px solid var(--bl-line-strong); border-radius: 999px; background: var(--bl-surface); color: var(--bl-ink); font: inherit; font-size: 13px; font-weight: 600; line-height: 1.3; cursor: pointer; }
.bl__chip:hover { border-color: var(--bl-accent); color: var(--bl-accent); }

/* ---- results: one card per printing ------------------------------ */
.bl__hit { display: grid; grid-template-columns: 104px minmax(0, 1fr); grid-template-areas: "img head" "img offers"; gap: 8px 16px; align-items: start; background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius); box-shadow: var(--bl-shadow); padding: 14px; margin-bottom: 12px; }
/* Both, deliberately: when buylist.js has wrapped the image the wrapper is
   the grid child and grid-area on the img is inert; if a browser is still
   running cached JS without the wrapper, the bare img takes the slot and
   width:100% still resolves to the column. Neither case breaks. */
.bl__hit .bl__cardwrap { grid-area: img; align-self: start; display: block; min-width: 0; }
.bl__hit .bl__card { grid-area: img; }
.bl__head { grid-area: head; min-width: 0; }
.bl__offers, .bl__none { grid-area: offers; margin: 0; }
/* The card floats off the row and invites a click. Owner, 2026-09-17: "make
   them look like they are floating" + "click to zoom".
   Deliberately a RESTING effect, not a loop. A continuous bob would promote
   every card to its own compositor layer and keep the GPU busy forever - one
   card on a product page is fine (see the theme's .card-float sway), twenty to
   sixty in a result list is not, and this list is mostly read on phones.
   A resting shadow is painted once and costs nothing.
   box-shadow, not filter: drop-shadow - these images are opaque JPEGs with no
   cutout to trace, and box-shadow follows the border-radius. Only transform
   moves on hover (compositor-only); the shadow swap is on the same transition
   but never animates per frame. */
.bl__card { display: block; width: 100%; aspect-ratio: 5 / 7; object-fit: cover; border-radius: var(--bl-card-radius); background: var(--bl-surface-2); align-self: start;
  /* NO negative spread. A real card is BLACK-bordered, so a tight dark blur
     pulled inward by -4px hid inside the card's own edge and the float was
     invisible (owner: "ITS NOT DOING THAT SUBTLE FLOAT HERE"). The shadow
     has to fall clear of the silhouette, onto the white panel, to read. */
  box-shadow: 0 3px 7px rgba(16, 24, 40, 0.20), 0 14px 26px -2px rgba(16, 24, 40, 0.30);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.bl__card[role="button"] { cursor: zoom-in; }
/* ---- the slow float (owner, 2026-09-17: "I want it slowly moving like the
   cards show on our site already when searching for a card") ---------------
   Same shape as the product page's cardFloat in custom.css: a 5.5s
   ease-in-out bob, scaled down for a thumbnail (6px against its 9px on a
   full-size photo).
   THE WRAPPER MOVES, NEVER THE IMAGE. That is how custom.css does it too, and
   it is what keeps the card sharp: the img's own transform stays untouched, so
   nothing resamples it. Transform-only, so this is compositor work with no
   layout or paint per frame.
   is-floating is added by buylist.js only while the row is ON SCREEN, and
   removed when it scrolls away, so a 60-row result list never has 60 cards
   animating at once - that was the cost worth avoiding. The negative
   animation-delay starts each card partway through its cycle, so they are
   out of phase immediately instead of rising in lockstep. */
@keyframes blCardFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(var(--bl-float-lift, -6px)); }
}
.bl__cardwrap.is-floating {
  animation: blCardFloat 5.5s ease-in-out infinite;
  animation-delay: var(--bl-float-delay, 0s);
}
/* pointing at a card stops it and holds it up - custom.css pauses its own
   float the same way while the card is being tilted */
.bl__cardwrap:hover.is-floating, .bl__cardwrap:focus-within.is-floating { animation-play-state: paused; }
/* NO scale() HERE. Owner, 2026-09-17: "when I hover over the card in the
   buylist it makes it blurrier". The first cut hovered with
   translateY(-4px) scale(1.02); scaling a composited layer resamples the
   raster the compositor already has instead of re-rendering the image at the
   new size, so a 2% grow reads as a softening. The lift alone gives the float
   without touching a single pixel of the image - translation by whole pixels
   resamples nothing. (A headless screenshot cannot reproduce the blur, which
   is why it got through: Playwright re-rasterizes the element as it captures,
   measuring 2195 vs 2207 sharpness rest vs hover. Real compositing does not.)
   There is deliberately no transform in the resting state either: any
   transform promotes the img to its own layer, and the resting lift added
   nothing the shadow was not already saying. */
.bl__card[role="button"]:hover, .bl__card[role="button"]:focus-visible {
  transform: translateY(-5px);
  box-shadow: 0 5px 10px rgba(16, 24, 40, 0.24), 0 22px 36px -2px rgba(16, 24, 40, 0.40);
}
.bl__card[role="button"]:focus-visible { outline: 2px solid var(--bl-accent); outline-offset: 3px; }
html[data-xg-theme="dark"] .bl__card,
/* Dark mode needs a different trick entirely: the panel is #181d20 and the
   card is black-bordered, so ANY dark shadow is invisible between them. The
   1px light ring is what draws the card's edge and makes it read as lifted;
   the drop underneath then gives it height. */
.xg-buylist--standalone .bl__card { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.13), 0 4px 8px rgba(0, 0, 0, 0.45), 0 16px 28px rgba(0, 0, 0, 0.55); }
html[data-xg-theme="dark"] .bl__card[role="button"]:hover,
html[data-xg-theme="dark"] .bl__card[role="button"]:focus-visible,
.xg-buylist--standalone .bl__card[role="button"]:hover {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.20), 0 6px 12px rgba(0, 0, 0, 0.5), 0 24px 40px rgba(0, 0, 0, 0.65);
}

/* ---- click to zoom: the 672x936 image the page already downloaded -------
   At 104px the card's rules text is about a pixel a line, so the thumbnail is
   unreadable by arithmetic, not by quality. The full-size image is already in
   the browser, so the overlay opens instantly and costs no new bytes.
   Self-contained here rather than borrowing the theme's .xg-zoom-overlay: the
   worker serves this page's css and js together, and the buylist must not
   depend on a theme asset it cannot see. */
/* A flex COLUMN with the caption as a real sibling, not absolutely
   positioned: at a short viewport the caption overlapped the bottom of the
   card. Stacked, they cannot collide at any height, and min-height 0 lets
   the image shrink instead of pushing the caption off-screen. */
.bl__zoom { position: fixed; inset: 0; z-index: 100000; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 20px; background: rgba(12, 15, 17, 0.86); cursor: zoom-out; animation: blZoomFade 0.16s ease-out; }
.bl__zoom img { display: block; min-height: 0; max-width: min(94vw, 520px); max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: 3.5% / 2.5%; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6); animation: blZoomPop 0.2s ease-out; }
.bl__zoom-cap { flex: 0 0 auto; margin: 0; max-width: min(94vw, 520px); text-align: center; color: #eef2f4; font-size: 13.5px; line-height: 1.35; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8); }
@keyframes blZoomFade { from { opacity: 0; } }
@keyframes blZoomPop { from { opacity: 0; transform: scale(0.97); } }
@media (prefers-reduced-motion: reduce) {
  .bl__card { transition: none; }
  .bl__cardwrap.is-floating { animation: none; }
  .bl__card[role="button"]:hover, .bl__card[role="button"]:focus-visible { transform: none; }
  .bl__zoom, .bl__zoom img { animation: none; }
}
.bl__name { margin: 2px 0 2px; font-size: 18px; font-weight: 700; line-height: 1.25; color: var(--bl-ink); letter-spacing: -0.01em; }
.bl__set { margin: 0; font-size: 13px; display: flex; align-items: center; gap: 6px; min-width: 0; }
.bl__set span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl__seticon { width: 18px; height: 18px; vertical-align: middle; flex: 0 0 auto; }
/* The offers grid: four aligned columns, every cell centred on its row —
   condition (left), cash, credit, action. Tabular figures keep the prices
   in a straight line. */
.bl__offers { display: grid; grid-template-columns: minmax(0, 1fr) minmax(64px, auto) minmax(64px, auto) minmax(72px, auto); column-gap: 8px; font-size: 14px; border: 1px solid var(--bl-line); border-radius: 12px; overflow: hidden; }
.bl__orow { display: contents; }
.bl__orow > span { display: flex; align-items: center; justify-content: center; min-height: 44px; padding: 6px 8px; border-top: 1px solid var(--bl-line); text-align: center; }
.bl__orow > span:first-child { justify-content: flex-start; text-align: left; padding-left: 12px; }
.bl__orow > span:last-child { padding-right: 10px; }
.bl__orow--head > span { min-height: 30px; padding-top: 4px; padding-bottom: 4px; border-top: 0; background: var(--bl-surface-2); font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--bl-muted); }
.bl__ocond { flex-wrap: wrap; gap: 4px 6px; color: var(--bl-ink); font-weight: 600; }
.bl__oprice { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--bl-ink); white-space: nowrap; }
.bl__oprice--credit { color: var(--bl-accent); }
.bl__pill { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; background: var(--bl-accent-soft); color: var(--bl-accent); line-height: 1.4; vertical-align: middle; white-space: nowrap; }
/* Foil rows: a holographic badge, a tinted row and a band above the foil
   block, so a seller cannot mistake the foil line for the plain one
   (owner, 2026-09-15). The tint is a translucent amber wash over whatever
   the surface is, so it reads the same in both themes and the text keeps
   the theme's ink (the earlier hard-coded cream looked pasted-on in dark
   mode - owner screenshot, 2026-09-22 - and needed its own dark ink). */
.bl__pill--finish { font-size: 12px; padding: 3px 10px; letter-spacing: 0.04em; text-transform: uppercase; color: #1d2327; background: linear-gradient(115deg, #ffe9a8 0%, #ffc6e0 30%, #bfe3ff 60%, #d2ffd8 85%, #ffe9a8 100%); border: 1px solid rgba(0, 0, 0, 0.14); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
.bl__orow--finish > span { background: rgba(240, 180, 41, 0.06); }
.bl__orow--finish > span:first-child { background: linear-gradient(90deg, rgba(240, 180, 41, 0.2) 0%, rgba(240, 180, 41, 0.06) 100%); box-shadow: inset 4px 0 0 #f0b429; }
.bl__orow--band > .bl__band { grid-column: 1 / -1; justify-content: flex-start; min-height: 26px; padding: 4px 12px; margin-top: 4px; border-top: 2px solid #f0b429; background: rgba(240, 180, 41, 0.14); color: #7a4d00; font-size: 11.5px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
html[data-xg-theme="dark"] .bl__orow--band > .bl__band, .xg-buylist--standalone.bl--dark .bl__orow--band > .bl__band { color: #f6c453; }
.bl__add { height: 34px; padding: 0 14px; font-size: 13px; border-radius: 999px; }
.bl__nobuy { display: inline-block; font-size: 11.5px; font-weight: 700; line-height: 1.2; padding: 6px 9px; border-radius: 999px; background: var(--bl-surface-2); color: var(--bl-muted); white-space: nowrap; }
/* Condition guide: a condition in the offers grid opens the store's own
   photo and definition for that grade (from /pages/grading-guide). */
.bl .bl__condbtn { margin: 0; padding: 0; border: 0; background: none; font: inherit; font-weight: 600; color: var(--bl-ink); text-decoration: underline dotted; text-decoration-color: var(--bl-muted); text-underline-offset: 3px; cursor: pointer; text-align: left; }
.bl .bl__condbtn:hover, .bl .bl__condbtn:focus-visible { color: var(--bl-accent); text-decoration-color: currentColor; }
.bl__guide { border: 0; border-radius: 18px; padding: 0; width: min(94vw, 440px); max-width: 94vw; max-height: 92vh; overflow: auto; background: var(--bl-surface); color: var(--bl-text); box-shadow: 0 24px 70px rgba(0, 0, 0, 0.4); }
.bl__guide::backdrop { background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(2px); }
/* The example photo is shown whole at its own proportions, never cropped
   to a square or blown up past its pixels (the store's originals are
   398×218: a square crop of that was the blur, 2026-09-11). */
.bl__guide-img { display: block; width: 100%; height: auto; max-height: 60vh; object-fit: contain; border-radius: 18px 18px 0 0; background: #0f1416; }
.bl__guide-body { padding: 16px 20px 20px; }
.bl__guide-body h3 { margin: 0 0 10px; font-size: 19px; color: var(--bl-ink); }
.bl__guide-body ul { margin: 0; padding: 0 0 0 18px; font-size: 13.5px; line-height: 1.5; }
.bl__guide-body li { margin: 0 0 5px; }
.bl__guide-body li b { color: var(--bl-ink); }
.bl__guide-note { font-size: 12px; margin: 12px 0 0; }
.bl__guide-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 16px; }
/* The "what happens next" popup at submission: the store's instructions,
   the buylist number on top, the address set off as a block. */
.bl__done { width: min(94vw, 560px); }
.bl__done-head { padding: 18px 20px 14px; background: var(--bl-accent); color: var(--bl-accent-ink); }
.bl__done-kicker { display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.85; }
.bl__done-head h3 { margin: 2px 0 0; font-size: 22px; line-height: 1.2; color: inherit; }
.bl__done-sum { margin: 6px 0 0; font-size: 14px; opacity: 0.95; }
.bl__done .bl__guide-body { max-height: 62vh; overflow: auto; }
.bl__done-next { margin: 0 0 6px; padding: 12px 14px; border-radius: 10px; background: var(--bl-accent-soft); color: var(--bl-ink); font-size: 14.5px; line-height: 1.5; }
.bl__done-notes { margin: 8px 0 0; padding: 10px 12px; border-radius: 10px; background: rgba(240, 180, 41, 0.14); color: var(--bl-ink); font-size: 13.5px; line-height: 1.5; }
.bl__done h4 { margin: 18px 0 6px; font-size: 15px; color: var(--bl-accent); }
.bl__done .bl__guide-body p { margin: 0 0 8px; font-size: 14px; line-height: 1.55; }
.bl__done-addr { display: inline-block; margin: 4px 0 6px; padding: 6px 14px; border-left: 4px solid var(--bl-accent); font-style: normal; font-size: 15px; line-height: 1.5; color: var(--bl-ink); }
.bl__done .bl__guide-actions .bl__btn--primary { padding: 10px 22px; border-radius: 999px; }
.bl__guide-actions .bl__btn { height: 42px; border-radius: 999px; }
.bl__link { color: var(--bl-accent); font-weight: 700; }
.bl__more { display: flex; margin: 8px auto 0; border-radius: 999px; }

/* ---- the list panel ----------------------------------------------- */
/* Stays in view under the fixed header and scrolls on its own; only the
   lines scroll, the title, payment choice, totals and buttons stay put.
   --xg-fixed-bottom is the header's bottom edge (xg-header-offset.js),
   --xg-tick-h the ticker pinned to the bottom of the screen (xg-ticker.js). */
/* Owner, 2026-09-22: "make it stand out a bit more from the card list so
   it looks more like a card area that they submitted the cards to". The
   panel is drawn as a tray: an accent-coloured frame, a tinted top, a
   heading with a subline saying what the area is, and the lines inside a
   dashed well - the place cards land when Add is pressed. */
.bl__cart { position: sticky; top: calc(var(--xg-fixed-bottom, 0px) + 14px); max-height: calc(100vh - var(--xg-fixed-bottom, 0px) - var(--xg-tick-h, 0px) - 28px); display: flex; flex-direction: column; background: linear-gradient(180deg, var(--bl-accent-soft) 0, transparent 120px), var(--bl-surface); border: 2px solid var(--bl-accent); border-radius: var(--bl-radius); box-shadow: 0 0 0 4px var(--bl-accent-soft), var(--bl-shadow); padding: 18px; }
.bl__cart > * { flex: 0 0 auto; }
.bl__cart > #bl-lines { flex: 1 1 auto; min-height: 96px; overflow-y: auto; overscroll-behavior: contain; margin: 0; padding: 8px 10px; border: 1.5px dashed var(--bl-line-strong); border-radius: 12px; background: var(--bl-surface-2); }
/* Desktop (owner, 2026-09-22: "on desktop, this should scroll down"): the
   panel is pinned to the viewport, and once the recent-buylists block made
   it taller than the screen its bottom was clipped with no way to reach it.
   Now the panel scrolls as a whole when it is taller than the viewport, and
   the card list keeps a scroll of its own only past 42vh, so totals, the
   buttons and the recent lists are always reachable. */
@media (min-width: 861px) {
  /* overflow-x hidden: a panel that scrolls down also scrolls sideways, and
     the store-credit effect's glow and sparks reach past its right edge -
     that drew a horizontal scrollbar under the buttons (owner, 2026-09-23:
     "creates this weird bar on bottom"). */
  .bl__cart { overflow-y: auto; overflow-x: hidden; overscroll-behavior: auto; scrollbar-gutter: stable; }
  .bl__cart > #bl-lines { flex: 0 0 auto; max-height: 42vh; overscroll-behavior: auto; }   /* the wheel carries on down the panel past the end of the list */
}
.bl__cart > #bl-lines > .bl__muted:only-child { margin: 0; padding: 18px 6px; text-align: center; }
.bl__h2 { margin: 0 0 10px; font-size: 18px; font-weight: 700; color: var(--bl-ink); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; }
.bl__h2 #bl-count { font-size: 12.5px; font-weight: 700; padding: 2px 9px; border-radius: 999px; background: var(--bl-accent-soft); color: var(--bl-accent); }
.bl__h2 #bl-count:empty { display: none; }
.bl__h2 small { flex: 1 0 100%; margin-top: 2px; font-size: 12.5px; font-weight: 500; color: var(--bl-muted); }
.bl__h2 .bl__tray { display: inline-block; width: 20px; height: 16px; margin-right: 8px; vertical-align: -2px; border: 2px solid var(--bl-accent); border-top: 0; border-radius: 0 0 6px 6px; position: relative; }
.bl__h2 .bl__tray::before { content: ""; position: absolute; left: 3px; right: 3px; top: -6px; height: 8px; border: 2px solid var(--bl-accent); border-bottom: 0; border-radius: 3px 3px 0 0; }
/* one heading per card, its conditions beneath it */
.bl__group { border-top: 1px solid var(--bl-line); padding: 10px 0 6px; }
.bl__group:first-child { border-top: 0; padding-top: 0; }
.bl__group-head { display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 10px; align-items: center; margin-bottom: 4px; }
.bl__group-head .bl__thumb { width: 36px; }
.bl__group-head b { display: block; color: var(--bl-ink); font-size: 14px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl__group-head .bl__muted { display: block; font-size: 12.5px; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl__group-head .bl__seticon { width: 14px; height: 14px; margin-right: 4px; vertical-align: -2px; }
.bl__line { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; padding: 5px 0 5px 46px; }
.bl__cond { min-width: 0; font-size: 13px; line-height: 1.3; color: var(--bl-ink); font-weight: 600; }
.bl__cond small { display: block; margin: 1px 0 0; font-size: 12px; font-weight: 500; color: var(--bl-muted); font-variant-numeric: tabular-nums; }
.bl__cond .bl__pill { margin-left: 5px; }
.bl__thumb { width: 40px; aspect-ratio: 5 / 7; object-fit: cover; border-radius: var(--bl-card-radius); background: var(--bl-surface-2); }
/* The theme stretches every input to 100% width, which turned the −/1/+
   stepper into most of the row on phones. Pin it. */
.bl .bl__qtywrap { display: flex; align-items: center; flex: 0 0 auto; width: auto; height: 34px; border: 1px solid var(--bl-line-strong); border-radius: 999px; overflow: hidden; background: var(--bl-surface); }
.bl .bl__qtywrap .bl__btn { height: 100%; padding: 0 10px; border: 0; border-radius: 0; background: transparent; font-size: 16px; }
.bl .bl__qtywrap .bl__btn:hover { background: var(--bl-accent-soft); color: var(--bl-accent); }
.bl .bl__qtywrap .bl__qty { width: 34px !important; min-width: 0; max-width: 34px; flex: 0 0 34px; height: 100%; margin: 0; padding: 0; text-align: center; border: 0; border-radius: 0; background: transparent; color: var(--bl-ink); font: inherit; font-weight: 700; font-variant-numeric: tabular-nums; -moz-appearance: textfield; box-shadow: none; }
.bl__qty::-webkit-outer-spin-button, .bl__qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.bl__remove { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border: 0; border-radius: 50%; background: transparent; color: var(--bl-muted); font-size: 20px; padding: 0; line-height: 1; cursor: pointer; }
.bl__remove:hover { color: var(--bl-danger); background: rgba(180, 35, 24, 0.08); }
/* payout choice as a segmented control */
.bl__pay { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin: 14px 0 10px; padding: 4px; border-radius: 12px; background: var(--bl-surface-2); font-size: 14px; color: var(--bl-ink); }
.bl__pay label { position: relative; display: flex; align-items: center; justify-content: center; gap: 6px; margin: 0; height: 36px; border-radius: 9px; font-weight: 600; cursor: pointer; }
.bl__pay input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.bl__pay label:has(input:checked) { background: var(--bl-surface); color: var(--bl-accent); box-shadow: 0 1px 2px rgba(16, 24, 40, 0.12); }
.bl__pay label:has(input:focus-visible) { outline: 2px solid var(--bl-accent); outline-offset: 1px; }
.bl__totals { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; padding: 12px 0; border-top: 1px solid var(--bl-line); border-bottom: 1px solid var(--bl-line); }
.bl__totals span { display: flex; flex-direction: column; gap: 2px; }
/* The store-credit total by position, not :last-child - the store-credit
   effect appends its caption to this row for 2.8 s, which made the total
   lose right alignment and jump back when the caption went (owner,
   2026-09-23: "this weirdly shifts after the animation"). */
.bl__totals > span:nth-child(2) { text-align: right; }
.bl__totals b { color: var(--bl-ink); font-size: 18px; font-variant-numeric: tabular-nums; }
.bl__actions { display: flex; gap: 8px; margin-top: 14px; }
.bl__actions .bl__btn { border-radius: 999px; }
.bl__actions .bl__btn--primary { flex: 1; }
.bl__msg { font-size: 13px; margin: 10px 0 0; min-height: 18px; }
.bl__toast { position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px); z-index: 50; max-width: min(92vw, 520px); padding: 12px 18px; border-radius: 999px; background: var(--bl-ink); color: var(--bl-bg); font-size: 14px; font-weight: 600; text-align: center; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); opacity: 0; pointer-events: none; transition: opacity 0.18s ease, transform 0.18s ease; }
.bl__toast--show { opacity: 1; transform: translate(-50%, 0); }

/* ---- phones and narrow tablets ------------------------------------ */
/* One column; the list panel becomes a bottom sheet pinned above the
   ticker. Collapsed it is one bar with the count and totals; tapping it
   opens the panel over the results, with the lines scrolling inside it.
   Doubled selectors beat the desktop .bl__cart rule on specificity. */
.bl__sheetbar { display: none; align-items: center; gap: 10px; min-height: 58px; padding: 8px 0; color: var(--bl-ink); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.bl__sheettext { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.bl__sheettext b { font-size: 15px; }
.bl__sheetsum { display: block; min-width: 0; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The bar's two buttons (owner, 2026-09-20): View (with the chevron) and
   Submit, sized to sit beside the two-line summary on a phone. */
.bl__sheetbtns { flex: 0 0 auto; display: flex; gap: 6px; }
.bl__btn--sm { height: 36px; padding: 0 12px; font-size: 13.5px; border-radius: 999px; }
.bl__chev { display: inline-flex; align-items: center; justify-content: center; font-size: 10px; transition: transform 0.18s ease; }
.bl__cart--open .bl__chev { transform: rotate(180deg); }
@media (max-width: 860px) {
  .xg-buylist { padding: 8px 14px calc(84px + var(--bl-sheet-off, var(--xg-tick-h, 0px))); }
  .bl { grid-template-columns: 1fr; gap: 16px; }
  .bl__bar { grid-template-columns: 1fr 1fr; padding: 8px; }
  .bl__bar .bl__select { grid-column: 1 / -1; }
  .bl__bar .bl__input[type="search"] { grid-column: 1 / -1; }
  .bl__bar .bl__setwrap { grid-column: 1 / 2; }
  .bl__bar .bl__btn--primary { grid-column: 2 / 3; }
  .bl__hit { grid-template-columns: 72px minmax(0, 1fr); grid-template-areas: "img head" "offers offers"; gap: 10px 12px; padding: 12px; }
  /* the grid column carries the width now; only the float amplitude changes */
  .bl__cardwrap { --bl-float-lift: -5px; }
  .bl__name { font-size: 16.5px; }
  .bl__offers { grid-template-columns: minmax(0, 1fr) minmax(58px, auto) minmax(58px, auto) auto; column-gap: 2px; font-size: 13.5px; }
  .bl__orow > span { padding: 6px 5px; min-height: 42px; }
  .bl__orow > span:first-child { padding-left: 10px; }
  .bl__orow > span:last-child { padding-right: 6px; }
  .bl__add { padding: 0 12px; height: 32px; }
  /* --bl-sheet-off is measured by buylist.js: the height of whatever fixed
     bars own the bottom edge (ticker, Shopify's preview bar, app bars). */
  .bl .bl__cart { position: fixed !important; top: auto !important; left: 0; right: 0; bottom: var(--bl-sheet-off, var(--xg-tick-h, 0px)); z-index: 9980; margin: 0; max-height: calc(100vh - var(--xg-fixed-bottom, 0px) - var(--bl-sheet-off, var(--xg-tick-h, 0px)) - 12px); border-radius: 18px 18px 0 0; border-bottom: 0; box-shadow: 0 -10px 34px rgba(0, 0, 0, 0.2); padding: 0 16px 16px; }
  .bl .bl__cart:not(.bl__cart--open) { padding-bottom: 0; }
  .bl .bl__cart:not(.bl__cart--open) > :not(.bl__sheetbar) { display: none; }
  .bl .bl__cart .bl__h2 { display: none; }
  .bl .bl__sheetbar { display: flex; }
  .js-drawer-open .bl .bl__cart { display: none; }
  .xg-buylist .bl__toast { bottom: calc(var(--bl-sheet-off, var(--xg-tick-h, 0px)) + 74px); }
  .bl__line { padding-left: 0; }
}
@media (max-width: 380px) {
  .bl__hit { grid-template-columns: 60px minmax(0, 1fr); }
  .bl__cardwrap { --bl-float-lift: -4px; }
}
@media (prefers-reduced-motion: reduce) {
  .xg-buylist * { transition: none !important; }
}
.bl__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- staged buylists: where each sent list stands (2026-09-19) ---- */
.bl__mine { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--bl-line); }
.bl__mine .bl__h3 { margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--bl-muted); }
.bl__mine-row { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; padding: 7px 0; border-top: 1px solid var(--bl-line); font-size: 13px; }
.bl__mine-row:first-of-type { border-top: 0; }
.bl__mine-when { color: var(--bl-muted); }
.bl__mine-what { color: var(--bl-text); }
.bl__mine-status { grid-column: 2; font-weight: 600; color: var(--bl-text); }
.bl__mine-row--staged .bl__mine-status { color: #8a5a00; }
.bl__mine-row--approved .bl__mine-status { color: var(--bl-accent); }
.bl__mine-row--rejected .bl__mine-status { color: var(--bl-danger); }
html[data-xg-theme="dark"] .bl__mine-row--staged .bl__mine-status { color: #f6c453; }
/* First view (owner, 2026-09-22): "Cards we need most right now" - the
   heading above the ten featured result cards. The cards themselves are the
   ordinary .bl__hit articles. */
.bl__wanted { margin: 2px 0 14px; padding: 12px 16px; border: 1.5px solid var(--bl-accent); border-radius: var(--bl-radius); background: linear-gradient(90deg, var(--bl-accent-soft) 0, transparent 70%), var(--bl-surface); }
.bl__wantedtitle { margin: 0 0 4px; font-size: 17px; font-weight: 800; color: var(--bl-ink); display: flex; align-items: center; gap: 8px; }
.bl__wanted .bl__muted { margin: 0; font-size: 13px; }
.bl__flame { display: inline-block; width: 12px; height: 16px; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; background: radial-gradient(circle at 50% 70%, #ffd166 0 30%, var(--bl-accent) 31% 100%); transform: rotate(-8deg); }
/* The submit confirmation (owner, 2026-09-22): payment type and total in
   so many words, with a switch to the other type. */
.bl__confirm { width: min(94vw, 480px); }
.bl__confirm-head h3 b { text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 4px; }
.bl__confirm-note { margin: 0; font-size: 14.5px; line-height: 1.55; }
.bl__confirm-note b { color: var(--bl-ink); }
.bl__confirm-actions { flex-wrap: wrap; justify-content: flex-end; }
.bl__confirm-actions .bl__btn--primary { flex: 1 1 100%; padding: 12px 16px; font-size: 15px; }
/* The upsell in the confirmation and the super-charged pop when store
   credit is picked (owner, 2026-09-22). The effect elements live inside
   .bl__totals, whose own `.bl__totals span` rule (flex column) would put
   them in the row, so every rule here names .bl__totals for specificity. */
.bl__confirm-head--credit { background: linear-gradient(135deg, var(--bl-accent), #1fa37c 60%, #ffd166); }
.bl__confirm-gain { color: var(--bl-accent); }
.bl__upsell { margin: 12px 0 0; padding: 12px 14px; border-radius: 12px; border: 1.5px dashed var(--bl-accent); background: var(--bl-accent-soft); }
.bl__upsell-kicker { display: block; font-size: 11.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--bl-accent); }
.bl__upsell-text { margin: 4px 0 10px; font-size: 14.5px; line-height: 1.5; color: var(--bl-ink); }
.bl__upsell-text b { color: var(--bl-ink); }
.bl__btn--upsell { width: 100%; border-color: var(--bl-accent); color: var(--bl-accent); font-weight: 800; }
.bl__totals { position: relative; }
.bl__totals > span { position: relative; }
.bl__totals #bl-tcredit { position: relative; z-index: 1; }
.bl__totals .bl__burst { position: absolute; display: block; right: 0; top: -8px; padding: 3px 9px; border-radius: 999px; background: var(--bl-accent); color: var(--bl-accent-ink); font-size: 12.5px; font-weight: 800; white-space: nowrap; pointer-events: none; z-index: 2; animation: bl-burst 1.7s ease-out forwards; }
@keyframes bl-burst { 0% { opacity: 0; transform: translateY(6px) scale(0.6); } 15% { opacity: 1; transform: translateY(-4px) scale(1.15); } 60% { opacity: 1; transform: translateY(-24px) scale(1); } 100% { opacity: 0; transform: translateY(-44px) scale(0.9); } }
.bl__pay--charged { animation: bl-charge 1.1s ease-out; }
@keyframes bl-charge { 0% { box-shadow: 0 0 0 0 rgba(47, 191, 149, 0.9); } 60% { box-shadow: 0 0 0 10px rgba(47, 191, 149, 0); } 100% { box-shadow: 0 0 0 0 rgba(47, 191, 149, 0); } }
.bl__totals .bl__tot--charged { display: inline-block; animation: bl-tot 1.2s cubic-bezier(0.2, 1.4, 0.4, 1); color: var(--bl-ink); text-shadow: 0 0 4px var(--bl-surface), 0 0 10px var(--bl-surface), 0 0 18px var(--bl-surface); }
@keyframes bl-tot { 0% { transform: scale(1); } 30% { transform: scale(1.45); } 100% { transform: scale(1); } }
/* Ultra: rainbow + fireworks from behind the credit total, and the caption. */
.bl__totals .bl__fx { position: absolute; display: block; left: 50%; top: 50%; width: 0; height: 0; z-index: -1; pointer-events: none; }
.bl__totals .bl__fx-rainbow { position: absolute; display: block; left: -50px; top: -50px; width: 100px; height: 100px; border-radius: 50%; background: conic-gradient(from 0deg, #ff6a5e, #ffd166, #2fbf95, #6ec6ff, #c77dff, #ff6a5e); filter: blur(9px); opacity: 0; animation: bl-rainbow 1.8s ease-out forwards; }
@keyframes bl-rainbow { 0% { opacity: 0; transform: scale(0.15) rotate(0deg); } 22% { opacity: 0.95; } 100% { opacity: 0; transform: scale(1.7) rotate(240deg); } }
.bl__totals .bl__spark { position: absolute; display: block; left: -4px; top: -4px; width: 8px; height: 8px; border-radius: 50%; background: var(--c); box-shadow: 0 0 10px var(--c), 0 0 3px #fff; opacity: 0; animation: bl-spark 1.2s cubic-bezier(0.1, 0.8, 0.3, 1) var(--d) forwards; }
@keyframes bl-spark { 0% { opacity: 0; transform: translate(0, 0) scale(0.3); } 12% { opacity: 1; transform: translate(calc(var(--dx) * 0.25), calc(var(--dy) * 0.25)) scale(1.2); } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(0.5); } }
.bl__totals .bl__fx-text { position: absolute; display: block; left: 0; bottom: -9px; margin: 0; padding: 0 8px 0 2px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; box-sizing: border-box; background: var(--bl-surface); border-radius: 999px; font-size: 10.5px; font-weight: 800; letter-spacing: 0.03em; line-height: 17px; text-transform: uppercase; white-space: nowrap; pointer-events: none; z-index: 2; animation: bl-fxtext 2.8s ease-out forwards; }
.bl__totals .bl__fx-text b { font-size: inherit; background: linear-gradient(90deg, #ff6a5e, #ffd166, #2fbf95, #6ec6ff, #c77dff); -webkit-background-clip: text; background-clip: text; color: transparent; }
@keyframes bl-fxtext { 0% { opacity: 0; transform: translateY(5px); } 15% { opacity: 1; transform: none; } 78% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .bl__totals .bl__fx { display: none; } .bl__totals .bl__burst, .bl__pay--charged, .bl__totals .bl__tot--charged { animation: none; } .bl__totals .bl__burst { opacity: 1; } .bl__totals .bl__fx-text { animation: none; opacity: 1; } }
/* The confirmation header's summary line read grey on the phone (owner,
   2026-09-22: "Grey hard to read"): the page body's own paragraph colour
   rule (.xg-prose p) beat the header's inherited white. */
.xg-buylist .bl__done-head, .xg-buylist .bl__done-head p, .xg-buylist .bl__done-head b, .xg-buylist .bl__done-head h3 { color: #fff !important; }
.xg-buylist .bl__done-head .bl__done-sum { opacity: 1; font-weight: 600; }
.xg-buylist .bl__confirm-head--credit { color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); }
/* Compact cards (owner, 2026-09-23): only the first offer until the toggle
   opens the rest. */
.bl__hit:not(.is-open) .bl__orow[data-j]:not([data-j="0"]),
.bl__hit:not(.is-open) .bl__orow--band { display: none; }
.bl__more-opts { grid-column: 1 / -1; grid-area: more; justify-self: start; display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0; padding: 6px 12px; border: 1px solid var(--bl-line-strong); border-radius: 999px; background: var(--bl-surface-2); color: var(--bl-ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.bl__more-opts:hover, .bl__more-opts:focus-visible { border-color: var(--bl-accent); color: var(--bl-accent); }
.bl__more-opts .bl__chev { font-size: 10px; transition: transform 0.15s; }
.bl__hit.is-open .bl__more-opts .bl__chev { transform: rotate(180deg); }
.bl__hit { grid-template-areas: "img head" "img offers" "img more"; }
@media (max-width: 860px) { .bl__hit { grid-template-areas: "img head" "offers offers" "more more"; } }
.bl__hit.is-open .bl__more-opts .bl__pill { display: none; }
/* The unchosen total looks switched off (owner, 2026-09-23). nth-child, not
   last-child: the store-credit caption is appended to the row for a moment. */
.bl__totals > span:nth-child(1), .bl__totals > span:nth-child(2) { transition: opacity 0.2s, filter 0.2s; }
.bl__totals[data-pay="credit"] > span:nth-child(1),
.bl__totals[data-pay="cash"] > span:nth-child(2) { opacity: 0.4; filter: grayscale(1); }
.bl__totals[data-pay="credit"] > span:nth-child(1) b,
.bl__totals[data-pay="cash"] > span:nth-child(2) b { font-weight: 600; }
