/* Doorway Supermarket — activity styles.
   1em = 1/50th of activity width (set by doorway.js onResize).
   All sizing in em; no px except borders.
*/

/* Shared item-visual scale knobs. Declared at `:root` (not on
   `.sm-screen-layout--shopping`) because the fly-animation clone is
   attached to `document.body` and needs to inherit these vars from
   above the shopping-screen container.

   Each destination sizes its item as `intrinsic × per-target scale`,
   where `intrinsic` = the SVG sprite's natural width/height converted
   to em (via `--sm-natural-w` / `--sm-natural-h` custom props set on
   each img by JS after load — see `applyNaturalSize` in
   `supermarket-render.js`). This preserves relative product sizes
   (small tuna tin renders small, tall loo-roll pack renders tall)
   instead of forcing every sprite into a single square. */
:root {
    /* Single source of truth for the shopping-item sprite scale used
       inside the trolley basket and the round-the-price overlay. The
       flyer sprite is derived as 2× this (matching Flash where the
       moving item briefly grew before shrinking back to basket size). */
    --sm-basket-item-scale: 0.65;
}

/* --- Welcome screen image ---
   Layered composition built from Flash sprites in pictures/:
     trolley.svg  — full trolley (handle, basket, wheels)
     belt.svg     — conveyor-belt cylinder
     till.svg     — checkout monitor + stand
   Items (item*.svg) are positioned via percent within the scene.
*/

/* Constrained for flow-mode welcome layout: the scene must fit inside
   .dw-welcome-body alongside title group and optional subtitle without
   pushing the subtitle past the sticky footer at typical viewport heights.
   max-height keeps the wide 800:360 strip from monopolising vertical space
   when the viewport is unusually tall. */
.welcome_image {
    width: 100%;
    max-width: 42em;
    max-height: 18em;
    margin: 0 auto;
    pointer-events: none;
}

/* Scene container — all children absolutely positioned within.
   Aspect ratio mirrors Flash welcome region (trolley to belt to till). */
.wimg-scene {
    position: relative;
    width: 100%;
    aspect-ratio: 800 / 360;
    overflow: hidden;
}

/* Belt sprite — wide, thin cylinder sitting roughly mid-height. The belt SVG
   has preserveAspectRatio="none" so we can squash it to a flat strip.
   Drawn first so trolley + till + items render on top. Starts under the
   trolley so the belt visually disappears behind the basket on the left.
   Flash places the belt high in the frame (~50% from the top) so the
   conveyor surface visually carries the carrots/milk above the bottom of
   the scene; raising the belt brings the HTML5 layout into line. */
.wimg-scene .wimg-belt {
    position: absolute;
    left: 35%;
    right: 0;
    top: 32%;
    width: 65% !important;
    height: 22% !important;
    pointer-events: none;
}

/* Trolley sprite — !important needed to override doorway.css rule
   "div.welcome_image img { width:100%; height:100% }". Sits flush against
   the belt on the right so less of the belt is visible on the left side,
   matching the Flash welcome layout. */
.wimg-scene .wimg-trolley {
    position: absolute;
    left: 7%;
    bottom: 0.5%;
    width: 43% !important;
    height: 100% !important;
    object-fit: contain;
    object-position: bottom left;
    pointer-events: none;
}

/* Trolley front rails overlay — separate Flash sprite (sprite_365,
   "trollyFront") whose job is to render the wire rails on the front of
   the basket OVER the items inside, so the items appear to be enclosed
   by the basket. Without this overlay the items float in front of the
   basket wireframe.
   Native sprite aspect 309:244 — landscape (the rails span the basket's
   open front face). Positioned to overlay the basket interior area
   (roughly left 8%-40%, top 30%-65% in scene coords, matching where
   the items sit). z-index 2 sits above .wimg-item (z:1). */
.wimg-scene .wimg-trolley-front {
    position: absolute;
    left: 10.5%;
    top: 17.5%;
    width: 36% !important;
    height: auto !important;
    aspect-ratio: 309 / 244;
    object-fit: contain;
    object-position: top left;
    pointer-events: none;
    z-index: 2;
}

/* Welcome-scene items (basket + on-belt). Sized off intrinsic SVG
   dimensions (published by initWelcomeSpriteSizes → applyNaturalSize)
   so each product renders at its true relative scale. Each per-item
   rule below sets its own width/height calc using an item-specific
   scale factor. */
.wimg-scene .wimg-item {
    position: absolute;
    object-fit: contain;
    pointer-events: none;
    z-index: 1;
}

/* Items inside the trolley basket (positioned over the trolley sprite).
   trolley-empty.svg is a side-view perspective trolley whose basket
   interior in scene-coordinates is roughly:
     left  edge: 11%  (back of basket, slightly left)
     right edge: 36%  (open front of basket, viewer's right)
     top edge:  35%  (rim of basket)
     bottom:    65%  (bottom of basket where items rest)
   Items stack inside, with cereal box upright at the back-left and
   shorter items in front. Beans is parked at the front-left corner
   separated from the noodle/juice cluster. */
.wimg-scene .wimg-beans {
    left: 16%;
    top:  23%;
    width:  calc(var(--sm-natural-w, 3em) * 0.66);
    height: calc(var(--sm-natural-h, 2em) * 0.66);
}
.wimg-scene .wimg-cereal {
    left: 27%;
    top:  15.5%;
    width:  calc(var(--sm-natural-w, 3em) * 0.66);
    height: calc(var(--sm-natural-h, 2em) * 0.66);
}
.wimg-scene .wimg-noodles {
    left: 19%;
    top:  38%;
    width:  calc(var(--sm-natural-w, 3em) * 0.66);
    height: calc(var(--sm-natural-h, 2em) * 0.66);
}
.wimg-scene .wimg-juice {
    left: 27%;
    top:  51%;
    width:  calc(var(--sm-natural-w, 3em) * 0.66);
    height: calc(var(--sm-natural-h, 2em) * 0.66);
}
.wimg-scene .wimg-pepper {
    left: 31.5%;
    top:  36%;
    width:  calc(var(--sm-natural-w, 3em) * 0.67);
    height: calc(var(--sm-natural-h, 2em) * 0.67);
}

/* Items on the conveyor belt. */
.wimg-scene .wimg-carrots {
    left: 47.5%;
    top:  28%;
    width:  calc(var(--sm-natural-w, 3em) * 0.6);
    height: calc(var(--sm-natural-h, 2em) * 0.6);
}
.wimg-scene .wimg-milk {
    left: 69.5%;
    top:  21%;
    width:  calc(var(--sm-natural-w, 3em) * 0.8);
    height: calc(var(--sm-natural-h, 2em) * 0.8);
}

/* Till group — checkout monitor + stand on the right, with the running
   total displayed in the black screen. Flash frame_02.as line 7 sets the
   till display to "£3.79" on the welcome screen. The group sizes match
   the till sprite aspect (298:353) so the price overlay can be positioned
   in percentage units relative to the rendered till.
   Sits above the belt so the monitor head reaches near the title and the
   stand base clears the belt (matching the Flash welcome). z-index above
   the belt/items so the till body overlays them where they meet. */
.wimg-scene .wimg-till-group {
    position: absolute;
    right: 2%;
    bottom: 42%;
    width: 20%;
    aspect-ratio: 298 / 353;
    z-index: 3;
    pointer-events: none;
}

.wimg-scene .wimg-till {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
    object-fit: contain;
    pointer-events: none;
}

/* The till sprite (298×353) has its black monitor screen at the very
   top: SVG y=18..59 of 353 ≈ 5%..17% of the sprite's height. Colour is
   white — the LCD readout on the sprite reads clearest against the
   #000 monitor rectangle. */
.wimg-scene .wimg-till-price {
    position: absolute;
    left: 19%;
    top:  5.5%;
    width: 56%;             /* keeps the original centered-at-22%/right:22% box */
    height: 11%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    font-family: "Courier New", monospace;
    font-weight: bold;
    font-size: 0.9em;
    line-height: 1;
    pointer-events: none;
    white-space: nowrap;
}

/* --- Options form --- */

/* Flash description paragraph at the top of the options panel.
   Sits above the first fieldset, matching the Flash layout. */
.sm-options-description {
    text-align: center;
    margin: 0 0 var(--dw-space-comfy);
    font-style: italic;
}

/* --- Options grid layout (replaces legacy <table class="options_layout_grid">) --- */

.sm-activity-grid {
    display: flex;
    flex-direction: column;
    gap: var(--dw-space-comfy);
    align-items: start;
}

/* --- Screen layout --- */

/* Outer sub-screen div is `display: contents` (via
 * .dw-activity-screen--contents) and imposes no layout mode. Layout mode +
 * per-variant sizing lives on the inner .sm-screen-layout--<variant>
 * wrapper below. Visibility is the shared `[hidden] { display: none
 * !important }` from doorway.css. */

/* Inner layout wrapper — shared box shape for all four sub-screens.
 * Per-variant classes below select the layout mode. */
.sm-screen-layout {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    overflow-y: auto;
    padding: 1.5em var(--dw-space-loose) var(--dw-space-loose);
    gap: var(--dw-space-default);
}

/* Receipt sub-screen — flex-column shell. */
.sm-screen-layout--receipt {
    display: flex;
    flex-direction: column;
}

/* --- Shopping screen layout ---
   Flash: aisle hanging sign at top, three perspective shelves on the right
   (sprite_482), trolley graphic parked bottom-left (sprite_382), round-the-
   price panel top-left over the trolley, "Pick some items" + Checkout at
   bottom-right. Light-cyan background.
*/

