/* play.css bản 3.2: cảm giác chơi của năm câu đố (C02–C06). Nạp sau app.css; chỉ thêm và đè các luật .pz-* khi cần.
   - Hiệu ứng ô (nảy, nở, lật, rung, sóng giải xong) do play.js gắn lớp fx-*, kèm biến --fx-*-t (animation-delay âm hoặc dương)
     để hiệu ứng chạy tiếp khi lưới dựng lại sau mỗi nước.
   - Chỉ transform và opacity (rung dùng thuộc tính translate riêng, để cộng được với transform của nảy hay lật).
   - Giảm chuyển động: play.js không gắn lớp fx-* (trừ ánh sáng nhóm, chỉ đổi độ đậm); cuối tệp chặn thêm bằng CSS ở cả hai cách bật. */

/* ---------- Lưới và lớp phủ dùng chung ---------- */
.pz-grid { position: relative; }
/* Chữ 200% (sửa 11/11): lưới không lớn theo chữ (phải vừa bề ngang máy), nên chữ số trong ô có trần cỡ và dòng cao 1.
   Trước đây số của Chia Luống và Sudoku chế độ số cao hơn ô, làm ô 46 × 63 và lệch cả lưới. Hoa số của Ong Tìm Đường đã có trần 20px. */
.pz-cell { line-height: 1; font-size: min(var(--text-lg), 24px); }
.pz-cell .num { font-size: min(var(--text-md), 20px); }
/* Mỗi ô là một lớp xếp chồng riêng: ánh sáng (z-index -1) nằm trên nền ô nhưng dưới hình, số và dấu chấm than */
#grid .pz-cell { isolation: isolate; }
/* Lớp phủ trùng khít các ô (cùng số cột, cùng khe), không nhận chạm */
.pz-layer { position: absolute; inset: var(--pz-gap); z-index: 2; display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); grid-template-rows: repeat(var(--n), minmax(0, 1fr)); gap: var(--pz-gap); pointer-events: none; }

/* ---------- Hiệu ứng trên ô ---------- */
#grid .pz-cell.fx-pop { animation: pop var(--dur-pop) var(--ease-spring) var(--fx-pop-t, 0ms) backwards; }
#grid .pz-cell.fx-flip { animation: pz-flip var(--dur-long) var(--ease-out) var(--fx-flip-t, 0ms) backwards; }
#grid .pz-cell.fx-wave { animation: pz-wave 360ms var(--ease-out) var(--fx-wave-t, 0ms) backwards; }
#grid .pz-cell.fx-shake { animation: pz-shake 420ms var(--ease-out) var(--fx-shake-t, 0ms) backwards; }
#grid .pz-cell.fx-pop.fx-shake { animation: pop var(--dur-pop) var(--ease-spring) var(--fx-pop-t, 0ms) backwards, pz-shake 420ms var(--ease-out) var(--fx-shake-t, 0ms) backwards; }
#grid .pz-cell.fx-flip.fx-shake { animation: pz-flip var(--dur-long) var(--ease-out) var(--fx-flip-t, 0ms) backwards, pz-shake 420ms var(--ease-out) var(--fx-shake-t, 0ms) backwards; }
@keyframes pz-flip { 0% { transform: perspective(260px) rotateY(-90deg); } 100% { transform: perspective(260px) rotateY(0deg); } }
@keyframes pz-wave { 0%, 100% { transform: scale(1); } 42% { transform: scale(1.12); } }
@keyframes pz-shake { 0%, 100% { translate: 0 0; } 16% { translate: -3px 0; } 34% { translate: 3px 0; } 52% { translate: -2px 0; } 70% { translate: 1.5px 0; } 86% { translate: -0.5px 0; } }
@keyframes pz-fade { from { opacity: 0; } }
@keyframes pz-ok { 0% { transform: scale(0.3); opacity: 0; } 100% { transform: none; opacity: 1; } }

/* Nhóm vừa xong: ánh sáng dịu nắng mơ, mờ vào rồi tắt (chỉ đổi độ đậm, nên vẫn giữ khi giảm chuyển động) */
.pz-glow { position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; box-shadow: inset 0 0 0 2px var(--color-accent), inset 0 0 10px 1px var(--color-accent); opacity: 0; animation: pz-glow 760ms var(--ease-out) both; }
.pz-glow::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--color-accent); opacity: 0.2; }
@keyframes pz-glow { 0% { opacity: 0; } 22% { opacity: 1; } 100% { opacity: 0; } }
#grid .pz-cell.is-error::before { z-index: 1; }

