/* rx-board.css — the outfit board: the canvas and its two gutters, the board's two tiers of tiles,
   the callouts and their lines, the numbered pins and the phone's pieces row that explains them,
   the hover tip, the credit line, and the board's lit / dim / busy states. Painted by rx-board.js.

   THE RULES THIS FILE KEEPS (BUILD_SPEC §0.2, 05 §16–§17):
   · No hex literal. Every colour is a token, a black or white alpha, or rgba(127,127,127,·) for a
     neutral rim, so a future theme only re-points tokens; there is no theme selector here at all.
     The only real colours on the board are the garments', and they arrive as inline styles that
     rx-core's face() writes after an isHex() check.
   · Every :hover that moves anything sits inside @media (hover:hover) and (pointer:fine): a touch
     browser fires :hover on tap and leaves it stuck, which here would leave one tile zoomed and the
     rest of the board dimmed after the drawer closed.
   · Every transition and animation is off, or lands on its finished state, under
     prefers-reduced-motion. leorve.css already zeroes every duration there; the explicit end
     states below are for the places where a START state would otherwise hide something.
   · Every class here that sets `display` on an element that can carry `hidden` has its own
     [hidden]{display:none!important} rule (08 #1). An author display rule beats the UA's [hidden]
     rule, and a "hidden" tip that is still laid out is a box that swallows the click under it.
   · The --rx-* values are rx-core.css's tokens (05 §1); each carries its 05 value as a fallback so
     the board degrades to the designed motion, not to none, if a token is ever renamed. */

/* ═══ 1. THE CANVAS: gutter · board · gutter (05 §4.4) ═══════════════════════════════════════
   BELOW 768 THERE ARE NO GUTTERS: the board is the full content width and the annotations become
   numbered pins with the pieces row under the board as their legend (R22). From 768 the callouts
   hang in a gutter either side — 150px or more until 1199, where the board is centred at up to
   560px; 124px from 1200, where the stage is eight of twelve columns and the board takes what the
   gutters leave (504px at 1440). The board's sizes at each width are 05 §4.4's table. */
.rx-board-host{position:relative;min-width:0;touch-action:pan-y}
.rx-canvas{position:relative;display:grid;grid-template-columns:minmax(0,1fr);
  -webkit-user-select:none;user-select:none}
.rx-gutter{display:none}
@media (min-width:768px){
  .rx-canvas{grid-template-columns:minmax(150px,1fr) minmax(0,560px) minmax(150px,1fr)}
  .rx-gutter{display:block;position:relative;min-width:0}
}
@media (min-width:1200px){
  .rx-canvas{grid-template-columns:124px minmax(0,1fr) 124px}
}

/* THE SWIPE (05 §14). While a finger drags, the canvas follows it with a transform and nothing
   else, so the drag costs no layout; letting go of a short drag returns it over 240ms on the house
   curve. The one curve everywhere, no overshoot (05 §1). */
.rx-canvas.is-drag{cursor:grabbing}
.rx-canvas.is-return{transition:transform 240ms var(--ease)}
.rx-board-host img{-webkit-user-drag:none}

/* ═══ 2. THE BOARD: two tiers, one ratio at several scales (05 §4.4) ═════════════════════════
   The garments are the main tier — the lead, then the layer, top and bottom that support it — and
   the footwear and jewellery are the detail tier under them. EVERY tile keeps the frame's native
   4:5 and nothing is cropped (CLAUDE.md's object-position trap); hierarchy comes from SIZE.
   The lead is 1.32 of a support so the outfit reads before the earrings; a lone garment is two
   thirds of the board, never all of it. */
.rx-board{position:relative;display:grid;row-gap:10px;align-content:start;min-width:0}
.rx-board-main{display:grid;grid-template-columns:1.32fr 1fr;column-gap:10px;align-items:start}
.rx-board-main[data-g="1"]{grid-template-columns:minmax(0,66%)}
.rx-board-main[data-g="3"]{grid-template-columns:1.5fr 1fr 1fr}
/* THE BROKEN BASELINE (house precedent, the app's .lk-c margin-top:26px): a lead and a support
   whose tops align read as a row of equal things; dropped a little, the support reads as worn WITH
   the lead. Keyed on the ROLE, not on nth-child, so it is the supports that drop whatever order a
   future model lists them in. In a three-garment row BOTH supports drop: that keeps them a pair
   beside the lead, and it leaves a clear band above the middle tile, which is the only way its
   callout line can reach it without crossing a neighbour (rx-board.js routeFor, the TOP route). */
