/* cat.caolibin.com — one fixed look (a dark room the cards glow in); the page colour
   follows the centred card. Card internals are sized in container units (cqw) so a
   card is the same design at carousel size and at full size. */
:root {
  color-scheme: dark;
  --page: #140d09;
  --ink: #f3ede4;
  --ink2: #b9b1a6;
  --cw: clamp(210px, 64vw, 300px);
  --zh: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --zh-serif: "Songti SC", "STSong", "Noto Serif SC", "SimSun", serif;
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  min-height: 100vh; min-height: 100dvh; color: var(--ink); font-family: var(--zh);
  background: radial-gradient(120% 80% at 50% 45%, color-mix(in oklab, var(--page) 70%, #fff 8%), var(--page) 70%) var(--page);
  transition: background-color .6s ease;
  display: flex; flex-direction: column; overflow-x: hidden;
  padding-top: env(safe-area-inset-top, 0px); padding-bottom: env(safe-area-inset-bottom, 0px);
}
body.staged { overflow: hidden; }
button { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* ---------------------------------------------------------------- backgrounds */
/* One painting per style behind everything, crossfading as the carousel moves.
   The tint on top keeps the white title and the cards readable over the bright
   ones (the sunny lawn, the pastel sky). */
.bgs { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.bgs i { position: absolute; inset: -2%; background: center / cover no-repeat; opacity: 0; transition: opacity .9s ease; }
.bgs i.on { opacity: 1; }
.bgs::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(70% 60% at 50% 55%, color-mix(in oklab, var(--page) 35%, transparent), color-mix(in oklab, var(--page) 78%, transparent) 100%),
              linear-gradient(color-mix(in oklab, var(--page) 55%, transparent), transparent 30%, transparent 75%, color-mix(in oklab, var(--page) 70%, transparent));
  transition: background .6s ease;
}

/* ambient particles (ambient.js): above the paintings and their tint, below everything else */
.ambient { position: fixed; inset: 0; z-index: -1; pointer-events: none; }

/* ---------------------------------------------------------------- page chrome */
.top { padding: 18px 16px 0; min-height: 44px; position: relative; }
.back { position: absolute; left: 16px; top: 18px; font: 500 12px "JetBrains Mono", ui-monospace, monospace; color: var(--ink2); text-decoration: none; }
.back:hover { color: var(--ink); }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
main { flex: 1; display: flex; flex-direction: column; justify-content: center; }

.track {
  display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
  padding: 28px calc(50vw - var(--cw) / 2) 18px; cursor: grab; outline: none;
}
.track::-webkit-scrollbar { display: none; }
.track.dragging { scroll-snap-type: none; cursor: grabbing; }
.slot {
  flex: none; width: var(--cw); scroll-snap-align: center; cursor: pointer; user-select: none; -webkit-user-select: none;
  transform: scale(.84); opacity: .5; filter: saturate(.7); transition: transform .35s ease, opacity .35s ease, filter .35s ease;
}
.slot.on { transform: scale(1); opacity: 1; filter: none; }
.slot.on .card { box-shadow: 0 24px 60px -18px rgba(0,0,0,.8), 0 0 0 1px rgba(255,255,255,.06); }
.slot.on:hover .card { transform: translateY(-6px); }
.slot .card { transition: transform .3s ease; }

.caption { display: flex; align-items: center; justify-content: center; gap: 18px; }
.cap-text { min-width: 170px; text-align: center; display: flex; flex-direction: column; gap: 2px; }
.cap-text b { font-size: 18px; }
.cap-text span { font: 500 11px "JetBrains Mono", monospace; letter-spacing: .12em; text-transform: uppercase; color: var(--ink2); }
.nav { width: 40px; height: 40px; border-radius: 50%; border: 1px solid rgba(255,255,255,.2); background: rgba(255,255,255,.06); font-size: 24px; line-height: 1; cursor: pointer; display: grid; place-items: center; padding-bottom: 3px; }
.nav:hover { background: rgba(255,255,255,.14); }
.nav:focus-visible, .dots button:focus-visible, .pill:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.dots { display: flex; justify-content: center; gap: 8px; margin-top: 14px; }
.dots button { width: 8px; height: 8px; padding: 0; border-radius: 99px; border: 0; background: rgba(255,255,255,.28); cursor: pointer; transition: width .3s ease, background .3s ease; }
.dots button.on { width: 22px; background: #fff; }
.hint { text-align: center; color: var(--ink2); font-size: 13px; margin: 14px 0 28px; }

/* ---------------------------------------------------------------- card base */
/* Radius in % of the card's own box: cqw here would measure the card's parent. */
.card { position: relative; width: 100%; aspect-ratio: 5 / 7; container-type: inline-size; border-radius: 4.6% / 3.29%; }
.face { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; }
.frame {
  position: absolute; inset: 0; padding: 2.8cqw; border-radius: inherit;
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto auto; gap: 1.3cqw;
  background: var(--frame); background-size: 220% 220%; background-position: var(--mx, 50%) var(--my, 50%);
  box-shadow: inset 0 0 0 .7cqw var(--edge), inset 0 0 0 1.4cqw rgba(0,0,0,.25);
  color: var(--cink);
}
.c-head { display: flex; align-items: center; justify-content: space-between; gap: 2cqw; padding: .6cqw 1.2cqw 0; }
.c-names { display: flex; align-items: baseline; gap: 2cqw; min-width: 0; }
.c-name { font: var(--name-font); font-size: 7.4cqw; line-height: 1; color: var(--name); white-space: nowrap; }
.c-title { font-family: var(--zh-serif); font-weight: 700; font-size: 3.5cqw; color: var(--sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-badge { flex: none; font: var(--badge-font); font-size: 3.4cqw; color: var(--badge); background: var(--badge-bg); padding: .7cqw 1.8cqw; border-radius: 9cqw; white-space: nowrap; }
.c-art { position: relative; overflow: hidden; border-radius: 1.6cqw; box-shadow: 0 0 0 .6cqw var(--art-edge); background: #000; }
.c-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 32%; display: block; }
.c-type { font-size: 2.8cqw; color: var(--sub); padding: 0 1.2cqw; font-weight: 600; letter-spacing: .02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-text { background: var(--panel); border: .35cqw solid var(--panel-edge); border-radius: 1.6cqw; padding: 1.7cqw 2.4cqw; display: grid; gap: 1.1cqw; }
.ab-head { display: flex; justify-content: space-between; align-items: baseline; gap: 2cqw; }
.ab b { font-size: 3.3cqw; color: var(--ab-name); }
.ab .dmg { font: 700 4.2cqw "Fredoka", var(--zh); color: var(--ab-name); }
.ab p { margin: .5cqw 0 0; font-size: 2.9cqw; line-height: 1.45; color: var(--cink); }
.flavor { margin: .4cqw 0 0; padding-top: 1.4cqw; border-top: .25cqw solid var(--panel-edge); font-family: var(--zh-serif); font-style: italic; font-size: 2.7cqw; line-height: 1.5; color: var(--flavor); }
.c-foot { display: flex; justify-content: space-between; font: 500 2.2cqw "JetBrains Mono", monospace; letter-spacing: .08em; color: var(--sub); padding: 0 1.2cqw; opacity: .85; }

/* foil and glare: only noticeable when the card tilts (--hyp grows off-centre) */
.holo, .sparkle, .glare { position: absolute; inset: 0; pointer-events: none; }
.holo {
  /* A narrow rainbow band that slides across as the card turns. Overlay, not
     color-dodge: dodge blew the dark paintings out to flat yellow-green. */
  background: linear-gradient(115deg, transparent 30%, hsl(0 100% 65% / .9) 38%, hsl(55 100% 62% / .9) 43%, hsl(140 90% 60% / .9) 48%, hsl(200 100% 62% / .9) 53%, hsl(280 100% 70% / .9) 58%, transparent 66%);
  background-size: 300% 300%; background-position: var(--mx, 50%) var(--my, 50%);
  mix-blend-mode: overlay; opacity: calc(.04 + var(--hyp, 0) * .34);
}
/* Glints fade to transparent WHITE: fading to plain `transparent` (transparent
   black) left dark specks on the white fur under a dodge blend. */
.sparkle {
  background-image:
    radial-gradient(circle at 20% 30%, #fff 0 .6px, #fff0 1.6px),
    radial-gradient(circle at 70% 60%, #fff 0 .5px, #fff0 1.3px),
    radial-gradient(circle at 45% 85%, #fff 0 .7px, #fff0 1.8px);
  background-size: 29px 37px, 41px 23px, 53px 47px;
  background-position: calc(var(--mx, 50%) * .4) calc(var(--my, 50%) * .4);
  mix-blend-mode: screen; opacity: calc(var(--hyp, 0) * .8);
}
.glare {
  border-radius: inherit;
  background: radial-gradient(farthest-corner circle at var(--mx, 50%) var(--my, 30%), rgba(255,255,255,.6) 0%, rgba(255,255,255,.14) 22%, transparent 55%);
  mix-blend-mode: overlay; opacity: calc(.25 + var(--hyp, 0) * .6);
}
.slot:not(.on) .glare { opacity: .1; }

/* ---------------------------------------------------------------- themes */
[data-theme="dark"] {
  --frame: linear-gradient(160deg, #3a2a17, #120c07 35%, #2d2012 55%, #0d0906 80%, #3a2a17);
  --edge: #c9a14a; --art-edge: #8a6a2c; --cink: #e8dcc0; --sub: #c9b48a; --name: #f0cf7e; --flavor: #b8a787;
  --name-font: 700 1em "Cinzel", serif; --badge-font: 700 1em "Cinzel", serif; --badge: #f0cf7e; --badge-bg: rgba(0,0,0,.45);
  --panel: rgba(8,6,4,.72); --panel-edge: #6d5424; --ab-name: #f0cf7e;
}
[data-theme="vangogh"] {
  --frame: repeating-radial-gradient(circle at 30% 20%, #1c3b8f 0 6px, #24489f 6px 11px, #1a3582 11px 17px), #1c3b8f;
  --edge: #f2c230; --art-edge: #f2c230; --cink: #1d2b5c; --sub: #f7dd7a; --name: #ffd84a; --flavor: #3a4a7a;
  --name-font: 400 1em "IM Fell English SC", serif; --badge-font: 700 1em "IM Fell English SC", serif; --badge: #1d2b5c; --badge-bg: #f2c230;
  --panel: #f4e8c6; --panel-edge: #c9a24a; --ab-name: #1c3b8f;
}
[data-theme="garden"] {
  --frame: linear-gradient(180deg, #8fdc45, #4fae22 60%, #3a8c18);
  --edge: #2f6b12; --art-edge: #fff6c9; --cink: #4a3212; --sub: #fffbe0; --name: #fff; --flavor: #7a5a2a;
  --name-font: 400 1em "Luckiest Guy", "Fredoka", sans-serif; --badge-font: 700 1em "Fredoka", sans-serif; --badge: #6b4a00; --badge-bg: #ffd83a;
  --panel: #fff4c2; --panel-edge: #b07a3a; --ab-name: #3d8a14;
}
[data-theme="garden"] .c-name { -webkit-text-stroke: .5cqw #2f6b12; paint-order: stroke fill; }
.card[data-theme="garden"] { border-radius: 7% / 5%; }
[data-theme="monster"] {
  --frame: linear-gradient(135deg, #ffd9f5, #c9e8ff 35%, #fff5bf 65%, #d9ccff);
  --edge: #ffffff; --art-edge: #fff; --cink: #2b2160; --sub: #5a4a9a; --name: #2b2160; --flavor: #6a5aa0;
  --name-font: 700 1em "Fredoka", sans-serif; --badge-font: 700 1em "Fredoka", sans-serif; --badge: #e0314b; --badge-bg: rgba(255,255,255,.75);
  --panel: rgba(255,255,255,.72); --panel-edge: rgba(90,74,154,.25); --ab-name: #2b2160;
}
[data-theme="ukiyoe"] {
  --frame: repeating-linear-gradient(90deg, rgba(120,90,50,.05) 0 2px, transparent 2px 5px), linear-gradient(#f3e8cf, #eadcbc);
  --edge: #1d3a5f; --art-edge: #1d3a5f; --cink: #1d2a3a; --sub: #3a4a5f; --name: #1d3a5f; --flavor: #5a5040;
  --name-font: 700 1em "Shippori Mincho B1", serif; --badge-font: 700 1em "Shippori Mincho B1", var(--zh-serif); --badge: #fff7ea; --badge-bg: #b3322a;
  --panel: rgba(255,250,238,.6); --panel-edge: #9a8a66; --ab-name: #b3322a;
}
[data-theme="ukiyoe"] .c-badge { border-radius: .8cqw; }
[data-theme="pixel"] {
  --frame: #2a1f5a;
  --edge: #ffffff; --art-edge: #000; --cink: #ffffff; --sub: #b8b0ff; --name: #ffe14d; --flavor: #c8c2ff;
  --name-font: 400 1em "Press Start 2P", monospace; --badge-font: 400 1em "Press Start 2P", monospace; --badge: #7dff8a; --badge-bg: #000;
  --panel: #10126a; --panel-edge: #ffffff; --ab-name: #ffe14d;
}
.card[data-theme="pixel"] { border-radius: 1.2% / .86%; }
[data-theme="pixel"] .c-name { font-size: 5.6cqw; }
[data-theme="pixel"] .c-badge { font-size: 2.6cqw; border-radius: 0; padding: 1.2cqw 1.4cqw; }
[data-theme="pixel"] .c-art, [data-theme="pixel"] .c-text { border-radius: 0; }
[data-theme="pixel"] .c-art img { image-rendering: pixelated; }
[data-theme="pixel"] .frame { box-shadow: inset 0 0 0 .9cqw #000, inset 0 0 0 1.8cqw #fff, inset 0 0 0 2.4cqw #000; }
[data-theme="pixel"] .c-text { border-width: .7cqw; box-shadow: 0 0 0 .7cqw #000; }
[data-theme="pixel"] .flavor { font-style: normal; font-family: var(--zh); }

[data-theme="cs"] {
  --frame: linear-gradient(160deg, #5d5438, #2c281a 55%, #4a4329);
  --edge: #c8b27a; --art-edge: #1a170e; --cink: #ece4c8; --sub: #cfc293; --name: #f2d36b; --flavor: #cfc293;
  --name-font: 400 1em "Black Ops One", sans-serif; --badge-font: 400 1em "Black Ops One", sans-serif; --badge: #9be27a; --badge-bg: rgba(0,0,0,.6);
  --panel: rgba(18,16,9,.82); --panel-edge: #6d6340; --ab-name: #f2d36b;
}
.card[data-theme="cs"] { border-radius: 2% / 1.43%; }
[data-theme="cs"] .c-art, [data-theme="cs"] .c-text { border-radius: .6cqw; }
[data-theme="greek"] {
  --frame: repeating-linear-gradient(90deg, rgba(216,116,58,.08) 0 2px, transparent 2px 9px), linear-gradient(#170d07, #0c0603);
  --edge: #d8743a; --art-edge: #d8743a; --cink: #f1d3b8; --sub: #d99a6a; --name: #ef9154; --flavor: #d9a37a;
  --name-font: 400 1em "Marcellus", serif; --badge-font: 700 1em var(--zh-serif); --badge: #120a06; --badge-bg: #d8743a;
  --panel: rgba(216,116,58,.1); --panel-edge: #b35a2a; --ab-name: #ef9154;
}
[data-theme="greek"] .frame { box-shadow: inset 0 0 0 .7cqw #d8743a, inset 0 0 0 1.5cqw #120a06, inset 0 0 0 1.8cqw #d8743a; }
[data-theme="ink"] {
  --frame: radial-gradient(120% 90% at 30% 20%, #f6f2e8, #e8e2d3 70%, #d8d0bd);
  --edge: #2b2b2b; --art-edge: #3a3a3a; --cink: #222; --sub: #555; --name: #151515; --flavor: #555;
  --name-font: 400 1em "Ma Shan Zheng", var(--zh-serif); --badge-font: 400 1em "Ma Shan Zheng", var(--zh-serif); --badge: #fff; --badge-bg: #a4251a;
  --panel: rgba(255,255,255,.5); --panel-edge: #bdb6a8; --ab-name: #8c1c13;
}
[data-theme="ink"] .c-name { font-size: 9cqw; }
[data-theme="ink"] .c-badge { border-radius: .8cqw; }
[data-theme="cyber"] {
  --frame: linear-gradient(160deg, #120d2e, #07061a 60%, #1a0c30);
  --edge: #00f0ff; --art-edge: #ff2bd6; --cink: #e9e6ff; --sub: #9f9ad6; --name: #00f0ff; --flavor: #b9b4ff;
  --name-font: 700 1em "Orbitron", sans-serif; --badge-font: 700 1em "Orbitron", sans-serif; --badge: #ff5ee3; --badge-bg: rgba(255,43,214,.16);
  --panel: rgba(8,6,28,.86); --panel-edge: #ff2bd6; --ab-name: #00f0ff;
}
[data-theme="cyber"] .frame { box-shadow: inset 0 0 0 .5cqw #00f0ff, inset 0 0 3cqw rgba(0,240,255,.35); }
[data-theme="cyber"] .c-name { text-shadow: 0 0 2cqw rgba(0,240,255,.8); font-size: 6.4cqw; }
[data-theme="steam"] {
  --frame: linear-gradient(160deg, #7a5029, #3a230f 55%, #6b4524);
  --edge: #d9a441; --art-edge: #d9a441; --cink: #3a2410; --sub: #f0cf8a; --name: #f4d27a; --flavor: #6a4a24;
  --name-font: 400 1em "Rye", serif; --badge-font: 700 1em "Rye", serif; --badge: #f4d27a; --badge-bg: #2a1809;
  --panel: #f3e3c3; --panel-edge: #8a5a2b; --ab-name: #7a3e12;
}
[data-theme="steam"] .frame { box-shadow: inset 0 0 0 .7cqw #d9a441, inset 0 0 0 1.3cqw #3a230f, inset 0 0 0 1.6cqw #b07a2a; }
[data-theme="egypt"] {
  --frame: linear-gradient(160deg, #22479c, #122a66 60%, #1d3d8f);
  --edge: #e7b93e; --art-edge: #e7b93e; --cink: #3a2a10; --sub: #f4dc8a; --name: #f4cf5a; --flavor: #6a5020;
  --name-font: 700 1em "Cinzel", serif; --badge-font: 700 1em "Cinzel", serif; --badge: #122a66; --badge-bg: #e7b93e;
  --panel: #efe0b8; --panel-edge: #b8892a; --ab-name: #1d3d8f;
}
[data-theme="egypt"] .frame { box-shadow: inset 0 0 0 .7cqw #e7b93e, inset 0 0 0 1.4cqw #122a66, inset 0 0 0 1.8cqw #3aa6a0; }

/* ---------------------------------------------------------------- card back */
.face-back { transform: rotateY(180deg); }
.back-inner {
  position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 2cqw;
  background: var(--frame); box-shadow: inset 0 0 0 .7cqw var(--edge), inset 0 0 0 4cqw rgba(0,0,0,.18); color: var(--name);
}
.back-inner .paw { width: 24cqw; fill: var(--edge); opacity: .9; }
.back-inner b { font: var(--name-font); font-size: 11cqw; }
.back-inner span { font: 500 2.6cqw "JetBrains Mono", var(--zh); letter-spacing: .12em; color: var(--sub); text-align: center; }
/* the flavor text lives on the back, so the front's art window can be taller */
.back-story { margin: 3cqw 9cqw 0; padding: 3.2cqw 3.6cqw; background: var(--panel); border: .35cqw solid var(--panel-edge); border-radius: 1.6cqw; font-family: var(--zh-serif); font-style: italic; font-size: 3.6cqw; line-height: 1.6; color: var(--cink); text-align: left; }
[data-theme="pixel"] .back-story { font-style: normal; font-family: var(--zh); border-radius: 0; }

/* ---------------------------------------------------------------- detail stage */
.stage { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; grid-template-rows: 1fr auto auto; padding: 24px 16px calc(18px + env(safe-area-inset-bottom, 0px)); animation: fade .3s ease; }
.stage-bg { position: absolute; inset: 0; background: color-mix(in oklab, color-mix(in oklab, var(--page) 70%, #000) 72%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.tilt {
  position: relative; width: min(86vw, 440px, calc((100dvh - 170px) * 5 / 7)); align-self: center;
  perspective: 1400px; cursor: pointer; touch-action: none;
  --rx: 0deg; --ry: 0deg; --mx: 50%; --my: 50%; --hyp: 0;
}
.flipper { transform: rotateX(var(--rx)) rotateY(var(--ry)); transform-style: preserve-3d; transition: transform .12s ease-out; }
.flipper > .card { transform-style: preserve-3d; transition: transform .7s cubic-bezier(.3,.7,.2,1); box-shadow: 0 40px 90px -30px rgba(0,0,0,.9); }
.flipper.flipped > .card { transform: rotateY(180deg); }
.card.big .face { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.stage-bar { position: relative; display: flex; gap: 10px; margin-top: 18px; }
.pill { padding: 10px 20px; border-radius: 99px; border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.08); cursor: pointer; font-size: 14px; }
.pill:hover { background: rgba(255,255,255,.18); }
.stage-hint { position: relative; margin: 10px 0 0; color: var(--ink2); font-size: 12px; }
@keyframes fade { from { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .slot, .flipper, .flipper > .card, .stage { transition: none; animation: none; }
}