/* ---------- Sen Nở ---------- */
/* Sen nở: nụ xoay nhẹ và lớn lên, cánh ngoài xòe ra */
#grid .pz-cell.fx-bloom > svg { transform-origin: 50% 80%; animation: pz-bloom var(--dur-long) var(--ease-spring) var(--fx-bloom-t, 0ms) backwards; }
#grid .pz-cell.fx-bloom > svg > path:first-child { transform-box: fill-box; transform-origin: 50% 100%; animation: pz-petal var(--dur-long) var(--ease-spring) var(--fx-bloom-t, 0ms) backwards; }
@keyframes pz-bloom { 0% { transform: scale(0.3) rotate(-12deg); opacity: 0; } 45% { opacity: 1; } 100% { transform: none; opacity: 1; } }
@keyframes pz-petal { 0% { transform: scale(0.3, 0.75); } 100% { transform: none; } }
/* Chấm tự đánh dấu: chấm tròn nhạt, khác hẳn dấu × của người chơi */
.pz-dot { width: 20%; aspect-ratio: 1; border-radius: 50%; background: var(--color-ink-2); opacity: 0.34; pointer-events: none; }
#grid .pz-cell.fx-dot .pz-dot { animation: pz-fade var(--dur-short) var(--ease-out) var(--fx-dot-t, 0ms) backwards; }
/* Công tắc "Tự đánh dấu" trên thanh câu đố */
/* Cả nhãn là vùng chạm (cao 48px); công tắc thu nhỏ để cả thanh nằm vừa một dòng trên điện thoại */
.pz-auto { display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap); margin-inline-start: auto; font-size: var(--text-sm); font-weight: var(--weight-strong); line-height: var(--leading-ui); cursor: pointer; }
.pz-auto .switch { width: 44px; height: 26px; }
.pz-auto .switch::after { top: 3px; left: 3px; width: 20px; height: 20px; }
.pz-auto .switch:checked::after { transform: translateX(18px); }

/* ---------- Ong Tìm Đường ---------- */
/* Đường bay: dải mật ong dày, bo tròn, hai tông (mép đậm, lõi nắng) và một vệt sáng giữa; rõ trên ô nhạt ở cả giao diện sáng và tối.
   Đoạn mới nhất vươn ra từ ô trước. */
.pz-path .pz-path__band, .pz-path .pz-path__core, .pz-path .pz-path__shine { fill: none; stroke-linecap: round; stroke-linejoin: round; opacity: 1; }
.pz-path .pz-path__band { stroke: var(--color-accent-deep); stroke-width: 16; }
.pz-path .pz-path__core { stroke: var(--color-accent); stroke-width: 9; }
.pz-path .pz-path__shine { stroke: var(--art-shine); stroke-width: 2.5; opacity: 0.6; }
.pz-seg { animation: pz-seg var(--dur-short) var(--ease-out) backwards; }
@keyframes pz-seg { from { transform: scale(0); } }
/* Hoa đánh số và ong ở lớp trên đường bay */
.pz-marks { z-index: 2; }
.pz-mark { position: relative; display: grid; place-items: center; min-width: 0; min-height: 0; }
.pz-flw { position: absolute; width: 88%; height: 88%; }
.pz-flw__n { position: relative; display: grid; place-items: center; width: 54%; aspect-ratio: 1; border-radius: 50%; background: var(--color-accent); color: var(--color-accent-ink); box-shadow: 0 0 0 2.5px var(--color-card); font-size: min(var(--text-md), 20px); font-weight: var(--weight-strong); line-height: 1; font-variant-numeric: tabular-nums; }
.pz-flower.is-bad .pz-flw__n { background: var(--color-error-wash); color: var(--color-error); box-shadow: 0 0 0 2.5px var(--color-error); }
.pz-flower.fx-bounce { animation: pz-bounce var(--dur-pop) var(--ease-out) var(--fx-bounce-t, 0ms) backwards; }
.pz-mark.fx-shake { animation: pz-shake 420ms var(--ease-out) var(--fx-shake-t, 0ms) backwards; }
@keyframes pz-bounce { 0%, 100% { transform: none; } 30% { transform: translateY(-9%) scale(1.28); } 62% { transform: translateY(2%) scale(0.95); } }
/* Ong quay mặt theo hướng bay (hình gốc nhìn sang phải) và bay từ ô trước sang */
.pz-bee { --dx: calc(-100% - var(--pz-gap)); --dy: 0px; z-index: 1; }
.pz-bee svg { width: 74%; height: 74%; }
.pz-bee.bee--l { --dx: calc(100% + var(--pz-gap)); }
.pz-bee.bee--u { --dx: 0px; --dy: calc(100% + var(--pz-gap)); }
.pz-bee.bee--d { --dx: 0px; --dy: calc(-100% - var(--pz-gap)); }
.pz-bee.bee--l svg { transform: scaleX(-1); }
.pz-bee.bee--u svg { transform: rotate(-90deg); }
.pz-bee.bee--d svg { transform: rotate(90deg); }
.pz-bee.on-num { place-items: start end; }
.pz-bee.on-num svg { width: 54%; height: 54%; margin: -14% -14% 0 0; }
.pz-bee.fx-fly { animation: pz-fly var(--dur-short) var(--ease-out) var(--fx-fly-t, 0ms) backwards; }
.pz-bee.fx-hop { animation: pop var(--dur-short) var(--ease-spring) var(--fx-hop-t, 0ms) backwards; }
@keyframes pz-fly { from { transform: translate(var(--dx), var(--dy)); } }