.rx-board-main > .rx-tile.is-support{margin-top:clamp(14px,2.4vw,26px)}
/* DETAILS NEVER GROW: four equal columns whatever the count, so a lone pair of earrings stays a
   quarter of the board instead of becoming its largest picture. */
.rx-board-detail{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));column-gap:10px}
@media (max-width:767.98px){
  .rx-board,.rx-board-main,.rx-board-detail{gap:8px}
}

/* A RULE ABOUT THE WHOLE LOOK (occasion, formality, season) frames the board rather than picking a
   tile (05 §6.2), and dims nothing: no single tile is more "about the occasion" than another. */
.rx-board::after{content:"";position:absolute;inset:-8px;border:1px solid var(--ink);
  border-radius:calc(var(--r) + 8px);pointer-events:none;opacity:0;transform:scale(1.015);
  transition:opacity var(--rx-d2,240ms) var(--ease),transform var(--rx-d2,240ms) var(--ease)}
.rx-board.is-lit-all::after{opacity:1;transform:none}

/* ═══ 3. THE TILE (05 §6.1–§6.2) ═════════════════════════════════════════════════════════════
   The whole tile is a button. Its face is rx-core's (.rx-face: the photograph or the colour card,
   one box and one rim for both); this file owns the tile around it and what the tile's states do
   to the face. EVERY DESCENDANT IGNORES THE POINTER, so the button itself is what the pointer hits:
   elementFromPoint at a tile's centre returns the tile (the binding harness checks a closed drawer
   that way), a click's target is the tile and not its <img>, and a long-press on a phone does not
   offer to save a photographer's picture. */
.rx-tile{position:relative;display:grid;gap:8px;align-content:start;min-width:0;margin:0;padding:0;
  border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer;
  -webkit-tap-highlight-color:transparent;transition:opacity var(--rx-d2,240ms) var(--ease)}
.rx-tile *{pointer-events:none}
.rx-cap{display:grid;gap:2px;min-width:0;padding:0 2px}
.rx-cap b{font:500 13.5px/1.35 var(--body);color:var(--ink);overflow-wrap:anywhere}
.rx-cap span{font:400 12.5px/1.35 var(--body);color:var(--ink-dim)}
/* THE CAPTION CARRIES THE ROLE TOO. The lead's name is a step heavier, because the size of its
   picture already says it is the look and the words should agree.
   A DETAIL TILE NAMES ITS COLOUR TOO (V PR-16). Its colour line used to be hidden on the theory
   that the card shows the colour — but a near-black drawing of plum bangles and a greyscale tikka
   photograph do not, and "plum" appeared nowhere on the board. One line, 12px, cut with an
   ellipsis rather than wrapped, so a quarter-width tile still reads as a caption, not a paragraph. */