/* Shopping sub-screen — grid shell. */
.sm-screen-layout--shopping {
    background: #d6f0ed;
    display: grid;
    /* Widen the left column so the trolley graphic can grow toward the
       shelves and read at a similar visual weight to the Flash version
       (where the trolley dominates the bottom-left quadrant). */
    grid-template-columns: 14em 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "aisle  aisle"
        "side   shelves"
        "footer footer";
    gap: var(--dw-space-snug) var(--dw-space-snug);
    padding: var(--dw-space-snug) var(--dw-space-comfy) var(--dw-space-narrow);
    position: relative;
}

/* --- Aisle navigation (top row) ---
   Centre: the hanging aisle sign (sprite_503) acts as the panel; the aisle
   name is overlaid as text. Sides: the cycling arrows (sprite_498), with the
   right button visually flipped. */

/* Aisle nav row: arrows hug the central sign, and the whole group is shifted
   right so the sign sits roughly central against the shelves (Flash places
   the hanging sign over the shelving unit, not over the trolley). `gap:0`
   because each arrow carries an explicit negative margin pulling it tight
   against the sign (Flash places the arrowheads almost touching the sign
   edges). `padding-left` shifts the entire row right so the sign moves
   toward the shelves. */
.sm-aisle-nav {
    grid-area: aisle;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0;
    padding-left: 19em;           /* push the whole nav past the trolley column */
    /* Sit above .sm-shelves-wrap in the stacking order — the shelves are
       scaled up 10% from bottom-centre, so they grow into the aisle-row
       above them; without this z-index the sign/arrows would be painted
       under the top of the shelves. */
    position: relative;
    z-index: 2;
}

/* Sign sized 5% larger than the previous 18em — Flash hanging sign reads as
   visually dominant.  Height bumped proportionally so the green painted
   band keeps its aspect. `padding-bottom` increased a touch so the text
   lifts off the bottom edge and sits cleanly inside the green band
   rather than hugging the rim. */
.sm-aisle-sign {
    position: relative;
    display: flex;
    align-items: flex-end;        /* push name down into the green band, away from hanger top */
    justify-content: center;
    width: 18.9em;
    height: 3.57em;
    padding-bottom: 0.55em;
    /* The sign is purely decorative — no click handler, no interactive
       descendants. Under the current arrow overlap the prev arrow sits
       inside the sign's visual box; since the sign paints on top of it
       (later DOM sibling in the same stacking context), clicks would
       land here and never reach the arrow. Pointer-events:none lets
       those clicks pass through to the arrow beneath. */
    pointer-events: none;
}

.sm-aisle-sign-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    pointer-events: none;
}

.sm-aisle-name {
    position: relative;
    z-index: 1;
    /* Sized to fit the longest aisle name ("3. Chilled Food") inside the
       painted green band of the hanging sign without wrapping. Flash text
       is regular weight (not bold). */
    font-size: 1em;
    margin: 0;
    font-weight: normal;
    color: #205313;
    white-space: nowrap;
}

.sm-nav-btn {
    background: transparent;
    border: 0.12em solid transparent;
    border-radius: 0.4em;
    padding: var(--dw-space-tight);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3em;
    height: 2.4em;
    transform: translateY(0.85em);
}

/* Pull each arrow tight against the hanging sign — Flash places the
   arrowheads almost touching the sign edges. Negative margin overlaps the
   transparent SVG padding into the sign's frame so the visible arrowhead
   sits next to the sign at ~0.2em from the visible edge. */
.sm-aisle-nav .sm-nav-btn-prev {
    margin-right: -4.65em;
    /* Shift the whole {prev, sign, next} group right — sign and next
       flex-flow after prev, so the visible gap on each side of the sign
       stays symmetric. */
    margin-left: 5.3em;
}
.sm-aisle-nav .sm-nav-btn-next {
    margin-left: -4.65em;
}

/* `.sm-nav-btn { display: flex }` comes later than the shared
   `.hidden_panel { display: none }` and has equal specificity, so it would
   otherwise win and leave both aisle arrows visible on the first/last shelf.
   Force display:none with `visibility:hidden` to also reserve layout space
   (the centre sign stays centred when one arrow disappears). */
.sm-nav-btn.hidden_panel {
    display: flex;
    visibility: hidden;
}

.sm-nav-btn img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.sm-nav-btn-next img {
    transform: scaleX(-1);
}

.sm-nav-btn:focus-visible {
    border-color: #205313;
    outline: 0.15em solid #205313;
}

@media (hover: hover) {
    .sm-nav-btn:hover img {
        filter: brightness(1.1);
    }
}

/* --- Shelves wrap (right) ---
   The Flash shelves sprite is the backdrop. We overlay items in a 3×4 grid
   that aligns to the shelf perspective. The sprite viewBox is 504.45 ×
   551.7; items occupy roughly y=18..96% inside it, three horizontal bands.
*/

/* The wrap matches the shelves sprite's aspect ratio (504.45 × 551.7) so the
   inset-percentage grid below aligns to the painted shelf surfaces — without
   this, the SVG centres inside a wider container and items drift off-shelf. */
.sm-shelves-wrap {
    grid-area: shelves;
    position: relative;
    min-height: 0;
    aspect-ratio: 504 / 552;
    height: 100%;
    margin: 0 auto;
    /* Visually scale the whole shelving unit + products + tags by 10%
       and drop the whole thing down by about half an arrow-button
       height (arrow is 2.4em → 1.2em drop) so the shelves don't crowd
       the aisle sign above. Uses transform so layout footprint stays
       put (sign above / trolley beside are unaffected). Origin at
       bottom-centre keeps the visual growth going upward + outward.
       Transform order: scale is applied first (right-to-left), then
       translate — so the whole scaled unit shifts down by 1.2em. */
    transform: translateY(1.2em) scale(1.1);
    transform-origin: bottom center;
    max-width: 100%;
}

.sm-shelves-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

/* The shelves sprite has perspective: the painted "shelf surface" occupies the
   centred ~62% width within the sprite frame, with depth/angle on the right.
   `.sm-item-grid` constrains items to that visible surface so the 4th item per
   row doesn't fall off into the perspective.

   The bottom inset is intentionally tight (≈2%) so items land directly on the
   bottom shelf surface — Flash places items/price-tags right at the shelf
   edge with no air gap below. The grid is divided into three equal-height
   row bands, each anchored to the bottom of its band so its contents sit on
   the shelf line for that row. */
.sm-item-grid {
    position: absolute;
    inset: 5% 18% 2% 6%;
    display: flex;
    flex-direction: column;
    gap: 0;
    pointer-events: none;        /* let the backdrop show through; buttons re-enable */
}

/* Price-tag overlay: mirrors .sm-item-grid geometry exactly and sits above
   it in the shelves-wrap stacking context. Each .sm-shelf-row inside
   .sm-item-grid establishes its own stacking context via `transform`, so
   a tag inside a row's own button was trapped inside that row — a
   neighbouring row's tall product would paint over the row-above's tags.
   Hoisting tags into this parallel layer at z-index:3 puts them above
   every product image regardless of which row they belong to.
   Populated by supermarket-render.js in lockstep with the item grid. */
.sm-tag-layer {
    position: absolute;
    inset: 5% 18% 2% 6%;
    display: flex;
    flex-direction: column;
    gap: 0;
    pointer-events: none;
    z-index: 3;
}

/* Empty cell that holds a single `.sm-item-price`. Acts as the price-tag's
   positioning container: the tag is absolutely positioned at
   `bottom: -1.2em; left: 50%;` inside this cell, so the cell needs
   `position: relative`. The row's `align-items: end` bottom-aligns the
   cell to the shelf line so the tag lands at `shelf-line - 1.2em`. */
.sm-tag-cell {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: end;
}

/* Shelves are drawn in perspective with the left edge slightly higher than
   the right (vanishing point off-right). Each row of four items sits along
   that perspective line — items further right drop down by an amount
   proportional to the per-row `--row-tilt` set below, expressed as the total
   drop between the leftmost and rightmost item. Items themselves stay
   upright — the row's tilt is realised as `translateY` per column position,
   NOT as a rotate on the row (matching Flash, where products sit upright
   on a sloped shelf surface).
   `padding-bottom` reserves breathing room at the bottom of each row band
   so products don't butt up against the shelf line below them.
   `align-items: end` bottom-aligns items within the row so taller and
   shorter products both rest on the shelf line (plus the tilt).
   Mid and bot rows shift UP (via their per-nth-child translate) so they
   read as further away in the perspective backdrop. */
.sm-shelf-row {
    --row-tilt: 0em;          /* overridden per-row below */
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1.15em;
    flex: 1;
    min-height: 0;
    align-items: end;
    position: relative;
    padding-bottom: 1.4em;
}

/* Per-shelf vertical shift + tilt magnitude.
   Each shelf in the SVG backdrop is drawn at a slightly different
   perspective angle (top nearly flat, bottom drops most); the product
   row's --row-tilt encodes the total L→R drop for that row and
   --row-tag-tilt rotates its price tags to track the same perspective.
   --row-tag-line-delta is (tag-line-tilt − row-tilt) — non-zero values
   let the tag row tilt independently of the products above.
   Mid and bot rows shift UP (negative Y translate) so their price-tag
   strip clips onto the green shelf-rim painted higher in the SVG
   backdrop — Flash places mid-shelf tags ≈ half a label-height higher
   and bottom-shelf tags ≈ a full label-height higher than naive even
   spacing. */