/* ---------- Cân Đôi: chỉ báo lá và hoa cuối mỗi hàng, dưới mỗi cột ---------- */
.pz-board { display: grid; grid-template-columns: minmax(0, calc(var(--n) * (var(--pz-cell) + var(--pz-gap)))) 28px; justify-content: center; gap: var(--space-xs) 6px; }
.pz-board .pz-grid { width: 100%; }
.pz-bal { display: grid; gap: var(--pz-gap); }
.pz-bal--row { grid-template-rows: repeat(var(--n), minmax(0, 1fr)); padding-block: var(--pz-gap); }
.pz-bal--col { grid-template-columns: repeat(var(--n), minmax(0, 1fr)); padding-inline: var(--pz-gap); height: 28px; }
.bal { position: relative; display: flex; align-items: center; justify-content: center; gap: 3px; min-width: 0; border-radius: var(--radius-pill); background: var(--color-paper-2); }
.pz-bal--col .bal { flex-direction: column; }
.bal__set { display: flex; gap: 2px; }
.pz-bal--row .bal__set { flex-direction: column; }
.bal__set i { width: 7px; height: 7px; border: 1.5px solid var(--color-edge); }
/* Lá: hình chiếc lá (hai góc nhọn); hoa: hình tròn. Đã điền thì tô đặc. Khác cả hình lẫn màu. */
.bal__set--l i { border-radius: 0 75% 0 75%; }
.bal__set--h i { border-radius: 50%; }
.bal__set--l i.is-on { border-color: var(--art-leaf-2); background: var(--art-leaf-2); }
.bal__set--h i.is-on { border-color: var(--art-pink-2); background: var(--art-pink-2); }
/* Xong: dấu kiểm trong vòng tròn thay cho các chấm */
.bal__ok { display: none; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--color-success); color: var(--color-paper); }
.bal__ok .icon { width: 15px; height: 15px; }
.bal.is-done { background: var(--color-success-wash); }
.bal.is-done .bal__set { display: none; }
.bal.is-done .bal__ok { display: grid; }
.bal.fx-ok .bal__ok { animation: pz-ok var(--dur-pop) var(--ease-spring) backwards; }
/* Lệch hoặc ba ô liền nhau: nền đỏ dịu kèm dấu chấm than */
.bal.is-bad { background: var(--color-error-wash); }
.bal.is-bad i.is-on { border-color: var(--color-error); background: var(--color-error); }
.bal.is-bad::after { content: ""; position: absolute; top: -4px; right: -4px; width: 12px; height: 12px; background: var(--color-error); -webkit-mask: var(--mask-alert) center / contain no-repeat; mask: var(--mask-alert) center / contain no-repeat; }

/* ---------- Sudoku Trái Cây ---------- */
/* Ô cùng loại trái cây với ô đang xem: nền mơ rất nhạt và viền trong mơ đậm (sửa 11/11).
   Trước đây nền là --tag-3, sáng ở cả hai giao diện: ở giao diện tối chuối trên nền đó gần như biến mất (1,01:1), chữ số mực trăng 1,25:1.
   Giao diện tối giờ dùng nền mơ tối: quả màu tối nhất (nho) vẫn đạt 3,2:1, chuối 9:1. */