.rx-tile.is-lead .rx-cap b{font-weight:600;font-size:14px}
.rx-tile.is-detail .rx-cap b{font-size:12.5px}
.rx-tile.is-detail .rx-cap span{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* THE ZOOM MOVES THE MEDIA INSIDE THE FACE, NEVER THE FACE'S BOX (05 §6.2): the face clips it, so
   nothing reflows and no neighbour is nudged. Written against the face's two children, img and
   .rx-fill, so a photograph and a colour card zoom identically — the locked "hero visual": a colour
   card is a first-class state and hovers like one. The advised-colour dot is not scaled. */
.rx-tile .rx-face > img,.rx-tile .rx-face > .rx-fill{transform:scale(1);
  transition:transform var(--rx-d2,240ms) var(--ease)}

/* LIT AND DIM. The tile being talked about keeps full strength, an ink outline 3px off its face
   and a slighter zoom; everything else on the board steps back to .4. Washing toward white keeps
   the garments' hue honest — a darkening scrim would shift every colour on the board. */
.rx-board.has-lit .rx-tile:not(.is-lit){opacity:var(--rx-dim,.4)}
.rx-tile.is-lit .rx-face{outline:1px solid var(--ink);outline-offset:3px}
.rx-tile.is-lit .rx-face > img,.rx-tile.is-lit .rx-face > .rx-fill{transform:scale(var(--rx-zoom-lit,1.03))}

/* THE POINTER'S OWN ZOOM COMES AFTER THE LIT ONE, ON PURPOSE. A hovered tile is also lit (its own
   hover lights it), and the two selectors weigh the same, so whichever is later wins: written
   above, the lit 1.03 silently replaced the 1.04 under the pointer. Measured, not assumed. */
@media (hover:hover) and (pointer:fine){
  .rx-tile:hover .rx-face > img,.rx-tile:hover .rx-face > .rx-fill{transform:scale(var(--rx-zoom,1.04))}
}

/* Focus rings the FACE, not the caption, in ink (leorve.css:529 rings anything inside a .hero in
   white, which is one reason this room never uses that class). */
.rx-tile:focus-visible{outline:none}
.rx-tile:focus-visible .rx-face{outline:2px solid var(--ink);outline-offset:3px}
.rx-tile:active .rx-face{transform:scale(var(--rx-press,.98));transition-duration:var(--rx-dp,90ms)}

/* UNDER REDUCED MOTION NOTHING SCALES. The zoom tokens go to 1 for the board alone, which turns off
   the hover zoom and the lit zoom in one place without writing a second :hover rule outside the
   hover gate; the lit OUTLINE and the dimming still say which tile is meant, instantly. */
@media (prefers-reduced-motion:reduce){
  .rx-board-host{--rx-zoom:1;--rx-zoom-lit:1}
  .rx-board::after{transform:none}
  .rx-tile:active .rx-face{transform:none}
}

/* ═══ 4. THE NUMBERED PIN (<768) — 05 §6.3, as a span (BUILD_SPEC B3) ══════════════════════════
   An ink disc with a white numeral and a 2px card ring, so it reads on any photograph and on any
   colour card. It takes no pointer: it is a label for the tile, and the tile is the control.
   Position comes inline from rx-board.js (a percentage margin, so the anchor lands on the 4:5 face
   whatever the caption under it wraps to). */
.rx-pin{position:absolute;top:0;z-index:4;display:grid;place-items:center;width:22px;height:22px;
  border-radius:50%;background:var(--ink);color:var(--on-ink);font:600 11px/1 var(--body);
  font-variant-numeric:tabular-nums;box-shadow:0 0 0 2px var(--card);pointer-events:none}
@media (min-width:768px){
  .rx-pin{display:none}
}

/* ═══ 5. THE CALLOUTS AND THEIR LINES (≥768) — 05 §6.3 ════════════════════════════════════════
   A callout's label always shows; its explanation opens downward on hover, focus or a pinning
   click, so opening never moves the line, which leaves the label at the height of its first line.
   The open uses grid-template-rows 0fr → 1fr, the house's own .honesty-p technique: it animates to
   the content's real height with no measured max-height to go stale. */
.rx-ann{position:absolute;left:0;right:0;top:0;display:grid;gap:4px;align-content:start;
  min-height:44px;margin:0;padding:6px 0;border:0;border-radius:6px;background:none;color:inherit;
  font:inherit;cursor:pointer;transition:opacity var(--rx-d2,240ms) var(--ease)}
.rx-ann[hidden]{display:none!important}
.rx-ann *{pointer-events:none}
.rx-gutter-l .rx-ann{text-align:right;padding-right:28px}
.rx-gutter-r .rx-ann{text-align:left;padding-left:28px}
.rx-ann-k{font:600 13px/1.3 var(--body);letter-spacing:.005em;color:var(--ink);text-wrap:balance}
.rx-ann-hits{font:600 10px/1.4 var(--body);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-dim)}
.rx-ann-d{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--rx-d2,240ms) var(--ease)}
/* The clipped row. Its width is --rx-ann-w, which rx-board.js measures when the callout opens: up
   to 240px, growing OUTWARD from the gutter (leftward in the left gutter, by a negative margin,
   rightward in the right one), so the explanation is set at a readable measure instead of fifteen
   lines in a 96px column, and never over the garments. */
.rx-ann-d > span{min-height:0;overflow:hidden;width:var(--rx-ann-w,auto);max-width:none}
.rx-gutter-l .rx-ann-d > span{margin-left:calc(100% - var(--rx-ann-w,100%))}
/* The card the explanation sits in: a white plane on white paper is only its hairline (leorve.css
   §1), and its text is set LEFT whichever gutter it hangs from — a ragged left edge is how a
   paragraph stops being readable. */
.rx-ann-d > span > span{display:block;margin-top:4px;padding:10px 12px;border:1px solid var(--line-2);
  border-radius:12px;background:var(--card);box-shadow:var(--shadow-xs);text-align:left;
  font:400 12.5px/1.5 var(--body);color:var(--ink-2);text-wrap:pretty}