.sm-shelf-row:nth-child(1) {
    --row-tilt: 0.35em;
    --row-tag-tilt: 1.5deg;
    --row-tag-line-delta: -0.05em;
    --row-tag-y-offset: 0.7em;
    transform: translate(0.1em, 0em);
}
.sm-shelf-row:nth-child(2) {
    --row-tilt: 1.05em;
    --row-tag-tilt: 5.5deg;
    --row-tag-line-delta: 0.2em;
    --row-tag-y-offset: 0.55em;
    transform: translate(0.1em, -1.25em);
}
.sm-shelf-row:nth-child(3) {
    --row-tilt: 2em;
    --row-tag-tilt: 8.5deg;
    --row-tag-line-delta: -0.2em;
    --row-tag-y-offset: 0.95em;
    transform: translate(-0.3em, -3.05em) rotate(-0.5deg);
}

/* Per-column drop, scaled by the current row's `--row-tilt` (the total drop
   from leftmost to rightmost item). Items stay upright.  The `--col-frac`
   var (0, 0.333, 0.667, 1.0) is reused below by `.sm-item-price` to slide
   its tag independently along the shelf's tag-line tilt.
   Uses `top` (with `position: relative`) instead of `transform: translateY`
   so the button doesn't establish its own stacking context (which would
   trap the price tag inside).
   Applied identically to `.sm-tag-cell` in the parallel tag-layer so tag
   positions track their buttons' column drop. */
.sm-shelf-row > .sm-item-btn:nth-child(1),
.sm-shelf-row > .sm-tag-cell:nth-child(1)  { --col-frac: 0;     top: 0; }
.sm-shelf-row > .sm-item-btn:nth-child(2),
.sm-shelf-row > .sm-tag-cell:nth-child(2)  { --col-frac: 0.333; top: calc(var(--row-tilt) * 0.333); }
.sm-shelf-row > .sm-item-btn:nth-child(3),
.sm-shelf-row > .sm-tag-cell:nth-child(3)  { --col-frac: 0.667; top: calc(var(--row-tilt) * 0.667); }
.sm-shelf-row > .sm-item-btn:nth-child(4),
.sm-shelf-row > .sm-tag-cell:nth-child(4)  { --col-frac: 1;     top: var(--row-tilt); }

/* The button wraps just the product image; the price tag is absolutely
   positioned below it on the green shelf rim painted in the SVG backdrop.
   No `height: 100%` — the click target hugs the visible product image
   rather than the whole row band. */
.sm-item-btn {
    pointer-events: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 1em;
    gap: 0;
    position: relative;
}

.sm-item-btn:focus-visible .sm-item-img {
    transform: scale(calc(1.44 * 1.08));
}
@media (hover: hover) {
    .sm-item-btn:hover .sm-item-img {
        transform: scale(calc(1.44 * 1.08));
    }
}

.sm-item-btn:focus-visible {
    outline: 0.18em solid var(--dw-color-focus-ring);
    border-radius: 0.3em;
}

/* Product sprite sizing — Flash shelves show noticeably larger product
   graphics than the shared HTML5 baseline.
   `object-position: center bottom` anchors the actual graphic to the
   bottom of the fixed-height img box, so short/squat products (e.g. a
   tuna tin) sit on the shelf line instead of centring vertically inside
   the 2.75em box and appearing to float. */
.sm-item-img {
    width: 100%;
    max-width: 3.75em;
    height: 2.75em;
    object-fit: contain;
    object-position: center bottom;
    transform: scale(1.44);
    transform-origin: center bottom;
    transition: transform 0.15s ease-out;
}

/* Green price-tag strip — Flash renders it floating ON the green shelf
   rim painted in the shelves backdrop, with each row's tags clinging to
   the bottom of the row band, BELOW the product image (the item is above
   the tag with a clear gap, not overlapping it). Absolutely positioned
   below the item-btn so the button's hover/click target wraps just the
   product image, not the tag. `bottom:-1.2em` pushes the tag down onto
   the green shelf-rim painted into the SVG backdrop.
   The tag reads --row-tag-tilt (rotation), --row-tag-line-delta (extra
   translateY per column, scaled by --col-frac 0..1), and --row-tag-y-offset
   (rigid drop) — all set on the parent .sm-shelf-row:nth-child(N) above.
   The translateY here is the *delta* from the product row's tilt, so when
   --row-tag-line-delta is 0 AND --row-tag-y-offset is 0 the tag row sits
   directly under the products; otherwise the tag row tracks its own
   perspective line and/or slides up/down as a unit. */
.sm-item-price {
    position: absolute;
    bottom: -1.2em;
    left: 50%;
    transform: translate(-50%, calc(var(--row-tag-line-delta, 0em) * var(--col-frac, 0) + var(--row-tag-y-offset, 0em)))
               rotate(var(--row-tag-tilt, 0deg));
    transform-origin: center center;
    font-size: 0.88em;
    color: #0c4e0c;
    font-weight: bold;
    background: #ffffff;
    border: 0.14em solid #000;
    border-radius: 0;
    /* Tag height ≈ font-line + 2 × border + 2 × 0.06em vertical padding
       ≈ 1.28em, so the price sits comfortably inside the label. */
    padding: 0.06em var(--dw-space-snug);
    min-width: 2.4em;
    text-align: center;
    box-shadow: 0 0.05em 0 #c8e8c0;
    z-index: 2;
    pointer-events: none;       /* clicks pass through to the button */
    white-space: nowrap;
}

/* --- Trolley + round overlay column (left side) --- */

/* --- Round-price overlay ---
   Flash positions the round panel top-left (over the trolley area). Snap it
   into the left grid column with absolute positioning so it overlays the
   trolley while open. */

.sm-round-overlay {
    position: absolute;
    top: 3em;
    left: 0.8em;
    width: 13em;
    background: #c4ebbc;
    border: 0.18em solid #205313;
    border-radius: 0.4em;
    padding: 0.7em;
    z-index: 100;
    text-align: center;
    box-shadow: 0 0.2em 0.6em rgba(0,0,0,0.25);
}

.sm-round-overlay h3 {
    font-size: 1em;
    margin: 0 0 var(--dw-space-narrow) 0;
    color: #205313;
    line-height: 1.2;
}

/* Drop-target slot for the flying product sprite. Sits in the right-hand
   column of .sm-round-body next to the £0 / − + / Add controls. Reserves
   its full 4em × 4em box even when empty so the overlay layout doesn't
   jump when the flyer lands or the item is returned. Fixed (not min) so
   an arriving flyer can't push the overlay wider or taller; oversized
   items are contained via the img rules below.
   `.sm-round-itemslot-filled` is retained as a JS state marker; it does
   not change the slot's dimensions. */
.sm-round-itemslot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width:  4em;
    height: 4em;
    overflow: visible;
}

/* Button wrapper stretches to fill the reserved slot so the img inside
   can measure its max-width/max-height against a definite parent. */
.sm-round-itemslot > .sm-round-itemslot-btn {
    width:  100%;
    height: 100%;
    /* Flex-center the img so the resting position matches exactly what
       the flyer aimed at (slot centre). Without this, `margin: auto` on
       a block img only centres horizontally, and tall/short products
       would rest visibly off-centre from the flyer's landing point. */
    display: flex;
    align-items: center;
    justify-content: center;
}

.sm-round-itemslot img {
    /* Render at each product's natural aspect × basket-scale, but clamp
       to the reserved slot box so the overlay geometry stays put whichever
       product lands (tuna small, cornflakes tall). Centering is done by
       the flex button wrapper above. */
    display: block;
    max-width:  100%;
    max-height: 100%;
    width:  calc(var(--sm-natural-w, 3em) * var(--sm-basket-item-scale));
    height: calc(var(--sm-natural-h, 2em) * var(--sm-basket-item-scale));
    object-fit: contain;
}

/* The just-placed product sprite is wrapped in a button so clicking it
   returns the item (cancels the round-the-price step). Style as a plain
   image well — no chrome — with a hover/focus ring so users discover the
   click target. */
.sm-round-itemslot-btn {
    width: 100%;
    height: 100%;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    border-radius: 0.3em;
}

.sm-round-itemslot-btn:focus-visible img {
    transform: scale(1.08);
}
@media (hover: hover) {
    .sm-round-itemslot-btn:hover img {
        transform: scale(1.08);
    }
}

.sm-round-itemslot-btn:focus-visible {
    outline: 0.18em solid var(--dw-color-focus-ring);
}

.sm-round-itemslot-btn img {
    transition: transform 0.15s ease-out;
}

/* Fade-in applied via JS each time the overlay is revealed (Flash used
   a 0.5s alpha tween: `fadeIn("roundMenu", true)`). Decorative — the
   overlay text and spoken `round-prompt` audio carry the meaning. Only
   opacity is animated (not transform: scale) because flyItem captures
   the item-slot's rect at animation-start and would otherwise land at
   the scale-0.85 position while the item's resting spot is at scale 1. */
.sm-round-overlay-enter {
    animation: sm-round-overlay-enter 0.35s ease-out;
}

