/* Doorway Till We Meet Again — activity styles.
   1em = activity_width/50 (set by doorway.js onResize).
   The visible activity height is ~28em (constrained by doorway max-height: 56.25vw).
   All absolute positions are scaled from the Flash 800×600 stage
   (original 37.5em height → multiply by 28/37.5 ≈ 0.75).

   Scene background palette from the Flash:
     White (#ffffff)    — upper ~62% of height (shop interior)
     Green (#a2c18c)    — lower ~38% (floor / till front)
     Cash register      — grey-purple (#928e92 / #656165)
     LCD display        — yellow (#ffff66)
     Hand               — skin tone (#eac0a8)
*/

/* R3 — Inner/control fieldsets (radio-button pairs) have no visible box in Flash.
   Outer section fieldsets (Activity, Speech, Accessibility) keep their default border. */
.options_group fieldset {
    border: none;
    padding: 0;
    margin: 0;
}

/* Welcome illustration — portrait till SVG (376×588 → aspect 0.64). The
   activity's till art is taller than it is wide, so we size by HEIGHT to
   match the Flash composition (till occupies roughly the centre third) and
   let width follow the aspect ratio. Without an explicit height on the
   wrapper, the inner img's `height: 100%` (from shared doorway.css) collapses
   to auto, and the image stretches taller than max-height, overlapping the
   title above and subtitle below. */
.welcome_image {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: auto;
    height: 9.5em;
    margin: var(--dw-space-narrow) auto;
}

/* Override shared `div.welcome_image img { width: 100%; height: 100%; }` so
   the portrait till SVG isn't squashed into a square and isn't forced wider
   than its container. */
.welcome_image img {
    width: auto;
    height: 100%;
    max-width: 100%;
    object-fit: contain;
    display: block;
}

/* ─── Options screen — scale up to fill the 16:9 activity area ──────────── */

/* Larger radio-toggle buttons to match Flash button prominence */
#dwUserOptions label.user_options_radio {
    padding: 0.45em 0.75em;
    font-size: 1.15em;
    min-width: 2.5em;
    text-align: center;
}

/* Till-screen mode buttons render their Flash-faithful primary label on one
   line ("Price + change") plus a smaller help-text subtitle below
   ("(most help)"). */
#dwUserOptions label.user_options_radio strong {
    display: block;
    font-weight: bold;
    line-height: 1.1;
}

#dwUserOptions label.user_options_radio .user_options_radio_subtitle {
    display: block;
    font-size: 0.78em;
    font-weight: normal;
    line-height: 1.2;
    margin-top: 0.1em;
    opacity: 0.85;
}

/* ─── Results screen (flex column, unchanged) ───────────────────────────── */

/* Flex-column skeleton comes from .dw-activity-screen in shared/doorway.css. */
.tw-screen {
    overflow-y: auto;
    /* Top padding sized so the title baseline sits level with the nav-header
       buttons (.teacher_button height 2em, top margin 0.1em) rather than in a
       big banner below them. */
    padding: var(--dw-space-tight) var(--dw-space-loose) var(--dw-space-loose);
    gap: var(--dw-space-narrow);
}

.tw-screen-title {
    /* Nav-level heading, not banner — proportional to the .teacher_button
       height (2em) so the title reads as part of the top toolbar band. */
    font-size: var(--dw-font-size-large);
    margin: 0 0 var(--dw-space-narrow) 0;
    text-align: center;
    font-weight: normal;
}

/* ─── Activity scene container ──────────────────────────────────────────── */

.tw-scene {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    box-sizing: border-box;
    /* Flash palette: white shop interior; green floor sprite covers lower band. */
    background: #ffffff;
}

/* ─── Green floor (Flash sprite_228) ────────────────────────────────────── */
/* Flash stage: floor occupies bottom ~38% (y 372..600 of 600). HTML5 stage
   is 16:9; raised the floor top to ~42% so it meets the closed till's bottom
   edge with a small overlap (no visible white gap between till and floor),
   matching Flash. The drawer (z=2) is painted ABOVE the floor (z=0) so it
   remains fully visible when sliding out below the body. */
.tw-floor-bg {
    position: absolute;
    left:   0;
    right:  0;
    bottom: 0;
    width:  100%;
    height: 42%;
    display: block;
    z-index: 0;
    object-fit: fill;
}

/* ─── Till assembly ─────────────────────────────────────────────────────── */
/* Cash register at the left of the stage, drawn with the Flash sprite_172
   SVG (till body + monitor surround + closed drawer) as the background image.
   The LCD bezel, check button, "Tendered:" label, and open-drawer overlay
   are absolutely positioned over the body sprite.

   Flash native sprite_172 is 376×588 (4:3 origin). Mapping to the 50em wide
   16:9 stage: width ≈ 19em, native aspect ≈ 0.64 → height ≈ 19/0.64 ≈ 29.7em.
   That overflows our 28em stage, so we cap height to the play area and let
   the SVG's intrinsic aspect ratio scale width to ~17.4em. */

.tw-till-assembly {
    position: absolute;
    /* Flash till: left edge x≈30, top y≈80 on the 800×600 stage; visible
       width ≈ 330px ≈ 20.6em, with the drawer drop included it extends
       almost full stage height. Top in HTML5: 80 × 0.75 / 16 ≈ 3.75em.
       Native till-body.svg aspect 376/588 ≈ 0.64. Sizing the assembly to
       this aspect ratio means the absolute child positions (LCD bezel,
       check button, "Tendered:" label) align with the painted artwork
       directly — no letterbox offset to compensate for. */
    /* Shifted right by ~1.5 × the shared nav-button width (3em — see
       .teacher_button in doorway.css) so the till sits clear of the
       top-left nav-header buttons (gear / fullscreen / audio toggle). */
    left:    6em;
    top:     0.4em;
    width:   17em;
    height:  26.6em;
    z-index: 1;
}