/* An open explanation can run past the label beneath it, so the open callout rises above it. */
.rx-ann[aria-expanded="true"]{z-index:5}
.rx-ann[aria-expanded="true"] .rx-ann-d{grid-template-rows:1fr}
.rx-ann.is-on .rx-ann-k{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.rx-ann:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* THE LINES. 1px in both states, so the board stays editorial and never heavy; --line-3 at
   rest clears WCAG 1.4.11's 3:1 for graphics on white (3.55:1) and goes ink when what it points at
   is lit. The layer never takes the pointer, so a line drawn over a gap cannot block a tile. */
.rx-ann-lines{position:absolute;inset:0;z-index:3;width:100%;height:100%;overflow:visible;
  pointer-events:none}
@media (max-width:767.98px){
  .rx-ann-lines{display:none}
}
.rx-ann-ln{fill:none;stroke:var(--line-3);stroke-width:1;vector-effect:non-scaling-stroke;
  shape-rendering:geometricPrecision;
  transition:stroke var(--rx-d2,240ms) var(--ease),opacity var(--rx-d2,240ms) var(--ease)}
.rx-ann-pt{fill:var(--card);stroke:var(--ink);stroke-width:1;vector-effect:non-scaling-stroke;
  transition:fill var(--rx-d2,240ms) var(--ease),opacity var(--rx-d2,240ms) var(--ease)}
.rx-ann-ln.is-on{stroke:var(--ink)}
.rx-ann-pt.is-on{fill:var(--ink)}
/* A CALLOUT UNDER ANOTHER'S OPEN CARD steps back with its line and dot (rx-board.js
   coverSiblings), so the card never sits half over a label. Only ever set by script while a card
   is open, and lifted when it closes: no state of the stylesheet alone hides a callout. */
.rx-ann.is-covered,.rx-ann-ln.is-covered,.rx-ann-pt.is-covered{opacity:0}

/* THE DRAW-IN, ONCE PER VISIT (05 §6.3 rule 6). Every path carries pathLength="1", so a dash of 1
   offset by 1 is "not yet drawn" whatever the line's real length, and the animation runs to 0.
   Fill-mode backwards holds the undrawn state through each line's stagger delay and lets go at
   the end, where the plain dash of 1 is the whole line. Gated to no-preference: under reduced
   motion the class has no effect and the lines are simply there. */
@media (prefers-reduced-motion:no-preference){
  .rx-ann-lines.is-drawing .rx-ann-ln{stroke-dasharray:1;
    animation:rx-ann-draw var(--rx-dr,600ms) var(--ease) backwards}
  .rx-ann-lines.is-drawing .rx-ann-pt{animation:rx-ann-dot var(--rx-d2,240ms) var(--ease) backwards}
}
@keyframes rx-ann-draw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@keyframes rx-ann-dot{from{opacity:0}to{opacity:1}}

/* ═══ 6. THE CREDIT LINE ═════════════════════════════════════════════════════════════════════
   Under the board, at the board's own width: centred between the gutters it is as wide as the
   pictures it credits, which is what makes it read as their caption rather than as page fine print. */
.rx-credit{margin:14px 0 0;font:400 12px/1.5 var(--body);color:var(--ink-dim);text-wrap:pretty}
@media (min-width:768px){
  .rx-credit{width:min(560px,calc(100% - 300px));margin-left:auto;margin-right:auto}
}
@media (min-width:1200px){
  .rx-credit{width:calc(100% - 248px)}
}

/* ═══ 7. THE PIECES ROW (<768): the swipeable list of pieces, and the pins' legend (R22) ══════
   One card per piece in board order, scrolled sideways with snap, so a phone gets the brief's
   swipeable product list and the meaning of every numbered pin in the same row. From 768 the
   callouts say all of this beside the board, so the row is not laid out at all. */
.rx-pieces-host{min-width:0}
@media (min-width:768px){
  .rx-pieces-host{display:none}
}
.rx-pieces{display:flex;gap:10px;margin:0;padding:2px 2px 8px;list-style:none;overflow-x:auto;
  overscroll-behavior-x:contain;scroll-snap-type:x mandatory;scroll-padding:0 2px;scrollbar-width:none}
.rx-pieces::-webkit-scrollbar{display:none}
.rx-pieces > li{display:flex;flex:0 0 auto;scroll-snap-align:start}
/* A WHITE CARD ON WHITE PAPER IS ONLY ITS HAIRLINE (leorve.css §1), so --line-2 is not optional. */
.rx-pc{display:grid;grid-template-columns:56px minmax(0,1fr);column-gap:12px;align-items:start;
  width:min(74vw,272px);min-height:44px;margin:0;padding:10px;border:1px solid var(--line-2);
  border-radius:var(--r);background:var(--card);color:inherit;font:inherit;text-align:left;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color var(--rx-d1,180ms) var(--ease),transform var(--rx-d1,180ms) var(--ease)}
.rx-pc *{pointer-events:none}
.rx-pc > .rx-face{width:56px;border-radius:10px}
/* NO NAME INSIDE THE 56px THUMB. The fallback colour field (drawn when rx-flats.js fails to load)
   prints the piece's name, and rx-core.css re-shows a NEUTRAL card's name in its small-container
   query at 0,3,0 — so the neutral selector is spelled out to beat it, as rx-drawer.css does for
   .rx-alt-face. The name is already the row's own bold first line 12px to the right. */
.rx-pc .rx-fill-name,.rx-pc .rx-fill.is-neutral .rx-fill-name{display:none}
.rx-pc > .rx-face + span{display:grid;gap:2px;min-width:0}
.rx-pc b{display:flex;align-items:center;gap:6px;font:600 13.5px/1.35 var(--body);color:var(--ink)}
.rx-pc em{font:400 12.5px/1.35 var(--body);font-style:normal;color:var(--ink-dim)}
.rx-pc strong{margin-top:6px;font:600 13px/1.3 var(--body);color:var(--ink)}
/* Four lines, then the drawer: the full sentence is one tap away, and a row of cards seven lines
   tall would push the actions under the board off the first screen. */
.rx-pc small{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;overflow:hidden;
  font:400 12.5px/1.45 var(--body);color:var(--ink-2)}
.rx-pc-n{display:inline-grid;flex:0 0 20px;place-items:center;width:20px;height:20px;border-radius:50%;
  background:var(--ink);color:var(--on-ink);font:600 11px/1 var(--body);font-variant-numeric:tabular-nums}
@media (hover:hover) and (pointer:fine){
  .rx-pc:hover{border-color:var(--ink)}
}
.rx-pc:active{transform:scale(var(--rx-press,.98));transition-duration:var(--rx-dp,90ms)}
.rx-pc:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
/* After the press rule on purpose: a media query adds no specificity, so the later rule wins. */
@media (prefers-reduced-motion:reduce){
  .rx-pc:active{transform:none}
}

/* ═══ 8. THE TIP (05 §6.2) — one node on <body>, for a fine pointer or keyboard focus ═════════
   It duplicates words that are in the tile's label and the drawer, so it may rest hidden; it
   never takes the pointer, so it can never sit between the customer and the tile under it. The
   resting state is written as a compound (:not(.is-on)) and only ever applies once rx-board.js has
   un-hidden the node, so there is no stylesheet state in which content waits on a script. */
.rx-tip{position:absolute;top:0;left:0;z-index:30;max-width:260px;padding:12px 14px;
  border:1px solid var(--line-2);border-radius:var(--r);background:var(--card);box-shadow:var(--shadow-1);
  font:400 13px/1.5 var(--body);color:var(--ink-2);pointer-events:none;
  transition:opacity var(--rx-d1,180ms) var(--ease),transform var(--rx-d1,180ms) var(--ease)}
.rx-tip[hidden]{display:none!important}
.rx-tip:not(.is-on){opacity:0;transform:translateY(4px)}
.rx-tip b{display:block;margin:0 0 2px;font:600 13.5px/1.35 var(--body);color:var(--ink)}
.rx-tip span{display:block}
.rx-tip small{display:flex;align-items:center;gap:6px;margin-top:6px;font:400 12.5px/1.4 var(--body);
  color:var(--ink-dim)}
.rx-tip small i{flex:0 0 10px;width:10px;height:10px;border-radius:50%;
  box-shadow:inset 0 0 0 1px rgba(127,127,127,.35)}
.rx-tip em{display:block;margin-top:8px;font:600 10.5px/1.3 var(--body);font-style:normal;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-dim)}
@media (prefers-reduced-motion:reduce){
  .rx-tip:not(.is-on){transform:none}
}

