/* Menus, buttons and the boxes inside them. Anything that stands for a product shows the product:
   box art in its real silhouette with a printed side for depth, props as rendered 3D shots.
   Motion answers taps: tabs slide, a picked box hops out of the carton, Open wakes up. */

/* ---------- Box art as an object ---------- */
/* The printed side: the box's own silhouette stacked a pixel at a time up and to the right, darker
   with each step, then a contact shadow. Works for every template shape (coffin, capsule, cup...). */
.boxart { --d: 1px; display: block; position: relative; }
.boxart .box {
  display: block; width: 100%; height: auto; overflow: visible;
  filter:
    drop-shadow(var(--d) calc(var(--d) * -1) 0 color-mix(in oklab, var(--side) 70%, #000))
    drop-shadow(var(--d) calc(var(--d) * -1) 0 color-mix(in oklab, var(--side) 62%, #000))
    drop-shadow(var(--d) calc(var(--d) * -1) 0 color-mix(in oklab, var(--side) 52%, #000))
    drop-shadow(-1px 5px 4px rgba(20, 30, 25, .32));
}
/* shrink-wrap: the mask is the box body painted white, so the gloss never spills past the edges */
.box-mask * { fill: #fff; stroke: #fff; }
.box-mask image, .box-mask text, .box-mask [fill="#000"] { opacity: 0; }
.sheen-band { transform: translateX(-130px); }
@keyframes sheen { from { transform: translateX(-130px); } to { transform: translateX(240px); } }

/* series hero: bigger, slower, with a floor under it and a gloss pass every few seconds */
.hero-box .boxart.is-hero { --d: 2.2px; animation: sway 8s ease-in-out infinite; transform-origin: 50% 90%; }
.hero-box .boxart.is-hero .box { animation: none; }
.hero-box .boxart.is-hero .sheen-band { animation: hero-sheen 6s cubic-bezier(.5, 0, .3, 1) .8s infinite; }
@keyframes hero-sheen { 0% { transform: translateX(-130px); } 22%, 100% { transform: translateX(240px); } }
.hero-floor { position: absolute; left: 12%; right: 0; top: 94%; height: 18px; border-radius: 50%; background: radial-gradient(closest-side, rgba(20, 30, 25, .28), transparent); }
@keyframes sway { 0%, 100% { transform: rotateY(-12deg) rotateZ(-1deg); } 50% { transform: rotateY(12deg) rotateZ(1deg); } }

/* ---------- Icons ---------- */
.ic { width: 22px; height: 22px; flex: none; display: block; overflow: visible; }
.ic .ic-fill { fill: var(--ic-fill, transparent); transition: fill .25s; }
.ic.obj { width: 30px; height: 30px; }

/* ---------- Tab bar: icons, and a pill that slides to the active tab ---------- */
.tabbar { display: grid; grid-template-columns: repeat(var(--n, 3), 1fr); gap: 0; }
.tab-blob {
  position: absolute; top: 8px; bottom: calc(8px + env(safe-area-inset-bottom)); left: 10px;
  width: calc((100% - 20px) / var(--n, 3)); transform: translateX(calc(var(--i, 0) * 100%));
  border-radius: 15px; background: var(--jade-tint);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .35), rgba(255, 255, 255, 0) 60%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 -2px 0 color-mix(in oklab, var(--jade) 18%, transparent) inset;
  transition: transform .42s cubic-bezier(.3, 1.35, .5, 1);
}
.tabbar button, .tabbar button.is-active { background: transparent; background-image: none; display: flex; align-items: center; justify-content: center; gap: 6px; z-index: 1; transition: color .25s; }
.tabbar button.is-active::after { display: none; }
.tabbar button.is-active { --ic-fill: color-mix(in oklab, var(--tag) 80%, transparent); }
.tabbar button:active .ic { transform: scale(.88); }
.tabbar .ic { transition: transform .15s; }
.tabbar button.pop .ic { animation: tab-pop .5s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes tab-pop { 0% { transform: scale(1); } 30% { transform: scale(.78) rotate(-10deg); } 65% { transform: scale(1.18) rotate(5deg); } 100% { transform: scale(1); } }
@media (max-width: 360px) { .tabbar button { font-size: 13px; gap: 4px; } .tabbar .ic { width: 19px; height: 19px; } }

/* ---------- Shop HUD ---------- */
.allow-box { width: 22px; height: 22px; margin-right: -4px; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M5 11l11-5 11 5v14l-11 5-11-5z' fill='%23C8A072'/%3E%3Cpath d='M5 11l11 5v14L5 25z' fill='%23B48A5C'/%3E%3Cpath d='M27 11l-11 5v14l11-5z' fill='%23D9B484'/%3E%3Cpath d='M5 11l11-5 11 5-11 5z' fill='%23E4C69C'/%3E%3Cpath d='M10.5 8.5l11 5v4' fill='none' stroke='%23fff' stroke-opacity='.75' stroke-width='3'/%3E%3C/svg%3E") center / contain no-repeat; flex: none; }
.hud-allow.is-empty .allow-box { filter: grayscale(1); opacity: .6; }
.hud-mystery .q { width: 30px; height: 30px; background: none; display: block; }
.hud-mystery .q .ic { width: 30px; height: 30px; transform-origin: 50% 85%; }
.hud-mystery:not(.is-used) .q .ic { animation: wiggle 3.2s ease-in-out infinite; }
.hud-map { gap: 7px; padding-inline: 14px 18px; --ic-fill: rgba(255, 255, 255, .28); }
.hud-map .ic { width: 22px; height: 22px; }

.hud-aim { grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 12px; align-items: center; text-align: left; padding: 8px 18px 8px 10px; }
.hud-aim .aim-thumb { grid-row: 1 / 3; width: 38px; display: grid; place-items: center; }
.hud-aim .aim-thumb:empty { display: none; }
.hud-aim .aim-thumb:empty ~ * { grid-column: 1 / -1; text-align: center; }
.hud-aim .aim-thumb .boxart { width: 34px; }
.hud-aim .aim-thumb .ic.obj { width: 36px; height: 36px; }
.hud-aim.is-new .aim-thumb { animation: aim-thumb .45s cubic-bezier(.3, 1.6, .5, 1); }
.hud-aim.is-new strong, .hud-aim.is-new small { animation: aim-text .3s ease-out; }
@keyframes aim-thumb { from { transform: translateY(8px) scale(.6) rotate(-12deg); opacity: 0; } }
@keyframes aim-text { from { transform: translateY(4px); opacity: 0; } }

/* ---------- Sheets (jump to, collectors) ---------- */
.shop-sheet:not([hidden]) { animation: scrim .25s ease-out; }
.shop-sheet:not([hidden]) > .sheet-head, .shop-sheet:not([hidden]) > .sheet-body { animation: sheet-up .36s cubic-bezier(.2, 1, .3, 1); }
.shop-sheet.is-closing { animation: scrim .2s ease-in reverse forwards; }
.shop-sheet.is-closing > .sheet-head, .shop-sheet.is-closing > .sheet-body { animation: sheet-down .2s ease-in forwards; }
@keyframes scrim { from { background-color: transparent; backdrop-filter: blur(0); } }
@keyframes sheet-up { from { transform: translateY(40%); opacity: 0; } }
@keyframes sheet-down { to { transform: translateY(30%); opacity: 0; } }
.sheet-close, .opening .close { display: grid; place-items: center; }
.opening .close .ic { width: 16px; height: 16px; color: var(--ink); }
.sheet-close .ic { width: 18px; height: 18px; }

.map-item { grid-template-columns: 40px 1fr; column-gap: 10px; padding: 8px 12px 8px 8px; min-height: 60px; position: relative; overflow: hidden; transition: transform .15s; }
.shop-sheet:not([hidden]) .map-item { animation: item-in .4s cubic-bezier(.2, 1.2, .4, 1) backwards; animation-delay: calc(80ms + min(var(--k, 0), 16) * 22ms); }
@keyframes item-in { from { transform: translateY(14px) scale(.96); opacity: 0; } }
.map-item .swatch, .map-item .swatch.q, .map-item .swatch.till, .map-item .swatch.door { width: 40px; height: 44px; background: none; box-shadow: none; border-radius: 0; display: grid; place-items: center; }
.map-item .swatch .boxart { width: 32px; transform: rotate(-4deg); transition: transform .25s cubic-bezier(.3, 1.6, .5, 1); }
.map-item .swatch .ic.obj { width: 36px; height: 36px; }
.map-item:active .swatch .boxart, .map-item:hover .swatch .boxart { transform: rotate(3deg) translateY(-3px) scale(1.06); }
/* a strip of the box colour down the left edge, like a shelf label */
.map-item[style*="--box"]::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--box); }
.map-bar { display: inline-block; width: 34px; height: 5px; border-radius: 3px; background: var(--paper-2); position: relative; overflow: hidden; }
.map-bar::after { content: ""; position: absolute; inset: 0; transform-origin: left; transform: scaleX(var(--f, 0)); background: var(--jade); border-radius: inherit; }
.map-item.is-complete .map-bar::after { background: #E0A82E; }
.map-meta em { text-transform: none; letter-spacing: 0; }

/* ---------- Series header and tabs ---------- */
.back { display: grid; place-items: center; }
.back .ic { width: 22px; height: 22px; }
.back:active { transform: scale(.92); }
.tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; padding: 14px 20px; position: sticky; top: 0; z-index: 5; isolation: isolate; }
.tabs::before { content: ""; position: absolute; inset: 10px 16px; border-radius: 14px; background: var(--paper-2); box-shadow: inset 0 1px 3px rgba(0, 0, 0, .1); z-index: -2; }
.tabs-thumb {
  position: absolute; top: 14px; bottom: 14px; left: calc(20px + var(--i, 0) * (100% - 40px) / 3); width: calc((100% - 40px) / 3);
  border-radius: 10px; background: var(--ink); z-index: -1;
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0) 55%);
  box-shadow: 0 6px 12px -6px rgba(0, 0, 0, .45);
  transition: left .34s cubic-bezier(.3, 1.3, .5, 1);
}
.tabs button, .tabs button[aria-selected="true"] { background: transparent; border-radius: 10px; transition: color .25s; }
.tabs button[aria-selected="true"] { color: var(--paper); }

/* ---------- Carton: a kraft case seen from above, boxes standing in its cells ---------- */
.tray {
  position: relative; margin-top: 32px; gap: 12px 9px; padding: 14px 12px 12px; border-radius: 5px;
  background:
    repeating-linear-gradient(90deg, rgba(90, 55, 20, .05) 0 2px, transparent 2px 7px),
    radial-gradient(ellipse at 30% 0%, rgba(255, 255, 255, .18), transparent 60%),
    linear-gradient(180deg, #C69B67, #B4874F);
  box-shadow: inset 0 0 0 3px #A57A45, inset 0 14px 18px -8px rgba(60, 35, 10, .6), inset 0 -4px 10px -4px rgba(60, 35, 10, .35), 0 14px 26px -14px rgba(60, 40, 20, .7);
}
/* the back flap, folded up, with a printed handling mark and a strip of tape */
.tray::before { content: ""; position: absolute; left: 4%; right: 4%; top: -22px; height: 22px; background: linear-gradient(180deg, #D8B381, #C79E69); clip-path: polygon(3% 100%, 0 0, 100% 0, 97% 100%); border-radius: 3px 3px 0 0; }
.tray::after { content: ""; position: absolute; left: 50%; top: -21px; width: 52px; height: 26px; margin-left: -26px; background: linear-gradient(180deg, rgba(255, 236, 170, .75), rgba(240, 214, 140, .7)); clip-path: polygon(0 4%, 100% 0, 98% 100%, 2% 96%); }
.slot { isolation: isolate; animation: slot-in .45s cubic-bezier(.2, 1.3, .4, 1) backwards; animation-delay: calc(var(--k, 0) * 28ms); }
@keyframes slot-in { from { transform: translateY(-18px); opacity: 0; } }
/* each cell: a shallow pocket in the cardboard */
.slot::before { content: ""; position: absolute; inset: 6% -4px -5px; border-radius: 5px; background: rgba(80, 50, 20, .16); box-shadow: inset 0 3px 5px rgba(60, 35, 10, .4); z-index: -2; }
/* contact shadow that softens as the box lifts */
.slot::after { content: ""; position: absolute; left: 12%; right: 12%; bottom: -4px; height: 10px; border-radius: 50%; background: radial-gradient(closest-side, rgba(40, 20, 5, .45), transparent); z-index: -1; transition: transform .3s, opacity .3s; }
.slot.is-picked::after { transform: scale(1.25, 1.1); opacity: .55; }
.slot .sealed { filter: drop-shadow(0 2px 2px rgba(40, 20, 5, .3)); }
.slot .sealed .boxart, .slot .sealed .box { display: block; }
.slot.is-picked .sealed { animation: hop .5s cubic-bezier(.3, 1.5, .5, 1), float 2.8s ease-in-out .5s infinite; filter: drop-shadow(0 14px 10px rgba(40, 20, 5, .35)); }
.slot.is-picked .sheen-band { animation: sheen .9s cubic-bezier(.5, 0, .3, 1) .15s; }
.slot.is-picked.is-shaking .sealed { animation: shake .45s ease-in-out; }
@keyframes hop {
  0% { transform: rotate(var(--tilt)); }
  25% { transform: translateY(2px) scale(1.08, .9) rotate(var(--tilt)); }
  60% { transform: translateY(-18px) scale(.97, 1.1) rotate(0deg); }
  100% { transform: translateY(-10px) scale(1.1) rotate(var(--tilt)); }
}
@keyframes float { 0%, 100% { transform: translateY(-10px) scale(1.1) rotate(var(--tilt)); } 50% { transform: translateY(-14px) scale(1.1) rotate(calc(var(--tilt) * -1)); } }
/* the seal: a die-cut round sticker straddling the lid edge */
.slot .seal-q {
  left: var(--sx, 50%); top: var(--sy, 6%); width: 27%; margin: 0; transform: translate(-50%, -50%) rotate(var(--spin, 0deg));
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, .7) 0 14%, transparent 34%), var(--tag);
  box-shadow: 0 0 0 2px #fff, 0 2px 3px 1px rgba(0, 0, 0, .3); font-size: clamp(10px, 2.8vw, 15px); line-height: 1;
}
.slot.is-open .sealed { filter: grayscale(.85) opacity(.38); transform: rotate(var(--tilt)) scale(.9); }
.slot.is-open .seal-q { background: var(--jade); }
.slot.is-wait .sealed { filter: saturate(.6) brightness(.9); }
.slot.is-wait { opacity: .7; }
.slot:focus-visible { outline: 3px solid var(--tag); outline-offset: 3px; }

.carton-actions { grid-template-columns: 1fr; margin-top: 16px; }
.carton-actions .open { position: relative; overflow: hidden; padding: 15px 20px; font-size: 19px; }
.carton-actions .open::after { content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 40%; background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .45), transparent); transform: skewX(-18deg); opacity: 0; }
.carton-actions .open.is-ready { animation: ready .55s cubic-bezier(.3, 1.6, .5, 1); }
.carton-actions .open.is-ready::after { animation: shine .9s ease-out .15s; }
.carton-actions .open:disabled { background: var(--paper-2); color: var(--ink-2); box-shadow: inset 0 0 0 2px var(--line); background-image: none; opacity: 1; }
@keyframes ready { 0% { transform: scale(.94); } 50% { transform: scale(1.04); } 100% { transform: scale(1); } }
@keyframes shine { 0% { left: -60%; opacity: 1; } 100% { left: 130%; opacity: 1; } }
.carton-note span { box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 2px 4px -2px rgba(0, 0, 0, .3); transform: rotate(-2deg); }

/* ---------- Lineup and swap cards ---------- */
.lineup-card, .swap-card { animation: item-in .4s cubic-bezier(.2, 1.2, .4, 1) backwards; animation-delay: calc(min(var(--k, 0), 18) * 25ms); transition: transform .18s; }
.lineup-card.is-owned:active { transform: scale(.95) rotate(-1deg); }
.lineup-card.is-owned::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--accent, var(--jade)) 45%, transparent); }
.lineup-card.is-missing { background: color-mix(in oklab, var(--card) 70%, var(--paper-2)); box-shadow: inset 0 0 0 2px var(--line); }
/* rares get a gold edge, owned secrets a moving foil */
.lineup-card.rarity-rare.is-owned::after { box-shadow: inset 0 0 0 2px #E8BF5A; }
.lineup-card.rarity-secret.is-owned { background: linear-gradient(115deg, var(--card) 20%, color-mix(in oklab, #B48CF2 30%, var(--card)) 40%, color-mix(in oklab, #7FD1FF 30%, var(--card)) 55%, color-mix(in oklab, var(--tag) 35%, var(--card)) 70%, var(--card) 85%); background-size: 300% 100%; animation: item-in .4s backwards, foil 5s linear infinite; }
@keyframes foil { to { background-position: -300% 0; } }
.token-btn { display: inline-flex; align-items: center; gap: 4px; padding: 7px 10px 7px 6px; font-size: 13px; white-space: nowrap; }
.token-btn .ic { width: 18px; height: 18px; }
.token-btn:disabled .ic { filter: grayscale(1); }

/* ---------- Settings: switches and stickers ---------- */
.row input.switch {
  appearance: none; -webkit-appearance: none; width: 52px; height: 30px; margin: 0; border-radius: 999px; position: relative; cursor: pointer; flex: none;
  background: var(--paper-2); box-shadow: inset 0 2px 4px rgba(0, 0, 0, .18); transition: background .25s;
}
.row input.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .3), inset 0 -2px 0 rgba(0, 0, 0, .06); transition: transform .32s cubic-bezier(.3, 1.5, .5, 1);
}
.row input.switch:checked { background: var(--jade); }
.row input.switch:checked::after { transform: translateX(22px); }
.row input.switch:focus-visible { outline: 3px solid var(--tag); outline-offset: 2px; }
.seg { position: relative; }
.seg button { transition: background .2s, color .2s; }
/* earned stickers peel up at one corner; locked ones are an outline waiting to be filled */
.sticker { opacity: 1; filter: none; background: transparent; box-shadow: inset 0 0 0 2px var(--line); }
.sticker img { filter: brightness(0) opacity(.14); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sticker:not(.is-got) img { filter: brightness(0) invert(1) opacity(.16); } }
:root[data-theme="dark"] .sticker:not(.is-got) img { filter: brightness(0) invert(1) opacity(.16); }
.sticker span, .sticker small { opacity: .55; }
.sticker.is-got { background: var(--card); box-shadow: 0 0 0 3px #fff, 0 6px 12px -6px rgba(0, 0, 0, .4); position: relative; overflow: hidden; }
.sticker.is-got img { filter: drop-shadow(0 3px 3px rgba(0, 0, 0, .2)); }
.sticker.is-got span, .sticker.is-got small { opacity: 1; }
.sticker.is-got::after { content: ""; position: absolute; right: 0; bottom: 0; width: 18px; height: 18px; background: linear-gradient(135deg, transparent 50%, var(--paper-2) 50%); box-shadow: -2px -2px 3px rgba(0, 0, 0, .12); border-top-left-radius: 6px; }
.sticker.is-got:nth-child(3n + 2) { transform: rotate(1.5deg); }

@media (prefers-reduced-motion: reduce) {
  .tab-blob, .tabs-thumb { transition: none; }
  .hero-box .boxart.is-hero, .hud-mystery .q .ic, .lineup-card.rarity-secret.is-owned { animation: none; }
}

/* ---------- Shelf: props shown as rendered shots ---------- */
/* a slightly deeper backdrop than the tile, so white props read; plain hex because three.js reads it */
.dio-panel { --thumb-bg: #D5E0D9; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .dio-panel { --thumb-bg: #2A3A32; } }
:root[data-theme="dark"] .dio-panel { --thumb-bg: #2A3A32; }
.dio-thumb { width: 64px; height: 64px; border-radius: 14px; background: var(--thumb-bg); overflow: hidden; box-shadow: inset 0 1px 2px rgba(0, 0, 0, .08); }
.dio-thumb img, .dio-cats .cat .ic img { width: 100%; height: 100%; display: block; object-fit: cover; }
.dio-thumb.is-shot img, .dio-cats .cat .ic.is-shot img { animation: shot-in .35s ease-out; }
@keyframes shot-in { from { opacity: 0; transform: scale(.85); } }
.dio-thumb.is-loading, .dio-cats .cat .ic.is-loading { background: linear-gradient(100deg, var(--paper-2) 30%, color-mix(in oklab, var(--card) 70%, var(--paper-2)) 50%, var(--paper-2) 70%) 0 0 / 300% 100%; animation: shimmer 1.2s linear infinite; }
@keyframes shimmer { to { background-position: -300% 0; } }
.prop-tile { min-height: 96px; padding-top: 4px; }
.prop-tile:active .dio-thumb img { transform: scale(1.08) rotate(-3deg); transition: transform .15s; }
.dio-flag { text-transform: none; letter-spacing: 0; font-size: 10px; top: 4px; right: 4px; box-shadow: 0 1px 2px rgba(0, 0, 0, .15); }
.dio-cats .cat { gap: 7px; padding-left: 4px; }
.dio-cats .cat .ic { width: 30px; height: 30px; border-radius: 50%; overflow: hidden; background: var(--paper-2); box-shadow: 0 0 0 2px var(--card); font-size: 0; }
.dio-cats .cat.is-on .ic { box-shadow: 0 0 0 2px rgba(255, 255, 255, .85); }