@keyframes sm-round-overlay-enter {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 3-column × 2-row grid:
     Row 1: [£0 spanning cols 1-2] [item in col 3]
     Row 2: [ − ]                  [ + ] [Add in col 3]
   This anchors £0 centrally over the − + stepper pair and the item slot
   centrally over the Add button. Matches the Flash layout where the
   current rounded value sits directly above the − and + steppers, with
   the item indicator sitting above the Add pencil. */
.sm-round-body {
    display: grid;
    grid-template-columns: auto auto auto;
    grid-template-rows: auto auto;
    justify-items: center;
    align-items: center;
    gap: var(--dw-space-snug) var(--dw-space-default);
    margin: var(--dw-space-snug) 0 var(--dw-space-tight) 0;
    justify-content: center;
}
#smRoundNum      { grid-column: 1 / span 2; grid-row: 1; }
#smRoundItemSlot { grid-column: 3;          grid-row: 1; }
#smRoundMinus    { grid-column: 1;          grid-row: 2; }
#smRoundPlus     { grid-column: 2;          grid-row: 2; }
#smRoundAdd      { grid-column: 3;          grid-row: 2; }

.sm-stepper-btn {
    font-size: var(--dw-font-size-large);
    width:  1.6em;
    height: 1.6em;
    border: 2px solid var(--dw-color-text-strong);
    /* Square with only slightly rounded corners — matches .sm-round-add so
       the three buttons on this row read as a set. */
    border-radius: 0.15em;
    cursor: pointer;
    background: #f0f0f0;
    padding: 0;
    line-height: 1;
}

/* "Add" button shares the stepper row in Flash — make it sit alongside +/-
   without inheriting the giant default main_button padding.  Matches the
   stepper corner-radius for a consistent square-ish look. */
.sm-round-add {
    font-size: 1em;
    padding: var(--dw-space-snug) 0.9em;
    margin: 0;
    border-radius: 0.15em;
}

.sm-stepper-btn:focus-visible {
    background: var(--dw-color-border-faint);
    outline: 0.2em solid var(--dw-color-focus-ring);
}
@media (hover: hover) {
    .sm-stepper-btn:hover {
        background: var(--dw-color-border-faint);
        outline: 0.2em solid var(--dw-color-focus-ring);
    }
}

.sm-round-value {
    font-size: 1.6em;
    font-weight: bold;
    min-width: 2em;
    padding: 0 var(--dw-space-snug);
    text-align: center;
    background: #fff;
    border: 0.1em solid #205313;
    border-radius: 0.2em;
    color: #205313;
}

.sm-round-feedback {
    color: var(--dw-color-feedback-wrong);
    font-size: 1em;
    min-height: 1.4em;
    margin: var(--dw-space-snug) 0;
}

/* --- Trolley (left column on shopping screen) ---
   Flash uses a perspective trolley sprite (sprite_382) parked bottom-left.
   We use it as a backdrop; the list of collected items overlays the basket.
*/

.sm-trolly-area {
    grid-area: side;
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: stretch;
    min-height: 0;
    padding: 0;
}

.sm-trolly-bg {
    position: absolute;
    left: -0.5em;
    bottom: -4em;
    /* Grow the trolley so it visually dominates the bottom-left quadrant
       (matching Flash) rather than being a small thumbnail. */
    width: 126%;
    height: 100%;
    object-fit: contain;
    object-position: bottom left;
    pointer-events: none;
    z-index: 0;
}

/* Front wire rails overlay (Flash sprite_365 "trollyFront", attached in
   frame_05.as:273 at high depth 999000 → 900000 after items land, so it
   always renders on top of the trolley contents). Sits over the basket's
   open front so items in .sm-trolly-list look enclosed by the rails
   rather than floating in front of the basket wireframe. */
.sm-trolly-front {
    position: absolute;
    left: 6%;
    top: 37%;
    width: 115.5%;
    height: auto;
    aspect-ratio: 309 / 244;
    object-fit: contain;
    pointer-events: none;
    z-index: 2;
}

.sm-trolly-heading {
    margin: 0;
}

/* Items in the basket — laid out as 10 absolutely-positioned slots inside
   the basket opening of the trolley SVG. No panel chrome (no background,
   no border) — Flash drops items straight into the basket so the trolley
   graphic does the visual work.
   Slots follow a 3-2-3-2 pattern: rows 1 and 3 hold 3 items each,
   rows 2 and 4 hold 2 items nested between them. Row Y positions are
   integer multiples of --slot-row-step; each successive row is shifted
   right by an extra --slot-slant-x, producing the diagonal `\` bias that
   tracks the trolley basket's painted perspective. --slot-col-step is the
   horizontal spacing between adjacent columns. Per-slot --slot-x/--slot-y
   values are set by the :nth-child rules below. */
.sm-trolly-list {
    list-style: none;
    padding: 0;
    margin: 0;
    position: absolute;
    left:   23.5%;
    right:  0%;
    top:    48.5%;
    bottom: 21%;
    z-index: 1;
    overflow: visible;
    --slot-col-step: 32%;
    --slot-row-step: 25.5%;
    --slot-slant-x:  7.4%;
}

.sm-trolly-item {
    position: absolute;
    left: var(--slot-x, 0);
    top: var(--slot-y, 0);
    /* Fixed reserved size — keeps an empty slot's bounding rect identical
       to a filled slot's, so the fly animation aims at the slot's centre
       pre-population without a diagonal snap when the img actually lands.
       Matches .sm-round-itemslot for basket-geometry consistency. */
    width:  4em;
    height: 4em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Row spacing (--slot-row-step) is tighter than the 4em slot height,
       so neighbouring rows visually overlap. The <li> passes clicks
       through; the inner <button> (auto-sized to its img) intercepts
       them, so the click target hugs the sprite instead of covering the
       row below. */
    pointer-events: none;
}

/* Per-slot positioning — 10 slots in a 3-2-3-2 pattern. Columns for
   even-numbered rows (2 slots) sit at half-step offsets so they nest
   between the odd rows' 3 slots. Y positions are integer multiples of
   --slot-row-step; X positions accumulate slant as row index grows. */
/* Row 1 (y=0): 3 slots at columns 0, 1, 2. */
.sm-trolly-item:nth-child(1)  { --slot-x: 0;
                                --slot-y: 0; }
.sm-trolly-item:nth-child(2)  { --slot-x: var(--slot-col-step);
                                --slot-y: 0; }
.sm-trolly-item:nth-child(3)  { --slot-x: calc(var(--slot-col-step) * 2);
                                --slot-y: 0; }
/* Row 2 (y=1×row): 2 slots at columns 0.5, 1.5 + 1 slant. */
.sm-trolly-item:nth-child(4)  { --slot-x: calc(var(--slot-col-step) * 0.5 + var(--slot-slant-x));
                                --slot-y: var(--slot-row-step); }
.sm-trolly-item:nth-child(5)  { --slot-x: calc(var(--slot-col-step) * 1.5 + var(--slot-slant-x));
                                --slot-y: var(--slot-row-step); }
/* Row 3 (y=2×row): 3 slots at columns 0, 1, 2 + 2 slant. */
.sm-trolly-item:nth-child(6)  { --slot-x: calc(var(--slot-slant-x) * 2);
                                --slot-y: calc(var(--slot-row-step) * 2); }
.sm-trolly-item:nth-child(7)  { --slot-x: calc(var(--slot-col-step) + var(--slot-slant-x) * 2);
                                --slot-y: calc(var(--slot-row-step) * 2); }
.sm-trolly-item:nth-child(8)  { --slot-x: calc(var(--slot-col-step) * 2 + var(--slot-slant-x) * 2);
                                --slot-y: calc(var(--slot-row-step) * 2); }
/* Row 4 (y=3×row): 2 slots at columns 0.5, 1.5 + 3 slant. */
.sm-trolly-item:nth-child(9)  { --slot-x: calc(var(--slot-col-step) * 0.5 + var(--slot-slant-x) * 3);
                                --slot-y: calc(var(--slot-row-step) * 3); }
.sm-trolly-item:nth-child(10) { --slot-x: calc(var(--slot-col-step) * 1.5 + var(--slot-slant-x) * 3);
                                --slot-y: calc(var(--slot-row-step) * 3); }

/* Transient "flyer" — a cloned item sprite that animates from a shelf
   button to the round-overlay item slot (on click) and from there into
   the specific trolley slot cell the item is about to occupy (on Add).
   Mounted on document.body and removed on transitionend; uses fixed
   positioning so its coordinates aren't warped by ancestor transforms. */
.sm-fly-item {
    position: fixed;
    pointer-events: none;
    z-index: 1000;
    will-change: transform, opacity;
    /* Size = the sprite's own intrinsic width/height (in em) × the
       fly-scale knob. `--sm-natural-w` / `--sm-natural-h` are set on
       the img by `applyNaturalSize` once the SVG has loaded — until
       then the fallback keeps the flyer at a reasonable placeholder
       size so it doesn't paint at 0×0 during the load window. */
    width:  calc(var(--sm-natural-w, 3em) * var(--sm-basket-item-scale) * 2);
    height: calc(var(--sm-natural-h, 2em) * var(--sm-basket-item-scale) * 2);
}

.sm-fly-item-go {
    transition: transform 0.4s ease-out, opacity 0.4s ease-out;
}

/* Clickable wrapper inside each slot — bare button restyled to look like
   the bare image it replaces. Clicking returns the item to the shelf
   (Flash frame_05.as:435–469 newItem<N>.onRelease). */
.sm-trolly-item-btn {
    /* Auto-size to the img content (not 100% of slot) so the click target
       hugs the sprite. Combined with pointer-events: none on the parent
       slot, users can only click the visible product, not the empty slot
       area — which prevents neighbouring rows from stealing clicks where
       row_step is tighter than the slot box. */
    width:  auto;
    height: auto;
    padding: 0;
    margin: 0;
    background: transparent;
    border: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
}

.sm-trolly-item-btn:focus-visible {
    outline: 0.15em solid #1976d2;
    outline-offset: 0.1em;
}

/* Product sprite inside the basket — rendered at the sprite's own
   intrinsic aspect × trolley-scale (see `applyNaturalSize`). */
.sm-trolly-img {
    /* Clamped to the fixed slot box so oversize sprites don't push the
       slot's visual centre away from the flyer's target. */
    max-width:  100%;
    max-height: 100%;
    width:  calc(var(--sm-natural-w, 3em) * var(--sm-basket-item-scale));
    height: calc(var(--sm-natural-h, 2em) * var(--sm-basket-item-scale));
    object-fit: contain;
    flex-shrink: 0;
}

/* Trolley total — Flash didn't render an on-screen total on the shopping
   screen, just the items in the basket. Keep the element for screen
   readers but visually hide it via the standard sr-only pattern.
   `!important` overrides the high-specificity ID rules earlier in this
   stylesheet. */
.sm-trolly-total {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* --- Screen navigation ---
   Bottom-right placement everywhere; on the shopping screen the parent grid
   places this row in the "footer" area alongside the "Pick some items" hint.
*/

.sm-screen-nav {
    display: flex;
    gap: var(--dw-space-loose);
    justify-content: flex-end;
    align-items: center;
    margin-top: auto;
    padding-top: var(--dw-space-snug);
}

#dwShoppingScreen .sm-shopping-footer {
    grid-area: footer;
    justify-content: flex-end;
    align-items: center;
    gap: var(--dw-space-comfy);
    /* Reserve vertical space for the Checkout button so showing/hiding it
       (during round-the-price overlay) doesn't reflow the grid above. */
    min-height: 2.6em;
}

/* Reserve layout space for the Checkout button. Using visibility:hidden
   instead of display:none keeps the button slot in flow so the grid above
   doesn't reflow up and down each time the round-overlay opens/closes. */
.sm-shopping-next.hidden_panel {
    display: inline-block;
    visibility: hidden;
}

.sm-shopping-hint {
    margin: 0;
    text-align: center;
    font-style: italic;
    font-weight: bold;
    color: var(--dw-color-text-secondary);
    background: #fff;
    border: 0.12em solid var(--dw-color-border-muted);
    border-radius: 0.4em;
    padding: var(--dw-space-tight) var(--dw-space-comfy);
}

.sm-back-btn {
    padding: var(--dw-space-default) var(--dw-space-loose);
    font-size: var(--dw-font-size-subheading);
    border: 2px solid var(--dw-color-border-muted);
    border-radius: 0.4em;
    background: #eee;
    cursor: pointer;
}

.sm-back-btn:focus-visible {
    background: var(--dw-color-border-faint);
    outline: 0.2em solid var(--dw-color-focus-ring);
}
@media (hover: hover) {
    .sm-back-btn:hover {
        background: var(--dw-color-border-faint);
        outline: 0.2em solid var(--dw-color-focus-ring);
    }
}

/* --- Conveyor screen ---
   Flash: pale cyan background, dark grey 3D belt cylinder spanning the
   bottom half, till on the right (above belt surface), simple orange
   item-dots rolling left along the belt.
*/

/* Conveyor sub-screen — block shell. The outer .sm-conveyor-screen class is
 * retained as a semantic marker for other selectors downstream. */
.sm-screen-layout--conveyor {
    background: #e0f7f5;
    /* Conveyor scene fills the screen — no flex column, the scene is the
       sole positioned context for belt, till, items, text, and Next button. */
    display: block;
    position: relative;
    overflow: hidden;
    padding: 0;
    gap: 0;
}

.sm-conveyor-scene {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

/* Estimate + till-total text block — right-aligned lines in the
   upper-middle of the stage. Mirrors Flash frame_06: "You estimated £N"
   sits on top, "The total is £N" fades in below once scanning completes.
   The mid-scan running total is a *separate* element (.sm-till-pending)
   that overlays the till's monitor screen — see below. */
.sm-conveyor-text-block {
    position: absolute;
    top: 4em;
    right: 4em;
    text-align: right;
    z-index: 5;             /* above the belt, below the till sprite */
    pointer-events: none;
}

.sm-estimate-text,
.sm-till-total {
    margin: 0;
    font-size: 1.6em;
    line-height: 1.4;
    color: var(--dw-color-text-primary);
    white-space: nowrap;
}

.sm-till-total {
    min-height: 1.4em;       /* reserve a line so the layout doesn't jitter
                                between empty state and the final reveal */
}

/* Running till total: overlaid on the till sprite's black monitor
   screen while items are being scanned; stays up through the final
   summary so the on-till value is always visible. Also reused on the
   payment screen (.sm-payment-scene) so the total still reads on the
   till while the cashier asks for it. Position lands on the till
   screen at the current till size/position. */
.sm-till-pending {
    position: absolute;
    left: 22.6em;
    top:  8.45em;
    width: 10em;
    margin: 0;
    font-size: 1.4em;
    line-height: 1;
    color: #ffffff;
    text-align: center;
    white-space: nowrap;
    z-index: 15;             /* above the till sprite (z-index 10) */
    pointer-events: none;
}

/* Belt: cylinder anchored to the bottom of the stage. Flash reference
   has the belt occupy ~32 % of the (4:3) Flash stage height; rendered into
   a 16:9 stage that's the same proportion (~9em on a 28em-tall stage). */
.sm-conveyor-belt,
.sm-payment-belt {
    position: absolute;
    left: 0;
    right: 0;
    top: 17.15em;
    width: 100%;
    height: 9em;
    object-fit: fill;
    pointer-events: none;
}
.sm-payment-belt { z-index: 0; }

/* Till: The till.svg viewBox is 298×353 (aspect 0.844 = taller than wide),
   but in Flash the till was horizontally scaled to look closer to square.
   1.35× the base 16em × 13em → 21.6em × 17.55em. Shared with the
   payment stage's .sm-payment-till so both screens draw the till at
   identical position/size. */
.sm-conveyor-till,
.sm-payment-till {
    position: absolute;
    left: 28.5em;
    top:  10.6em;
    width: 21.6em;
    height: 17.55em;
    pointer-events: none;
    z-index: 10;
}
.sm-payment-till { z-index: 3; }

/* Items track: sits on the visible top portion of the belt (top = 20em,
   tuned to sit on the belt at its current y=17.15em placement). */
.sm-conveyor {
    position: absolute;
    left: 0;
    right: 0;
    top: 20em;
    height: 3em;
    overflow: visible;
}

/* Next button anchored to the bottom-right, overlapping the till's lower
   edge — mirrors Flash where the pencil tab sits inside the till's base. */
.sm-conveyor-next {
    position: absolute;
    right: 0.5em;
    bottom: 0.5em;
    z-index: 20;
}

/* Each conveyor item: actual product sprite sliding LEFT → RIGHT along
   the belt, passing behind the till sprite and continuing off the right
   edge of the screen. Flash frame_06 moves the `newItem*` clips across
   the belt (the orange dots seen in extracted reference captures are a
   runtime fallback when sprites fail to attach; the deployed Flash showed
   actual item graphics).

   Two chained CSS animations:
     1. sm-conveyor-approach — slide from off-left to the till's scanner
        window. Its `animationend` fires the beep (mirrors Flash
        `_root.hitBlock.hitTest` in frame_06).
     2. sm-conveyor-exit     — slide from the till's window off the right
        edge of the stage. Its `animationend` on the LAST item triggers
        the till-total reveal (mirrors Flash `sayTotal`).

   --sm-conveyor-approach-x : translateX at the moment the item is at the
                              till's scanner (= the till's left-edge minus
                              a bit, so the item is half-inside the till).
   --sm-conveyor-exit-x     : translateX at the moment the item leaves the
                              stage on the right (off-screen). */
.sm-conveyor-item {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-direction: column;
    width: 9em;
    height: 9em;
    left: -9em;            /* start just off the left edge so it enters the belt */
    top: 50%;
    /* approach-x: translateX value when the item reaches the till's
       scanner. Item starts at left:-9em with width 9em (item centre at
       -4.5em when translateX=0). Till sits at left:28.5em width:21.6em;
       scanner window ~30 % from its left edge lands at ~35em, so 40.95em
       puts the item centre ~36.45em — inside the scanner window.
       exit-x: translateX needed to clear the right edge. Item left edge
       starts at -9em; translating 60em puts it at 51em, fully off-screen
       past the till's right edge. */
    --sm-conveyor-approach-x: 40.95em;
    --sm-conveyor-exit-x: 60em;
    /* Timing mirrors Flash frame_06.as: items move 5 px/frame at 24 fps
       (= 120 px/s) and are spaced 140 px (~1.17 s) apart on the belt.
       `sayTotal` fires `3100 + N × 1000` ms after the conveyor starts.
       Items start 1.0 s apart; total per-item travel is 4.1 s (2.4 s
       approach + 1.7 s exit), so the last item's exit ends at
       `(N-1) × 1.0 + 4.1 = N + 3.1` s after the conveyor starts. The
       middle keyframe at 58.5 % (= 2.4 / 4.1) marks the scanner-crossing
       moment; supermarket-render.js fires the beep + till tick on the
       same schedule via setTimeout. */
    animation: sm-conveyor-belt 4.1s linear forwards;
    animation-delay: calc(var(--item-index) * 1s);
    transform: translate(0, -50%);
}

/* Item sprite sized so products at the checkout read at a smaller scale
   than the shelf sprites — they're meant to pass behind the till. */
.sm-conveyor-img {
    display: block;
    width: 5.46em;
    height: 5.04em;
    object-fit: contain;
}

@keyframes sm-conveyor-belt {
    0%    { transform: translate(0,                                  -50%); }
    58.5% { transform: translate(var(--sm-conveyor-approach-x, 40.95em), -50%); }
    100%  { transform: translate(var(--sm-conveyor-exit-x,     60em), -50%); }
}

/* Till total fade-in once the conveyor finishes. */
.sm-till-total-reveal {
    animation: sm-till-total-fade 0.4s ease-out forwards;
}

@keyframes sm-till-total-fade {
    from { opacity: 0; transform: translateY(0.3em); }
    to   { opacity: 1; transform: translateY(0);     }
}

/* --- Payment screen ---
   Flash frame_07 scene: pale cyan background, customer's hand at top-right
   fanning the bank of money (£5/£10/£20 notes plus 1p..£2 coins), brown
   leather wallet at bottom-left with three note slots held by the cashier's
   hand, black counter band running horizontally across the middle.
*/

/* Payment sub-screen — block shell. */
.sm-screen-layout--payment {
    background: #e0f7f5;
    /* Match .sm-conveyor-screen so the belt+till sit in the same place on
       both stages (conveyor animation and payment). */
    display: block;
    position: relative;
    overflow: hidden;
    padding: 0;
    gap: 0;
}

/* Belt + till on the payment stage share their positioning + sizing with
   the conveyor stage via merged selector rules (see .sm-conveyor-belt,
   .sm-conveyor-till above) so the shopping-counter backdrop is
   pixel-identical across the two screens. Only the z-indexes differ,
   which are overridden in those merged rules. */

/* Payment nav: Done + Next pencils positioned above the till, similar to
   how the conveyor's Next sits inside/near the till. */
.sm-payment-nav {
    position: absolute;
    right:  0.55em;
    bottom: 14.3em;
    display: flex;
    gap: var(--dw-space-loose);
    z-index: 20;
    margin-top: 0;
    padding-top: 0;
}

/* Cashier's spoken line ("That's £X please") shown on the left of the
   payment screen, matching Flash frame_07's cashierText position.
   Sits above the belt/till/wallet in the stacking context. */
.sm-cashier-text {
    position: absolute;
    top: 3em;
    left: 2em;
    max-width: 22em;
    margin: 0;
    font-size: 1.3em;
    color: #205313;
    text-shadow: 0 0.05em 0.15em rgba(255,255,255,0.7);
    z-index: 6;
    pointer-events: none;
}

/* Graphical scene container — fills the entire screen, mirroring the
   conveyor stage so belt/till appear in the same place across both. */
.sm-payment-scene {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

/* Loose coins in the wallet — single overlapping row over the wallet
   body with a per-coin y-jitter so it reads as a scattered handful.
   Each coin has an absolute left keyed to its data-idx so removing
   one (when the user places it on the hand) leaves the slot empty
   rather than the row collapsing to close the gap.  Only coins live
   here; £5/£10/£20 notes are peek buttons inside .sm-wallet-group. */
.sm-cashier-hand-money {
    position: absolute;
    left: 3em;
    bottom: 2em;
    width: 14em;
    height: 3em;
    pointer-events: auto;
    z-index: 5;
    padding: 0.3em 0.5em;
    box-sizing: border-box;
    transform: translate(1.62em, -1.39em) scale(1.3375);
    transform-origin: top left;
}

.sm-cashier-hand-money .sm-money-coin {
    position: absolute;
    top: 50%;
    transform: translateY(calc(-50% + var(--y-jitter, 0em)));
}

/* Fixed slot per denomination — left in em from walletArea's padding
   edge; y-jitter is a small intrinsic offset that keeps the row from
   looking too grid-like. */
.sm-cashier-hand-money .sm-money-coin[data-idx="0"] { left: 0em;     --y-jitter: -0.2em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="1"] { left: 0.9em;   --y-jitter:  0.3em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="2"] { left: 2.5em;   --y-jitter: -0.4em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="3"] { left: 4.1em;   --y-jitter:  0.1em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="4"] { left: 5.35em;  --y-jitter: -0.3em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="5"] { left: 7.25em;  --y-jitter:  0.4em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="6"] { left: 8.75em;  --y-jitter: -0.1em; }
.sm-cashier-hand-money .sm-money-coin[data-idx="7"] { left: 10.25em; --y-jitter:  0.2em; }

/* Money handed to the cashier — piled on the cashier's palm at the
   top-right (Flash cashierStartLocs).  Sits ABOVE the hand sprite so
   placed money reads as being in front of the palm.  Children are
   absolutely positioned, each offset by their append-order index so
   later placements overlap and slightly cascade off the earlier ones. */
.sm-till-drop {
    position: absolute;
    right: 5em;
    top: 5em;
    width: 14em;
    height: 8em;
    overflow: visible;
    z-index: 8;                     /* above .sm-cashier-hand-sprite (z 6) */
    pointer-events: auto;
    transform: translate(-3.35em, 0) scale(1.25);
    transform-origin: top right;
}

.sm-till-drop .sm-money-btn {
    position: absolute;
    left: var(--till-left, 0);
    top:  var(--till-top, 0);
    z-index: calc(var(--till-idx, 0) + 1);
}
/* Placed coins always paint above placed notes, regardless of which
   was placed first — coins sit on top of the pile visually. */
.sm-till-drop .sm-money-coin {
    z-index: calc(var(--till-idx, 0) + 100);
}

/* --- Wallet at bottom-left, held by the cashier's hand. ---
   Uses Flash sprite_549 (wallet-full.svg) which bundles the cashier hand
   and the brown leather wallet (with three slot dividers) into a single
   SVG.  The cashier hand is at the lower-right of the sprite, the wallet
   body fills most of the upper portion.  Native aspect ratio is 399:465
   ≈ 0.86. */
.sm-wallet-group {
    position: absolute;
    left: -1em;
    bottom: -1em;
    width: 13em;
    height: auto;
    z-index: 2;
    transform: translate(3.45em, 15.35em) scale(1.4);
    transform-origin: top left;
    /* Private stacking context so peek/mask z-indices don't leak into
       the scene-level stack. */
    isolation: isolate;
    /* Shared scale for the three wallet flap masks. */
    --mask-scale: 2.12;
}

.sm-wallet-bg {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 13em;
    height: auto;
    pointer-events: none;
    z-index: 2;
    transform: translate(1.75em, -7.25em);
}

/* Peek notes (each is a real .sm-money-btn — clicking it flies the note
   to the cashier) paired with a wallet-mask overlay (Flash
   walletMask1/2/3).  £5 sits in the FRONT pocket at the top of the
   stack; £20 is at the back:

     wallet-bg      (z 2)   ← backmost
     ├─ £20 note    (z 3)   ─ mask (z 4)
     ├─ £10 note    (z 5)   ─ mask (z 6)
     └─ £5  note    (z 7)   ─ mask (z 8)   ← front pocket / topmost

   Coin row (#smWalletArea) sits above the whole stack when in
   notes+coins mode. */
.sm-wallet-peek,
.sm-wallet-mask {
    position: absolute;
    width: 6em;
    height: auto;
}
.sm-wallet-mask {
    pointer-events: none;   /* masks are decorative overlays */
}
.sm-wallet-peek.sm-money-btn {
    /* Reset the shared .sm-money-btn defaults so the peek button reads
       as a note in a pocket, not an inline flow element. */
    display: block;
    padding: 0;
    background: transparent;
    border: none;
    pointer-events: auto;
}
/* Suppresses a peek note between "user paid with it" and "next round
   renders". Kept in the DOM so its wired-once click handler survives,
   but visually withheld until renderWallet() clears the class. */
.sm-money-await-restore {
    visibility: hidden;
}

.sm-wallet-peek-5  { left: 1.5em;  top: 3.5em;  z-index: 7 !important;
                     transform: translate(0.5em, -21.3em) scale(1.5);
                     transform-origin: top left; }
.sm-wallet-mask-5  { left: 1.5em;  top: 4.5em;  z-index: 8 !important;
                     transform: translate(0.5em, -21em) scale(var(--mask-scale));
                     transform-origin: top left; }
.sm-wallet-peek-10 { left: 3.25em; top: 3em;    z-index: 5 !important;
                     transform: translate(0.25em, -22.3em) scale(1.5);
                     transform-origin: top left; }
.sm-wallet-mask-10 { left: 3.25em; top: 4em;    z-index: 6 !important;
                     transform: translate(-1.4em, -22em) scale(var(--mask-scale));
                     transform-origin: top left; }
.sm-wallet-peek-20 { left: 5em;    top: 2.5em;  z-index: 3 !important;
                     transform: translate(0.5em, -23.2em) scale(1.5);
                     transform-origin: top left; }
.sm-wallet-mask-20 { left: 5em;    top: 3.5em;  z-index: 4 !important;
                     transform: translate(-3.1em, -23em) scale(var(--mask-scale));
                     transform-origin: top left; }

/* --- Money button (used for both hand-fan, counter, and wallet slot). --- */
.sm-money-btn {
    display: inline-block;
    border: none;
    background: transparent;
    padding: 0;
    cursor: pointer;
    /* FLIP-scale animations from onMoneyClick scale the button from
       top-left so the src/dst top-left anchor stays put; the CSS
       class transforms on peek buttons already use this origin. */
    transform-origin: top left;
    /* Coin buttons flow in the flex row inside #smWalletArea; note peek
       buttons pick up their fixed position from .sm-wallet-peek-*. */
}

.sm-money-btn img {
    display: block;
    pointer-events: none;
    object-fit: contain;
}

/* Per-denomination coin sizes — proportional to real-world diameters
   (£2 is 28.4mm; 5p is only 18mm), so a 50p and a 5p aren't the same
   height in the wallet fan. Same ratios as the change cluster, just
   scaled up ~2× for the bank-of-money display. */
.sm-money-coin img {
    width: 3em;
    height: 3em;
}
.sm-money-coin[data-value="1"]   img { width: 2.1em;  height: 2.1em;  }
.sm-money-coin[data-value="2"]   img { width: 2.75em; height: 2.75em; }
.sm-money-coin[data-value="5"]   img { width: 1.9em;  height: 1.9em;  }
.sm-money-coin[data-value="10"]  img { width: 2.6em;  height: 2.6em;  }
.sm-money-coin[data-value="20"]  img { width: 2.25em; height: 2.25em; }
.sm-money-coin[data-value="50"]  img { width: 2.9em;  height: 2.9em;  }
.sm-money-coin[data-value="100"] img { width: 2.5em;  height: 2.5em;  }
.sm-money-coin[data-value="200"] img { width: 3em;    height: 3em;    }

.sm-money-note img {
    width: 10em;
    height: auto;
}

/* Peek-note button image sizing. At rest in the wallet, the image fills
   the 6em peek button.  Placed in the till-drop, it bumps up to the
   note's standard 10em width (same as coins-only fan notes did). */
.sm-wallet-peek.sm-money-btn img {
    width: 6em;
    height: auto;
}
.sm-till-drop .sm-wallet-peek img {
    width: 10em;
    height: auto;
}
/* In the wallet, the £5 button's box is the visible top strip only.
   Explicit height + overflow (not clip-path) so getBoundingClientRect
   returns the strip's rect, keeping the hover outline and FLIP src
   rect aligned with what's visible.  Lifts on reparent into till-drop. */
.sm-wallet-group .sm-wallet-peek-5 {
    height: 1.6em;
    overflow: hidden;
}
/* When a peek note is placed in the till-drop, its resting position +
   transform (from .sm-wallet-peek-N) must not carry over — the till-drop
   cascade handles position via --till-idx.  Width also gets sized to
   the placed-note image (10em) so the click hit-box matches what the
   user sees; without this the button remains 6em wide and clicks on
   the overflowing image edges miss. */
.sm-till-drop .sm-wallet-peek {
    transform: none;
    width: 10em;
}

.sm-money-btn:focus-visible {
    outline: 0.18em solid var(--dw-color-focus-ring);
    outline-offset: 0.05em;
    border-radius: 0.35em;
}
@media (hover: hover) {
    .sm-money-btn:hover {
        outline: 0.18em solid var(--dw-color-focus-ring);
        outline-offset: 0.05em;
        border-radius: 0.35em;
    }
}

.sm-money-placed {
    /* Visual hint that this item has been paid — slight glow + drop shadow */
    filter: drop-shadow(0 0.1em 0.2em var(--dw-color-shadow-strong));
}

.sm-payment-feedback {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 5.5em;
    text-align: center;
    font-size: 1.3em;
    color: var(--dw-color-feedback-wrong);
    min-height: 1.5em;
    margin: 0;
    z-index: 4;
    pointer-events: none;
    text-shadow: 0 0.05em 0.15em rgba(255,255,255,0.7);
}

/* --- Stage E: post-payment cashier line ("Thanks, here's your change.").
       Visible counterpart of cashierText2 in Flash frame_07 line 1045.
       Sits above the change cluster, fading in as it arrives. */
.sm-cashier-text2 {
    position: absolute;
    left: 0;
    right: 0;
    top: 0.4em;
    text-align: center;
    font-size: 1.3em;
    color: #205313;
    min-height: 1.5em;
    margin: 0;
    z-index: 5;
    pointer-events: none;
    text-shadow: 0 0.05em 0.15em rgba(255,255,255,0.7);
    animation: sm-cashier-text-fade 0.4s ease-out;
}

@keyframes sm-cashier-text-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Single cashier-hand sprite used for the whole payment stage. Reaches
   in from the top-right holding an empty palm — resting pose visible
   throughout the coin-payment loop, hidden instantly on Done, then
   slid back in for the change-delivery / see-you-soon beats. */
.sm-cashier-hand-sprite {
    position: absolute;
    width: 12em;
    height: auto;
    /* Position via right/top so the enter/exit keyframes' translate(0,0)
       resting state maps to the visible rest pose.  Rotation must match
       the keyframes' rotate(36deg). */
    right: 5em;
    top: -2.5em;
    z-index: 6;
    pointer-events: none;
    transform: rotate(36deg);
    transform-origin: top right;
}

/* Vanish: applied on Done. Instantaneous — the hand withdraws off-stage
   without a tween so the counter reads as "cashier just took the money". */
.sm-cashier-hand-vanish {
    opacity: 0;
    visibility: hidden;
}

/* Slide back in from off the top-right. Used for both the change-owed
   re-entry (hand carries the change cluster) and the exact-payment
   goodbye beat. The 500ms delay gives a beat between "cashier took the
   money" and "cashier reappears". */
.sm-cashier-hand-enter-change,
.sm-cashier-hand-enter-empty {
    animation: sm-cashier-hand-enter 0.6s ease-out 0.5s both;
}

@keyframes sm-cashier-hand-enter {
    from { transform: translate(20em, -12em) rotate(36deg); opacity: 0; }
    to   { transform: translate(0,    0)     rotate(36deg); opacity: 1; }
}

/* Final exit (after the user takes the change): hand slides off the
   top-right again. */
.sm-cashier-hand-final-exit {
    animation: sm-cashier-hand-exit 0.6s ease-in 0.6s forwards;
}

@keyframes sm-cashier-hand-exit {
    from { transform: translate(0,    0)     rotate(36deg); opacity: 1; }
    to   { transform: translate(20em, -12em) rotate(36deg); opacity: 0; }
}

/* Wallet exit: at "Thanks, see you soon" the customer's hand (wallet
   group) drops away downward alongside the cashier hand's final exit.
   The `from` transforms match the resting transforms on .sm-wallet-group
   and .sm-cashier-hand-money EXACTLY so the wallet doesn't jump to a
   different position for one frame at animation start (which read as
   the wallet lifting up before dropping down). */
.sm-wallet-exit-down {
    /* Delay long enough that the change pile has finished fading into
       the wallet (collect animation runs 1.2s) before the wallet drops
       away — otherwise the wallet slides down under coins that are still
       visible, which reads as the change being spilled. */
    animation: sm-wallet-exit-down 0.6s ease-in 1.2s forwards;
}

@keyframes sm-wallet-exit-down {
    from { transform: translate(3.45em, 15.35em) scale(1.4); opacity: 1; }
    to   { transform: translate(3.45em, 35.35em) scale(1.4); opacity: 0; }
}

.sm-wallet-area-exit-down {
    /* Same delay as .sm-wallet-exit-down — wallet-group + money-fan
       drop together after the change pile has faded. */
    animation: sm-wallet-area-exit-down 0.6s ease-in 1.2s forwards;
}

@keyframes sm-wallet-area-exit-down {
    from { transform: translate(1.62em, -1.39em) scale(1.3375); opacity: 1; }
    to   { transform: translate(1.62em, 22.36em) scale(1.3375); opacity: 0; }
}

/* --- Change cluster (Flash changeClip) ----------------------------------

   A single clickable button — the user "picks up the pile of change" in
   one click (Flash-style, per the stage-E spec).  Greedy-change coins
   are positioned inside the cluster using --sm-cl-x / --sm-cl-y custom
   properties (per-coin) so we don't have to inline pixel positions in JS.

   Resting position roughly matches Flash (570, 160) — over the counter,
   slightly left of centre. Entry tweens from off-top-right (800, -300),
   exit (in stages: to the customer's hand at (235, 439), then off the
   bottom-left to (100, 900)) via the -collect / -exit classes below.
*/
.sm-change-cluster-btn {
    position: absolute;
    border: none;
    background: transparent;
    padding: var(--dw-space-snug);
    cursor: pointer;
    /* Position via right/top so the enter/collect keyframes keep their
       translate(0,0) resting state.  scale stays in transform. */
    right: 2em;
    top: 5.95em;
    width: 10em;
    height: 6em;
    z-index: 9;                     /* above hand + till-drop coins */
    transform: scale(2.32);
    transform-origin: top right;
}

/* Hover/focus feedback: only a yellow glow on the individual coin/note
   sprites (via drop-shadow tracing each alpha edge). Suppress the global
   button:hover background (doorway.css) so the invisible bounding rect
   doesn't paint a semi-transparent rounded rectangle behind the pile. */
.sm-change-cluster-btn:focus-visible {
    background: transparent;
}
@media (hover: hover) {
    .sm-change-cluster-btn:hover {
        background: transparent;
    }
}
.sm-change-cluster-btn:focus-visible img {
    filter: drop-shadow(0 0 0.25em #ffec3b)
            drop-shadow(0 0 0.15em #ffec3b);
}
@media (hover: hover) {
    .sm-change-cluster-btn:hover img {
        filter: drop-shadow(0 0 0.25em #ffec3b)
                drop-shadow(0 0 0.15em #ffec3b);
    }
}

/* Coins/notes inside the cluster are decorative — clicks land on the
   parent button as a single target.  Per-denomination widths mirror
   real-world diameters (1p is 20mm; £2 is 28.4mm — noticeably wider;
   £5/£10/£20 notes are ~125/132/139mm — each slightly wider than
   the last).  Notes stay behind, coins scatter on top. */
.sm-change-cluster-btn img {
    position: absolute;
    left: var(--sm-cl-x, 0);
    top:  var(--sm-cl-y, 0);
    pointer-events: none;
    width: 1.6em;                   /* fallback if data-value missing */
    height: auto;
    object-fit: contain;
    z-index: 2;                     /* coins in front of notes */
}

/* Coin sizes — proportional to real-world diameters. */
.sm-change-cluster-btn img[data-value="1"]    { width: 1.1em;  }
.sm-change-cluster-btn img[data-value="2"]    { width: 1.45em; }
.sm-change-cluster-btn img[data-value="5"]    { width: 1.0em;  }
.sm-change-cluster-btn img[data-value="10"]   { width: 1.4em;  }
.sm-change-cluster-btn img[data-value="20"]   { width: 1.2em;  }
.sm-change-cluster-btn img[data-value="50"]   { width: 1.55em; }
.sm-change-cluster-btn img[data-value="100"]  { width: 1.3em;  }
.sm-change-cluster-btn img[data-value="200"]  { width: 1.6em;  }

/* Note sizes — proportional to real-world widths, sized so notes sit
   alongside the coins in the change cluster without dominating the pile. */
.sm-change-cluster-btn img.sm-cl-note              { z-index: 1; }  /* behind coins */
.sm-change-cluster-btn img[data-value="500"]  { width: 5.32em;  }
.sm-change-cluster-btn img[data-value="1000"] { width: 5.624em; }
.sm-change-cluster-btn img[data-value="2000"] { width: 5.928em; }

/* Entry: cluster slides in from off-right in sync with the cashier
   hand (same 0.5s delay, 0.6s duration, same start offset). */
.sm-change-cluster-enter {
    animation: sm-change-cluster-enter 0.6s ease-out 0.5s both;
}

@keyframes sm-change-cluster-enter {
    from { transform: translate(20em, -12em) scale(2.32); opacity: 0; }
    to   { transform: translate(0,    0)     scale(2.32); opacity: 1; }
}

/* Collect: cluster tweens from rest → over the top of the wallet at
   bottom-left, so the change visibly lands where the customer keeps
   their money. Scale is preserved so the pile doesn't shrink en route.
   Fade-out is folded into the same keyframes (58% → 100%) so the
   arrival and disappearance share one animation. */
.sm-change-cluster-collect {
    animation: sm-change-cluster-collect 1.2s ease-in-out forwards;
}

@keyframes sm-change-cluster-collect {
    0%   { transform: translate(0,      0)     scale(2.32); opacity: 1; }
    58%  { transform: translate(-15em,  8.3em) scale(2.32); opacity: 1; }
    100% { transform: translate(-15em, 10.3em) scale(2.32); opacity: 0; }
}

/* --- Receipt screen ---
   Flash: white paper with horizontal ruled lines, title at the top, table
   filling the body, totals/cash/change at the bottom-right, and a four-
   checkbox self-assessment row below ("How well did you use rounding?").
*/

/* Receipt "ruled paper" geometry.
   --sm-receipt-row is a single em-scaled number that drives both the
   table's line-height AND the striped-paper gradient pitch, so the
   horizontal blue rules always land exactly on each row's baseline
   (rather than drifting between rows). Value = table font-size (1.05em)
   * table line-height (1.6). Bumped once here → everything follows. */
.sm-receipt {
    --sm-receipt-row: 1.68em;
    flex: 1;
    overflow-y: auto;
    padding: 0.8em 1.2em;
    background:
        repeating-linear-gradient(
            to bottom,
            #ffffff 0em,
            #ffffff calc(var(--sm-receipt-row) - 0.05em),
            #b8c8d4 calc(var(--sm-receipt-row) - 0.05em),
            #b8c8d4 var(--sm-receipt-row)
        );
    /* Anchor the gradient so the first blue rule sits on the baseline of
       the "Item / Price / Rounded" header row.
         title font-size 1.4em × margin-bottom 0.6em  ≈ 0.84em
         title padding-bottom 0.2em × 1.4em          ≈ 0.28em
         title height ≈ 1.4em × line-height (~1.15)  ≈ 1.61em
         + container padding-top 0.8em, then one header row-height
         under it. Rather than trying to compute this in CSS, we set
         the position offset to the value that visually lines up
         with the first header baseline (verified in screenshots).
       If the receipt title height or padding changes, re-tune here. */
    background-position: 0 3.35em;
    background-attachment: local;
    border: 1px solid var(--dw-color-border-muted);
    box-shadow: 0 0.2em 0.6em rgba(0,0,0,0.1);
    color: var(--dw-color-text-primary);
}

.sm-receipt-title {
    font-size: var(--dw-font-size-large);
    margin: 0 0 var(--dw-space-comfy) 0;
    text-align: left;
    border-bottom: 1px solid var(--dw-color-border-muted);
    padding-bottom: var(--dw-space-tight);
}

.sm-receipt-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 1.05em;
    /* Row height = --sm-receipt-row (in the receipt container's em),
       which is 1.6em in the table's own em (since font-size is 1.05em).
       Keep them in sync. */
    line-height: 1.6em;
    table-layout: fixed;
}

.sm-receipt-table col.sm-col-item    { width: 50%; }
.sm-receipt-table col.sm-col-price   { width: 25%; }
.sm-receipt-table col.sm-col-rounded { width: 25%; }

.sm-receipt-table th,
.sm-receipt-table td {
    padding: 0 var(--dw-space-comfy);
    border: none;
    text-align: left;
    vertical-align: baseline;
}

.sm-receipt-table thead th {
    font-weight: bold;
    border-bottom: 1px solid var(--dw-color-border-muted);
}

/* Money columns: cells right-aligned (standard money-table
   convention) AND the header sits over the same right edge. */
.sm-receipt-table thead th:nth-child(2),
.sm-receipt-table thead th:nth-child(3),
.sm-receipt-table tbody td:nth-child(2),
.sm-receipt-table tbody td:nth-child(3),
.sm-receipt-table tfoot td {
    text-align: right;
}

.sm-receipt-table tfoot th {
    text-align: right;
    font-weight: bold;
}

.sm-receipt-table tfoot tr:first-child th,
.sm-receipt-table tfoot tr:first-child td {
    border-top: 1px solid var(--dw-color-border-muted);
    padding-top: var(--dw-space-snug);
}

/* Self-assessment row, below the receipt paper. Uses `display: flex` when
   shown, but must respect `.hidden_panel` when round_on=false — the two
   selectors are the same specificity (0,1,0), so a matching-specificity
   compound (`.sm-receipt-eval.hidden_panel`) overrides flex back to none. */
.sm-receipt-eval {
    border: none;
    padding: var(--dw-space-narrow) 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--dw-space-narrow) var(--dw-space-comfy);
    font-size: 1em;
}

.sm-receipt-eval.hidden_panel {
    display: none;
}

.sm-receipt-eval legend {
    font-weight: bold;
    width: 100%;
    margin-bottom: var(--dw-space-tight);
}

/* The rounding-quality answer isn't a real form the app submits — it's
   a self-assessment badge — but keeping it as a radio group means keyboard
   users can still pick one and see the pill highlight the selection.
   Shared pill styling in doorway.css is scoped to `div.user_options`, so
   re-declare the pill look here for the receipt's fieldset. */
.sm-receipt-eval input[type="radio"] {
    /* Hide the native radio dot; the pill label acts as the visual. */
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.sm-receipt-eval label.user_options_radio {
    border: 0.1em solid grey;
    margin: 0.1em;
    padding: 0.1em var(--dw-space-comfy);
    border-radius: 0.5em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.sm-receipt-eval input[type="radio"]:checked + label.user_options_radio {
    background-color: chartreuse;
}

/* Keyboard focus visible on the pill even though the input is hidden. */
.sm-receipt-eval input[type="radio"]:focus-visible + label.user_options_radio {
    outline: 0.15em solid #205313;
    outline-offset: 0.1em;
}

/* --- Accessibility --- */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}

.sm-print-hint {
    font-size: 0.75em;
    color: var(--dw-color-text-muted);
    text-align: right;
    margin: var(--dw-space-snug) 0 0 0;
}

/* --- Print stylesheet — show only the receipt paper ---
   The Flash original printed the receipt (frame_08 printButton), so the
   learner can take home a record of their shopping. We strip the page
   chrome, the eval radios, and the action buttons so the printed sheet
   is just the receipt itself. */
@media print {
    @page { margin: 1.5cm; }

    body { background: #fff; }

    #dwNavigationHeader,
    .dw-screen-header,
    .dw-app-footer,
    #dwWelcomeScreen,
    #dwUserOptions,
    #dwShoppingScreen,
    #dwPaymentScreen,
    .sm-screen-nav,
    .sm-receipt-eval,
    .sm-print-hint {
        display: none !important;
    }

    .doorway_application,
    .doorway_fullscreen_div,
    .doorway_aspect_outer_div,
    .doorway_aspect_div,
    main {
        position: static !important;
        width: auto !important;
        height: auto !important;
        max-width: none !important;
        max-height: none !important;
        overflow: visible !important;
        transform: none !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    #dwReceiptScreen {
        position: static !important;
        display: block !important;
        width: 100% !important;
        height: auto !important;
        padding: 0 !important;
        overflow: visible !important;
        font-size: 12pt;
    }

    .sm-receipt {
        flex: none;
        overflow: visible;
        box-shadow: none;
        background: #fff;
        border: 1px solid var(--dw-color-border-muted);
    }

    .sm-receipt-table { font-size: 1em; }
}

/* --- Reduced motion ---
   Collapse all animations and transitions to 0.01ms so
   `animationend`/`transitionend` listeners still fire and game-state
   sequencing still works, but the visible motion is removed. Each
   conveyor item jumps straight to its exit position (off-screen), and
   the animationend fires so the beep + till-total reveal sequencing
   still completes.
*/
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