/* ═══ 9. LOADING (05 §12) ════════════════════════════════════════════════════════════════════
   THE SKELETON is the board's own grid with a sheen block in each 4:5 face (rx-board.js skeleton),
   so nothing jumps when the looks land. The sheen itself is rx-core's .rx-sk; these two rules only
   make it fill a face and sit as a block in a caption. */
.rx-board-host .rx-face > .rx-sk{position:absolute;inset:0;border-radius:inherit}
/* EACH SKELETON LINE TAKES ITS REAL LINE'S BOX: a 12px bar, centred by its margins in the height
   the text line will have (the name 13.5px × 1.35 ≈ 18px, 14px on the lead; the colour 12.5px ×
   1.35 ≈ 17px). rx-core's .rx-sk-line carries a 10px bottom margin for paragraphs; under a tile
   that margin was the difference between the skeleton's caption and the real one. */
.rx-board-host .rx-cap > b.rx-sk{display:block;width:70%;height:12px;margin:3px 0}
.rx-board-host .rx-tile.is-lead .rx-cap > b.rx-sk{margin:3.5px 0}
.rx-board-host .rx-tile.is-detail .rx-cap > b.rx-sk{margin:2.5px 0}
.rx-board-host .rx-cap > span.rx-sk{display:block;width:45%;height:12px;margin:2.5px 0}
/* A detail's colour line is painted now (V PR-16), so its skeleton draws the bar above too — it
   used to be hidden here to match a painted detail that hid its colour, and keeping that hide
   would make every detail tile grow by a line when the looks land.
   BELOW 768 A DETAIL'S NAME IS TWO LINES. An 82px detail tile holds about eleven characters of
   12.5px type, and four of the five fixture looks have a detail whose name wraps ("Pointed-toe
   Mules", "Glass bangles", "Glass Bangles Stack" takes three) — so the painted tier is a two-line
   name and the colour line: 33.75 + 2 + 16.2 = 51.95px (C:\tmp\shot\RX-P4-skelhead.mjs measured
   the name). The skeleton's two bars stand for that: the name bar (17) and the colour bar (12),
   with the bottom margin carrying the rest so the tier lands at the painted height. From 768 the
   tile is 100px+ wide and the name is one line, which the rule above already matches. */