/* Till body — Flash sprite_172. Fits the assembly box; the inner monitor
   cutout and closed-drawer artwork are part of the sprite. */
.tw-till-bg {
    position: absolute;
    left:   0;
    top:    0;
    width:  100%;
    height: 100%;
    object-fit: contain;
    object-position: top center;
    pointer-events: none;
    /* Above the drawer (z=2/3) so the body acts like a mask: anything
       below the body's bottom clip line shows the drawer; above shows
       only the body. Interior elements (bezel z=5, check z=6, etc.)
       remain on top of the body via DOM order / higher z. */
    z-index: 5;
    /* Clip the body so it ends at the open-drawer's top line. The
       open-drawer overlay slides UP from behind the body until it
       rests just below the clip line. */
    clip-path: inset(0 0 43.5% 0);
}

/* Background copy of the till body: same SVG, full uncropped, painted
   BELOW the drawer animation so the till silhouette persists behind the
   drawer when it slides out (no transparent gap between body bottom and
   drawer top). Only the upper-clip mask copy (.tw-till-bg above) and
   the closed-front lip act on top of the drawer. */
.tw-till-bg.tw-till-bg-back {
    z-index: 1;
    clip-path: none;
}

/* Closed-drawer front face — same SVG as the open drawer but clipped
   to expose only the front lip portion at the bottom. Sits over the
   till body's bottom edge so the closed till reads as having a drawer
   flush against the register. Hidden when the drawer is open. */
.tw-drawer-closed-front {
    position: absolute;
    /* Box at the open-drawer's natural width (20em); the horizontal
       squeeze is applied via transform: scaleX so the painted SVG
       actually shrinks (object-fit:contain would otherwise preserve
       the SVG's aspect and just letterbox a narrower box). */
    left:   -1.5em;
    width:  20em;
    top:    4.6em;
    height: 12.2em;
    object-fit: contain;
    object-position: top center;
    pointer-events: none;
    z-index: 4;
    /* Clip the top so only the front-lip portion of the drawer SVG
       shows below the body clip line. */
    clip-path: inset(85.5% 0 0 0);
    /* Squeeze the painted lip 10% narrower than the open drawer. */
    transform: scaleX(0.9);
    transform-origin: center;
    transition: opacity 0.3s ease-out;
}

/* When the drawer is open (.tw-drawer-open-img is not .hidden_panel),
   hide the closed-front lip so it doesn't double up with the open
   drawer's own front. */
.tw-drawer-open-img:not(.hidden_panel) ~ .tw-drawer-closed-front {
    opacity: 0;
}

/* Open-drawer overlay (Flash sprite_171) — swapped in over the closed-drawer
   portion of sprite_172 when the till opens. Positioned to align with the
   drawer cutout in the body sprite.
   When closed (hidden_panel), the overlay sits tucked up inside the till
   body (translateY) so the user sees only the closed-drawer face painted
   into till-body.svg. On open, it slides down into its resting position.
   The drawer extends sideways beyond the till body to read as "pulled out"
   and to give the painted coins inside enough room to render at a size
   closer to the palm coins (so the fly-in animation doesn't visibly scale). */
.tw-drawer-open-img {
    position: absolute;
    /* Sized and offset so the drawer overlay aligns with the painted
       closed-drawer face in till-body.svg and extends sideways beyond
       the 17em-wide till body to read as "pulled out". */
    left:   -1.5em;
    width:  20em;
    top:    15em;
    height: 12.2em;
    object-fit: contain;
    object-position: top center;
    pointer-events: none;
    z-index: 2;
    /* `visibility 0s linear 0s` — when going to visible (drawer opening),
       flip immediately so the animation is seen. When going to hidden
       (drawer closing) the transition is overridden inside .hidden_panel
       below to delay until after opacity/transform finish, so the
       slide-up animation also plays before the element hides. */
    transition: transform 0.45s ease-out, opacity 0.3s ease-out, visibility 0s linear 0s;
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
}

/* Override the shared `.hidden_panel { display: none }` so the drawer can
   actually animate. With display:none the browser short-circuits the
   transform/opacity transitions (display → block is not interpolatable, so
   the drawer would teleport into place). Using visibility + opacity keeps
   the element in the layout tree so the transition runs visibly. */
.tw-drawer-open-img.hidden_panel {
    display: block;
    visibility: hidden;
    pointer-events: none;
    opacity: 0;
    /* Tuck the open-drawer SVG up inside the till body so when it becomes
       visible the user sees a "slide down" motion (the drawer opening). */
    transform: translateY(-3em);
    /* Delay the visibility flip until after the slide-up + fade-out
       animations finish, so the close also animates visibly. */
    transition: transform 0.45s ease-out, opacity 0.3s ease-out, visibility 0s linear 0.45s;
}

/* Black LCD monitor area — sits over the black monitor cutout drawn into
   sprite_172. Flash's monitor is at top-centre of the till body, roughly
   x=80..330, y=10..60 of the 376×588 till sprite. */