#grid .pz-cell.is-same { --cell-bg: oklch(94% 0.045 70); box-shadow: inset 0 0 0 2px oklch(58% 0.15 52); }
:root[data-mode="dark"] #grid .pz-cell.is-same { --cell-bg: oklch(32% 0.055 65); box-shadow: inset 0 0 0 2px var(--color-accent-deep); }
@media (prefers-color-scheme: dark) {
  :root:not([data-mode]) #grid .pz-cell.is-same { --cell-bg: oklch(32% 0.055 65); box-shadow: inset 0 0 0 2px var(--color-accent-deep); }
}
/* Viền thân quả (play.js gắn lớp fr fr--i). Giao diện sáng: quả màu nhạt trên ô sáng không đủ tương phản (chuối 1,4:1, xoài 2,2:1),
   nên thân quả có viền cùng tông nhưng đậm hơn, đo được ít nhất 4,3:1 với mọi nền ô sáng (thường, có sẵn, chọn, cùng loại, cùng hàng, lỗi, gợi ý).
   Viền vẽ dưới phần tô (paint-order), nên chỉ nửa ngoài lộ ra, hình quả không bị thu nhỏ. Giao diện tối: quả đã rõ trên nền tối, không viền. */
.fr { --fr-w: 2; overflow: visible; }
.fr > :first-child, .fr--5 > circle { stroke: var(--fr-rim); stroke-width: var(--fr-w); stroke-linejoin: round; paint-order: stroke; }
.fr--0, .fr--4 { --fr-rim: oklch(52% 0.13 55); }
.fr--1 { --fr-rim: oklch(45% 0.12 150); }
.fr--2 { --fr-rim: oklch(53% 0.11 78); }
.fr--3 { --fr-rim: oklch(50% 0.16 355); }
.fr--5 { --fr-rim: oklch(43% 0.13 306); }
:root[data-mode="dark"] .fr { --fr-w: 0; }
@media (prefers-color-scheme: dark) { :root:not([data-mode]) .fr { --fr-w: 0; } }
/* Bàn phím trái cây: góc mỗi nút là số quả còn thiếu; đủ 6 quả không vướng luật thì thành dấu kiểm */
.pad .btn { position: relative; }
.pad__face { display: grid; place-items: center; line-height: 1; font-size: min(var(--text-lg), 24px); }
.pad__left { position: absolute; top: -6px; right: -4px; display: grid; place-items: center; min-width: 20px; min-height: 20px; padding: 1px 5px; border-radius: var(--radius-pill); background: var(--color-paper-3); color: var(--color-ink); box-shadow: 0 0 0 2px var(--color-paper); font-size: min(var(--text-xs), 15px); font-weight: var(--weight-strong); line-height: 1; font-variant-numeric: tabular-nums; pointer-events: none; }
.pad .btn .pad__left svg { width: 12px; height: 12px; }
/* Đủ 6 quả: nút như "đã dùng hết" (bỏ nền, viền nét đứt, hình nhỏ lại một chút) nhưng quả giữ nguyên màu, vẫn rõ như nút thường.
   Trước đây hình mờ 45%, còn 1,2 tới 3,2:1. */
.pad .btn.is-done { border-style: dashed; border-color: var(--color-edge); background: transparent; }
.pad .btn.is-done .pad__face { transform: scale(0.86); }
.pad .btn.is-done .pad__left { padding: 1px 3px; background: var(--color-success); color: var(--color-paper); }
.pad .btn.fx-ok .pad__left { animation: pz-ok var(--dur-pop) var(--ease-spring) backwards; }

