/* ---------- quests of the day (quest.js): the home card, its sheet, the banner when one is done ---------- */
.qs-card { margin: 0 0 14px; padding: 14px 14px 10px; background: var(--card, #fff); border-radius: 22px; cursor: pointer;
  box-shadow: 0 1px 0 var(--line, #E8E4D8), 0 12px 26px -20px rgba(0, 0, 0, .45); -webkit-tap-highlight-color: transparent;
  transition: transform var(--t-press, 90ms) ease; }
.qs-card:active { transform: scale(.985); }
.qs-card:focus-visible { outline: 3px solid var(--acc, #2DBE70); outline-offset: 2px; }
.qs-head { display: flex; align-items: center; gap: 8px; min-height: 40px; margin-bottom: 4px; }
.qs-head b { font-size: 17px; font-weight: 800; color: var(--ink, #1E211D); }
.qs-n { padding: 2px 9px; border-radius: 99px; font-size: 14px; font-weight: 700; color: var(--acc-ink, #0F7543); background: var(--acc-soft, #E3F4EA); }
.qs-card.all .qs-n { color: var(--honey-ink, #8A5A00); background: var(--honey-soft, #FFF1CC); }
.qs-head .qs-chest { margin-left: auto; }

.qs-list { display: flex; flex-direction: column; }
.qs-row { display: flex; align-items: center; gap: 12px; width: 100%; padding: 9px 0; border: 0; background: none; font: inherit; color: inherit; text-align: left; }
.qs-row + .qs-row { border-top: 1px solid var(--line, #E8E4D8); }
.qs-ic { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 13px; background: var(--fill, #F1EEE5); }
.qs-ic svg { width: 24px; height: 24px; }
.qs-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.qs-tx b { font-size: 15px; font-weight: 700; color: var(--ink, #1E211D); line-height: 1.25; }
.qs-tx small { font-size: 14px; color: var(--ink2, #5C635D); margin-top: -2px; }
.qs-pr { display: flex; align-items: center; gap: 8px; }
.qs-bar { position: relative; flex: 1; height: 8px; border-radius: 99px; background: var(--fill, #F1EEE5); overflow: hidden; }
.qs-bar > i { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--honey, #F4B63C); transition: width .6s var(--ease-out, ease); }
.qs-pr em { flex: none; min-width: 34px; font-style: normal; font-size: 14px; font-weight: 700; color: var(--ink2, #5C635D); text-align: right; font-variant-numeric: tabular-nums; }
.qs-g { flex: none; display: flex; align-items: center; gap: 2px; min-width: 52px; justify-content: flex-end; font-size: 15px; font-weight: 800; color: var(--honey-ink, #8A5A00); }
.qs-g svg { width: 18px; height: 18px; }
.qs-ok { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; color: #fff; background: var(--acc-btn, #14884F); }
.qs-ok svg { width: 18px; height: 18px; }
.qs-row.done .qs-bar > i { background: var(--acc, #2DBE70); }
.qs-row.done .qs-tx b { color: var(--ink2, #5C635D); }
.qs-row.done .qs-ic { background: var(--acc-soft, #E3F4EA); }

/* the chest: shut and pale until all three are done, then it bobs, then it opens */
.qs-chest { flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 14px; background: none; cursor: pointer; }
.qs-chest svg { width: 34px; height: 31px; overflow: visible; }
.qs-chest.big svg { width: 46px; height: 41px; }
.qs-chest.big { width: 56px; height: 56px; }
.qs-chest.lock svg { filter: grayscale(.85); opacity: .55; }
.qs-chest.ready { background: var(--honey-soft, #FFF1CC); animation: qs-bob 1.4s ease-in-out infinite; }
.qs-chest.ready svg { filter: drop-shadow(0 0 6px rgba(244, 182, 60, .8)); }
.qs-chest .qs-lid { transform-box: fill-box; transform-origin: 10% 100%; transition: transform .45s cubic-bezier(.3, 1.6, .5, 1); }
.qs-chest.opening svg { animation: qs-shake .6s ease-in-out; }
.qs-chest.open .qs-lid { transform: rotate(-32deg) translate(-2px, -5px); }
@keyframes qs-bob { 0%, 100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-3px) rotate(-4deg); } }
@keyframes qs-shake { 0%, 100% { transform: rotate(0); } 20%, 60% { transform: rotate(-9deg); } 40%, 80% { transform: rotate(9deg); } }

/* the sheet */
.qs-sh-head { display: flex; align-items: center; gap: 12px; margin: 4px 0 8px; }
.qs-sh-head canvas, .qs-sh-head img { width: 64px; height: 64px; flex: none; }
.qs-sh-head b { display: block; font-size: 19px; font-weight: 800; color: var(--ink, #1E211D); }
.qs-sh-head p { margin: 2px 0 0; font-size: 15px; color: var(--ink2, #5C635D); }
.qs-list.big .qs-row { padding: 12px 0; }
button.qs-row { cursor: pointer; }
.qs-box { display: flex; align-items: center; gap: 12px; margin: 10px 0 6px; padding: 10px 12px; border-radius: 18px; background: var(--fill, #F1EEE5); }
.qs-box > span { flex: 1; display: flex; flex-direction: column; }
.qs-box b { font-size: 15px; font-weight: 800; color: var(--ink, #1E211D); }
.qs-box small { font-size: 14px; color: var(--ink2, #5C635D); }
.qs-box.ready { background: var(--honey-soft, #FFF1CC); }
.qs-box .btn { flex: none; min-width: 72px; }
.qs-reset { margin: 6px 0 10px; font-size: 14px; color: var(--ink2, #5C635D); text-align: center; }
.qs-sheet > .btn:last-child { width: 100%; }

/* the banner when a quest is done: drops in at the top, Nếp in it, the grains fly out of its corner */
.qs-pop { position: fixed; z-index: 205; top: calc(64px + env(safe-area-inset-top)); left: 50%; width: min(360px, calc(100% - 32px));
  display: flex; align-items: center; gap: 10px; padding: 8px 14px 8px 8px; border-radius: 20px; pointer-events: none;
  background: var(--card, #fff); box-shadow: 0 0 0 2px var(--honey, #F4B63C), 0 16px 30px -14px rgba(0, 0, 0, .5);
  transform: translateX(-50%); animation: qs-in .5s cubic-bezier(.3, 1.5, .5, 1) both; }
/* an end screen has its title and Nếp at the top: the banner comes in above its buttons instead */
body:has(.hn-end, .win) .qs-pop { top: auto; bottom: calc(100px + env(safe-area-inset-bottom)); }
.qs-pop.out { animation: qs-outk .3s ease-in forwards; }
.qs-pop canvas, .qs-pop img { width: 52px; height: 52px; flex: none; }
.qs-pop-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.qs-pop-tx small { font-size: 14px; font-weight: 700; color: var(--acc-ink, #0F7543); }
.qs-pop-tx b { font-size: 16px; font-weight: 800; color: var(--ink, #1E211D); line-height: 1.25; }
.qs-pop em { flex: none; display: flex; align-items: center; gap: 2px; font-style: normal; font-size: 18px; font-weight: 800; color: var(--honey-ink, #8A5A00); }
.qs-pop em svg { width: 22px; height: 22px; }
@keyframes qs-in { from { transform: translate(-50%, -24px) scale(.9); opacity: 0; } to { transform: translate(-50%, 0) scale(1); opacity: 1; } }
@keyframes qs-outk { to { transform: translate(-50%, -16px) scale(.96); opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .qs-chest.ready, .qs-chest.opening svg { animation: none; }
  .qs-pop, .qs-pop.out { animation: none; }
  .qs-pop.out { opacity: 0; }
}

/* ---------- a chest opening, full screen (chest.js) ---------- */
/* Beats are classes the script adds in turn: go (falls), land, tense, crouch, open, done, exit. Only transform and
   opacity move; springs are written out as keyframes that overshoot and settle. */
.cr { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; overflow: hidden; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: opacity .2s ease; }
.cr.out { opacity: 0; }
/* the dim is a layer of its own, so fading it is only opacity */
.cr::before { content: ""; position: absolute; inset: 0; will-change: opacity; animation: cr-in .22s ease-out both;
  background: radial-gradient(circle at 50% 48%, rgba(120, 70, 10, .5), rgba(26, 16, 4, .84) 64%); }
html[data-theme="dark"] .cr::before { background: radial-gradient(circle at 50% 48%, rgba(110, 66, 8, .5), rgba(0, 0, 0, .84) 64%); }
.cr.exit::before { opacity: 0; transition: opacity .3s ease-in; }
@keyframes cr-in { from { opacity: 0; } }
.cr-stage { position: relative; display: grid; place-items: center; width: min(230px, 60vw); aspect-ratio: 200 / 184; will-change: transform; }
@media (min-width: 1000px) { .cr-stage { width: 270px; } }
.cr-stage > * { grid-area: 1 / 1; }
.cr-rays, .cr-glow, .cr-flash { position: absolute; left: 50%; top: 46%; pointer-events: none; }
.cr-svg { position: relative; z-index: 1; display: block; width: 100%; height: auto; overflow: visible; }
.cr-lid, .cr-bands, .cr-lock { transform-box: fill-box; }
.cr-lid { transform-origin: 10% 100%; }
.cr-bands { transform-origin: 50% 100%; }
.cr-mouth, .cr-beam, .cr-flash, .cr-star, .cr-n span, .cr-cf, .cr-dust, .cr-ring { opacity: 0; }

/* 1. the fall: held above the screen, then down fast, stretched a little */
.cr-fall { position: relative; width: 100%; transform: translateY(calc(-50vh - 140%)); will-change: transform; }
.cr.go .cr-fall { animation: cr-fall .36s .04s cubic-bezier(.55, 0, 1, .55) both; }
@keyframes cr-fall {
  0% { transform: translateY(calc(-50vh - 140%)) rotate(-8deg) scale(.92, 1.12); }
  100% { transform: translateY(0) rotate(0) scale(.94, 1.1); }
}
.cr-chest { position: relative; width: 100%; transform-origin: 50% 96%; will-change: transform; }

/* 2. the landing: squash, spring back, settle; the bands jiggle a beat later; dust and a ring; the screen jolts */
.cr.land .cr-fall { animation: none; transform: none; }
.cr.land .cr-chest { animation: cr-land .5s linear both; }
@keyframes cr-land {
  0% { transform: scale(1.3, .68); } 18% { transform: scale(.86, 1.16) translateY(-12px); } 38% { transform: scale(1.07, .94); }
  58% { transform: scale(.97, 1.03); } 78% { transform: scale(1.01, .99); } 100% { transform: none; }
}
.cr.land .cr-bands { animation: cr-jig .5s .07s linear both; }
.cr.open .cr-bands { animation: cr-jig2 .55s .1s linear both; }
@keyframes cr-jig { 0% { transform: none; } 25% { transform: scaleY(.9); } 50% { transform: scaleY(1.05); } 75% { transform: scaleY(.98); } 100% { transform: none; } }
@keyframes cr-jig2 { 0% { transform: none; } 25% { transform: scaleY(.9); } 50% { transform: scaleY(1.05); } 75% { transform: scaleY(.98); } 100% { transform: none; } }
.cr.land .cr-stage { animation: cr-jolt .3s linear both; }
@keyframes cr-jolt { 0%, 100% { transform: none; } 20% { transform: translateY(7px); } 45% { transform: translate(-3px, -3px); } 70% { transform: translate(2px, 1px); } }
.cr-ring { align-self: end; width: 120%; aspect-ratio: 4 / 1; margin-bottom: -8%; border-radius: 50%; border: 4px solid rgba(255, 236, 190, .85); pointer-events: none; }
.cr.land .cr-ring { animation: cr-ring .5s cubic-bezier(.2, .7, .3, 1) forwards; }
@keyframes cr-ring { 0% { transform: scale(.4); opacity: .95; } 100% { transform: scale(1.8); opacity: 0; } }
.cr-dust { align-self: end; justify-self: center; width: 28px; height: 28px; border-radius: 50%; pointer-events: none; background: #F6E3C4; }
html[data-theme="dark"] .cr-dust { background: #B89B72; }
.cr.land .cr-dust { animation: cr-dust .6s var(--d) cubic-bezier(.2, .8, .3, 1) forwards; }
@keyframes cr-dust { 0% { transform: scale(.3); opacity: .9; } 100% { transform: translate(var(--x), var(--y)) scale(calc(var(--s) * 1.6)); opacity: 0; } }
.cr-glow { width: 200%; margin: -100% 0 0 -100%; aspect-ratio: 1; border-radius: 50%; opacity: 0; transform: scale(.4); will-change: transform, opacity;
  background: radial-gradient(circle, rgba(255, 214, 90, .55), rgba(255, 180, 40, .16) 42%, transparent 68%); transition: transform .5s cubic-bezier(.3, 1.4, .5, 1), opacity .4s; }
.cr.land .cr-glow { opacity: .7; transform: scale(.85); }
.cr.crouch .cr-glow { opacity: 1; transform: scale(1.05); transition-duration: .25s; }

/* 3. tension: shakes that grow, little hops */
.cr.tense .cr-chest { animation: cr-tense .48s linear both; }
@keyframes cr-tense {
  0% { transform: none; } 12% { transform: rotate(-3deg) translateY(-3px); } 25% { transform: rotate(3deg); } 38% { transform: rotate(-5deg) translateY(-5px); }
  52% { transform: rotate(5deg); } 66% { transform: rotate(-7deg) translateY(-7px); } 82% { transform: rotate(7deg); } 100% { transform: none; }
}
/* 4. the crouch: squashes down and holds there a beat, trembling */
.cr.crouch .cr-chest { animation: cr-crouch .28s cubic-bezier(.3, 0, .2, 1) both; }
@keyframes cr-crouch {
  0% { transform: none; } 45% { transform: scale(1.14, .82); } 60% { transform: scale(1.15, .81) translateX(-1.5px); }
  75% { transform: scale(1.15, .81) translateX(1.5px); } 90% { transform: scale(1.16, .8) translateX(-1px); } 100% { transform: scale(1.16, .8); }
}

/* 5. the burst: the chest springs up tall, the lid flies and bounces before it rests, light pours out */
.cr.open .cr-chest { animation: cr-burst .6s linear both; }
@keyframes cr-burst {
  0% { transform: scale(1.16, .8); } 16% { transform: scale(.84, 1.22) translateY(-18px); } 36% { transform: scale(1.08, .93); }
  56% { transform: scale(.97, 1.04); } 78% { transform: scale(1.01, .99); } 100% { transform: none; }
}
.cr.open .cr-lid { animation: cr-lid .9s linear both; }
@keyframes cr-lid {
  0% { transform: none; } 20% { transform: translate(-6px, -84px) rotate(-26deg); } 42% { transform: translate(-4px, -36px) rotate(-6deg); }
  60% { transform: translate(-4px, -54px) rotate(-14deg); } 78% { transform: translate(-4px, -44px) rotate(-9deg); } 100% { transform: translate(-4px, -48px) rotate(-11deg); }
}
.cr.open .cr-lock { animation: cr-jig .4s .05s linear both; }
.cr.open .cr-mouth { opacity: 1; }
.cr-beam { position: absolute; left: 16%; right: 16%; bottom: 50%; height: 110%; transform-origin: 50% 100%; transform: scaleY(0); pointer-events: none; will-change: transform, opacity;
  background: linear-gradient(to top, rgba(255, 236, 150, .9), rgba(255, 220, 110, .3) 50%, transparent); clip-path: polygon(6% 100%, 94% 100%, 114% 0, -14% 0); }
.cr.open .cr-beam { animation: cr-beam .45s .04s cubic-bezier(.2, 1.4, .5, 1) both; }
@keyframes cr-beam { to { transform: scaleY(1); opacity: 1; } }
.cr-flash { width: 150%; margin: -75% 0 0 -75%; aspect-ratio: 1; border-radius: 50%; background: radial-gradient(circle, #fff, rgba(255, 240, 180, .6) 32%, transparent 66%); will-change: transform, opacity; }
.cr.open .cr-flash { animation: cr-flash .45s ease-out both; }
@keyframes cr-flash { 0% { transform: scale(.2); opacity: 1; } 100% { transform: scale(1.4); opacity: 0; } }
.cr-rays { width: 320%; margin: -160% 0 0 -160%; aspect-ratio: 1; border-radius: 50%; opacity: 0; transform: scale(.3); will-change: transform, opacity;
  background: repeating-conic-gradient(rgba(255, 222, 130, .38) 0 7deg, transparent 7deg 20deg);
  -webkit-mask: radial-gradient(circle, #000 12%, transparent 62%); mask: radial-gradient(circle, #000 12%, transparent 62%); }
.cr.open .cr-rays { opacity: 1; transform: none; transition: opacity .3s, transform .5s cubic-bezier(.2, 1.5, .5, 1); animation: cr-spin 16s linear infinite; }
@keyframes cr-spin { to { rotate: 360deg; } }
.cr-star { position: absolute; left: 50%; top: 42%; width: 20px; height: 20px; margin: -10px; will-change: transform, opacity; }
.cr-star svg { display: block; width: 100%; height: 100%; }
.cr.open .cr-star { animation: cr-star .8s var(--d) cubic-bezier(.15, .8, .35, 1) both; }
@keyframes cr-star { 0% { transform: scale(0); opacity: 1; } 35% { transform: translate(calc(var(--x) * .7), calc(var(--y) * .7)) scale(var(--s)) rotate(45deg); opacity: 1; }
  100% { transform: translate(var(--x), calc(var(--y) + 24px)) scale(0) rotate(120deg); opacity: 0; } }

/* Nếp: pops up at the right of the chest when it lands, leans in while it shakes, jumps when it opens */
.cr-nep { position: absolute; right: -34%; bottom: 0; width: 50%; aspect-ratio: 1; z-index: 2; transform: scale(0); transform-origin: 50% 100%; will-change: transform; pointer-events: none; }
.cr-nep canvas { display: block; width: 100%; height: 100%; }
.cr.land .cr-nep { animation: cr-nep-in .5s .12s linear both; }
@keyframes cr-nep-in { 0% { transform: scale(0) rotate(12deg); } 40% { transform: scale(1.12, .92) rotate(-4deg); } 65% { transform: scale(.95, 1.06) rotate(-2deg); } 100% { transform: rotate(-3deg); } }
.cr.tense .cr-nep { animation: cr-nep-lean .5s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes cr-nep-lean { from { transform: rotate(-3deg); } to { transform: rotate(-12deg) translateX(-6px); } }
.cr.open .cr-nep { animation: cr-nep-hop .6s linear both; }
@keyframes cr-nep-hop { 0% { transform: rotate(-12deg) translateX(-6px) scale(1.08, .9); } 25% { transform: translateY(-26px) scale(.92, 1.1) rotate(4deg); }
  50% { transform: translateY(0) scale(1.08, .92); } 72% { transform: scale(.97, 1.03); } 100% { transform: none; } }
@media (max-width: 360px) { .cr-nep { right: -22%; width: 36%; } }

/* the big grain counter the grains fly into */
.cr-bank { position: absolute; left: 50%; top: calc(max(56px, 11vh) + env(safe-area-inset-top)); translate: -50% 0; z-index: 2; opacity: 0; contain: layout style; will-change: transform, opacity;
  display: flex; align-items: center; gap: 8px; padding: 8px 22px 8px 12px; white-space: nowrap;
  font-family: Nunito, var(--ui, system-ui); font-weight: 900; font-size: 40px; line-height: 1; color: var(--honey-ink, #8A5A00);
  background: #FFF4D6; border-radius: 26px; box-shadow: inset 0 -6px 0 #F7D88B, 0 6px 0 #E0AC45, 0 16px 26px -10px rgba(0, 0, 0, .5); }
html[data-theme="dark"] .cr-bank { color: #FFD873; background: #3E2D0E; box-shadow: inset 0 -6px 0 #2E2108, 0 6px 0 #6B4B12, 0 16px 26px -10px rgba(0, 0, 0, .7); }
.cr-bank svg { width: 44px; height: 44px; }
.cr-bank b { min-width: 2ch; font-variant-numeric: tabular-nums; }
.cr-bank.on { opacity: 1; }

/* 6. "+N hạt": chunky gold letters land one by one on a spring, with a puff of confetti */
.cr-n { position: absolute; top: calc(100% + 12px); left: 50%; translate: -50% 0; white-space: nowrap; z-index: 3;
  font-family: Nunito, var(--ui, system-ui); font-weight: 900; font-size: 46px; line-height: 1.1; letter-spacing: .01em; }
.cr-n span { display: inline-block; color: #FFC93C; will-change: transform, opacity;
  text-shadow: 0 2px 0 #E8A21A, 0 4px 0 #B86E0C, 0 9px 14px rgba(40, 20, 0, .45); -webkit-text-stroke: 1.5px #9A5A08; paint-order: stroke fill; }
.cr.done .cr-n span { animation: cr-let .5s calc(var(--i) * 40ms) linear both; }
@keyframes cr-let { 0% { transform: translateY(-40px) scale(.3) rotate(-10deg); opacity: 0; } 35% { transform: translateY(6px) scale(1.15, .85); opacity: 1; }
  60% { transform: translateY(-4px) scale(.95, 1.06); opacity: 1; } 80% { transform: scale(1.02, .98); opacity: 1; } 100% { transform: none; opacity: 1; } }
.cr-conf { position: absolute; left: 50%; top: 40%; width: 0; height: 0; pointer-events: none; }
.cr-cf { position: absolute; width: var(--w); height: calc(var(--w) * 1.6); margin: -6px; border-radius: 2px; background: var(--c); will-change: transform, opacity; }
.cr-cf:nth-child(3n) { border-radius: 50%; height: var(--w); }
.cr.done .cr-cf { animation: cr-cf .9s calc(.12s + var(--d)) linear both; }
@keyframes cr-cf {
  0% { transform: scale(.2); opacity: 1; animation-timing-function: cubic-bezier(.15, .8, .35, 1); }
  40% { transform: translate(var(--x), var(--y)) rotate(calc(var(--r) * .5)); opacity: 1; animation-timing-function: cubic-bezier(.5, 0, .9, .5); }
  100% { transform: translate(calc(var(--x) * 1.15), var(--y2)) rotate(var(--r)); opacity: 0; }
}

/* 7. the exit: everything springs out, the counter dives home */
.cr.exit .cr-stage { animation: cr-out .3s cubic-bezier(.5, 0, .9, .4) both; }
@keyframes cr-out { 0% { transform: none; opacity: 1; } 30% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(.2); opacity: 0; } }

/* reduced motion: no fall, no shake, the lid fades off, the line fades in */
.cr.still *, .cr.still::before { animation: none !important; }
.cr.still .cr-fall { transform: none; }
.cr.still .cr-nep { transform: none; }
.cr.still .cr-glow { opacity: .7; transform: scale(.85); }
.cr.still .cr-lid, .cr.still .cr-mouth, .cr.still .cr-n span, .cr.still .cr-bank, .cr.still .cr-stage { transition: opacity .35s; }
.cr.still .cr-rays, .cr.still .cr-ring, .cr.still .cr-dust, .cr.still .cr-conf, .cr.still .cr-star { display: none; }
.cr.still.open .cr-lid { opacity: 0; }
.cr.still.done .cr-n span { opacity: 1; }
.cr.still.exit .cr-stage { opacity: 0; }