.tw-till-bezel {
    position: absolute;
    /* Black LCD cutout in till-body.svg occupies x≈113..316 of width 376
       (30%..84%) → 5.1em..14.3em on the 17em-wide assembly. Anchor the
       text bezel slightly left of LCD centre so the Price/Change strings
       sit comfortably within the cutout (shifted +7% of bezel width right
       from the previous 3.72em to better centre over the painted black
       monitor cutout). */
    left:    4.36em;
    top:     0.3em;
    width:   9.2em;
    height:  2.5em;
    background: transparent;       /* sprite_172 already paints the black box */
    padding: var(--dw-space-tight) var(--dw-space-narrow);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    overflow: hidden;
    z-index: 5;
}

.tw-till-bezel-line {
    margin: 0;
    color: #fff;
    font-family: "Courier New", monospace;
    font-size: 0.7em;
    font-weight: bold;
    text-align: center;
    line-height: 1.15;
    white-space: nowrap;
}

.tw-till-bezel-line.tw-till-bezel-hidden {
    visibility: hidden;
}

/* Check button — Flash sprite_159 (white box, green border, ✓). Sits on the
   till body on the lighter grey "neck" platform between the LCD and the
   main body. Flash stage coords: roughly x=105..235, y=90..130 of the
   800×600 stage. Mapped to the till assembly (17em wide × 26.6em tall,
   starting at left:1.5em top:0.4em): the neck strip is at viewbox y≈86..149
   of the 588px SVG (14.6%..25.3% of 26.6em = 3.9em..6.7em). */
.tw-till-check {
    position: absolute;
    left:    5.1em;
    top:     4.1em;
    width:   6.7em;
    height:  2em;
    z-index: 6;
    background: #ffffff;
    border: 0.18em solid #00aa1a;
    border-radius: 0.35em;
    font-family: 'Patrick Hand', 'Comic Sans MS', cursive;
    font-size: 1em;
    font-weight: bold;
    cursor: pointer;
    padding: 0 var(--dw-space-default);
    color: #000;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.tw-till-check::after {
    content: "✓";
    color: #00aa1a;
    margin-left: var(--dw-space-snug);
    font-size: var(--dw-font-size-subheading);
    font-weight: bold;
}

.tw-till-check:focus-visible {
    outline: 0.25em solid #ff9900;
    outline-offset: 0.05em;
}
@media (hover: hover) {
    .tw-till-check:hover {
        outline: 0.25em solid #ff9900;
        outline-offset: 0.05em;
    }
}

.tw-till-check:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Tendered-money destination box: the customer's payment lands here after
   _onTakePayment's fly-tween, and remains visible until the next question
   re-renders. Sits below the "Tendered:" label on the till body's grey
   neck, above the drawer line. Sized to hold a £5 note at the same size
   the note renders in the drawer (.tw-denom-note: 11.9em × 6.3em) so the
   note doesn't change size when it lands. */