@media (max-width:767.98px){
  .rx-board-host .rx-tile.is-detail .rx-cap > span.rx-sk{display:block;width:52%;margin:0 0 20.95px}
}
.rx-board-host span.rx-tile{cursor:default}

/* THE PIECES ROW'S SKELETON (<768; rx-board.js piecesSkeletonHtml). It is the real row — the same
   <ul class="rx-pieces">, the same .rx-pc cards, the same <b>/<em>/<strong>/<small> lines — so its
   height comes from the rules above and not from a number here; without it the actions and
   everything under them dropped ~170px when the looks landed. Each bar is one line box of the line
   it sits in: 1lh tall less a quarter-em of air above and below, inline-block and top-aligned so
   the margins never collapse (the hero's skeleton found that blocks lose a quarter-em a line).
   The small line holds four bars, one per line its clamp allows. The cards take no pointer: there
   is nothing to press, and a press would draw the real card's :active shrink on a placeholder. */
.rx-pieces-sk .rx-pc{cursor:default;pointer-events:none}
.rx-pieces-sk .rx-face > .rx-sk{position:absolute;inset:0;border-radius:inherit}
.rx-pc-skl{display:inline-block;vertical-align:top;height:.8em;height:calc(1lh - .5em);margin:.25em 0;
  border-radius:6px}
.rx-pc-skn{display:block;flex:0 0 20px;width:20px;height:20px;border-radius:50%}

/* A REFINE IN FLIGHT: the look stays on screen and a sheen crosses each face. On ::before because
   ::after is the face's rim (rx-core.css); z-index 2 lifts it over the absolutely placed image.
   The busy state is the hero's (aria-busy on #rxHero, set by rx-hero.js setBusy); every exit path
   clears it, a 402 included. Under reduced motion there is no sheen, and the hero's own dimmed
   head says the page is working. */
#rxHero[aria-busy="true"] .rx-face::before{content:"";position:absolute;inset:0;z-index:2;
  pointer-events:none;transform:translateX(-100%);
  background:linear-gradient(100deg,transparent 20%,rgba(255,255,255,.55) 50%,transparent 80%);
  animation:rx-board-shim 1.6s var(--ease) infinite}
@keyframes rx-board-shim{to{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){
  #rxHero[aria-busy="true"] .rx-face::before{display:none}
}