/* ---------- Chia Luống ---------- */
/* Vùng đang chọn: một khung bo tròn và nhãn số ô ở góc; khớp luật thì khung xanh, nhãn có dấu kiểm */
#grid .pz-cell.is-drag { box-shadow: none; }
.pz-sel { position: relative; border-radius: var(--radius-cell); box-shadow: inset 0 0 0 3px var(--color-accent-deep); }
.pz-sel::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--color-accent); opacity: 0.24; }
.pz-sel.is-ok { box-shadow: inset 0 0 0 3px var(--color-success); }
.pz-sel.is-ok::before { background: var(--color-success); opacity: 0.16; }
/* Đang kéo: cả vùng đã kéo qua có khung nét đứt; phần nằm ngoài luống sẽ vẽ (bị cắt khi thả tay) chỉ có nền rất nhạt */
.pz-sel.is-ghost { border: 2px dashed var(--color-accent-deep); box-shadow: none; }
.pz-sel.is-ghost::before { opacity: 0.1; }
.pz-area { position: absolute; top: 0; right: 0; translate: 30% -55%; display: inline-flex; align-items: center; gap: 2px; min-height: 26px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--color-ink); color: var(--color-paper); box-shadow: 0 0 0 2px var(--color-paper); font-size: min(var(--text-sm), 18px); font-weight: var(--weight-strong); line-height: 1.1; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pz-sel.is-ok .pz-area { padding-inline-start: 5px; background: var(--color-success); }
.pz-area .icon { width: 16px; height: 16px; }
/* Luống đúng luật nảy mầm: chồi nhỏ ở đáy mỗi ô không có số */
.pz-sprout { position: absolute; left: 50%; bottom: 3%; width: 46%; translate: -50% 0; pointer-events: none; }
.pz-sprout svg { display: block; width: 100%; height: auto; transform-origin: 50% 100%; }
#grid .pz-cell.fx-sprout .pz-sprout svg { animation: sprout-pop var(--dur-pop) var(--ease-spring) var(--fx-sprout-t, 0ms) backwards; }

/* ---------- Dòng tiến độ dưới lưới ---------- */
.pz-prog { display: flex; align-items: center; justify-content: center; gap: var(--space-xs); margin-top: calc(-1 * var(--space-xs)); color: var(--color-muted); font-size: var(--text-sm); font-weight: var(--weight-strong); font-variant-numeric: tabular-nums; }
.pz-prog__bar { flex: 0 0 auto; width: 56px; height: 6px; border-radius: var(--radius-pill); background: var(--color-paper-3); overflow: hidden; }
.pz-prog__bar i { display: block; height: 100%; border-radius: inherit; background: var(--heat-3); transform-origin: left center; transform: scaleX(var(--v, 0)); transition: transform var(--dur-long) var(--ease-out); }

/* ---------- C08: lấp lánh trong cảnh thắng (sao bốn cánh chớp sáng hai lượt rồi tắt) ---------- */
.win .w-spark { transform-box: fill-box; transform-origin: center; opacity: 0; animation: w-spark 1.5s var(--ease-out) var(--d, 0ms) 2 both; }
@keyframes w-spark { 0% { transform: scale(0) rotate(0deg); opacity: 0; } 35% { transform: scale(1.15) rotate(45deg); opacity: 1; } 70%, 100% { transform: scale(0) rotate(90deg); opacity: 0; } }

/* ---------- Giảm chuyển động: không nảy, rung, lật, bay, lấp lánh; ánh sáng nhóm (.pz-glow, có keep-motion) chỉ đổi độ đậm ---------- */
@media (prefers-reduced-motion: reduce) {
  #grid .pz-cell.fx-pop, #grid .pz-cell.fx-flip, #grid .pz-cell.fx-wave, #grid .pz-cell.fx-shake, #grid .pz-cell.fx-bloom > svg, #grid .pz-cell.fx-bloom > svg > path, #grid .pz-cell.fx-dot .pz-dot, #grid .pz-cell.fx-sprout .pz-sprout svg,
  .pz-mark, .pz-seg, .bal.fx-ok .bal__ok, .pad .btn.fx-ok .pad__left, .win .w-spark { animation: none !important; }
}
:root[data-motion="reduce"] #grid .pz-cell.fx-pop, :root[data-motion="reduce"] #grid .pz-cell.fx-flip, :root[data-motion="reduce"] #grid .pz-cell.fx-wave, :root[data-motion="reduce"] #grid .pz-cell.fx-shake, :root[data-motion="reduce"] #grid .pz-cell.fx-bloom > svg, :root[data-motion="reduce"] #grid .pz-cell.fx-bloom > svg > path, :root[data-motion="reduce"] #grid .pz-cell.fx-dot .pz-dot, :root[data-motion="reduce"] #grid .pz-cell.fx-sprout .pz-sprout svg,
:root[data-motion="reduce"] .pz-mark, :root[data-motion="reduce"] .pz-seg, :root[data-motion="reduce"] .bal.fx-ok .bal__ok, :root[data-motion="reduce"] .pad .btn.fx-ok .pad__left, :root[data-motion="reduce"] .win .w-spark { animation: none !important; }
