/* ============================================================================
   The Role Play Goblin — Magical Library shop archive
   Ported from the <style> block of design-reference/shop.html
   ----------------------------------------------------------------------------
   Shared components (.btn, .prod, .sec, .sechead, .rv, .badge, .celestial,
   .darkwrap, .wrap …) come from rpg-site-styles/assets/ml-chrome.css, which
   this file declares as a dependency. Only what shop.html marks page-specific
   lives here.

   Every rule is scoped under `.rpg-ml-shop` for the same reason ml-chrome.css
   scopes under `.rpg-ml`: `.grid`, `.card`, `.toolbar`, `.chip`, `.count` and
   `.wrap` are far too generic to let loose in a WordPress document — Kadence's
   own <main> is literally `class="wrap"`. The markup matches the reference;
   only the selectors carry a prefix.
   ========================================================================== */

/* Kadence constrains the content column; the hero, deals band and card
   catalogue run edge to edge. Same release the front page uses. */
body.rpg-ml-full #inner-wrap,
body.rpg-ml-full #inner-wrap > .content-container,
body.rpg-ml-full #inner-wrap > .entry-content-wrap,
body.rpg-ml-full .content-container.site-container{
  max-width:none; width:100%; padding-left:0; padding-right:0; margin-left:0; margin-right:0;
}

/* ------------------------------------------------------------------- HERO */
.rpg-ml-shop .shophero{ position:relative; overflow:hidden; color:#f6eeda;
  /* Side padding lives on `.in` now — ml-chrome.css, THE HERO GRID. */
  border-bottom:1px solid #0a1c14; padding-block:48px 46px;
  /* Round 6 gave this hero a floor to stand a cauldron on: 330px was the
     tavern's wall (6 + 3x76 = 234) plus a 96px floor band. Round 8 replaced the
     room with a cave and the height stayed. ROUND 9 needs 50px more: the heap
     is 205px now and the dragon's head — the whole point of the round — is
     247px of drawing that has to clear it.

     THE PLANTED TREASURE IS WHAT SETS THIS NUMBER, not the dragon. The sword
     and the staff are anchored to the bottom of the hero, and at 380 the
     sword's pommel came up through the word "run" in the lede — the one place
     in this scene where geometry and typography actually compete, because the
     copy is a 56ch line that reaches 944px on a 1280 screen and the heap is
     under its right end. Raising the hero to 420 alone fixed the collision and
     opened a dead band of cave between the copy and the gold; 400 with a taller
     heap and SHORTER planted pieces fixed it without one. A sword driven into a
     hoard does not need 210px of blade showing. Kept as a min so a long
     category description or a search scope row grows the cave rather than
     burying the dragon in it. */
  min-height:400px;
  background:linear-gradient(100deg,rgba(15,34,27,.98) 0 34%,rgba(15,34,27,.82) 55%,rgba(20,42,33,.55)); }
/* `.in` is a full-wrap-width box holding a headline that is at most 56ch, so
   most of it is empty — and being z-index 3 over the scene, that empty part
   was absorbing every click aimed at the shelves behind it (the top two
   shelves of the general store were unpokeable for that reason alone). It
   hands pointer events to its children, which are the actual content: the
   copy stays selectable and the search-scope chips stay clickable, and the
   gaps between them let a poke through to the ware underneath. */
.rpg-ml-shop .shophero .in{ position:relative; z-index:3; pointer-events:none; }

/* ---------------------------------------------- THE SEARCH HEADER (round 26)
   A search reuses the hero ELEMENT and none of its scene: no cave, no dragon,
   no hoard, no sky (the template does not print them). What is left is the
   copy block, so the 400px minimum that exists to clear a 247px dragon has to
   go with them — otherwise the results start below the fold on a laptop for no
   reason a visitor could name.

   The header keeps the forest ground, because the results grid below it is
   parchment and a search page with no band at the top reads as a page that
   failed to load its header. */
.rpg-ml-shop .shophero--search{ min-height:0; padding-block:30px 26px;
  background:linear-gradient(100deg,rgba(15,34,27,.98) 0 60%,rgba(20,42,33,.9)); }
.rpg-ml-shop .shophero--search h1{ font-size:clamp(24px,3.4vw,36px); margin:4px 0 6px; }
.rpg-ml-shop .shophero--search p{ max-width:60ch; }
/* The scope chips are the one interactive thing in this header, so they get
   the room the scene used to take. */
.rpg-ml-shop .shophero--search .srchscopes{ margin-top:12px; }

@media (max-width:600px){
  .rpg-ml-shop .shophero--search{ padding-block:22px 20px; }
}
/* …and its children are BLOCKS, so "Shop the hoard" is a three-word headline
   in a box the full width of the hero. `width:fit-content` shrinks each box to
   the text actually in it — no visual change, the copy is left-aligned and
   already capped at 56ch — so the right half of the hero, where the shelves
   are, stops being covered by an empty heading. */