.tw-till-tendered-box {
    position: absolute;
    /* Horizontally centred on the 17em-wide till body so the box sits
       symmetrically below the LCD bezel / check button area.
       Centre = (17em − 11.9em) / 2 = 2.55em.
       Sized to the canonical note footprint (11.9em × 6.3em — same as
       the drawer .tw-denom-note, in-hand .tw-slot-note, and customer
       offering .tw-tendered-money) so the £5 note doesn't grow or
       shrink when it lands here. */
    left:    2.55em;
    top:     8.2em;
    width:   11.9em;
    height:  6.3em;
    background: transparent;
    border: 0;
    box-sizing: border-box;
    z-index: 6;
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* The landed money image inside the tendered box. */
.tw-till-tendered-box img {
    width: auto;
    height: 100%;
    max-width: 100%;
    object-fit: contain;
    display: block;
    /* Match the drop-shadow used on palm coins so the note reads as a
       physical object resting in the box. */
    filter: drop-shadow(0.08em 0.1em 0.05em var(--dw-color-shadow-strong));
}

/* Static "Tendered:" label, printed on the till body to the right of check.
   Flash places it at roughly (60, 165) of the till sprite (under the check
   button on the left, below the monitor). */
.tw-till-tendered-label {
    position: absolute;
    /* "Tendered:" label on the till body. Flash places it just below the
       check button. In our HTML5 till sprite the lighter grey neck strip
       sits between LCD and the dark trapezoid; we land the label on that
       neck strip just right of the check button so it's centred on the
       till's grey body and clearly inside the till's outline. Dark text
       on the light grey neck matches Flash's high-contrast rendering. */
    left:    5em;
    top:     8em;
    margin:  0;
    font-family: 'Patrick Hand', 'Comic Sans MS', cursive;
    font-size: 0.85em;
    color: #1a1a1a;
    z-index: 5;
    pointer-events: none;
}

/* Drawer-interior overlay: Flash coinsImage.svg occupies the open-drawer
   area. Transparent hit-target buttons are absolutely positioned over each
   coin denomination (positions derived from the <use> declarations in
   coinsImage.svg — see till-we-meet-again-debug.html for the % coordinates).
   The £5 note button sits over its drawer slot.

   Sized to the coins-image.svg native aspect (354.75 × 189.5 ≈ 1.87) so the
   `object-fit: contain` letterbox vanishes and the % hit targets stay aligned
   with the painted coins. */
.tw-drawer {
    position: absolute;
    /* Match the scaled-down open-drawer SVG sideways extent
       (left:-0.7em width:18.4em). Inset slightly so coins sit inside the
       painted tray rim, not on it. */
    left:    -1.5em;
    right:   -1.5em;
    /* Aligns with the open-drawer SVG (top:15em + small inset to sit
       inside the drawer's coin tray, not on its lip). */
    top:     15.7em;
    /* Height matches the open-drawer SVG's coin-tray band. The
       coin-image and percentage-positioned hit targets scale with
       this container; absolute-em hit-target sizes on
       .tw-denom-coin / .tw-denom-p* are set independently. */
    height:  9.25em;
    z-index: 3;
    box-sizing: border-box;
    /* visibility 0s linear 0s — flip immediately on open (so user sees the
       fade-in); the hidden state overrides this with a 0.45s delay so the
       close animates visibly before the element is removed. */
    transition: transform 0.45s ease-out, opacity 0.3s ease-out, visibility 0s linear 0s;
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
}

/* Same display-block override as .tw-drawer-open-img.hidden_panel above —
   keeps the coin-tray container in layout so its translate + opacity
   transitions actually run when the drawer opens/closes. */
.tw-drawer.hidden_panel {
    display: block;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    /* Slide down with the open-drawer artwork so the coins reveal as the
       drawer extends out. */
    transform: translateY(-3em);
    /* Delay the visibility flip so the close animation plays before the
       element is removed from view. */
    transition: transform 0.45s ease-out, opacity 0.3s ease-out, visibility 0s linear 0.45s;
}

/* coins-image.svg: visible 8-coin tray painted by Flash inside the drawer.
   Rendered as a 3-layer stack to read as 3 coins piled up — the front
   (last-painted) copy sits at the canonical position; back/mid copies are
   offset left + down so each denomination looks like a small stack.
   The whole asset is also shrunk 7% and shifted down ~1em (1/4 of a 5p
   height) to clear the top lip of the drawer. */
.tw-coins-image {
    position: absolute;
    left:   1.75%;
    top:    1.15em;
    width:  95%;
    height: 95%;
    object-fit: contain;
    object-position: top center;
    pointer-events: none;
    z-index: 3;
}

/* Back/mid copies of the stack sit UP-RIGHT of the front coin so the
   painted top reads as resting on smaller coins peeking out behind it. */
.tw-coins-image.tw-coins-image-back {
    transform: translate(0.25em, -0.25em);
    z-index: 1;
}

.tw-coins-image.tw-coins-image-mid {
    transform: translate(0.12em, -0.12em);
    z-index: 2;
}

/* Coin-button container: matches the FRONT .tw-coins-image so the
   percentage-positioned hit targets line up with the painted top coin
   of each stack (not the back/mid copies that are offset below-left).
   pointer-events: none so the transparent gaps between coin buttons
   don't swallow clicks — they fall through to whatever is underneath
   (e.g. the £5 note that overhangs the upper-row coin region). The
   individual .tw-denom-coin buttons re-enable pointer events on their
   own footprint. */
.tw-coin-buttons {
    position: absolute;
    left:   8.25%;
    top:    1.15em;
    width:  82%;
    height: 95%;
    z-index: 4;
    pointer-events: none;
}

/* Coin hit targets: invisible buttons over each coin in coins-image.svg.
   Sized in em so the targets are circular (not stretched ovals matching the
   container's aspect). Positions are centres of each coin as a % of the
   354.75×189.5 SVG box, derived from the <use> transforms in coinsImage.svg
   (outer translate (3, 68.9) + per-coin matrix offsets). The 50p and £2
   coins are visually larger in the Flash artwork, so their hit boxes are
   correspondingly larger. */
.tw-denom-coin {
    position: absolute;
    /* Hit-target diameter matches the painted coin and the palm-slot
       diameter (TillWeMeetAgain.COIN_FACE_SIZES_EM) so the same coin
       reads the same size in the drawer, mid-flight, and on the palm. */
    width:  2.8em;
    height: 2.8em;
    transform: translate(-50%, -50%);
    background: transparent;
    border: 0.15em solid transparent;
    border-radius: 50%;
    cursor: pointer;
    padding: 0;
    /* Re-enable hit testing inside the pointer-events:none .tw-coin-buttons
       container so each coin button captures clicks within its own
       footprint while the gaps fall through to the £5 note behind. */
    pointer-events: auto;
}

/* Per-denomination centres (% of coins-image.svg native viewport 354.75×189.5).
   Hit-target sizes mirror the painted coin sizes so each drawer coin reads
   at the same visible diameter as the corresponding palm coin. */
.tw-denom-p1   { left: 12.3%; top: 33.6%; }
.tw-denom-p2   { left: 34.5%; top: 25.6%; width: 3.2em; height: 3.2em; }
.tw-denom-p5   { left: 54.7%; top: 40.4%; width: 2.4em; height: 2.4em; }
.tw-denom-p10  { left: 74.3%; top: 35.9%; width: 2.9em; height: 2.9em; }
.tw-denom-p20  { left: 10.7%; top: 73.2%; }
.tw-denom-p50  { left: 34.4%; top: 73.5%; width: 3.5em; height: 3.5em; }
.tw-denom-p100 { left: 59.7%; top: 76.8%; width: 2.9em; height: 2.9em; }
.tw-denom-p200 { left: 85.6%; top: 73.0%; width: 3.6em; height: 3.6em; }

/* £5 note button. The Flash composition places `t500` (the note's drawer
   slot) above the coin tray, inside the drawer. We position it just over
   the upper edge of the open drawer SVG and size it to match the palm
   .tw-slot-note (11.9em × 6.3em) so the note never changes size between
   drawer and palm. */
.tw-denom-note {
    position: absolute;
    /* Sits inside the drawer's coin tray. Footprint matches the in-hand
       .tw-slot-note (11.9em × 6.3em) and the tendered-money offering
       (.tw-tendered-money) so the £5 note renders at the same apparent
       size in the drawer, in the customer's offering hand, and as change
       on the palm. */
    left:    8.1em;
    top:     0em;
    width:   11.9em;
    height:  6.3em;
    padding: 0;
    background: transparent;
    border: 0.2em solid transparent;
    border-radius: 0.3em;
    /* Sit BEHIND the painted coin SVG so coins occlude the note where they
       overlap, but in front of the drawer interior. The note button's
       bounding box overlaps the upper-row coin hit targets (5p/10p);
       click priority is handled by stacking — the .tw-coin-buttons
       container is z:4 so each coin button wins on its own footprint,
       and the container itself uses pointer-events:none so the gaps
       between coins fall through to this note (z:0) underneath. */
    z-index: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

.tw-denom-note img {
    width:  auto;
    height: 100%;
    max-width: 100%;
    object-fit: contain;
    display: block;
}

.tw-denom-btn:focus-visible {
    outline: 0.18em solid #ff9900;
    outline-offset: 0.05em;
}
@media (hover: hover) {
    .tw-denom-btn:hover {
        outline: 0.18em solid #ff9900;
        outline-offset: 0.05em;
    }
}

/* The drawer £5 note uses the same 0.2em flush outline as the other
   note positions (.tw-slot-note in-hand, .tw-tendered-btn customer
   offering) so the hover/focus ring is consistent across all note
   positions, not the thinner offset ring used for coin denominations. */
.tw-denom-btn.tw-denom-note:focus-visible {
    outline: 0.2em solid #ff9900;
    outline-offset: 0;
}
@media (hover: hover) {
    .tw-denom-btn.tw-denom-note:hover {
        outline: 0.2em solid #ff9900;
        outline-offset: 0;
    }
}

.tw-denom-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* When the £5 note button is disabled (after a note has been given) we
   release pointer events so clicks pass through to the painted coin hit
   targets underneath. Without this, the note button's bounding box
   (which overlaps the 5p/10p coin slots in the drawer interior) swallows
   the click and the coin button never fires. */
.tw-denom-note:disabled,
.tw-denom-note:disabled img {
    pointer-events: none;
}

/* ─── Hand ──────────────────────────────────────────────────────────────── */
/* The customer's hand reaches in from the right, palm-up — Flash sprite_223
   is drawn in this exact orientation, so no CSS rotation is needed. The
   wrapper is sized to the hand SVG's intrinsic aspect (247×438 → ~0.564);
   palm-centre offsets in PALM_SLOTS are relative to this box.
   Flash hand starts at _x=1040 (off-stage right) and ends at _x=540
   (centre-right). Our `right` keyframe interpolates between off-stage
   (-22em) and on-stage (-1em) over the Flash-equivalent ~1.0 s. */

.tw-hand-wrapper {
    position: absolute;
    /* Hand SVG intrinsic aspect 247:438 ≈ 0.564 (portrait). Flash positions
       the customer's hand reaching in from the right, palm-up, tilted ~28°
       clockwise so the fingertips point upper-right (toward the wrist that
       enters off-stage upper-right) — wait, in Flash the wrist enters
       upper-right and fingers angle down-left. The wrapper sits in the
       upper-right of the stage, sized to keep the rotated palm compact. */
    right:  -22em;                /* off-stage right initially */
    top:    -6em;
    width:  20em;
    height: 24em;
    z-index: 8;
    overflow: visible;
    /* Flash hand move-in: ~25 frames @ 24fps ≈ 1.0s; move-out: ~51 frames
       ≈ 2.1s. Default to 2.1s here so `_handExit` plays at Flash-faithful
       speed; `_handEnter` overrides --tw-hand-duration to 1s for the
       move-in (see till-we-meet-again.js). */
    transition: right var(--tw-hand-duration, 2.1s) ease-out;
}

.tw-hand-wrapper.tw-hand-on-stage {
    /* Flash final hand _x ≈ 540 on the 800-wide stage; the hand visibly
       fills the upper-right half. In HTML5 we anchor the wrapper so the
       rotated wrist exits off-stage bottom-right while the palm and
       fingers stay on-stage upper-left. The off-stage `right: -22em`
       (below) is still wide enough to keep the wrist clear of the stage
       at this resting offset. */
    right: 5em;
}

.tw-hand-img {
    position: absolute;
    /* Pin to the wrapper's right edge and fix width. The rotation is
       applied to the entire .tw-hand-rotator wrapper around hand +
       tendered + coin slots so coins/notes follow the rotated palm. */
    right:  0;
    top:    0;
    width:  18em;
    height: auto;
    pointer-events: none;
    display: block;
}

/* Rotate the hand image AND all child overlays (tendered money, coin slots)
   together so coins/notes stay aligned with the rotated palm. Applied to a
   wrapper inside .tw-hand-wrapper rather than the wrapper itself, so the
   on-stage horizontal slide on .tw-hand-wrapper still works in CSS pixels
   without compounding with the rotation.
   transform-origin sits at the visual palm centre on the pre-rotation
   hand layout. With hand-img right:0 width:18em inside a 20em-wide
   wrapper, the image's palm region (viewbox x≈30..230/247, y≈100..360/438)
   maps to wrapper x≈4..18em, y≈8..27em → centre (55%, 73%). */
.tw-hand-rotator {
    position: absolute;
    inset: 0;
    transform-origin: 55% 73%;
    transform: rotate(28deg);
    pointer-events: none;
}

.tw-hand-rotator > * {
    pointer-events: auto;
}

/* ─── Item on counter ──────────────────────────────────────────────────── */
/* The item sits on the green counter in the bottom-right of the play area
   (Flash itemToBuy is at depth z12, ABOVE the customer hand z9). We anchor
   it to the right/bottom corner so it always reads as the thing being
   bought, regardless of the surrounding hand pose. pointer-events: none so
   the item never intercepts clicks meant for hand/coin buttons underneath. */
.tw-item-on-counter {
    position: absolute;
    /* Bottom-right anchor: ~1em margin from the right edge, sitting just
       above the floor line (floor is 28% of 28em ≈ 7.84em from bottom). */
    right:   1em;
    bottom:  1em;
    /* Sized to match Flash's item-on-counter footprint (the placeholder
       items take about 1/5 of the stage width). */
    width:   10em;
    height:  10em;
    object-fit: contain;
    object-position: right bottom;
    z-index: 9;
    pointer-events: none;
    display: block;
}

/* Item slides off-stage right when the question is correctly answered,
   timed with the till drawer closing — matches Flash frame_04.as:451
   (Regular.easeOut, 2 s, _x → 1200). Transition lives only on the
   .tw-item-exiting rule so removing the class on next-question render
   snaps the item back to its base position with no reverse animation. */
.tw-item-on-counter.tw-item-exiting,
.tw-item-price-label.tw-item-exiting {
    transform: translateX(15em);
    transition: transform 2s ease-out;
}

/* ─── Item price label ─────────────────────────────────────────────────── */
/* Small white "price tag" placed above the item on the counter — shows the
   numeric price of the current item in black writing on a white background
   (shopkeeper-style label). Same z-index as the item so it travels with it
   when the question is completed and the item slides off-stage. */
.tw-item-price-label {
    position: absolute;
    /* Sticker on top of the item in the bottom-right of the stage. The item
       sits at right:1em bottom:1em width:10em — we anchor the label to the
       same corner with a bit of medium padding so it overlays the item. The
       bottom buffer is half the right buffer so the label sits lower on the
       item (per visual review) without bleeding off the bottom of the stage. */
    right:   2em;
    bottom:  1em;
    margin:  0;
    padding: var(--dw-space-tight) 0.7em;
    background: #ffffff;
    color: #000000;
    border: 0.15em solid #1a1a1a;
    border-radius: 0.3em;
    font-family: 'Patrick Hand', 'Comic Sans MS', cursive;
    font-size: 1.1em;
    font-weight: bold;
    line-height: 1.2;
    z-index: 10;
    pointer-events: none;
    box-shadow: 0.1em 0.15em 0 rgba(0,0,0,0.15);
}

/* Hide the price label when no item is on the counter (e.g. between
   questions) to avoid a floating label with no anchor. */
.tw-item-price-label:empty {
    display: none;
}

/* ─── Next pencil button (Flash-style: arrow + "next" label) ──────────── */
.tw-next-btn {
    position: absolute;
    right:   3em;
    bottom:  2em;
    z-index: 10;
}

/* ─── Speech bubble (upper right, above hand) ──────────────────────────── */
/* Flash's speech bubble is a compact white pill at the top-right with a
   tail pointing down-right toward the customer's hand. The bubble also
   carries the feedback text (e.g. "That's great, thanks!"). */

.tw-speech-area {
    position: absolute;
    right:  1em;
    top:    0.3em;
    width:  22em;
    /* Above the hand (z-index 8) so the bubble isn't covered by the cuff. */
    z-index: 12;
    /* The bubble itself is decorative and never receives clicks. Keep the
       wrapper transparent to pointer events so coin/hand buttons sitting
       underneath the bubble area aren't blocked. */
    pointer-events: none;
}

.tw-speech-bubble {
    position: relative;
    /* Re-enable pointer events on the bubble itself in case it ever needs
       to be interactive (e.g. a future click-to-replay-speech affordance).
       Today the bubble has no handlers, but keeping it `auto` documents
       the intent and matches the wrapper/bubble convention. */
    pointer-events: auto;
    background: #ffffff;
    border: 0.2em solid #1a1a1a;
    border-radius: 0.7em;
    padding: var(--dw-space-comfy) var(--dw-space-loose);
    font-family: 'Patrick Hand', 'Comic Sans MS', cursive;
    font-size: 1.1em;
    text-align: center;
    color: #000;
    box-shadow: 0.1em 0.15em 0 rgba(0,0,0,0.08);
    transition: color 0.15s;
}

/* Speech bubble feedback colour cues (subtle — the bubble itself is the
   primary feedback channel, but tinting the border helps sighted users). */
.tw-speech-bubble.tw-speech-correct  { border-color: var(--dw-color-feedback-correct); }
.tw-speech-bubble.tw-speech-wrong    { border-color: var(--dw-color-feedback-wrong); }

.tw-speech-bubble::after {
    content: "";
    position: absolute;
    right: 2em;
    bottom: -0.95em;
    width: 0;
    height: 0;
    border: 0.6em solid transparent;
    border-top-color: #1a1a1a;
    border-bottom: 0;
}

.tw-speech-bubble::before {
    content: "";
    position: absolute;
    right: 2.12em;
    bottom: -0.65em;
    width: 0;
    height: 0;
    border: 0.48em solid transparent;
    border-top-color: #ffffff;
    border-bottom: 0;
    z-index: 1;
}

.tw-speech-bubble p {
    margin: 0;
    position: relative;
    z-index: 2;
}

/* ─── Customer payment (sits on the palm) ──────────────────────────────── */
/* The tendered note/coin starts on the palm where the customer is offering */
/* it. Clicking "takes" the money: it slides toward the till (down-left).   */

.tw-tendered-money {
    position: absolute;
    /* Coords relative to .tw-hand-wrapper (20em × 24em). The customer
       offers payment in the upper palm. left/top/width/height are
       overridden per-render by sizeTenderedEl() — it centres the
       wrapper on PALM_TENDER_ANCHOR_EM so resizing across denominations
       keeps the centroid pinned. The defaults below apply only on
       first paint before JS runs and match the canonical note footprint
       (NOTE_FACE_W_EM × NOTE_FACE_H_EM). */
    left:    8.1em;
    top:     15.55em;
    width:   11.9em;
    height:  6.3em;
    z-index: 9;
}

.tw-tendered-btn {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    /* Rectangular outline shape matches .tw-slot-note and .tw-denom-note
       so every note hit-target on stage has the same simple rectangular
       feedback (rather than the disc-shaped outline coins use). */
    border-radius: 0.3em;
    display: block;
}

.tw-tendered-btn img {
    width:  100%;
    height: auto;
    object-fit: contain;
    display: block;
}

.tw-tendered-btn:focus-visible {
    outline: 0.2em solid #ff9900;
}
@media (hover: hover) {
    .tw-tendered-btn:hover {
        outline: 0.2em solid #ff9900;
    }
}

.tw-tendered-taken {
    width:   5em;
    height:  auto;
    object-fit: contain;
    opacity: 0.0;     /* once taken, hide — Flash moves it into the drawer */
}

/* ─── Coin slots on the palm ───────────────────────────────────────────── */
/* Twelve fixed (left, top) positions in em, relative to .tw-hand-wrapper.
   Layout: roughly 4 staggered rows of 3, fanning across the palm.
   Position 12 is the £5 note (separate). */

.tw-coin-slots {
    position: absolute;
    left: 0; top: 0;
    width: 100%; height: 100%;
    pointer-events: none;          /* slot wrappers ignore pointer; only filled coins receive clicks */
    z-index: 7;
}

.tw-slot {
    position: absolute;
    /* Per-denomination diameter (em) is set on the slot at render time via the
       --tw-slot-size custom property so every palm coin matches the painted
       drawer coin of the same denomination exactly. The width/height pull
       from that property; margin-left/top centre the slot on its (left, top)
       anchor. The default fallback (4em) is rarely used — the JS always sets
       --tw-slot-size when rendering a slot. */
    width:  var(--tw-slot-size, 4em);
    height: var(--tw-slot-size, 4em);
    margin-left: calc(var(--tw-slot-size, 4em) / -2);
    margin-top:  calc(var(--tw-slot-size, 4em) / -2);
    /* Slots live outside .tw-hand-rotator now (in the wrapper directly)
       so they sit in stage-aligned coords — coin faces upright, row
       arrangement horizontal. PALM_SLOTS positions are tuned so the
       grid still overlays the visible (rotated) palm. */
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    background: transparent;
    border: none;
    /* Allow the inflated SVG's highlight rim to spill outside the slot's
       bounding box so the hit-target / hover-outline stays snug on the
       visible coin face. */
    overflow: visible;
}

/* Filled coin: visible image + clickable. */
.tw-slot.tw-slot-filled {
    cursor: pointer;
    pointer-events: auto;
    border-radius: 50%;
}

.tw-slot.tw-slot-filled:focus-visible {
    outline: 0.2em solid #ff9900;
}
@media (hover: hover) {
    .tw-slot.tw-slot-filled:hover {
        outline: 0.2em solid #ff9900;
    }
}

/* Slot reserved by an in-flight drawer→palm clone — hide the resting
   coin until the flying clone lands so the user sees a single coin
   travelling, not a pre-painted destination plus the clone. Toggled in
   renderCoinSlots / onAddCoin / spawnFlyInCoin. visibility (not display)
   keeps the slot's layout box so subsequent renders find it by index. */
.tw-slot.tw-slot-in-flight {
    visibility: hidden;
}

.tw-slot img {
    width:  100%;
    height: 100%;
    object-fit: contain;
    display: block;
    /* Inflate the SVG so its visible coin face fills the slot box —
       --tw-coin-img-inflate is set per denomination by renderCoinSlots
       (COIN_IMG_INFLATE). With slot size = visible face diameter, the
       SVG's outer highlight rim spills slightly outside the slot but
       reads as part of the coin's painted edge. Notes (rectangular
       SVGs with no padding) leave --tw-coin-img-inflate unset and fall
       back to the default 1. */
    transform: scale(var(--tw-coin-img-inflate, 1));
    transform-origin: center;
    /* Coin drop-shadow gives them a sense of resting on the palm. */
    filter: drop-shadow(0.08em 0.1em 0.05em var(--dw-color-shadow-strong));
}

/* Note slot (separate position). Note image is landscape (≈1.876:1 aspect).
   Width/height are fixed here (the note has no per-denomination
   variation) and override the default --tw-slot-size sizing for the
   disc coins. Sized to NOTE_FACE_W_EM × NOTE_FACE_H_EM (11.9em ×
   6.3em — canonical note footprint, matched by .tw-denom-note,
   .tw-tendered-money, and .tw-till-tendered-box). The note SVG fills
   its viewBox so no inflate is needed — --tw-coin-img-inflate stays at
   its default of 1. */
.tw-slot.tw-slot-note {
    width:  11.9em;
    height: 6.3em;
    margin-left: -5.95em;
    margin-top: -3.15em;
}
.tw-slot.tw-slot-note img {
    width: auto;
    height: 100%;
    max-width: 100%;
}
/* Override the circular hover/focus outline inherited from .tw-slot-filled
   (which is shaped for disc-like coins). The £5 note is a landscape
   rectangle, so its hit-target outline should be rectangular and match
   the drawer note (.tw-denom-note) and the tendered note (.tw-tendered-btn)
   for a single consistent feedback shape across every note position. */
.tw-slot.tw-slot-filled.tw-slot-note {
    border-radius: 0.3em;
}
.tw-slot.tw-slot-filled.tw-slot-note:focus-visible {
    outline: 0.2em solid #ff9900;
}
@media (hover: hover) {
    .tw-slot.tw-slot-filled.tw-slot-note:hover {
        outline: 0.2em solid #ff9900;
    }
}

/* Feedback text is now carried by the speech bubble (Flash-faithful); the
   #twFeedback element is sr-only (live region for SR announcements only). */

/* ─── Results screen ─────────────────────────────────────────────────────── */

.tw-results-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: var(--dw-space-loose);
    font-size: 1.1em;
}

.tw-results-table th,
.tw-results-table td {
    padding: var(--dw-space-narrow) var(--dw-space-comfy);
    border-bottom: 0.07em solid var(--dw-color-border-faint);
    text-align: left;
}

.tw-results-table th {
    background: #f0f0f0;
    font-weight: bold;
}

.tw-score-percent {
    font-size: var(--dw-font-size-heading);
    font-weight: bold;
    text-align: center;
    margin: var(--dw-space-default) 0;
}

/* Row number column (Flash: "1.", "2.", … left of each row) */
.tw-results-table .tw-col-num {
    width: 2.5em;
    text-align: right;
    color: var(--dw-color-text-muted);
    background: transparent;
}

.tw-results-table tbody th {
    text-align: right;
    background: transparent;
    color: var(--dw-color-text-muted);
    font-weight: normal;
}

/* "Till Screen: <mode>" caption above the results table — Flash
   tillScreenOptionText set in frame_05.as. */
.tw-results-mode-label {
    text-align: center;
    margin: 0 0 var(--dw-space-snug) 0;
    font-family: 'Patrick Hand', 'Comic Sans MS', cursive;
    font-size: 1.05em;
    color: var(--dw-color-text-strong);
}

/* Repeat pencil sits bottom-right of the results screen. */
.tw-action-buttons {
    display: flex;
    justify-content: center;
    margin-top: var(--dw-space-narrow);
}

/* ─── 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;
}

/* ─── Coin fly animations ────────────────────────────────────────────────── */

/* Fly-in is a pure translate (drawer button → palm slot) — no scale. The JS
   spawns the flying clone at the palm-slot's resting size, and the palm slot
   itself is sized per-denomination to match the painted drawer coin (see
   --tw-slot-size on .tw-slot), so the coin's apparent diameter is constant
   from the moment it leaves the drawer until it lands on the palm. */
@keyframes tw-fly-in {
    from {
        transform: translate(var(--tw-fly-dx), var(--tw-fly-dy));
    }
    to {
        transform: translate(0, 0);
    }
}

/* Flash mx.transitions.Tween over 1.1s ease-out for coin fly drawer → palm.
   Applied to a clone spawned outside .tw-hand-rotator so the translate is in
   stage coordinates (the rotator's 28° transform would otherwise rotate the
   visible flight path). */
.tw-flying-coin.tw-fly-in-coin {
    animation: tw-fly-in 1.1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

.tw-flying-coin {
    position: absolute;
    pointer-events: none;
    z-index: 200;
    /* Allow the inflated SVG to spill outside the clone's bounding box,
       matching the .tw-slot rule — otherwise the highlight rim gets
       clipped during flight while the resting palm coin shows it. */
    overflow: visible;
}

.tw-flying-coin img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Inflate the SVG so its visible coin face fills the clone box,
       matching the resting palm slot. The JS sets --tw-coin-img-inflate
       on the clone for coin denominations (no inflate for the £5 note
       — its SVG fills its viewBox). */
    transform: scale(var(--tw-coin-img-inflate, 1));
    transform-origin: center;
}

/* Fly-out (palm → drawer) is also a pure translate. The flying clone is
   spawned at the palm slot's size, which now matches the drawer's painted
   coin size for that denomination, so no end-scale is needed. */
@keyframes tw-fly-out {
    from {
        transform: translate(0, 0);
    }
    to {
        transform: translate(var(--tw-fly-dx), var(--tw-fly-dy));
    }
}

/* Flash moveBackTween (coin returning to drawer) is 1.1s ease-out. */
.tw-flying-coin.tw-fly-out-coin {
    animation: tw-fly-out 1.1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

/* Tendered-money drop into till: Flash 1.8s ease-out tween from hand
   position to (186, 230) for coins / (86, 230) for notes. JS positions
   the flying clone (sets left/top inline) and toggles this class to
   drive the transition. The clone box is sized to the canonical
   denomFootprintEm × emPx so the apparent size is constant across the
   source palm-tendered display and the landed Tendered-box img (which
   are both sized to denomFootprintEm via sizeTenderedEl and
   sizeTenderedImg respectively). */
.tw-tendered-flying {
    position: absolute;
    pointer-events: none;
    z-index: 220;
    transition: left 1.8s cubic-bezier(0.25, 0.46, 0.45, 0.94),
                top  1.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.tw-tendered-flying img {
    /* Match .tw-tendered-btn img: width:100% of the clone box, height
       auto so the SVG keeps its natural aspect. The JS sets the clone
       box to the canonical denomFootprint dims, which already match the
       SVG's aspect for notes (1.876:1 ≈ 11.9:6.3) and are square for
       coins (square SVGs), so the auto height resolves to the box
       height within sub-pixel. */
    width: 100%;
    height: auto;
    object-fit: contain;
    display: block;
}

/* ─── Reduced motion ─────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

