/* Splash Chest tab, reveal stage and Refine sheet (M1). Same surface language as the Shop; phone floors: information
   text >= 11px, prices and primary buttons >= 14px, spend/confirm/close targets >= 44x44px. */
.chest-hero{display:grid;grid-template-columns:minmax(220px,360px) 1fr;gap:24px;align-items:center;max-width:1120px;margin:0 auto 18px;padding:18px 22px;border:3px solid #cdeefb;border-radius:24px;background:radial-gradient(circle at 22% 45%,#fffbe8 0,#e4f8ff 42%,#c7ecf6 100%);box-shadow:0 5px 0 #6cb6d4}
.chest-showcase{display:grid;place-items:center}
.chest-showcase .chest-svg{width:100%;max-width:300px;height:auto;filter:drop-shadow(0 10px 12px #0b3b5233);animation:chestIdle 3.2s ease-in-out infinite}
@keyframes chestIdle{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
/* The closed chest (M6): the approved still, cropped to the chest by closedChestMarkup; the idle bob moves the picture
   inside its frame. The drawn chest above is the fallback if the picture fails. */
.chest-still{position:relative;display:block;width:100%;overflow:hidden}
.chest-still img{position:absolute;height:auto;max-width:none;pointer-events:none;user-select:none;-webkit-user-drag:none}
.chest-showcase .chest-still{max-width:300px}
.chest-showcase .chest-still img{animation:chestIdle 3.2s ease-in-out infinite}
.chest-panel{display:flex;flex-direction:column;gap:12px}
.shop-dialog .chest-contents{margin:0;font-size:14px;line-height:1.4;color:#1d5268}
.chest-actions{display:flex;flex-wrap:wrap;gap:12px}
.shop-dialog .chest-open{display:inline-flex;align-items:center;gap:6px;min-height:52px;margin:0;padding:10px 20px;font-size:17px}
.chest-open .shop-icon{width:24px;height:24px}
.shop-dialog .chest-open span{color:#5b3208;font:800 20px/1 "Baloo 2",sans-serif}
.chest-odds-link{align-self:flex-start;min-height:44px;padding:8px 14px;border:2px solid #eafff5;border-radius:12px;background:linear-gradient(#e9fff7,#b4ecdf);color:#22576c;font:900 14px/1 "Nunito Sans",sans-serif;box-shadow:0 3px 0 #4b99a8}
.shop-dialog .chest-note{margin:0;font-size:12px;font-weight:800;color:#3c6576}
.chest-recent{max-width:1120px;margin:0 auto}
.chest-recent h3{margin:0 0 8px;font:800 18px/1.1 "Baloo 2",sans-serif;color:#15506f}
.chest-recent ul{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;margin:0;padding:0;list-style:none}
.chest-recent li{display:grid;grid-template-columns:1fr auto;gap:2px 8px;padding:8px 12px;border-radius:14px;background:#f5fffb;border:2px solid #d3efe5}
.shop-dialog .chest-recent li small{grid-column:1/-1;font-size:11px;font-weight:900;letter-spacing:1px;color:#3b7a82}
.shop-dialog .chest-recent li span{font-weight:800;color:#15506f}
.shop-dialog .chest-recent li em{font-style:normal;font-weight:900;color:#5d3f8f}
.chest-recent li[data-category=red]{border-color:#f5b9c1;background:#fff6f7}
.chest-recent li[data-category=yellow]{border-color:#f3d98e;background:#fffaf0}
.chest-recent li[data-category=purple]{border-color:#d8c3f7;background:#fbf7ff}
.chest-recent li[data-category=blue]{border-color:#bfe0f5;background:#f5fbff}
.chest-sheet-art{display:grid;place-items:center;border-radius:18px;background:radial-gradient(circle at 50% 45%,#fffbe8,#d6f1fb 70%)}
.chest-sheet-art .chest-svg{width:100%;height:auto}
.shop-dialog .chest-sheet-note{font-size:13px;color:#3c6576}
.shop-refine{min-height:44px;min-width:76px;margin-left:auto;padding:8px 14px;border:2px solid #fbefff;border-radius:13px;background:linear-gradient(#fbf1ff,#e5c9fb);color:#4f2470;font:900 14px/1 "Nunito Sans",sans-serif;box-shadow:0 3px 0 #9e6fc6}
.shop-dialog .shop-refine{color:#4f2470}

/* Odds sheet */
.chest-odds{max-height:60vh;overflow:auto}
.chest-odds-group{margin:10px 0}
.chest-odds-group h3{margin:0 0 4px;font:800 16px/1.2 "Baloo 2",sans-serif;color:#15506f}
.shop-dialog .chest-odds-group h3 small{font:800 12px "Nunito Sans",sans-serif;color:#5d3f8f;margin-left:6px}
.chest-odds table{width:100%;border-collapse:collapse}
.chest-odds th,.chest-odds td{padding:5px 8px;border-bottom:1px solid #cfe9e1;font-size:13px;color:#1d5268;text-align:left}
.chest-odds td{text-align:right;font-weight:900;font-variant-numeric:tabular-nums}
.shop-dialog .chest-odds-total{margin-top:8px;font-size:13px}

/* Refine sheet */
.refine-stars{display:flex;gap:4px;margin:4px 0 8px}
.refine-stars span svg{width:34px;height:34px;fill:#d9d3c3;stroke:#a89c7c;stroke-width:1.2}
.refine-stars span[data-lit=true] svg{fill:#ffcf3f;stroke:#b8841d;filter:drop-shadow(0 0 6px #ffe7907a)}
.refine-stars span[data-new=true] svg{animation:starLight .9s ease-out}
@keyframes starLight{0%{transform:scale(.4) rotate(-30deg);opacity:.3}60%{transform:scale(1.35) rotate(8deg);opacity:1}100%{transform:scale(1) rotate(0)}}
.shop-dialog .refine-result{margin:4px 0 8px;padding:8px 12px;border-radius:12px;background:#eef6fb;color:#1d5268;font-size:14px}
.shop-dialog .refine-result[data-success=true]{background:#fff4cc;color:#6b4a0f}
.shop-dialog .refine-rules p{font-size:13px;margin:4px 0}
.refine-progress{height:12px;border-radius:999px;background:#d9ecef;overflow:hidden;box-shadow:inset 0 1px 2px #0b3b5222}
.refine-progress span{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#c07ef2,#ffcf3f)}
.shop-dialog .refine-copy .refine-count{font-size:12px;font-weight:800;color:#3c6576}
.shop-dialog .refine-copy .refine-next{font-size:12px;color:#3c6576}

/* Reveal stage. The stage fills the Shop. Results sit above a bottom bar (Skip while the reveal plays, then Done and
   Open again), so cards never run under the buttons, and the results always fit the space that is left: one card; ten
   as a 5 x 2 grid of cards on tall screens, or as a compact list of rows on short or narrow screens. If a result ever
   needs more room than the screen has, the results scroll from their top instead of being cut off. */
.chest-stage-layer{position:absolute;inset:0;z-index:20;display:flex;flex-direction:column;overflow:hidden;background:radial-gradient(circle at 50% 55%,#1e5f86 0,#0d3452 60%,#08243a 100%)}
.chest-stage-layer[hidden]{display:none}
.chest-stage{position:relative;flex:1 1 0;min-height:0;width:100%;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:6px;padding:16px 16px 2px}
.chest-rays{position:absolute;left:50%;top:56%;width:160vmax;height:160vmax;transform:translate(-50%,-50%) scale(.2);opacity:0;border-radius:50%;background:repeating-conic-gradient(from 0deg,color-mix(in srgb,var(--chest-color) 70%,#fff) 0 5deg,transparent 5deg 15deg);-webkit-mask:radial-gradient(circle,#000 0,#0000 55%);mask:radial-gradient(circle,#000 0,#0000 55%);pointer-events:none}
.chest-stage-chest::before{content:"";position:absolute;left:50%;bottom:48%;width:70%;height:0;transform:translateX(-50%);border-radius:50% 50% 12px 12px;background:radial-gradient(ellipse at 50% 100%,var(--chest-glow) 0,color-mix(in srgb,var(--chest-color) 60%,transparent) 45%,transparent 72%);opacity:0;pointer-events:none;transition:height .5s ease-out,opacity .35s}
.chest-stage[data-phase=burst] .chest-stage-chest::before,.chest-stage[data-phase=reveal] .chest-stage-chest::before{height:150%;opacity:.95}
.chest-stage-chest{position:absolute;left:50%;top:56%;width:min(300px,46vmin);transform:translate(-50%,-50%);transition:opacity .4s}
.chest-stage-chest .chest-svg{width:100%;height:auto;overflow:visible}
.chest-stage .chest-lid{transform-box:fill-box;transform-origin:50% 100%}
.chest-burst{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.chest-results{--cols:1;--rows:1;position:relative;z-index:3;flex:1 1 0;min-height:0;width:min(1120px,calc(100% + 20px));margin:-10px;box-sizing:border-box;display:grid;grid-template-columns:repeat(var(--cols),minmax(0,1fr));grid-template-rows:repeat(var(--rows),1fr);gap:10px;padding:12px;overflow-y:auto;overscroll-behavior:contain}
.chest-stage[data-count="10"] .chest-results{--cols:5;--rows:2}
.chest-card{display:none;min-width:0;min-height:min-content;box-sizing:border-box;flex-direction:column;align-items:center;gap:4px;padding:10px;border-radius:18px;border:3px solid var(--card-edge,#cdeefb);background:linear-gradient(170deg,#fbfff6,#dff4f1);box-shadow:0 6px 0 #0b3b5255,0 0 12px var(--card-glow,#fff0);text-align:center;overflow:hidden}
/* Card colour = reward category (user decision 2026-09-30 14:30Z): red balloon skin, yellow Legendary character skin,
   purple trail, blue everything else. Mirrors CHEST_CATEGORIES in chest-v32.mjs. */
.chest-card[data-category=red]{--card-edge:#ec4d5f;--card-glow:#ffb3bd99;--card-ink:#9b1c2e;background:linear-gradient(170deg,#fff6f7,#fbd9de)}
.chest-card[data-category=yellow]{--card-edge:#f5b92e;--card-glow:#ffe08a88;--card-ink:#7a5200;background:linear-gradient(170deg,#fffbef,#fbe9c4)}
.chest-card[data-category=purple]{--card-edge:#9a5cf0;--card-glow:#d9c2ff99;--card-ink:#51259a;background:linear-gradient(170deg,#fbf7ff,#e9dcfd)}
.chest-card[data-category=blue]{--card-edge:#3ea6ec;--card-glow:#bfe6ff88;--card-ink:#1f5f86;background:linear-gradient(170deg,#f5fbff,#d8eefb)}
.chest-card[data-shown=true]{display:flex;animation:cardIn .55s cubic-bezier(.2,1.4,.4,1) both}
/* Result drops (root 2026-09-30): one per committed roll, card order, neutral until filled with the roll's category. */
.chest-drops{position:relative;z-index:3;flex:none;display:flex;justify-content:center;gap:7px;padding:4px 0 2px;pointer-events:none}
.chest-drop{width:13px;height:13px;border-radius:50% 0 50% 50%;transform:rotate(-45deg);box-sizing:border-box;border:2px solid #ffffffb8;background:#ffffff26;transition:background-color .25s,border-color .25s,transform .25s}
.chest-drop[data-filled=true][data-category=red]{--drop:#ec4d5f}
.chest-drop[data-filled=true][data-category=yellow]{--drop:#f5b92e}
.chest-drop[data-filled=true][data-category=purple]{--drop:#9a5cf0}
.chest-drop[data-filled=true][data-category=blue]{--drop:#3ea6ec}
.chest-drop[data-filled=true]{background:var(--drop);border-color:#fff;transform:rotate(-45deg) scale(1.12)}
.chest-stage[data-reduced=true] .chest-drop{transition:none}
@keyframes cardIn{0%{transform:translateY(40px) rotateY(80deg) scale(.7);opacity:0}100%{transform:none;opacity:1}}
.chest-stage[data-count="1"] .chest-card{justify-self:center;align-self:center;width:min(300px,100%);height:min(100%,480px)}
/* The picture takes whatever height the text leaves and keeps its own proportions inside that box. */
.chest-card-art{flex:1 1 0;min-height:40px;width:100%;container-type:size;display:flex;align-items:center;justify-content:center}
.chest-card-art .character-card-art{width:min(100cqw,66.667cqh);height:auto;flex:none}
.chest-card-art img{width:min(100cqw,100cqh);height:auto;aspect-ratio:1;object-fit:contain;filter:drop-shadow(0 6px 6px #1a4d5a40)}
.chest-card-art svg{width:min(80cqw,80cqh);height:auto}
.chest-card-text{flex:none;display:flex;flex-direction:column;align-items:center;gap:3px;width:100%;min-width:0}
.shop-dialog .chest-card-tier{font-size:11px;font-weight:900;letter-spacing:1.2px;line-height:1.25;color:var(--card-ink,#6b4a0f)}
/* outcome accent (New!, +Sparkle, +coins) in the category ink */
.shop-dialog .chest-card .chest-card-outcome strong{color:var(--card-ink,#15506f)}
.shop-dialog .chest-card h3{margin:0;font:800 18px/1.12 "Baloo 2",sans-serif;color:#15506f;overflow-wrap:normal}
.shop-dialog .chest-card-outcome{margin:0;font-size:13px;line-height:1.3;color:#1d5268}
.shop-dialog .chest-card[data-outcome=duplicate] .chest-card-outcome{color:#5d3f8f}
.shop-dialog .chest-card-bundle{margin:0;font-size:12px;line-height:1.25;color:#3c6576}
.chest-card-short{display:none}
/* Ten on a tall screen: smaller cards; the picture keeps its rarity emblem, the name is written once below it. */
.chest-stage[data-count="10"] .chest-card{padding:8px 6px;gap:3px;border-radius:14px}
.shop-dialog .chest-stage[data-count="10"] .chest-card h3{font-size:15px}
.shop-dialog .chest-stage[data-count="10"] .chest-card-outcome{font-size:12px}
.chest-stage[data-count="10"] .chest-card-art .character-card-copy{display:none}
.chest-stage[data-count="10"] .chest-card-long{display:none}
.chest-stage[data-count="10"] .chest-card-short{display:inline}
.shop-dialog .chest-stage-status{position:relative;z-index:3;flex:none;margin:0;min-height:18px;text-align:center;font-weight:900;font-size:14px;line-height:18px;color:#e8fbff}
.chest-stage-bar{position:relative;z-index:5;flex:none;display:flex;justify-content:center;align-items:center;gap:12px;min-height:62px;padding:6px 16px 12px;box-sizing:border-box}
.chest-skip{min-width:96px;min-height:44px;padding:8px 18px;border:2px solid #b4ebff;border-radius:12px;background:#0d3452cc;color:#e8fbff;font:900 15px/1 "Nunito Sans",sans-serif}
.chest-skip[hidden]{display:none}
.chest-stage-buttons{display:flex;justify-content:center;gap:12px}
.chest-stage-buttons[hidden]{display:none}
.chest-stage-buttons button:not(.shop-primary){min-height:44px;padding:8px 18px;border:2px solid #eafff5;border-radius:13px;background:linear-gradient(#e9fff7,#b4ecdf);color:#22576c;font:900 15px/1 "Nunito Sans",sans-serif;box-shadow:0 3px 0 #4b99a8}
.chest-stage-buttons .shop-primary{margin:0}
.chest-stage-bar:has(.chest-repeat-status:not([hidden])){flex-wrap:wrap}
.chest-repeat-status{flex:0 0 100%;margin:0;text-align:center;color:#f0ffff;font:800 14px/1.35 "Nunito Sans",sans-serif}
.chest-repeat-status[hidden]{display:none}
.chest-stage-buttons[aria-busy=true] button{opacity:.65;cursor:progress}

/* Reveal phases: one soft burst; no strobing */
.chest-stage[data-phase=arrive] .chest-stage-chest{animation:chestArrive .6s cubic-bezier(.3,1.5,.5,1) both}
@keyframes chestArrive{0%{transform:translate(-50%,-160%) scale(.8);opacity:0}100%{transform:translate(-50%,-50%) scale(1);opacity:1}}
.chest-stage[data-phase=tease] .chest-stage-chest{animation:chestShake 1.4s ease-in both}
@keyframes chestShake{0%{transform:translate(-50%,-50%) rotate(0)}20%{transform:translate(-50%,-50%) rotate(-2deg)}40%{transform:translate(-50%,-50%) rotate(2.5deg)}60%{transform:translate(-50%,-51%) rotate(-4deg) scale(1.03)}80%{transform:translate(-50%,-51%) rotate(5deg) scale(1.05)}100%{transform:translate(-50%,-52%) rotate(0) scale(1.06)}}
.chest-stage[data-phase=tease] .chest-stage-chest .chest-svg{filter:drop-shadow(0 0 18px var(--chest-color))}
.chest-stage[data-phase=tease] .chest-rays{opacity:.18;transform:translate(-50%,-50%) scale(.45);transition:opacity 1.2s,transform 1.4s}
.chest-stage[data-phase=burst] .chest-lid{animation:lidOpen .5s cubic-bezier(.2,1.6,.4,1) both}
@keyframes lidOpen{to{transform:translateY(-38%) rotate(-24deg)}}
.chest-stage[data-phase=burst] .chest-inner{opacity:1;transition:opacity .2s}
.chest-stage[data-phase=burst] .chest-rays,.chest-stage[data-phase=reveal] .chest-rays,.chest-stage[data-phase=convert] .chest-rays{opacity:.55;transform:translate(-50%,-50%) scale(1) rotate(20deg);transition:opacity .35s,transform 6s linear}
.chest-stage[data-phase=reveal] .chest-stage-chest,.chest-stage[data-phase=convert] .chest-stage-chest,.chest-stage[data-phase=done] .chest-stage-chest{opacity:.18}
/* Settled: the rays keep the same turn and transition target, so their slow turn carries on past the settle and only
   the brightness eases down (Fable m1-chest-02 b: they used to snap back and stop at the settle). */
.chest-stage[data-phase=done] .chest-rays{opacity:.35;transform:translate(-50%,-50%) scale(1) rotate(20deg);transition:opacity .6s ease-out,transform 6s linear}
/* cardIn stays in the list: removing it and adding it back at the settle replayed the card entrance (Fable m1-chest-02 a). */
.chest-stage[data-phase=convert] .chest-card[data-outcome=duplicate]{animation:cardIn .55s cubic-bezier(.2,1.4,.4,1) both,convertPulse .9s ease-in-out}
@keyframes convertPulse{50%{transform:scale(.94);box-shadow:0 0 30px #d8a8ff}}
.chest-stage[data-reduced=true] .chest-rays{display:none}
.chest-stage[data-reduced=true] .chest-card[data-shown=true]{animation:fadeIn .2s both}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.chest-showcase .chest-svg,.chest-showcase .chest-still img{animation:none}}

/* Approved chest media (M6). playReveal lays the clip box out with chestClipLayout over the whole stage layer (the
   bottom bar floats above it) and the layer paints the clip's own gradient around it. The cards arrive at 2.6 s and the
   clip dims to 18 %; at the settle the poster (the clip's settled last frame) takes the clip's place. */
.chest-clip{position:absolute;z-index:0;pointer-events:none;opacity:1;transition:opacity .4s ease-out}
.chest-clip[data-dim=true]{opacity:.18}
.chest-clip[data-reduced=true]{transition-duration:.2s}
.chest-clip-video,.chest-clip-poster{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:fill}
.chest-clip-video[hidden],.chest-clip-poster[hidden]{display:none}
/* Reduced motion: a still pixel (u, v) is the clip pixel (u + 128, v - 132), so the 1024 px still spans 80 % of the
   clip's width from 10 % in, and starts 18.33 % above it. The closed still fades to the open one in 200 ms. */
.chest-clip-still{position:absolute;left:0;top:0;width:100%;height:100%;max-width:none;transition:opacity .2s linear}
.chest-clip-still[data-open=true]{opacity:0}
.chest-clip[data-fade=open] .chest-clip-still[data-open=true]{opacity:1}
.chest-clip[data-fade=open] .chest-clip-still[data-open=false]{opacity:0}
/* The app and the Shop switch every transition and animation off for reduced motion (styles.css, shop-v32.css). The
   reveal's reduced form is itself made of short opacity fades, with no movement: the stills' 200 ms fade (root
   VISUAL-HANDOFF-01), the dim under the cards and the cards' fade-in, so these three are exempt. */
@media (prefers-reduced-motion:reduce){
 .shop-dialog .chest-clip .chest-clip-still{transition:opacity .2s linear!important}
 .shop-dialog .chest-stage-layer .chest-clip[data-reduced=true]{transition:opacity .2s ease-out!important}
 .shop-dialog .chest-stage[data-reduced=true] .chest-card[data-shown=true]{animation:fadeIn .2s both!important}
}

@media (max-height:600px){
 .chest-hero{grid-template-columns:150px 1fr;gap:12px;padding:10px 12px;margin-bottom:10px}
 .shop-dialog .chest-contents{font-size:12px}
 .shop-dialog .chest-open{min-height:44px;padding:8px 14px;font-size:15px}
 .shop-dialog .chest-open span{font-size:17px}
 .chest-stage{padding:6px 12px 0;gap:4px}
 .chest-stage-bar{min-height:50px;padding:3px 12px}
 /* Ten on a short screen: the summary line stays for screen readers only; the rows need the height. */
 .chest-stage[data-count="10"] .chest-stage-status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
 /* One result on a short screen: picture beside the words. */
 .chest-stage[data-count="1"] .chest-card{flex-direction:row;width:min(560px,100%);height:min(100%,300px);padding:10px 16px 10px 10px;gap:16px;text-align:left}
 .chest-stage[data-count="1"] .chest-card-art{flex:0 0 38%;height:100%;min-height:0}
 .chest-stage[data-count="1"] .chest-card-text{flex:1 1 0;align-items:flex-start;gap:6px}
 .shop-dialog .chest-stage[data-count="1"] .chest-card h3{font-size:22px}
 /* Ten on a short screen: a compact list of rows in two columns, name first, then rarity and outcome. */
 .chest-stage[data-count="10"] .chest-results{--cols:2;--rows:5;gap:6px 10px;width:min(840px,calc(100% + 20px))}
 .chest-stage[data-count="10"] .chest-card{flex-direction:row;align-items:center;gap:8px;padding:3px 10px 3px 4px;border-width:2px;border-radius:12px;box-shadow:0 3px 0 #0b3b5255,0 0 12px var(--card-glow,#fff0);text-align:left}
 .chest-stage[data-count="10"] .chest-card-art{flex:0 0 auto;width:auto;height:100%;min-height:0;aspect-ratio:1}
 .chest-stage[data-count="10"] .chest-card-art .character-card-stamp{display:none}
 .chest-stage[data-count="10"] .chest-card-text{flex:1 1 0;flex-direction:row;flex-wrap:wrap;align-items:baseline;column-gap:6px;row-gap:0}
 .shop-dialog .chest-stage[data-count="10"] .chest-card h3{order:-3;font-size:14px;line-height:1.15}
 .chest-stage[data-count="10"] .chest-card-bundle{order:-2}
 .chest-stage[data-count="10"] .chest-card-text::before{content:"";flex-basis:100%;height:0;order:-1}
 .shop-dialog .chest-stage[data-count="10"] .chest-card-tier{letter-spacing:.6px}
 .shop-dialog .chest-stage[data-count="10"] .chest-card-outcome,.shop-dialog .chest-stage[data-count="10"] .chest-card-bundle{font-size:12px;line-height:1.25}
 .chest-stage[data-count="10"] .chest-card-outcome::before,.chest-stage[data-count="10"] .chest-card-bundle::before{content:"·";margin-right:6px;color:#56707c}
}
@media (max-width:560px){
 .chest-hero{grid-template-columns:1fr;padding:12px}
 .chest-showcase .chest-svg{max-width:180px}
 /* Ten on a narrow screen: one column of rows. */
 .chest-stage[data-count="10"] .chest-results{--cols:1;--rows:10;gap:6px}
 .chest-stage[data-count="10"] .chest-card{flex-direction:row;align-items:center;gap:10px;padding:4px 12px 4px 4px;border-width:2px;border-radius:12px;box-shadow:0 3px 0 #0b3b5255,0 0 12px var(--card-glow,#fff0);text-align:left}
 .chest-stage[data-count="10"] .chest-card-art{flex:0 0 auto;width:auto;height:100%;min-height:0;aspect-ratio:1}
 .chest-stage[data-count="10"] .chest-card-art .character-card-stamp{display:none}
 .chest-stage[data-count="10"] .chest-card-text{flex:1 1 0;flex-direction:row;flex-wrap:wrap;align-items:baseline;column-gap:6px;row-gap:0}
 .shop-dialog .chest-stage[data-count="10"] .chest-card h3{order:-3;font-size:15px;line-height:1.15}
 .chest-stage[data-count="10"] .chest-card-bundle{order:-2}
 .chest-stage[data-count="10"] .chest-card-text::before{content:"";flex-basis:100%;height:0;order:-1}
 .shop-dialog .chest-stage[data-count="10"] .chest-card-tier{letter-spacing:.6px}
 .chest-stage[data-count="10"] .chest-card-outcome::before,.chest-stage[data-count="10"] .chest-card-bundle::before{content:"·";margin-right:6px;color:#56707c}
}
/* The shared card component drops its stamp and subtitle to 9-10px on phones; inside reveal cards they keep 11px. */
.shop-dialog .chest-card .character-card-stamp-label,.shop-dialog .chest-card .character-card-subtitle{font-size:11px}
/* Root CHEST-PREVIEW-01: the reveal shows the art once, then one rarity line, the name and one outcome line. The shared
   card's own stamp and name overlay would repeat them. */
.chest-card-art .character-card-stamp,.chest-card-art .character-card-copy{display:none}
/* One result: the card already says it all, so the summary line is kept for screen readers only. */
.chest-stage[data-count="1"] .chest-stage-status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
/* Short screens: the refine sheet fits its success line and the next-star line without scrolling. */
@media (max-height:430px){
 .refine-stars{margin:2px 0 4px}
 .refine-stars span svg{width:26px;height:26px}
 .shop-dialog .refine-result{margin:2px 0 6px;padding:6px 10px;font-size:13px;line-height:1.35}
 .shop-dialog .refine-rules p{margin:2px 0}
}

/* V32 (user economy decision 2026-10-01): held Splash Chests. Earned chests (Premium pass levels, season rank, events)
   open free from a row above the Splash Drops buttons; the Splash Chest tab and the home Shop button carry their count.
   With none held, the Chest tab keeps its markup and layout. */
.chest-held{display:flex;flex-direction:column;gap:8px;padding:10px 12px;border-radius:16px;background:#fff8e6;border:2px solid #ecd49a}
.chest-held-count{margin:0}
.shop-dialog .chest-held-count strong{display:block;font:800 18px/1.2 "Baloo 2",sans-serif;color:#7a5200}
.shop-dialog .chest-held-count small{display:block;font-size:12px;line-height:1.35;color:#5b4a1e}
.shop-dialog .chest-held-note{margin:0;align-self:center;font-size:12px;font-weight:800;color:#5b4a1e}
.shop-dialog .chest-free-note{margin:0;padding:8px 12px;border-radius:12px;background:#fff8e6;border:2px solid #ecd49a;font-size:13px;font-weight:800;line-height:1.35;color:#5b4a1e}
/* with chests held, the Drops buttons step back: a lighter face, same size and the same 14px+ label */
.shop-dialog .chest-open[data-paid]{background:linear-gradient(#fffdf3,#f3e3bb);border-color:#fff8de;box-shadow:0 4px 0 #c9a85a}
.shop-tabs button[data-shop-tab=chest]{position:relative}
.shop-dialog .shop-tab-count{position:absolute;top:-3px;right:-5px;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:#c8243a;color:#fff;font:900 11px/18px sans-serif;text-align:center;box-shadow:0 1px 0 #7d1322;pointer-events:none}
.home-nav [data-home=shop]{position:relative}
@media (max-height:600px){
 .chest-held{padding:6px 8px;gap:6px}
 .shop-dialog .chest-held-count strong{font-size:15px}
 .shop-dialog .chest-held-count small{font-size:11px}
 .shop-dialog .chest-held-note{font-size:11px}
 .shop-dialog .chest-free-note{padding:5px 8px;font-size:11px}
}

/* The lobby card for rewards the island server granted on its own (season end, events): dismissible, one at a time,
   only on the home screen and never over an open dialog; on wide screens it sits in the open island between the mode
   bar and the invite stand, clear of the mode buttons. */
.reward-notice{position:fixed;top:200px;left:44%;transform:translateX(-50%);z-index:20;display:flex;align-items:center;gap:12px;width:min(460px,calc(100vw - 24px));padding:12px 14px;border:3px solid #ecd49a;border-radius:18px;background:#fff8e6;color:#3d2a00;box-shadow:0 5px 0 #c9a85a,0 14px 30px #03253a55}
.reward-notice[hidden]{display:none}
body:not(.arcade-home) .reward-notice,body:has(dialog[open]) .reward-notice{display:none}
.reward-notice-text{flex:1 1 auto;margin:0;font-size:14px;font-weight:800;line-height:1.35;color:#3d2a00}
.reward-notice-actions{display:flex;gap:8px;flex:none}
.reward-notice button{min-height:44px;min-width:56px;padding:8px 14px;border-radius:13px;font:900 14px/1 'Nunito Sans',sans-serif;cursor:pointer}
.reward-notice-open{border:0;background:#7a5200;color:#fff;box-shadow:0 3px 0 #523700}
.reward-notice-open[hidden]{display:none}
.reward-notice-ok{border:2px solid #ecd49a;background:#fff;color:#5b4a1e;box-shadow:0 3px 0 #c9a85a}
@media (max-width:900px){.reward-notice{left:50%}}
@media (max-height:520px){
 .reward-notice{top:58px;left:50%;padding:6px 10px;gap:8px;width:min(620px,calc(100vw - 24px))}
 .reward-notice-text{font-size:12px}
}
/* V32 (VC-4): phone landscape (the lobby's short layout, 650px and wider). The card no longer lies over the party bar
   ("Your next splash" and the 1 vs 1 to 4 vs 4 buttons). It takes the player's own place on the island under the bar: as
   wide as the hero's place in a 2 vs 2 party (so Invite friend stays clear) and down to just above the chat and nav row,
   so it covers the hero and its name label whole, never half (a longer text would scroll inside it). In 1 vs 1 there are
   no teammate places: the card spans the stage and stays above the hero's name. In 3 vs 3 it ends with the first
   teammate place, so that invite is covered whole too (in 4 vs 4 the hero's half holds two places). These widths follow
   the party seats (home-party-v17.css: left 13px, right 42%). Words at the 11px floor, buttons 36px. Desktop keeps its
   placement. */
@media (max-height:520px) and (min-width:650px){
 .reward-notice{top:118px;left:16px;transform:none;flex-direction:column;align-items:stretch;justify-content:space-between;gap:5px;width:calc((100vw - 24px)*.29);height:max(calc(100vh - 237px),140px);padding:5px 8px;border-width:2px;border-radius:14px}
 body:has(.home-screen[data-party-size="1"]) .reward-notice{width:calc((100vw - 24px)*.58 - 8px);height:auto;max-height:max(calc(100vh - 237px),140px)}
 body:has(.home-screen[data-party-size="3"]) .reward-notice{width:calc(((100vw - 24px)*.58 - 16px)*2/3 + 11px)}
 .reward-notice-text{flex:0 1 auto;min-height:0;overflow-y:auto;font-size:11px;line-height:1.25}
 .reward-notice-actions{justify-content:flex-end}
 .reward-notice button{min-height:36px;padding:6px 12px;font-size:13px}
}

/* Ten-chest opening (user 2026-10-02 ten-chest; chest-ten-v32.mjs). Over the stage gradient, in this order: the clip box
   (parked on frame 16, out of sight until the hand-off), a vignette that subdues the edges, the lights behind the chest,
   the closed still at the clip's own placement (its alpha hides those lights; the camera moves it), the lights in front.
   At the hand-off the clip shows at once under the still (only its ring appears, under the flare), then the still fades
   out over it in 90 ms (TEN_TIMING.crossfadeMs), before the clip's first rattle. */
.chest-ten-vignette{position:absolute;inset:0;z-index:0;pointer-events:none;background:radial-gradient(ellipse 64% 72% at 50% 54%,#0000 42%,#020c18a8 100%);opacity:0;transition:opacity .6s ease-out}
.chest-ten-vignette[data-on=true]{opacity:1}
.chest-ten-canvas,.chest-emission-canvas{position:absolute;left:0;top:0;z-index:0;pointer-events:none}
.chest-ten-still{position:absolute;z-index:0;pointer-events:none;transform-origin:50% 56.1111%;opacity:0}
.chest-ten-still[hidden]{display:none}
.chest-ten-still[data-fade=out]{opacity:0;transition:opacity .09s linear}
.chest-ten-still[data-fade=open] .chest-clip-still[data-open=true]{opacity:1}
.chest-ten-still[data-fade=open] .chest-clip-still[data-open=false]{opacity:0}
.chest-ten-still[data-dim=true]{opacity:.18!important;transition:opacity .4s ease-out}
.chest-clip[data-ten=wait] .chest-clip-video{opacity:0}
.chest-clip[data-dim=hero]{opacity:.42}
/* The best reward, large, before the board: the single-result card's look, then it flies to its cell. */
.chest-card.chest-ten-hero{position:absolute;z-index:4;display:flex;width:min(300px,calc(100% - 32px));height:var(--hero-h,420px);padding:12px;gap:6px;transform:translate(-50%,-50%);pointer-events:none;box-shadow:0 6px 0 #0b3b5255,0 0 38px 8px var(--card-glow,#fff0);animation:tenHeroIn .55s cubic-bezier(.2,1.3,.4,1) both}
@keyframes tenHeroIn{0%{opacity:0;transform:translate(-50%,-34%) scale(.66)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}}
.shop-dialog .chest-card.chest-ten-hero h3{font-size:22px}
.chest-card.chest-ten-hero{transition:background .3s,border-color .3s,box-shadow .3s}
.chest-card.chest-ten-hero[data-treasure=true]{background:transparent!important;border-color:transparent;box-shadow:none;overflow:visible}
.chest-card.chest-ten-hero[data-treasure=true] .chest-card-text{display:none}
.chest-card.chest-ten-hero[data-treasure=true] .chest-card-art{width:100%;height:100%;flex:1;background:radial-gradient(ellipse,var(--card-glow),transparent 65%);overflow:visible;filter:drop-shadow(0 0 22px var(--card-edge));animation:tenTreasureRise .65s cubic-bezier(.15,.7,.2,1) both}
.chest-card.chest-ten-hero .chest-card-art>img{height:100%!important;width:100%!important;object-fit:contain}
@keyframes tenTreasureRise{from{opacity:0;transform:translateY(22%) scale(.5)}to{opacity:1;transform:translateY(-8%) scale(1.04)}}
@media (max-height:600px){
 .chest-card.chest-ten-hero{flex-direction:row;width:min(540px,calc(100% - 24px));padding:10px 16px 10px 10px;gap:16px;text-align:left}
 .chest-card.chest-ten-hero .chest-card-art{flex:0 0 38%;height:100%;min-height:0}
 .chest-card.chest-ten-hero .chest-card-text{flex:1 1 0;align-items:flex-start;gap:6px}
}
/* The board: every card holds its cell from the start (hidden), then they come in row order; the hero's own card fades
   in under the landing hero. A drop pops as its light arrives; the best category's drops glow at the flare. */
.chest-stage[data-ten=true] .chest-card[data-board=wait]{visibility:hidden;animation:none}
.chest-stage[data-ten=true] .chest-card[data-board=land]{animation:fadeIn .22s both}
.chest-stage[data-ten=true] .chest-drop[data-filled=true]{animation:tenMarker .5s ease-out}
@keyframes tenMarker{0%{transform:rotate(-45deg) scale(.5)}55%{transform:rotate(-45deg) scale(1.5)}100%{transform:rotate(-45deg) scale(1.12)}}
.chest-stage[data-ten=true] .chest-drop[data-top=true]{box-shadow:0 0 9px 2px var(--drop)}
/* Ten as rows (short or narrow screens): a row is never shorter than its card (a duplicate's conversion can need a third
   line), so no card is ever clipped; if the rows then need more height than the screen has, the list scrolls and fades
   out at the bottom while more cards are below (data-more, set by playReveal). */
@media (max-height:600px){.chest-stage[data-count="10"] .chest-results{grid-template-rows:repeat(var(--rows),minmax(min-content,1fr));gap:5px 10px;padding-top:6px;padding-bottom:6px}.chest-stage[data-count="10"] .chest-card{padding-top:2px;padding-bottom:2px}}
@media (max-width:560px){.chest-stage[data-count="10"] .chest-results{grid-template-rows:repeat(var(--rows),minmax(min-content,1fr))}}
.chest-stage[data-count="10"] .chest-results[data-tight=true]{row-gap:3px;padding-top:3px;padding-bottom:3px}
.shop-dialog .chest-stage[data-count="10"] .chest-results[data-tight=true] .chest-card h3{line-height:1.04}
.shop-dialog .chest-stage[data-count="10"] .chest-results[data-tight=true] :is(.chest-card-tier,.chest-card-outcome,.chest-card-bundle){line-height:1.12}
.chest-stage[data-count="10"] .chest-results[data-more=true]{-webkit-mask-image:linear-gradient(#000 calc(100% - 30px),#0000);mask-image:linear-gradient(#000 calc(100% - 30px),#0000)}

/* Approved chest identity; no CSS-drawn substitute on failed media. */
.chest-approved-image{display:block;width:100%;height:100%;object-fit:contain}
.chest-clip-still[hidden]{display:none}
.chest-clip-still[data-art-unavailable=true],.chest-clip-poster[data-art-unavailable=true],.chest-still img[data-art-unavailable=true]{display:none}