.rpg-ml-shop .shophero .in > *{ pointer-events:auto; width:fit-content; max-width:100%; }
.rpg-ml-shop .shophero h1{ font-size:clamp(30px,4.4vw,50px); color:#f7edd6; margin:6px 0 6px; }
.rpg-ml-shop .shophero p{ color:#dcd2ba; max-width:56ch; font-family:var(--book); font-style:italic; }

/* ---- THE DRAGON'S HOARD (round 8, rebuilt round 9) -----------------------
   Round 8 built this from Kevin's brief: a heap of treasure with a red dragon
   asleep on it, a coin plinked loose by a poke, eyes that open. Round 9 is his
   review of what that produced, and it is two criticisms, both fair:

   *"The full-body dragon reads as a little potato — replace with JUST THE
   DRAGON'S HEAD, blown up BIG, entering from the RIGHT edge of the hero (neck
   running off-frame) … The GOLD PILE is very low resolution — rebuild as a
   bigger, cleaner shape: layered gold silhouettes with highlight edges instead
   of a repeating texture … Dress the edges with protruding treasure."*

   Both notes are about RESOLUTION rather than about design. A whole dragon in
   232px has a 40px head, and a head is the only part of a dragon anybody
   reads; the pile was one `repeating-linear-gradient` of coin ellipses, which
   at any size larger than the tile is visibly woven.

   WHAT REPLACED THE TILING TEXTURE is the thing the texture was standing in
   for: coins. Three layered mounds carry the mass and the dealt treasure
   carries the surface, ~165 objects on the front mound and ~60 dimmed ones on
   the mid, biased towards the crest — see ml-shop.js. A mound is a gradient,
   and a gradient is a dune; what makes gold read as gold is that it is made of
   objects.

   THE HIGHLIGHT EDGE is a parent/child pair per mound. A `clip-path` takes no
   border and a `linear-gradient` cannot follow a lumpy edge, so each mound is
   a BRIGHT parent with the SAME clip-path as a gradient CHILD offset a few
   pixels down. What shows above the child is a rim that follows the silhouette
   exactly, and it costs one element.

   THE POINTER RULE SURVIVES ITS FIFTH ROUND, because five rounds of clicking
   at real coordinates paid for it. The layer is `pointer-events:none` and only
   the DRAWN things opt back in: each mound is clipped to its own silhouette
   (a clip-path clips the hit area as well as the paint, so the empty corners
   of the box are cave rather than a target answering over nothing), and the
   dragon's own PATHS take the events, never the box they live in.

   `--pileh` is declared once and read by the mounds, the planted treasure and
   the dragon that rests its chin in them, so nothing can drift apart at a
   viewport width nobody checked. */
.rpg-ml-shop .hoard{ position:absolute; top:0; right:0; bottom:0; width:56%; z-index:1;
  --pileh:clamp(130px,18.5vw,225px);
  pointer-events:none;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 28%);
  mask-image:linear-gradient(90deg,transparent,#000 28%); }

/* The light the cave is lit BY — the gold itself, from below. Everything else
   in the hero is lit from above, which is what makes this read as a hoard in
   the dark rather than as a picture of a hoard. */
.rpg-ml-shop .hoard .cavelight{ position:absolute; left:-10%; right:-10%; top:-12%; bottom:0;
  pointer-events:none;
  background:
    radial-gradient(58% 62% at 60% 104%,rgba(232,182,78,.34),rgba(232,182,78,0) 70%),
    radial-gradient(38% 46% at 78% 98%,rgba(226,120,40,.15),rgba(226,120,40,0) 72%); }

/* Coins that got away, scattered across the cave floor to the left of the
   heap. A field rather than objects, and it fades UPWARD into the dark while
   `.hoard`'s own mask fades it out to the left. */
.rpg-ml-shop .hoard .spill{ position:absolute; left:0; right:0; bottom:0; height:52px;
  pointer-events:none; opacity:.7;
  background-image:
    radial-gradient(7px 3px at 50% 50%,rgba(248,220,146,.95),rgba(248,220,146,0) 70%),
    radial-gradient(5px 2.2px at 50% 50%,rgba(206,160,68,.85),rgba(206,160,68,0) 72%);
  background-size:43px 21px,29px 15px;
  background-position:0 4px,13px 11px;
  -webkit-mask-image:linear-gradient(rgba(0,0,0,0),#000 72%);
  mask-image:linear-gradient(rgba(0,0,0,0),#000 72%); }

/* ---- the heap, in three mounds ------------------------------------------
   `.pile` is the positioning box and takes no events. It runs to the layer's
   left edge rather than starting at 14% as the round-8 heap did: the mound's
   left flank used to end on a visible stepped edge just inside the mask's
   fade, and a silhouette that stops in mid-air is worse than one that
   dissolves into the dark.

   Each mound peaks somewhere different — right, left, right again — because
   three crests in a line is one crest with contour lines drawn on it, which is
   exactly what the first rebuild rendered. */
.rpg-ml-shop .hoard .pile{ position:absolute; left:0; right:0; bottom:0;
  height:var(--pileh); pointer-events:none; }
.rpg-ml-shop .hoard .hp{ position:absolute; left:0; right:0; top:0; bottom:0;
  pointer-events:auto; cursor:pointer; transition:filter .25s var(--ease-out); }
.rpg-ml-shop .hoard .hp i{ position:absolute; left:0; right:0; bottom:0; display:block;
  pointer-events:none; }

/* back mound — dimmest and tallest. Atmospheric perspective: the far heap in a
   cave lit from its own gold is darker, not lighter. */
.rpg-ml-shop .hoard .hp.b1{ background:linear-gradient(90deg,#6d5622,#a8842f 46%,#6a5320); }
.rpg-ml-shop .hoard .hp.b1,
.rpg-ml-shop .hoard .hp.b1 i{ clip-path:polygon(0% 100%,0% 70%,4% 61%,9% 64%,13% 55%,
  19% 51%,23% 53%,29% 42%,35% 37%,39% 40%,44% 28%,50% 22%,54% 25%,60% 15%,66% 9%,
  70% 13%,75% 8%,80% 17%,85% 13%,90% 24%,95% 20%,100% 30%,100% 100%); }
.rpg-ml-shop .hoard .hp.b1 i{ top:2px;
  background:linear-gradient(174deg,#8a6a24 0 8%,#6d5219 30%,#4a370f 58%,#2b1f07); }

/* mid mound */
.rpg-ml-shop .hoard .hp.b2{ background:linear-gradient(90deg,#a8873a,#e2be69 42%,#a8873a); }
.rpg-ml-shop .hoard .hp.b2,
.rpg-ml-shop .hoard .hp.b2 i{ clip-path:polygon(0% 100%,0% 78%,5% 68%,10% 72%,15% 58%,
  21% 50%,26% 53%,31% 40%,37% 32%,41% 36%,46% 27%,52% 23%,57% 28%,63% 24%,68% 32%,
  73% 27%,78% 35%,84% 42%,89% 38%,94% 47%,100% 54%,100% 100%); }
.rpg-ml-shop .hoard .hp.b2 i{ top:2.5px;
  background:linear-gradient(174deg,#a8842f 0 6%,#836320 28%,#5a4212 56%,#2f2107); }

/* front mound — the one the treasure lies on and the one a poke plinks a coin
   out of. Its bare face is deliberately NOT the brightest thing in the scene:
   the first rebuild lit the crest to #e8c672 and the gold read as a lit dune
   with some coins at its foot. The coins are the highlight. */
.rpg-ml-shop .hoard .hp.b3{ background:linear-gradient(90deg,#d0ac5c,#fff0c2 58%,#cda44e); }
.rpg-ml-shop .hoard .hp.b3,
.rpg-ml-shop .hoard .hp.b3 i{ clip-path:polygon(0% 100%,0% 93%,4% 85%,8% 89%,13% 80%,
  17% 83%,22% 74%,26% 77%,31% 67%,35% 70%,39% 61%,44% 56%,48% 60%,52% 52%,57% 55%,
  61% 47%,66% 44%,70% 48%,75% 42%,79% 46%,84% 51%,88% 47%,93% 53%,97% 49%,
  100% 56%,100% 100%); }
.rpg-ml-shop .hoard .hp.b3 i{ top:3.5px;
  background:linear-gradient(174deg,#c9a247 0 5%,#a9812c 26%,#7b5c17 54%,#4d380c 78%,#241a06); }

/* Hover BRIGHTENS. It does not lift, tilt or grow: the general store lost a
   third of its shelf to a 3deg hover that moved the ware out from under the
   cursor between the mousemove and the mousedown, and a filter moves nothing. */
.rpg-ml-shop .hoard .hp:hover{ filter:brightness(1.1); }
/* the heap settles when something is pulled out of it */
.rpg-ml-shop .hoard .pile.settling .hp{ animation:rpg-hoard-settle .5s ease-out; }
@keyframes rpg-hoard-settle{
  0%{ transform:none } 30%{ transform:translateY(1.6px) scaleY(.993) }
  62%{ transform:translateY(-.6px) } 100%{ transform:none } }

/* ---- the planted treasure ------------------------------------------------
   Kevin: *"Dress the edges with protruding treasure: a magic sword or two, a
   staff, AND/OR a LICH HAND sticking out holding a DIAMOND."* All three, and
   EACH SITS BETWEEN TWO MOUNDS rather than on top of the finished pile — the
   mound in front buries its base. An object laid over the whole heap is an
   object standing on the heap, which is the difference between a sword driven
   into a hoard and a sword balanced on one. */
.rpg-ml-shop .hoard .pr{ position:absolute; bottom:0; pointer-events:none;
  transform-origin:50% 100%; }
.rpg-ml-shop .hoard .pr svg{ display:block; width:100%; height:auto; overflow:visible; }
.rpg-ml-shop .hoard .pr.sword{ width:clamp(28px,3.4vw,44px); }
.rpg-ml-shop .hoard .pr.staff{ width:clamp(22px,2.8vw,36px); }
.rpg-ml-shop .hoard .pr.lich{ width:clamp(70px,9vw,118px); }
/* The lich's hand is the one planted thing that answers a poke — and THE
   STONE ANSWERS TOO, because the stone is what a visitor reaches for. The hand
   is bones: five 3px strokes and a palm inside a 139x220 box, so grip-only took
   5 of 25 probe points at real coordinates. Adding the diamond adds the one
   large solid shape in the drawing. */
.rpg-ml-shop .hoard .pr.lich .grip,
.rpg-ml-shop .hoard .pr.lich .dstone{ pointer-events:auto; cursor:pointer; }
.rpg-ml-shop .hoard .pr.lich .grip:hover,
.rpg-ml-shop .hoard .pr.lich .dstone:hover{ filter:brightness(1.18); }
/* …but not while it is in the air: a stone mid-roll that takes a click is a
   stone that can be re-thrown from wherever it happens to be. */
.rpg-ml-shop .hoard .pr.lich.rolling .dstone{ pointer-events:none; }

/* The staff's crystal breathes, on its own long period — it is the only cold
   light in a scene lit entirely by gold, and a steady one reads as a sticker. */
.rpg-ml-shop .hoard .pr.staff .crystal{ animation:rpg-hoard-pulse 6.5s ease-in-out infinite; }
@keyframes rpg-hoard-pulse{
  0%,100%{ opacity:.82 } 50%{ opacity:1 } }

/* THE DIAMOND ROLLS. Kevin: *"clicking it makes the diamond roll down the
   pile."* It leaves the hand, bounces twice down the slope and is back in the
   grip when it has played — a stone that stays where it stopped means the
   scene can only be poked once, and every other interaction in this redesign
   can be poked again. `translate` and `rotate` as separate properties, not one
   `transform`, so the tumble and the travel are independent curves. */
.rpg-ml-shop .hoard .pr.lich .dstone{ transform-box:fill-box; transform-origin:50% 50%; }
.rpg-ml-shop .hoard .pr.lich.rolling .dstone{
  animation:rpg-hoard-roll var(--roll,2400ms) cubic-bezier(.4,0,.7,1) forwards; }
/* DOWN THE FRONT FACE, not along the crest. The first version rolled the
   stone left, which is downhill on this silhouette and looked right on paper —
   and put it 12% into the layer, where `.hoard`'s mask has faded the gold to
   nothing and a diamond finishes its journey hanging in a dark cave. The face
   of a heap runs towards the viewer; travelling down it keeps the stone on the
   gold the whole way and buries it in the coins at the foot. */
@keyframes rpg-hoard-roll{
  0%{ translate:0 0; rotate:0deg }
  8%{ translate:-6px -18px; rotate:-50deg }
  22%{ translate:10px 20px; rotate:-180deg }
  32%{ translate:22px 8px; rotate:-260deg }
  50%{ translate:40px 62px; rotate:-430deg }
  58%{ translate:48px 50px; rotate:-500deg }
  78%{ translate:58px 112px; rotate:-680deg }
  86%{ translate:62px 104px; rotate:-740deg }
  100%{ translate:66px 150px; rotate:-820deg; opacity:0 }
}
/* …and it is back, because the keyframe ends invisible and the class comes off */
.rpg-ml-shop .hoard .pr.lich.rolling .dstone{ opacity:1; }

/* ---- the dealt treasure -------------------------------------------------
   Rolled per load by ml-shop.js and laid down BACK TO FRONT — an item lower on
   the heap is nearer the viewer, so it is painted later and overlaps the ones
   behind it. Without that the pile is a flat sticker sheet. */
.rpg-ml-shop .hoard .tr{ position:absolute; pointer-events:none;
  transform:translateX(-50%) rotate(var(--rot,0deg)); }
/* the mid mound's deal is dimmed and shrunk by the same rule that dims the
   mound it lies on */
.rpg-ml-shop .hoard .tr.far{ filter:brightness(.76); }

/* a coin, face on */
.rpg-ml-shop .hoard .coin{ width:var(--w); height:calc(var(--w) * .42); border-radius:50%;
  background:linear-gradient(150deg,#ffeab2,#d9ab46 44%,#8a6420);
  box-shadow:0 1px 0 rgba(0,0,0,.45),inset 0 0 0 1px rgba(255,244,205,.32); }
/* …and one standing on its edge, which is what stops a heap of ellipses from
   reading as a heap of buttons */
.rpg-ml-shop .hoard .coin.edge{ width:calc(var(--w) * .34); height:calc(var(--w) * .8);
  border-radius:2px/50%;
  background:linear-gradient(90deg,#7d5a1c,#ffeab2 46%,#a97f2c); }

/* a gem. The facet highlight is a child, so the stone's clip-path cuts it to
   the stone — the highlight can never hang over the edge of its own gem. */
.rpg-ml-shop .hoard .gem{ width:var(--w); height:var(--w);
  clip-path:polygon(50% 0,100% 36%,79% 100%,21% 100%,0 36%);
  background:linear-gradient(160deg,var(--g2),var(--g) 62%,rgba(0,0,0,.55));
  /* Two drop-shadows: a tight dark one that gives the stone an edge against
     the gold, then the glow. A clip-path takes no border, so this is the only
     way a faceted shape gets an outline. */
  filter:drop-shadow(0 0 1px rgba(20,10,2,.9)) drop-shadow(0 0 5px var(--g2)); }
.rpg-ml-shop .hoard .gem::after{ content:""; position:absolute; left:20%; top:14%;
  width:30%; height:38%; background:rgba(255,255,255,.55);
  clip-path:polygon(0 0,100% 24%,58% 100%,0 60%); }

/* a goblet, tipped over in the gold. Warm, not white: the first draft's bowl
   started at #ffe6a4 and every goblet on the heap read as a wine glass. */
.rpg-ml-shop .hoard .cup{ width:var(--w); height:calc(var(--w) * 1.4); }
.rpg-ml-shop .hoard .cup i{ position:absolute; }
.rpg-ml-shop .hoard .cup .bowl{ left:0; right:0; top:0; height:52%;
  border-radius:3px 3px 48% 48%/3px 3px 88% 88%;
  background:linear-gradient(158deg,#f5d489,#b8862c 52%,#6b4c14);
  box-shadow:inset 0 1.5px 0 rgba(255,240,192,.5); }
.rpg-ml-shop .hoard .cup .stem{ left:50%; top:50%; bottom:13%; width:2px; margin-left:-1px;
  background:linear-gradient(90deg,#6b4c14,#dbb055,#6b4c14); }
.rpg-ml-shop .hoard .cup .foot{ left:18%; right:18%; bottom:0; height:13%; border-radius:2px;
  background:linear-gradient(#c99a3c,#6b4c14); }

/* THE TWINKLE. A four-point star drawn as two crossed gradients on one
   pseudo-element, so a sparkling coin costs no extra node. Only coins get it:
   `.gem` is clipped to its silhouette and would cut the star's arms off at the
   stone's edge. `--tw` is rolled per item — a field of gold that all glints on
   the same beat reads as a broken loop, not as treasure. */
.rpg-ml-shop .hoard .coin.tw::before{ content:""; position:absolute; left:50%; top:50%;
  width:11px; height:11px; margin:-5.5px 0 0 -5.5px; pointer-events:none; opacity:0;
  background:
    linear-gradient(rgba(255,247,214,0),rgba(255,247,214,.95) 50%,rgba(255,247,214,0)) 50% 0/1.4px 100% no-repeat,
    linear-gradient(90deg,rgba(255,247,214,0),rgba(255,247,214,.95) 50%,rgba(255,247,214,0)) 0 50%/100% 1.4px no-repeat;
  animation:rpg-hoard-tw 7s var(--tw,0s) ease-in-out infinite; }
@keyframes rpg-hoard-tw{
  0%,88%,100%{ opacity:0; transform:scale(.35) rotate(0) }
  94%{ opacity:1; transform:scale(1) rotate(45deg) } }

/* ---- THE DRAGON ---------------------------------------------------------
   Round 9: the head alone, entering from the right with the neck running
   off-frame. It sits between the mid and the front mound in the markup, so the
   front mound BURIES ITS CHIN — a head resting exactly on the surface of a
   heap of loose coins is a head on a table.

   SIX DRAFTS, AND EVERY FAILURE WAS A DIFFERENT ANIMAL. The test that found
   them is in the file this was drawn in: render the whole thing with every
   fill black and no strokes and look at the silhouette, because that is what a
   visitor's eye reads first and it is where all six failures lived. Smooth
   curves gave a CROCODILE (muzzle too long, no brow), then an EEL (the brow
   flattened out of the outline entirely), then a SHARK — a brow bump with a
   horn standing on it merges into one dorsal fin — then a DOLPHIN, the muzzle
   and jaw rounding into one bottom-heavy mass.

   What fixed it was ANGLES. A skull is corners, not curves: the top line is a
   long shallow muzzle, ONE sharp brow corner, then a straight roof back to the
   occiput. No second bump — a bump behind the brow reads as a bird. */
.rpg-ml-shop .hoard .dragon{ position:absolute; right:-7%;
  bottom:calc(var(--pileh) * .46);
  width:clamp(220px,31vw,396px); z-index:2; pointer-events:none; }
.rpg-ml-shop .hoard .drake{ display:block; width:100%; height:auto; overflow:visible;
  pointer-events:none; transform-origin:88% 78%;
  animation:rpg-hoard-breathe var(--breath,5.4s) ease-in-out infinite; }
/* The breath. It is also the clock the smoke runs on — see `.puff`. The origin
   is the base of the neck, because a head on a neck pivots at the shoulder;
   scaling it about its own middle makes the whole animal inflate. */
@keyframes rpg-hoard-breathe{
  0%,100%{ transform:scale(1) translateY(0) }
  46%{ transform:scale(1.016,1.026) translateY(-1.4px) } }

/* THE HIT TARGETS ARE THE PAINTED SHAPES, not the box they live in. The head's
   bounding box is more than half air; as one target it would swallow every
   poke aimed at the heap underneath it. */
.rpg-ml-shop .hoard .drake .dk,
.rpg-ml-shop .hoard .drake .neck,
.rpg-ml-shop .hoard .drake .jaw,
.rpg-ml-shop .hoard .drake .horn,
.rpg-ml-shop .hoard .drake .spike{ pointer-events:auto; cursor:pointer;
  transition:filter .25s var(--ease-out); }
.rpg-ml-shop .hoard .drake .dk:hover,
.rpg-ml-shop .hoard .drake .neck:hover,
.rpg-ml-shop .hoard .drake .jaw:hover,
.rpg-ml-shop .hoard .drake .horn:hover,
.rpg-ml-shop .hoard .drake .spike:hover{ filter:brightness(1.2); }

/* THE STROKE IS NOT A FLOURISH. One fill across overlapping shapes gives one
   silhouette, which is what put a whale on this page in round 8. */
.rpg-ml-shop .hoard .drake .dk,
.rpg-ml-shop .hoard .drake .neck,
.rpg-ml-shop .hoard .drake .jaw,
.rpg-ml-shop .hoard .drake .horn,
.rpg-ml-shop .hoard .drake .spike{ stroke:#1d0705; stroke-linejoin:round; }
.rpg-ml-shop .hoard .drake .dk,
.rpg-ml-shop .hoard .drake .neck{ stroke-width:1.6; }
.rpg-ml-shop .hoard .drake .jaw{ stroke-width:1.5; }
.rpg-ml-shop .hoard .drake .horn{ stroke-width:1.2; }
.rpg-ml-shop .hoard .drake .spike{ stroke-width:1; }
.rpg-ml-shop .hoard .drake .dk{ fill:url(#rpgDrakeSkin); }
.rpg-ml-shop .hoard .drake .neck{ fill:url(#rpgDrakeDeep); }
.rpg-ml-shop .hoard .drake .jaw{ fill:url(#rpgDrakeJaw); }
.rpg-ml-shop .hoard .drake .horn,
.rpg-ml-shop .hoard .drake .spike{ fill:url(#rpgDrakeHorn); }
.rpg-ml-shop .hoard .drake .tooth{ fill:#e9dcbe; stroke:#3a1008; stroke-width:.6;
  stroke-linejoin:round; pointer-events:none; }
/* The scale texture. A `<pattern>` fill and NOT a mask over one: Chrome drops
   a pattern fill outright when the element carrying it is masked, which is how
   the first attempt at fading these towards the muzzle produced a head with no
   texture at all. The wash below does the fading instead, and models the head
   while it is there. */
.rpg-ml-shop .hoard .drake .scales{ fill:url(#rpgDrakeScale); stroke:none; opacity:.26;
  pointer-events:none; }
.rpg-ml-shop .hoard .drake .wash{ stroke:none; pointer-events:none; }
.rpg-ml-shop .hoard .drake .brow{ fill:rgba(246,176,120,.18); stroke:none; pointer-events:none; }
.rpg-ml-shop .hoard .drake .shade{ fill:rgba(20,5,3,.42); stroke:none; pointer-events:none; }
.rpg-ml-shop .hoard .drake .fold{ fill:none; stroke:rgba(30,8,4,.45); stroke-width:1.1;
  stroke-linecap:round; pointer-events:none; }
.rpg-ml-shop .hoard .drake .nost{ fill:#170504; pointer-events:none; }
/* the gold below is the only light in this cave, so it catches the underjaw */
.rpg-ml-shop .hoard .drake .rim{ fill:none; stroke:rgba(255,164,84,.45); stroke-width:2.6;
  stroke-linecap:round; pointer-events:none; }
/* The socket is SKIN, a shade darker — not a hole. An eye the same colour as
   the head is a missing eye, and a black one on a sleeping animal is a hole. */
.rpg-ml-shop .hoard .drake .socket{ fill:#5a1a0e; stroke:rgba(25,6,4,.55); stroke-width:1;
  pointer-events:none; }
.rpg-ml-shop .hoard .drake .lid{ fill:none; stroke:#1c0705; stroke-width:2.2;
  stroke-linecap:round; pointer-events:none; }
.rpg-ml-shop .hoard .drake .eyeball{ fill:#2c0c07; }
.rpg-ml-shop .hoard .drake .pupil{ fill:#150403; }
/* Asleep: the lid is shut. `transform-box:fill-box` is required — without it an
   SVG transform-origin resolves against the whole viewBox and the eye scales
   towards the corner of the drawing instead of about itself. The `<g>` carries
   it so the eyeball and its slit pupil close about ONE origin: two shapes of
   different heights closing about their own centres do not close, they slide
   past each other. */
.rpg-ml-shop .hoard .drake .eye{ pointer-events:none;
  transform-box:fill-box; transform-origin:50% 50%; transform:scaleY(.08); }

/* the ember bed under the jaw — behind the drawing, so what shows is the light
   escaping around the silhouette. Kevin asked for the glow UNDER THE JAW this
   round rather than under a whole body, which is also where a furnace would
   be. */
.rpg-ml-shop .hoard .dragon .ember{ position:absolute; left:4%; right:34%; bottom:2%; height:34%;
  pointer-events:none; opacity:0; border-radius:50%; filter:blur(8px);
  background:radial-gradient(closest-side,rgba(255,104,36,.9),rgba(255,64,22,.36) 54%,rgba(255,54,16,0) 78%); }

/* ---- waking it ----------------------------------------------------------
   One duration, `--wake`, shared by the four animations the poke starts, so
   the eyes, the ember, the hot skin and the head all settle on the same beat.
   ml-shop.js removes `.awake` on the same timer for the same reason. */
.rpg-ml-shop .hoard .dragon{ --wake:4200ms; }
.rpg-ml-shop .hoard .dragon.awake .drake{ animation:rpg-hoard-tense var(--wake) ease-in-out; }
@keyframes rpg-hoard-tense{
  0%{ transform:none; filter:none }
  12%{ transform:translateY(-5px) rotate(-1deg);
       filter:drop-shadow(0 0 16px rgba(255,86,34,.75)) }
  34%{ transform:translateY(-2px) rotate(.4deg);
       filter:drop-shadow(0 0 10px rgba(255,86,34,.45)) }
  62%{ transform:translateY(-4px) rotate(-.6deg);
       filter:drop-shadow(0 0 15px rgba(255,86,34,.7)) }
  100%{ transform:none; filter:none } }
/* The lid and the iris are two animations because they are on two elements —
   the `<g>` carries the opening, the eyeball inside it carries the colour, and
   the slit pupil must NOT take the colour or the eye has no pupil while it is
   open. Same duration, same easing, so they are one movement. */
.rpg-ml-shop .hoard .dragon.awake .eye{ animation:rpg-hoard-eye var(--wake) ease-in-out; }
@keyframes rpg-hoard-eye{
  0%{ transform:scaleY(.08); filter:none }
  7%{ transform:scaleY(1) }
  12%,72%{ transform:scaleY(1); filter:drop-shadow(0 0 6px rgba(255,150,40,.95)) }
  42%{ transform:scaleY(.84) }
  90%,100%{ transform:scaleY(.08); filter:none } }
.rpg-ml-shop .hoard .dragon.awake .eyeball{ animation:rpg-hoard-iris var(--wake) ease-in-out; }
@keyframes rpg-hoard-iris{
  0%{ fill:#2c0c07 } 7%{ fill:#ffb43a } 12%,72%{ fill:#ffce5c }
  90%,100%{ fill:#2c0c07 } }
.rpg-ml-shop .hoard .dragon.awake .ember{ animation:rpg-hoard-ember var(--wake) ease-in-out; }
@keyframes rpg-hoard-ember{
  0%{ opacity:0; transform:scale(.86) }
  14%{ opacity:1; transform:scale(1.06) }
  38%{ opacity:.62; transform:scale(.97) }
  60%{ opacity:.94; transform:scale(1.04) }
  100%{ opacity:0; transform:scale(.9) } }
/* The hot skin: a second copy of the skull path over the first, so waking can
   CROSS-FADE to a different gradient. `fill` cannot be animated between two
   `url()` references at all — one of them simply wins on the first frame. */
.rpg-ml-shop .hoard .drake .heat{ fill:url(#rpgDrakeHot); opacity:0; pointer-events:none; }
.rpg-ml-shop .hoard .dragon.awake .heat{ animation:rpg-hoard-heat var(--wake) ease-in-out; }
@keyframes rpg-hoard-heat{
  0%{ opacity:0 } 16%{ opacity:.74 } 40%{ opacity:.4 } 62%{ opacity:.68 } 100%{ opacity:0 } }

/* ---- the nostril smoke --------------------------------------------------
   THREE WISPS ON ONE PERIOD, offset by a third of a second — not three
   independent timings. Smoke on independent timers reads as a smouldering
   object; smoke that leaves the nose together, once per cycle, reads as
   breathing, which is what was asked for. The period IS `--breath`, and the
   visible half of the keyframe is the second half, because `rpg-hoard-breathe`
   peaks (inhale) at 46% and returns (exhale) after it. */
.rpg-ml-shop .hoard .dragon .puff{ position:absolute; left:6%; top:52%; width:34%; height:38%;
  pointer-events:none; }
.rpg-ml-shop .hoard .dragon .puff i{ position:absolute; left:0; bottom:0; width:10px; height:10px;
  border-radius:50%; opacity:0; filter:blur(4px);
  background:radial-gradient(circle,rgba(216,200,182,.62),rgba(190,172,152,0) 70%);
  animation:rpg-hoard-puff var(--breath,5.4s) ease-out infinite; }
.rpg-ml-shop .hoard .dragon .puff i:nth-child(2){ animation-delay:.32s; }
.rpg-ml-shop .hoard .dragon .puff i:nth-child(3){ animation-delay:.66s; }
@keyframes rpg-hoard-puff{
  0%,50%{ opacity:0; transform:translate(0,0) scale(.4) }
  58%{ opacity:.5 }
  100%{ opacity:0; transform:translate(-30px,-38px) scale(2.2) } }
/* awake: the rumble. More smoke, faster, and lit from inside. */
.rpg-ml-shop .hoard .dragon.awake .puff i{ animation-duration:1.5s;
  background:radial-gradient(circle,rgba(255,152,82,.64),rgba(255,112,52,0) 70%); }

/* ---- a coin plinked loose -----------------------------------------------
   Spawned by ml-shop.js at the point that was clicked and removed when it has
   played. Its own layer above the heap so nothing clips it mid-flight, and
   `pointer-events:none` throughout so a coin in the air can never intercept
   the next poke.

   `scaleY` flipping through the arc is the coin SPINNING: a gold ellipse that
   travels without turning edge-on reads as a sticker being dragged. `--dx` and
   `--dy` are rolled per coin — dx is which way it flies, dy how far down the
   heap it finally settles, because a coin knocked out of a pile ends up lower
   than it started. */
.rpg-ml-shop .hoard .plinks{ position:absolute; left:0; right:0; top:0; bottom:0;
  pointer-events:none; z-index:3; overflow:hidden; }
.rpg-ml-shop .hoard .plink{ position:absolute; width:11px; height:5px; margin:-2.5px 0 0 -5.5px;
  border-radius:50%; pointer-events:none;
  background:linear-gradient(150deg,#fff4cf,#e0b352 46%,#8a6420);
  box-shadow:0 0 6px rgba(255,222,140,.6),inset 0 0 0 1px rgba(255,246,214,.42);
  animation:rpg-hoard-plink var(--ms,1450ms) linear forwards; }
@keyframes rpg-hoard-plink{
  0%{ opacity:0; transform:translate(0,0) rotate(0) scaleY(1) }
  5%{ opacity:1 }
  14%{ transform:translate(calc(var(--dx) * .22),-38px) rotate(150deg) scaleY(.4) }
  26%{ transform:translate(calc(var(--dx) * .40),-52px) rotate(280deg) scaleY(1) }
  40%{ transform:translate(calc(var(--dx) * .58),-30px) rotate(430deg) scaleY(.45) }
  50%{ transform:translate(calc(var(--dx) * .68),calc(var(--dy) * .5)) rotate(520deg) scaleY(1) }
  60%{ transform:translate(calc(var(--dx) * .78),calc(var(--dy) * .5 - 17px)) rotate(600deg) scaleY(.6) }
  70%{ transform:translate(calc(var(--dx) * .86),calc(var(--dy) * .8)) rotate(660deg) scaleY(1) }
  78%{ transform:translate(calc(var(--dx) * .92),calc(var(--dy) * .8 - 6px)) rotate(700deg) scaleY(.82) }
  86%,100%{ transform:translate(var(--dx),var(--dy)) rotate(724deg) scaleY(1) }
  100%{ opacity:0 } }
/* the glint, at the top of the arc where the coin catches the light */
.rpg-ml-shop .hoard .plink::after{ content:""; position:absolute; left:-6px; top:-6px;
  width:23px; height:17px; border-radius:50%; opacity:0;
  background:radial-gradient(closest-side,rgba(255,246,214,.9),rgba(255,246,214,0) 72%);
  animation:rpg-hoard-glint var(--ms,1450ms) linear forwards; }
@keyframes rpg-hoard-glint{
  0%,16%{ opacity:0 } 25%{ opacity:.95 } 34%,100%{ opacity:0 } }

/* On a narrow screen the head goes DOWN and further off-frame rather than
   getting smaller and staying put: at 360px the headline wraps to three lines
   and a head at hero-middle height sits behind the second of them. */
/* On a phone the whole scene is already handled further down this file, in the
   BREAKPOINTS block: round 8 made it a .32-opacity wash across the full width
   of a content-height hero, and that is the right answer — the copy is the
   content and the scene is texture behind it.

   What the head needs on top of that is to sit LOWER. The round-8 heap lived
   at the foot of the hero and left the headline alone; a head anchored at
   `--pileh * .46` puts its horns through "Shop the hoard" at 390px. It drops to
   the gold and travels further off-frame, so the faint shape behind the copy is
   behind the LAST line of it rather than the first. */
@media (max-width:900px){
  .rpg-ml-shop .hoard .dragon{ right:-18%; bottom:calc(var(--pileh) * .06);
    width:clamp(200px,52vw,300px); }
}

/* ------------------------------------------------------- CHIPS (shared) */
/* ROUND 30 — `.chiprows` / `.chiprow` / `.chiprow .lb` are gone with the two
   rows at the top of /shop (see the shelf doors further down). `.chip` and
   `.chips` STAY: the agenda's month and type filters, the Library's chips and
   the search page's scope row are all real filters wearing this pill, and they
   are the reason the shape means "this narrows the list" — which is exactly
   the claim the two shop rows could not make. */
.rpg-ml-shop .chips{ display:flex; gap:8px; flex-wrap:wrap; flex:1; min-width:0; }
/* `.chip .g` went too — nothing renders `<span class="g">` any more; the emoji
   it positioned was the play-style row's, and the doors draw SVG scenes. */
.rpg-ml-shop .chip{ background:var(--card); border:1px solid var(--line); border-radius:999px;
  padding:8px 15px; font-size:13px; font-weight:600; color:var(--ink);
  /* The reference's chips are <span>s that only look tappable; these are real
     links to real archives, so they also need a 44px target. */
  display:inline-flex; align-items:center; min-height:38px; }
.rpg-ml-shop .chip:hover{ border-color:var(--brass); }
.rpg-ml-shop .chip.on{ background:var(--forest); color:#f3ead6; border-color:var(--forest); }

/* ------------------------------- THE RELATED-CATEGORY STRIP (round 28) -----
   What a TERM ARCHIVE gets instead of the two chip rows. Kevin: *"they look
   like filters, navigate elsewhere, and eat space … taxonomy/category archives
   get at most a slim breadcrumb/related-category strip clearly styled as
   navigation, not chips."*

   So it is deliberately everything a chip is not: no pill, no border, no fill,
   no 38px target grid. Underlined links in the mono voice the breadcrumb and
   the eyebrows already use, on one line that wraps, with a back-arrow to the
   parent at its head. A visitor should be able to tell what a control does
   from a metre away without pressing it, and on this site a pill means "this
   narrows the list below" — one shape, one meaning.

   `min-height:44px` is still on the LINKS, because navigation on a phone is
   pressed as often as a filter is. Tap size is not what distinguishes them;
   the drawing is. */
.rpg-ml-shop .catnav{ margin:18px 0 4px; display:flex; flex-wrap:wrap;
  align-items:baseline; gap:6px 14px; font-family:var(--mono); font-size:11.5px;
  letter-spacing:.06em; padding-bottom:14px; border-bottom:1px solid var(--line); }
.rpg-ml-shop .catnav .up{ color:var(--brass); font-weight:700; text-transform:uppercase;
  letter-spacing:.1em; font-size:10.5px; display:inline-flex; align-items:center; min-height:44px; }
.rpg-ml-shop .catnav .up:hover{ text-decoration:underline; }
.rpg-ml-shop .catnav .lb{ color:var(--muted); text-transform:uppercase;
  letter-spacing:.1em; font-size:10.5px; }
.rpg-ml-shop .catnav .items{ display:flex; flex-wrap:wrap; gap:2px 14px; min-width:0; }
.rpg-ml-shop .catnav .items a{ color:var(--ink); text-decoration:underline;
  text-decoration-color:rgba(120,92,40,.35); text-underline-offset:3px;
  display:inline-flex; align-items:center; min-height:44px; }
.rpg-ml-shop .catnav .items a:hover{ color:var(--brass); text-decoration-color:currentColor; }
/* Where you are: stated, not hidden. A nav that omits the current page is a nav
   you cannot orient in — and `aria-current` says the same thing out loud. */
.rpg-ml-shop .catnav .items a.on{ color:var(--forest); font-weight:700; text-decoration:none; }

/* ------------------------------ WHAT IS ACTUALLY ON, IN WORDS (round 28) ---
   Under the toolbar, beside the count the filters changed. Kevin: *"they lead
   to sub pages and are NOT filters"* — the chips have carried real query
   parameters since round 15, but pressing one reloads the page, the heading
   still says "Shop the hoard", and the only evidence was a small number on the
   Filter button. This is the evidence.

   Tokens are `.tok` and NOT `.chip`, even though they are close relatives: a
   chip is a control you press to turn something ON and this is a receipt you
   press to take something OFF. Wine ground rather than the chips' forest, so
   the two are never mistaken for one row that wrapped. */
.rpg-ml-shop .onfilters{ display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  margin:0 0 16px; }
.rpg-ml-shop .onfilters .lb{ font-family:var(--mono); font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--brass); font-weight:700; }
.rpg-ml-shop .onfilters .tok{ display:inline-flex; align-items:center; gap:8px;
  background:var(--wine); color:#f7ece0; border-radius:999px; padding:6px 12px;
  font-size:12.5px; font-weight:600; min-height:34px; }
.rpg-ml-shop .onfilters .tok .x{ font-size:15px; line-height:1; opacity:.72; }
.rpg-ml-shop .onfilters .tok:hover{ background:#5d1b23; }
.rpg-ml-shop .onfilters .tok:hover .x{ opacity:1; }

/* --------------------------------------- PRE-ORDERS & UPCOMING BAND */
.rpg-ml-shop .preband{ position:relative; overflow:hidden; color:var(--text-inverse);
  background:linear-gradient(120deg,#14301f,#0d2016);
  border-radius:14px; border:1px solid rgba(200,162,74,.3); margin:18px 0 20px;
  padding:22px 22px 24px; }
.rpg-ml-shop .preband .ph{ position:relative; z-index:2; display:flex; justify-content:space-between;
  align-items:flex-end; gap:16px; flex-wrap:wrap; margin-bottom:16px; }
.rpg-ml-shop .preband h2{ font-size:clamp(22px,3vw,30px); color:#f6eeda; }
.rpg-ml-shop .preband .k{ font-family:var(--book); font-style:italic; font-size:13.5px;
  color:#b9d0b4; margin-top:5px; }
.rpg-ml-shop .preband .rail{ position:relative; z-index:2; display:grid;
  grid-template-columns:repeat(4,1fr); gap:14px; }
.rpg-ml-shop .rel{ display:inline-flex; align-items:center; gap:6px; font-family:var(--mono);
  font-size:10px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  background:rgba(200,162,74,.16); border:1px solid rgba(200,162,74,.45); color:#e8c778;
  border-radius:999px; padding:4px 10px; margin-top:2px; }
/* the cards are light — don't inherit the band's cream text */
.rpg-ml-shop .preband .prod{ color:var(--ink); }
.rpg-ml-shop .preband .prod .pb{ gap:6px; }
.rpg-ml-shop .preband .prod .price{ color:var(--ink); }
.rpg-ml-shop .preband .prod .rel{ color:#7a5c1e; background:rgba(200,162,74,.22);
  border-color:rgba(138,106,47,.5);
  /* even layout with multiline titles: pin the chip + price to the card bottom */
  margin-top:auto; align-self:flex-start; }
.rpg-ml-shop .preband .prod .prow{ margin-top:0; }

/* ------------------------------------------------- CURATED SHELVES */
.rpg-ml-shop .curated{ display:grid; grid-template-columns:1fr 1fr; gap:14px; margin:8px 0 20px; }
.rpg-ml-shop .cur{ position:relative; overflow:hidden; border-radius:12px; padding:20px 22px;
  color:#fff; display:flex; gap:16px; align-items:center; border:1px solid rgba(0,0,0,.15);
  transition:transform .2s var(--ease-out); }
.rpg-ml-shop .cur:hover{ transform:translateY(-2px); }
.rpg-ml-shop .cur.ennie{ background:linear-gradient(120deg,#5a4310,#2a2008); }
.rpg-ml-shop .cur.quinns{ background:linear-gradient(120deg,#1e4b42,#0e241f); }
.rpg-ml-shop .cur .medal{ font-size:34px; line-height:1; }
.rpg-ml-shop .cur h3{ font-family:var(--serif); font-size:19px; color:#f6eeda; }
.rpg-ml-shop .cur p{ font-size:12.5px; color:rgba(255,255,255,.75); }

/* -------------------------------------------------------- PORTAL RAIL
   ROUND 35. The index card at the front of the drawer: three labelled rows of
   doors, above the toolbar, summarising the three bands that live below the
   grid. See includes/ml-portal.php for why it is a rail and not the bands
   themselves (1810px of navigation before the first product, measured).

   PARCHMENT ON PARCHMENT, one step lighter than the page and edged in the
   catalogue's own line colour — it has to read as furniture belonging to the
   stacks, not as a second toolbar. The real toolbar is `--card` with a shadow
   and sits directly under this; two shadowed cards in a row would read as one
   control panel and hide which of them is the thing you act on. */
.rpg-ml-shop .portalrail{ margin:18px 0 0; padding:14px 16px 12px;
  background:var(--paper-2); border:1px solid var(--line); border-radius:10px; }
.rpg-ml-shop .prhead{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  margin-bottom:10px; }
.rpg-ml-shop .preyebrow{ font-family:var(--mono); font-size:10.5px; letter-spacing:.12em;
  color:var(--brass); }
.rpg-ml-shop .prkick{ font-family:var(--serif); font-style:italic; font-size:13px;
  color:var(--muted); }
.rpg-ml-shop .prrow{ display:flex; align-items:center; gap:12px; padding:5px 0; }
.rpg-ml-shop .prrow+.prrow{ border-top:1px dashed var(--line); }
.rpg-ml-shop .prlabel{ flex:0 0 auto; width:132px; font-family:var(--mono); font-size:10.5px;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
/* SCROLL, don't wrap. Six chips plus "all" wrapped across three rows becomes
   eleven lines on a 360px phone and eats the screen the grid was meant to get;
   a rail that scrolls stays one line whatever is in it. */
.rpg-ml-shop .prdoors{ display:flex; gap:7px; align-items:center; min-width:0;
  overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch;
  padding-bottom:2px; }
.rpg-ml-shop .prdoors::-webkit-scrollbar{ display:none; }
.rpg-ml-shop .prchip{ flex:0 0 auto; display:inline-flex; align-items:center; gap:6px;
  background:var(--card); border:1px solid var(--line); border-radius:999px;
  padding:6px 11px; font-size:12.5px; color:var(--ink); text-decoration:none;
  transition:border-color .16s ease, background .16s ease, transform .16s ease; }
.rpg-ml-shop .prchip:hover,.rpg-ml-shop .prchip:focus-visible{ border-color:var(--brass);
  background:var(--paper); transform:translateY(-1px); }
/* The count is the specialist aura in miniature — "Fantasy 309" is a fact
   about this shop's depth. Tabular so the chips do not jitter in width. */
.rpg-ml-shop .prchip i{ font-style:normal; font-family:var(--mono); font-size:10.5px;
  font-variant-numeric:tabular-nums; color:var(--brass); }
.rpg-ml-shop .prchip--all{ background:transparent; border-style:dashed; color:var(--muted);
  font-family:var(--mono); font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; }

@media (max-width:720px){
  /* The label goes above its row: 132px of gutter out of a 360px screen leaves
     the chips 200px, which is one and a half of them. */
  .rpg-ml-shop .prrow{ display:block; padding:8px 0; position:relative; }
  .rpg-ml-shop .prlabel{ display:block; width:auto; margin-bottom:6px; }
  /* A FADE AT THE RIGHT EDGE, and it is not decoration. At 390px the third
     chip is cut mid-word by the scroller with nothing to say that it scrolls,
     which reads as a clipping bug rather than as an invitation. Shot at 390
     before adding it. Pointer-events off so it cannot eat a tap on the chip
     underneath it, and it stops short of the row's own padding so it never
     sits over the dashed rule between rows. */
  .rpg-ml-shop .prrow::after{ content:""; position:absolute; top:26px; right:0; bottom:10px;
    width:34px; pointer-events:none;
    background:linear-gradient(to right,rgba(240,232,212,0),var(--paper-2)); }
}

/* ------------------------------------------------------------ TOOLBAR */
.rpg-ml-shop .toolbar{ display:flex; justify-content:space-between; align-items:center; gap:12px;
  flex-wrap:wrap; background:var(--card); border:1px solid var(--line); border-radius:10px;
  padding:10px 14px; font-size:13px; color:var(--muted); margin:18px 0;
  position:sticky; z-index:30; box-shadow:0 6px 18px rgba(60,45,20,.07);
  /* The header is sticky too, so the toolbar parks directly under it rather
     than at the reference's fixed 64px — that number was drawn against a
     header this site condenses on scroll. */
  top:calc(var(--header-h,64px) - 58px); }
.rpg-ml-shop .tleft{ display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
.rpg-ml-shop .filterbtn{ display:inline-flex; align-items:center; gap:8px; background:var(--forest);
  color:#f3ead6; font-weight:700; font-size:13px; border-radius:8px; padding:9px 15px;
  min-height:38px; }
/* Round 15: filters can now come from a chip, the drawer or a shared URL, so
   the button carries the count. Gold on forest, because it is the one thing in
   the toolbar that changes what is below it. */
.rpg-ml-shop .filterbtn.on{ box-shadow:inset 0 0 0 1px var(--gold-hi); }
.rpg-ml-shop .filterbtn .fn{ display:inline-grid; place-items:center; min-width:19px; height:19px;
  padding:0 5px; border-radius:999px; background:var(--gold-hi); color:#231a07;
  font-family:var(--mono); font-size:10.5px; font-weight:700; line-height:1; }
.rpg-ml-shop .count{ font-family:var(--mono); font-size:11.5px; }
.rpg-ml-shop .clearfilters{ font-family:var(--mono); font-size:11px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--wine); text-decoration:underline;
  text-underline-offset:3px; }
.rpg-ml-shop .clearfilters:hover,
.rpg-ml-shop .clearfilters:focus-visible{ color:var(--ink); }
.rpg-ml-shop .tright{ display:flex; gap:10px; align-items:center; }
.rpg-ml-shop .sortform{ display:flex; gap:8px; align-items:center; margin:0; }
.rpg-ml-shop .sortsel{ border:1px solid var(--line); border-radius:8px; padding:8px 10px;
  font-size:13px; background:var(--paper); color:var(--ink); font-family:var(--sans);
  max-width:100%; }
.rpg-ml-shop .vtoggle{ display:inline-flex; border:1px solid var(--line); border-radius:8px;
  overflow:hidden; }
.rpg-ml-shop .vtoggle button{ padding:8px 11px; background:var(--paper); font-size:13px;
  color:var(--ink); min-height:36px; }
.rpg-ml-shop .vtoggle button.on{ background:var(--forest); color:#f3ead6; }

/* -------------------------------------------------- GRID & LIST VIEWS */
.rpg-ml-shop .grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:16px; }
.rpg-ml-shop .grid.list{ grid-template-columns:1fr; }
.rpg-ml-shop .grid.list .prod{ flex-direction:row; align-items:stretch; }
/* The reference releases the square ratio here (`aspect-ratio:auto`), which
   works in a mock where every cover is 300x300. Real covers run from 300x126
   to 300x444, so releasing it gives rows between 55px and 192px tall and the
   list stops reading as a list. Keeping the card's 1/1 crop makes every row
   the same height — the grid view already crops the same way. */
.rpg-ml-shop .grid.list .prod .pimg{ width:130px; flex:0 0 auto; }
.rpg-ml-shop .grid.list .prod .quick{ display:none; }
/* …except on a phone, where hiding it means the list view has no way to buy at
   all (round 30). The grid view's touch strip works here unchanged — a 130px
   thumb with a 108px button under it — so this only has to stop hiding it. */
@media (hover:none){
  .rpg-ml-shop .grid.list .prod .quick{ display:block; }
}
.rpg-ml-shop .grid.list .prod .pb{ flex:1; flex-direction:row; align-items:center; gap:18px;
  flex-wrap:wrap;
  /* The reference sets justify-content:space-between here. With three
     children in a row that is nearly 1200px wide it strands the title in the
     middle of an empty row and pushes the price to the far edge — the mock
     never shows the list view at full width. Same row, but the title takes the
     slack and only the price is pushed right. */
  justify-content:flex-start; }
.rpg-ml-shop .grid.list .prod .pb small{ flex:0 0 auto; min-width:130px; }
.rpg-ml-shop .grid.list .prod .pb h3{ flex:1 1 220px; margin:0; }
.rpg-ml-shop .grid.list .prod .prow{ flex:0 0 auto; margin-left:auto;
  /* The card's `margin-top:auto` pins the price to the bottom of a COLUMN;
     in this row it drops it to the bottom of the line box instead, which
     reads as a wrapped second line. */
  margin-top:0; }

.rpg-ml-shop .pagerow{ display:flex; justify-content:center; align-items:center; gap:8px;
  margin:26px 0 8px; font-family:var(--mono); font-size:12.5px; flex-wrap:wrap; }
.rpg-ml-shop .pagerow a,.rpg-ml-shop .pagerow span{ border:1px solid var(--line); border-radius:7px;
  padding:8px 13px; background:var(--card); color:var(--ink); min-width:40px; text-align:center; }
.rpg-ml-shop .pagerow .current,.rpg-ml-shop .pagerow a.on{ background:var(--forest);
  color:#f3ead6; border-color:var(--forest); }
/* paginate_links prints the ellipsis as a bare span; it is not a target */
.rpg-ml-shop .pagerow .dots{ border:0; background:none; padding:8px 4px; min-width:0; }

/* -------------------------------------------------------- EMPTY SHELF */
.rpg-ml-shop .emptyshelf{ background:var(--card); border:1px solid var(--line); border-radius:12px;
  padding:44px var(--gutter); text-align:center; margin:4px 0 22px; }
.rpg-ml-shop .emptyshelf .ey{ font-family:var(--mono); font-size:11.5px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--brass); }
.rpg-ml-shop .emptyshelf h2{ font-size:clamp(24px,3vw,32px); margin:8px 0 10px; }
.rpg-ml-shop .emptyshelf p{ color:var(--muted); font-family:var(--book); font-style:italic;
  max-width:52ch; margin:0 auto; }
.rpg-ml-shop .emptyshelf .ctas{ display:flex; gap:12px; flex-wrap:wrap; justify-content:center;
  margin-top:22px; }

/* --------------------------------- CARD SHOP — the fortune-teller's corner */
.rpg-ml-shop .cardshop{ position:relative; overflow:hidden; border-radius:14px; padding:22px 24px;
  display:flex; gap:22px; align-items:center; flex-wrap:wrap; margin:0 0 22px;
  font-size:13.5px; color:#efe2d2; border:1px solid rgba(200,162,74,.35);
  background:radial-gradient(90% 140% at 12% 0%,#4a2e44,#241326 60%,#160b18);
  box-shadow:0 16px 36px rgba(20,8,22,.35); }
.rpg-ml-shop .cardshop::before{ content:""; position:absolute; inset:7px;
  border:1px solid rgba(200,162,74,.25); border-radius:10px; pointer-events:none; }
.rpg-ml-shop .cardshop .txt{ flex:1; min-width:230px; position:relative; z-index:2; }
.rpg-ml-shop .cardshop .ey{ font-family:var(--mono); font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; color:#d8a6e0; }
.rpg-ml-shop .cardshop b{ font-family:var(--serif); font-size:19px; color:#f6e8d0; display:block;
  margin:3px 0 2px; }
.rpg-ml-shop .cardshop p{ color:#cbb3c7; font-family:var(--book); font-style:italic; font-size:13px; }
.rpg-ml-shop .cardshop .btn{ position:relative; z-index:2; }
/* fanned tarot trio */
.rpg-ml-shop .tarotfan{ position:relative; width:120px; height:96px; flex:0 0 auto; z-index:2; }
.rpg-ml-shop .tcard{ position:absolute; bottom:0; width:52px; height:82px; border-radius:6px;
  background:linear-gradient(160deg,#2a1631,#170b1c); border:1.5px solid var(--gold);
  display:grid; place-items:center; font-size:20px; color:#e8c07a;
  box-shadow:0 8px 16px rgba(0,0,0,.45); transition:transform .25s var(--ease-out); }
.rpg-ml-shop .tcard::before{ content:""; position:absolute; inset:4px;
  border:1px solid rgba(200,162,74,.4); border-radius:4px; }
.rpg-ml-shop .tcard.t1{ left:0; transform:rotate(-14deg); }
.rpg-ml-shop .tcard.t2{ left:34px; transform:rotate(0) translateY(-7px); z-index:2; }
.rpg-ml-shop .tcard.t3{ left:68px; transform:rotate(14deg); }
.rpg-ml-shop .cardshop:hover .tcard.t1{ transform:rotate(-20deg) translateY(-4px); }
.rpg-ml-shop .cardshop:hover .tcard.t2{ transform:translateY(-13px); }
.rpg-ml-shop .cardshop:hover .tcard.t3{ transform:rotate(20deg) translateY(-4px); }

/* ---------------------------------------------------------- DEALS BAND */
.rpg-ml-shop .deals{ position:relative; overflow:hidden; color:var(--text-inverse);
  background:linear-gradient(120deg,#3a1c14,#1d0f0b);
  border-top:1px solid #0a1c14; border-bottom:1px solid #0a1c14; }
.rpg-ml-shop .deals .sec{ position:relative; z-index:2; }
.rpg-ml-shop .deals .sechead h2{ color:#f6eeda; }
.rpg-ml-shop .deals .sechead .k{ color:#d9beb2; }
.rpg-ml-shop .deals .rail{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; }
.rpg-ml-shop .deals .prod{ color:var(--ink); }

/* ------------------------------------------------------ FILTER DRAWER */
.rpg-ml-shop .fdx{ position:fixed; inset:0; background:rgba(20,14,4,.5); opacity:0;
  visibility:hidden; transition:.3s; z-index:64; }
.rpg-ml-shop .fdx.open{ opacity:1; visibility:visible; }
.rpg-ml-shop .fdrawer{ position:fixed; inset:0 auto 0 0; width:330px; max-width:88vw;
  background:var(--paper); z-index:65; transform:translateX(-103%); transition:transform .3s;
  display:flex; flex-direction:column; }
.rpg-ml-shop .fdrawer.open{ transform:none; }
.rpg-ml-shop .fdrawer .fh{ display:flex; justify-content:space-between; align-items:center;
  padding:16px 18px; border-bottom:1px solid var(--line); background:var(--card); }
.rpg-ml-shop .fdrawer .fh h3{ font-size:17px; }
.rpg-ml-shop .fdrawer .fx{ font-size:22px; line-height:1; color:var(--ink);
  width:40px; height:40px; display:grid; place-items:center; }
.rpg-ml-shop .fdrawer .fb{ flex:1; overflow-y:auto; padding:6px 18px 18px;
  -webkit-overflow-scrolling:touch; }
.rpg-ml-shop .fgroup{ border-bottom:1px solid var(--line); padding:12px 0; }
.rpg-ml-shop .fgroup h4{ font-family:var(--mono); font-size:11px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--brass); margin-bottom:9px; }
/* The reference draws checkboxes; each facet here is a real archive URL, so
   the row is an anchor wearing a checkbox. Same shape, but shareable and
   working without JavaScript. */
.rpg-ml-shop .frow{ display:flex; gap:9px; align-items:center; font-size:13.5px;
  padding:7px 0; color:var(--ink); min-height:38px; }
.rpg-ml-shop .frow:hover .flabel{ color:var(--brass); }
.rpg-ml-shop .frow .fbox{ width:15px; height:15px; flex:0 0 auto; border-radius:3px;
  border:1.5px solid var(--brass); background:var(--card); position:relative; }
.rpg-ml-shop .frow.on .fbox{ background:var(--forest); border-color:var(--forest); }
.rpg-ml-shop .frow.on .fbox::after{ content:""; position:absolute; left:4px; top:0; width:5px;
  height:10px; border:solid #f3ead6; border-width:0 2px 2px 0; transform:rotate(42deg); }
.rpg-ml-shop .frow small{ margin-left:auto; font-family:var(--mono); font-size:10.5px;
  color:var(--muted); }
.rpg-ml-shop .fdrawer .ff{ padding:14px 18px; border-top:1px solid var(--line);
  background:var(--card); display:flex; gap:10px;
  padding-bottom:calc(14px + env(safe-area-inset-bottom)); }

/* --------------------------------- CARD CATALOGUE BAND (shared shapes) */
.rpg-ml-shop .sysband{ position:relative; overflow:hidden; background:var(--forest);
  color:var(--text-inverse); border-top:1px solid #0a1c14; margin-top:8px; }
/* ROUND 11 — Kevin: *"stray white gap between 'The hoard must move' (dark band)
   and 'Go straight to your system' (green band) — a sliver of page background
   leaks between bands."* Exactly 8px of it, and it is the margin above. That
   margin is right where this band follows the CATALOGUE — a grid of cards on
   parchment, which wants air before a full-bleed green band starts — and wrong
   where it follows another band, because two bands with a gap between them are
   not two bands, they are two boxes. The seam is the `border-top` above; it
   needs nothing else. Written as an adjacency rule rather than by deleting the
   margin, because the deals band is data-gated (`rpg_ml_archive_deals()`) and
   on a shop with nothing on sale the catalogue is what comes before. */
.rpg-ml-shop .deals + .sysband{ margin-top:0; }
.rpg-ml-shop .sysband .sec{ position:relative; z-index:2; }
.rpg-ml-shop .sysband .sechead h2{ color:#f6eeda; }
.rpg-ml-shop .sysband .sechead .k{ color:#c6cabb; }
.rpg-ml-shop .cat{ display:grid; grid-template-columns:repeat(4,1fr); gap:13px; }
.rpg-ml-shop .cat .card{ position:relative; color:var(--ink); border-radius:8px;
  padding:15px 15px 15px; border:1px solid rgba(0,0,0,.14); overflow:hidden; min-height:92px;
  background:linear-gradient(#f3ead6,#e9dcc0);
  box-shadow:0 4px 0 #c9b48a,0 12px 22px rgba(0,0,0,.22);
  transition:transform .2s var(--ease-out), box-shadow .2s; }
.rpg-ml-shop .cat .card:hover{ transform:translateY(-6px);
  box-shadow:0 10px 0 #c9b48a,0 22px 34px rgba(0,0,0,.3); }
.rpg-ml-shop .cat .card.has-cover{ padding-right:76px; }
.rpg-ml-shop .cat .card .cn{ font-family:var(--mono); font-size:10px; color:var(--brass); }
.rpg-ml-shop .cat .card b{ font-family:var(--serif); font-size:18px; display:block; margin:4px 0 2px; }
.rpg-ml-shop .cat .card small{ font-family:var(--mono); font-size:11px; color:var(--muted); }
.rpg-ml-shop .cat .card .arrow{ position:absolute; top:15px; right:14px; color:var(--brass);
  opacity:0; transform:translateX(-4px); transition:.2s; }
.rpg-ml-shop .cat .card:hover .arrow{ opacity:1; transform:none; }
.rpg-ml-shop .cat .card .knob{ position:absolute; left:50%; bottom:7px; transform:translateX(-50%);
  width:26px; height:6px; border-radius:4px; background:linear-gradient(#c79a4e,#9a742f);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4); }
.rpg-ml-shop .cat .card.has-cover .knob{ left:calc(50% - 30px); }
/* cover peeking out of the drawer */
.rpg-ml-shop .cat .card .thumb{ position:absolute; right:10px; top:12px; width:56px; height:72px;
  border-radius:3px; overflow:hidden; background:var(--forest);
  box-shadow:0 6px 12px rgba(0,0,0,.28); transform:rotate(4deg);
  transition:transform .2s var(--ease-out); }
.rpg-ml-shop .cat .card .thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.rpg-ml-shop .cat .card:hover .thumb{ transform:rotate(0) translateY(-4px); }

/* ------------------------------------ THE SHELF DOORS (round 30 item 2) -----
   "By how you play" and "By mood" were two rows of pills at the top of the
   page. They are two card grids here, in the system drawers' own language, so
   there is one card to learn and three shelves wearing it.

   THE BANDS ALTERNATE. Three `.sysband`s in a row are three greens of the same
   value, and the two seams between them vanish — the page reads as one 1400px
   band with headings inside it. The middle one drops to `--forest-deep`, which
   is the header/mega ground, so each shelf has an edge. */
.rpg-ml-shop .sysband--deep{ background:var(--forest-deep); }
.rpg-ml-shop .sysband + .sysband{ margin-top:0; }
/* A door always has its art plate, so `.has-cover`'s right inset is the only
   layout here — but the count line has to clear the plate's bottom edge on the
   narrowest card, and a system name is one word where "Post-Apocalyptic" is
   sixteen characters with a hyphen the browser may or may not break on. */
.rpg-ml-shop .cat.doors .card{ min-height:104px; }
/* A cover is a book and wants a book's proportions; a scene is an emblem and
   wants a square-ish plate. Narrower also buys the label 14px, which is the
   difference between "Post-Apocalyptic" fitting on one line at 1024 and not —
   measured, because it did not before this. */
.rpg-ml-shop .cat.doors .card.has-cover{ padding-right:62px; }
.rpg-ml-shop .cat.doors .card .thumb.scene{ width:48px; height:60px; }
/* `overflow-wrap` is the last-resort guard round 22 put site-wide; deliberately
   NO `hyphens:auto`, which would let the browser cut "Apocalyptic" wherever it
   liked and hide the cut behind a soft hyphen — a real mid-word break that
   looks deliberate. Without it the only break points are the space and the
   term's own hyphen, both of which are correct places to break. */
.rpg-ml-shop .cat.doors .card b{ font-size:17px; line-height:1.15;
  overflow-wrap:break-word; }
/* The gold underline the brief asks for: a short rule under the name, drawn on
   the card rather than under the text, so it holds its length whether the name
   wrapped to one line or two. */
.rpg-ml-shop .cat.doors .card b::after{ content:""; display:block; width:26px; height:2px;
  margin:6px 0 0; border-radius:2px; background:linear-gradient(90deg,var(--gold-hi),transparent);
  transition:width .2s var(--ease-out); }
.rpg-ml-shop .cat.doors .card:hover b::after,
.rpg-ml-shop .cat.doors .card:focus-visible b::after{ width:44px; }
/* The scene plate. Same slot and same tilt as a system drawer's cover, so the
   three grids line up; the forest ground is what every scene is drawn to be lit
   against (see rpg_ml_shelf_scene()). */
.rpg-ml-shop .cat.doors .card .thumb.scene{ background:var(--forest-deep);
  border:1px solid rgba(220,183,95,.28); }
.rpg-ml-shop .sysband--deep .cat.doors .card .thumb.scene{ background:var(--forest); }
.rpg-ml-shop .cat.doors .card .thumb.scene svg{ width:100%; height:100%; display:block; }

@media (prefers-reduced-motion:reduce){
  .rpg-ml-shop .cat.doors .card b::after{ transition:none; }
}

/* --------------------------------------------------------- BREAKPOINTS */
@media (max-width:900px){
  .rpg-ml-shop .hoard{ width:100%; opacity:.32; }
  /* Below 900 the scene spans the whole hero and sits at .32 — so its click
     targets would be invisible ones lying under the headline. The heap and the
     dragon hand their pointer events back; on a touch screen there is no hover
     to hint at them anyway. */
  /* Round 9 renamed every target in this list. `.mound` became three `.hp`
     mounds, the dragon lost its `.wing` and gained a `.neck`, a `.jaw` and
     `.spike`s, and the lich's hand arrived with two of its own — and a stale
     selector here fails SILENTLY, leaving an invisible click target under the
     headline, which is the exact bug this rule exists to prevent. */
  .rpg-ml-shop .hoard .hp,
  .rpg-ml-shop .hoard .pr.lich .grip,
  .rpg-ml-shop .hoard .pr.lich .dstone,
  .rpg-ml-shop .hoard .drake .dk,
  .rpg-ml-shop .hoard .drake .neck,
  .rpg-ml-shop .hoard .drake .jaw,
  .rpg-ml-shop .hoard .drake .spike,
  .rpg-ml-shop .hoard .drake .horn{ pointer-events:none; cursor:default; }
  /* The hero is content-height here, so the 330px the cave was drawn in is
     gone. `--pileh` and the dragon are already `clamp`ed against the viewport,
     so both shrink with it rather than being cropped by it. */
  .rpg-ml-shop .shophero{ min-height:0; }
  .rpg-ml-shop .preband .rail{ grid-template-columns:repeat(2,1fr); }
  .rpg-ml-shop .cat{ grid-template-columns:repeat(2,1fr); }
  .rpg-ml-shop .curated{ grid-template-columns:1fr; }
  .rpg-ml-shop .deals .rail{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:560px){
  .rpg-ml-shop .deals .rail,.rpg-ml-shop .preband .rail{ grid-template-columns:1fr 1fr; }
  /* Two 210px-minimum columns don't fit 320px; let the grid go to one. */
  .rpg-ml-shop .grid{ grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); }
  /* Sticky + a wrapping toolbar eats most of a small screen. */
  .rpg-ml-shop .toolbar{ position:static; }
  .rpg-ml-shop .tright{ width:100%; justify-content:space-between; }
  .rpg-ml-shop .sortform{ flex:1; }
  .rpg-ml-shop .sortsel{ width:100%; }
  .rpg-ml-shop .shophero{ padding-block:36px 34px; }
}

@media (prefers-reduced-motion:reduce){
  .rpg-ml-shop *,.rpg-ml-shop *::before,.rpg-ml-shop *::after{
    animation:none!important; transition:none!important; }
}

/* The catalogue drawers, one per row on a phone — the shop archive's copy of
   the front page's band, and it inherited the same fault. Measured in round
   22: "Mothership" is 107px in this face, while a two-column card gives its
   label 45px at 320 and 100px at 430, because `.has-cover` reserves 76px for
   the cover. So the longest system names have been breaking mid-word at every
   phone width since the band was built — over three lines at 320.

   Same reasoning as rpg-home 2.10.0, and the same deliberate deviation from
   the reference, which goes 4 columns to 2 and never to 1. Last in the file
   because the 2-column rule is itself inside a later media query and equal
   specificity is decided by source order. */
@media (max-width:479px){
  .rpg-ml-shop .cat{ grid-template-columns:1fr; }
  /* …but the SHELF DOORS stay two up — Kevin's ask, and right: a system name
     is a proper noun you scan for, a mood is a shelf you browse, and twelve
     one-per-row moods is a list, not a shelf.

     The side plate is what makes that impossible, and the arithmetic is the
     same one round 22 did for "Mothership": a 320px viewport gives a 2-column
     card 127px, and `.has-cover` reserves 76px of it, leaving 36px for
     "Post-Apocalyptic". So on a phone the plate goes ABOVE the label instead
     of beside it and the name gets the whole card — 97px, which fits every
     term this catalogue has once `hyphens:auto` is allowed to break the
     hyphenated ones where their own hyphen already is. */
  .rpg-ml-shop .cat.doors{ grid-template-columns:repeat(2,1fr); gap:10px; }
  .rpg-ml-shop .cat.doors .card,
  .rpg-ml-shop .cat.doors .card.has-cover{ padding:11px 11px 17px; min-height:0; }
  /* `display:block` is load-bearing, not tidiness: `.thumb` is a <span> with no
     display of its own, so it is only a box at all because the desktop rule
     makes it `position:absolute`. Taking that away hands it back to inline
     layout, where width and height are ignored — the plate sized itself to the
     SVG and came out 115x304 in a 139px card. */
  .rpg-ml-shop .cat.doors .card .thumb.scene{ display:block; position:static;
    width:100%; height:70px; transform:none; margin:0 0 9px; border-radius:4px;
    box-shadow:none; }
  .rpg-ml-shop .cat.doors .card:hover .thumb.scene{ transform:none; }
  .rpg-ml-shop .cat.doors .card b{ font-size:15px; }
  .rpg-ml-shop .cat.doors .card.has-cover .knob{ left:50%; }
}
