/* ============================================================
   ช่วงฮาโลวีน · จอโหลดกับจอเข้าสู่ระบบ (24 ต.ค. 69)
   ------------------------------------------------------------
   เจ้าของ: "อยากให้หน้านี้แล้วหน้าที่เข้าแอป เป็นเกี่ยวกับ halloween …
            เข้าแอปอยากให้เป็นธีม halloween แบบ animation เท่ ๆ มีค้างคาว"

   • ทุกกฎอยู่ใต้ :root.hw-season — สคริปต์ใน <head> ของ index.html ติดคลาสนี้ก่อนวาดจอแรก
     ถ้ายังไม่เลย endsAt ของ halloween/event/config.json · runtime.js ถอดคลาสออกเองเมื่อ config ปิดอีเวนต์
     หมดช่วง = จอโหลดขาวกับจอเข้าสู่ระบบแบบเดิมกลับมาเอง ไม่ต้องแก้โค้ด
   • ไม่ขึ้นกับธีมที่เลือก — คนเปิดแอปครั้งแรกยังไม่มีธีม จอสองจอนี้จึงหน้าตาเดียวกันทุกเครื่อง
   • จอโหลดยังเป็นแค่ชั้นบัง: ไม่มีอะไรรอแอนิเมชันจบ (เหตุผลอยู่เหนือ #boot ใน index.html)
     ค้างคาวฝูงแรกจึงพุ่งออกในวินาทีแรก — เปิดจากแคชเร็วแค่ไหนก็ยังทันเห็น
   • ลดการเคลื่อนไหว = ภาพนิ่ง · โหมดลื่น (data-lite) = ค้างคาวครึ่งเดียว
   ============================================================ */

/* ---------- ค้างคาว (ใช้ทั้งสองจอ) ----------
   ตัวค้างคาวคือ <symbol id="hw-bat"> ใน #boot · กระพือปีก = ยืด-หดแนวตั้งเร็ว ๆ ซึ่งถูกกว่าขยับปีกทีละข้าง
   ขอบเรืองม่วงจาง ๆ ให้เห็นตัวบนพื้นกลางคืน (เงาดำล้วนหายไปกับพื้น) */
.hw-bat { display: block; width: 100%; height: auto; overflow: visible; fill: #07040e;
  filter: drop-shadow(0 0 3px rgba(196, 150, 255, .55)); transform-origin: 50% 40%;
  animation: hw-flap .2s ease-in-out infinite alternate; }
.hw-bat .eye { fill: #ffb347; }
@keyframes hw-flap { from { transform: scaleY(1); } to { transform: scaleY(.32) translateY(4px); } }

.hb-sky, .lg-hw { display: none; }

/* ============================================================
   จอโหลด
   ============================================================ */
html:root.hw-season .boot {
  --fill: #ff8a1f; --grad-brand: linear-gradient(90deg, #ffb04a, #ff7a18 45%, #b77dff);
  --ink: #f6eefe; --muted: #b9a8d6;
  background:
    radial-gradient(90% 55% at 50% 46%, rgba(124, 58, 237, .28), transparent 70%),
    radial-gradient(70% 40% at 82% 12%, rgba(255, 170, 80, .16), transparent 70%),
    linear-gradient(180deg, #150b2b 0%, #0d0719 55%, #07040e 100%) !important;
  color: var(--ink); overflow: hidden;
}
html:root.hw-season .hb-sky { display: block; position: absolute; inset: 0; pointer-events: none; }
.hb-sky > * { position: absolute; display: block; }

/* ดาว — จุดเล็กหลายจุดในพื้นหลังเดียว กะพริบทั้งชั้นพร้อมกัน */
.hb-stars, .lg-hw .lh-stars { inset: 0; opacity: .8;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 18%, #fff 60%, transparent),
    radial-gradient(1px 1px at 28% 8%, #e9dcff 60%, transparent),
    radial-gradient(1.2px 1.2px at 44% 22%, #fff 60%, transparent),
    radial-gradient(1px 1px at 63% 6%, #ffe9c7 60%, transparent),
    radial-gradient(1.5px 1.5px at 74% 30%, #fff 60%, transparent),
    radial-gradient(1px 1px at 88% 44%, #e9dcff 60%, transparent),
    radial-gradient(1.2px 1.2px at 8% 52%, #fff 60%, transparent),
    radial-gradient(1px 1px at 22% 66%, #e9dcff 60%, transparent),
    radial-gradient(1.3px 1.3px at 92% 70%, #fff 60%, transparent),
    radial-gradient(1px 1px at 55% 38%, #fff 60%, transparent),
    radial-gradient(1px 1px at 36% 48%, #ffe9c7 60%, transparent);
  animation: hw-twinkle 2.6s ease-in-out infinite alternate; }
@keyframes hw-twinkle { from { opacity: .45; } to { opacity: .95; } }

/* พระจันทร์ — ลอยขึ้นตอนเปิด แล้วเรืองช้า ๆ */
.hb-moon { top: 9vh; right: 11vw; width: 104px; height: 104px; border-radius: 50%;
  background:
    radial-gradient(circle at 64% 30%, rgba(214, 170, 96, .55) 0 7px, transparent 8px),
    radial-gradient(circle at 34% 62%, rgba(214, 170, 96, .45) 0 11px, transparent 12px),
    radial-gradient(circle at 70% 70%, rgba(214, 170, 96, .35) 0 5px, transparent 6px),
    radial-gradient(circle at 38% 34%, #fff8e3, #ffe2a1 55%, #f2b45a 100%);
  box-shadow: 0 0 40px 10px rgba(255, 196, 110, .35), 0 0 140px 50px rgba(255, 140, 50, .14);
  animation: hb-moon-in 1.1s cubic-bezier(.22, 1, .36, 1) both, hb-moon-glow 3.2s 1.1s ease-in-out infinite alternate; }
@keyframes hb-moon-in { from { opacity: 0; transform: translateY(40px) scale(.9); } }
@keyframes hb-moon-glow { to { box-shadow: 0 0 52px 16px rgba(255, 196, 110, .45), 0 0 170px 64px rgba(255, 140, 50, .2); } }

/* หมอกกับป่าช้าที่ก้นจอ — ภาพเดียวกับฉากธีม Midnight Academy (แคชไว้แล้ว) */
.hb-grave { left: -10%; right: -10%; bottom: 0; height: 170px; opacity: .9;
  background: url('../rewards/theme-assets/graveyard.svg') center bottom / auto 100% no-repeat; }
.hb-fog { left: -40%; right: -40%; bottom: -30px; height: 200px;
  background: radial-gradient(ellipse at 30% 70%, rgba(168, 140, 220, .22), transparent 55%),
              radial-gradient(ellipse at 72% 60%, rgba(255, 150, 80, .12), transparent 50%);
  animation: hb-fog 9s ease-in-out infinite alternate; }
@keyframes hb-fog { to { transform: translate3d(8%, -10px, 0); } }

/* แสงฟักทองหลังโลโก้ */
html:root.hw-season .boot .boot-mid::before { content: ""; position: absolute; left: 50%; top: 50%;
  width: 230px; height: 230px; margin: -115px 0 0 -115px; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(168, 85, 247, .42), rgba(124, 58, 237, .18) 45%, transparent 70%);
  animation: hb-halo 2.4s ease-in-out infinite alternate; transition: background .4s; }
html:root.hw-season .boot.done .boot-mid::before { background: radial-gradient(circle, rgba(255, 150, 50, .45), rgba(124, 58, 237, .18) 50%, transparent 72%); }
@keyframes hb-halo { from { transform: scale(.88); opacity: .75; } to { transform: scale(1.08); opacity: 1; } }
html:root.hw-season .boot .boot-mid { z-index: 2; }
html:root.hw-season .boot .boot-mark { position: relative; z-index: 1; width: 108px; height: 108px; border-radius: 26px;
  filter: drop-shadow(0 0 16px rgba(168, 85, 247, .55)) drop-shadow(0 10px 22px rgba(0, 0, 0, .6));
  animation: boot-in .6s .3s cubic-bezier(.22, 1, .36, 1) both, hb-power .8s .85s ease-in-out both, hb-bob 2.8s 1.65s ease-in-out infinite alternate; }
@keyframes hb-bob { to { transform: translateY(-6px); } }
/* รวมพลัง: ไอคอนพองขึ้นนิดหนึ่งพร้อมแสงม่วงจัด แล้วคืนที่ */
@keyframes hb-power {
  45% { transform: scale(1.09); filter: brightness(1.25) drop-shadow(0 0 28px rgba(200, 140, 255, .95)) drop-shadow(0 0 60px rgba(124, 58, 237, .75)); }
  100% { transform: none; filter: drop-shadow(0 0 18px rgba(168, 85, 247, .6)) drop-shadow(0 10px 22px rgba(0, 0, 0, .6)); }
}
html:root.hw-season .boot.out .boot-mark { transform: scale(1.08); animation: none; }
/* เสร็จสิ้น: ไอคอนเรืองส้มฟักทอง (ต้องอยู่ใต้กฎ .out — ตอนจางยังเรืองค้างไว้ ไม่ดับวูบ) */
html:root.hw-season .boot.done .boot-mark { animation: hb-flare .7s ease-out both; }
@keyframes hb-flare { to { transform: scale(1.07); filter: brightness(1.15) drop-shadow(0 0 26px rgba(255, 170, 70, .9)) drop-shadow(0 0 64px rgba(255, 120, 30, .5)); } }

/* แถบโหลด: ม่วง → ชมพู → ส้มฟักทอง บนรางมืด · หัวแถบเป็นฟักทอง (ภาพ 4–6 ของเจ้าของ)
   โผล่หลังจังหวะรวมพลัง — ตรงกับ STORY_BAR ในสคริปต์ใต้ #boot (แถบไม่เดินก่อนเวลานั้น) */
html:root.hw-season .boot .boot-mid { width: min(196px, 56vw); }
html:root.hw-season .boot .boot-bar { top: calc(100% + 46px); animation: hb-bar-in .45s 1s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes hb-bar-in { from { opacity: 0; transform: translateY(8px) scaleX(.85); } }
html:root.hw-season .boot .hp-track { height: 6px; background: rgba(255, 255, 255, .1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .4); }
html:root.hw-season .boot .hp-fill { background: linear-gradient(90deg, #7c3aed, #c26bff 55%, #ff8a1f) !important; box-shadow: 0 0 12px rgba(200, 120, 255, .6) !important; }
html:root.hw-season .boot.done .hp-fill { transition: transform .3s ease-out; }
html:root.hw-season .boot .hp-track::after { width: 22px; height: 22px; border-radius: 0; box-shadow: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 6c.2-1.8 1.2-3 2.8-3.4' fill='none' stroke='%234a7a22' stroke-width='2' stroke-linecap='round'/%3E%3Cellipse cx='7.4' cy='14' rx='5.4' ry='7' fill='%23e0640f'/%3E%3Cellipse cx='16.6' cy='14' rx='5.4' ry='7' fill='%23e0640f'/%3E%3Cellipse cx='12' cy='14' rx='5.4' ry='7.6' fill='%23ff8a1f'/%3E%3Cpath d='M6.6 12.6l2.4-2.2.8 2.8zM17.4 12.6L15 10.4l-.8 2.8zM7 16q5 4 10 0l-1.6.3-1 1.3-1.2-1.2-1.2 1.2-1.2-1.2-1 1.2z' fill='%23ffe08a'/%3E%3C/svg%3E") center / contain no-repeat;
  filter: drop-shadow(0 0 6px rgba(255, 140, 40, .9)); animation: hb-pk-wob .9s ease-in-out infinite alternate; }
@keyframes hb-pk-wob { from { transform: translate(-50%, -54%) rotate(-10deg); } to { transform: translate(-50%, -54%) rotate(10deg); } }
html:root.hw-season .boot.done .hp-track::after { transition: left .3s ease-out; }
html:root.hw-season .boot .boot-from { z-index: 2; }
html:root.hw-season .boot .boot-from span { color: var(--muted); }

/* ฝูงแรก: ค้างคาวแปดตัวพุ่งออกจากหลังโลโก้กระจายทุกทิศ (เริ่มทันทีที่จอขึ้น)
   ออกตัวช้าใกล้โลโก้แล้วเร่งออกนอกจอ — ช่วงแรกต้องอยู่ในจอนานพอให้ทันเห็นแม้จอโหลดอยู่แค่วินาทีเดียว */
.hb-burst { left: 50%; top: 50%; width: 0; height: 0; z-index: 1; }
.hb-burst i { position: absolute; left: 0; top: 0; width: calc(48px * var(--s, 1)); margin: -12px 0 0 calc(-24px * var(--s, 1));
  opacity: 0; animation: hb-burst 2.4s var(--d, 0s) linear both; }
/* 25 ต.ค. 69 · ฝูงนี้พุ่งออกตอนผีรวมพลังเสร็จ (ราว 1 วินาที) แทนวินาทีแรก — ฉากผีรับประกันว่าจอนี้อยู่ถึงตอนนั้นแล้ว */
html:root.hw-season .hb-burst i { width: calc(36px * var(--s, 1)); animation-delay: calc(var(--d, 0s) + 1s); }
@keyframes hb-burst {
  0%   { opacity: 0; transform: rotate(var(--a)) translateX(0) rotate(calc(-1 * var(--a))) scale(.25); }
  10%  { opacity: 1; transform: rotate(var(--a)) translateX(64px) rotate(calc(-1 * var(--a))) scale(.55); }
  40%  { opacity: 1; transform: rotate(calc(var(--a) + 12deg)) translateX(120px) rotate(calc(-1 * var(--a) - 12deg)) scale(.85); }
  70%  { opacity: 1; transform: rotate(calc(var(--a) - 8deg)) translateX(220px) rotate(calc(-1 * var(--a) + 8deg)) scale(1.05); }
  100% { opacity: 0; transform: rotate(var(--a)) translateX(520px) rotate(calc(-1 * var(--a))) scale(1.3); }
}
/* ฝูงที่สอง: บินผ่านหน้าพระจันทร์เป็นคลื่น ไม่จบจนกว่าจอนี้จะหาย */
.hb-fly { inset: 0; }
.hb-fly i, .lg-hw .lh-fly i { position: absolute; left: 0; top: var(--y); width: var(--w, 30px);
  animation: hw-cross var(--t, 7s) var(--d, 0s) linear infinite both; }
@keyframes hw-cross {
  0%   { transform: translate3d(-60px, 0, 0); }
  25%  { transform: translate3d(25vw, -22px, 0); }
  50%  { transform: translate3d(52vw, 10px, 0); }
  75%  { transform: translate3d(78vw, -16px, 0); }
  100% { transform: translate3d(calc(100vw + 60px), 6px, 0); }
}
.hb-fly i.rev, .lg-hw .lh-fly i.rev { animation-name: hw-cross-rev; }
@keyframes hw-cross-rev {
  0%   { transform: translate3d(calc(100vw + 60px), 0, 0); }
  30%  { transform: translate3d(68vw, 18px, 0); }
  60%  { transform: translate3d(38vw, -14px, 0); }
  100% { transform: translate3d(-60px, 8px, 0); }
}

/* เมฆม่วงลอยช้า ๆ (ภาพ 1 ของเจ้าของ) */
.hb-cloud { top: 3vh; left: -14%; width: 74%; height: 24vh; opacity: .9;
  background:
    radial-gradient(42% 46% at 22% 62%, rgba(120, 96, 176, .34), transparent 70%),
    radial-gradient(38% 50% at 48% 44%, rgba(98, 76, 156, .3), transparent 70%),
    radial-gradient(34% 40% at 72% 66%, rgba(86, 64, 140, .26), transparent 70%);
  animation: hb-cloud 14s ease-in-out infinite alternate; }
.hb-cloud.b { top: 30vh; left: auto; right: -20%; width: 64%; height: 18vh; opacity: .6; animation-duration: 18s; animation-direction: alternate-reverse; }
@keyframes hb-cloud { to { transform: translate3d(9%, 0, 0); } }

/* ============================================================
   ฉากผีรวมพลัง (25 ต.ค. 69) — เจ้าของส่งภาพ 6 จังหวะ "ลองทำอนิเมชั่นตามภาพหน้ากดเข้าหน่อย ขอดีๆนะ"
   ------------------------------------------------------------
   นับเวลาจากจอขึ้น:
   0–0.3   เริ่มต้น: ฟ้า พระจันทร์ เมฆ (ของเดิมด้านบน)
   0.15–0.7 ผีมาปรากฏ: น้องฮูกหมวกแม่มด (ซ้าย · หางไฟส้ม) กับน้องไซหูตก (ขวา · หางม่วง) บินเข้าข้างไอคอน
   0.85–1.4 รวมพลัง: ผีสองตัวเข้ามากอดไอคอน วงพลังม่วงหมุนรอบ แสงวาบ ค้างคาวแตกฝูง แล้วถอยกลับที่
   1.0–    โหลดกำลังขึ้น / กำลังโหลด: แถบโผล่ หัวแถบฟักทอง ผีลอยขึ้นลงข้างไอคอน (แถบเดินตามงานจริง — สคริปต์ใต้ #boot)
   .done   เสร็จสิ้น: ผีบินออกขึ้นฟ้า ไอคอนเรืองส้ม แล้วจอจาง
   ทุกอย่างขยับด้วย transform/opacity · ตัวผีเป็น SVG ในหน้า ไม่โหลดภาพเพิ่ม
   ============================================================ */
.hb-cast { display: none; }
html:root.hw-season .boot .hb-cast { display: block; position: absolute; left: 50%; top: 50%; width: 0; height: 0;
  --gx: clamp(94px, 30vw, 128px); --gw: clamp(68px, 23vw, 96px); }
.hb-cast > * { position: absolute; display: block; left: 0; top: 0; }

/* ตัวผี — ห่อ (.hb-gw) ทำทางบิน · ตัวใน (.hb-g) ลอยขึ้นลง สองอย่างไม่แย่ง transform กัน */
.hb-gw { z-index: 2; width: var(--gw); margin: calc(var(--gw) * -.7) 0 0 calc(var(--gw) * -.5); opacity: 0; }
.hb-g { display: block; width: 100%; height: auto; overflow: visible; filter: drop-shadow(0 0 10px rgba(196, 150, 255, .75)); }
.hb-gw.l { animation: hb-in-l 1.25s .15s both; }
.hb-gw.r { animation: hb-in-r 1.15s .25s both; }
.hb-gw.l .hb-g { animation: hb-hover 2.3s 1.4s ease-in-out infinite alternate; }
.hb-gw.r .hb-g { animation: hb-hover 2s 1.4s ease-in-out infinite alternate-reverse; }
@keyframes hb-hover { from { transform: translateY(3px) rotate(2deg); } to { transform: translateY(-7px) rotate(-3deg); } }
@keyframes hb-in-l {
  0%   { opacity: 0; transform: translate(calc(-50vw - 60px), -48px) rotate(18deg) scale(.8); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  10%  { opacity: 1; }
  42%  { opacity: 1; transform: translate(calc(var(--gx) * -1), -4px) rotate(5deg) scale(1); animation-timing-function: ease-out; }
  52%  { transform: translate(calc(var(--gx) * -1 - 6px), 2px) rotate(-4deg); animation-timing-function: cubic-bezier(.5, 0, .4, 1); }
  66%  { transform: translate(calc(var(--gx) * -.56), -6px) rotate(12deg) scale(1.06); }
  82%  { transform: translate(calc(var(--gx) * -.54), -10px) rotate(9deg) scale(1.06); animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
  100% { opacity: 1; transform: translate(calc(var(--gx) * -1), 0) rotate(0) scale(1); }
}
@keyframes hb-in-r {
  0%   { opacity: 0; transform: translate(calc(50vw + 60px), -30px) rotate(-18deg) scale(.8); animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  10%  { opacity: 1; }
  40%  { opacity: 1; transform: translate(var(--gx), 0) rotate(-5deg) scale(1); animation-timing-function: ease-out; }
  50%  { transform: translate(calc(var(--gx) + 6px), -4px) rotate(4deg); animation-timing-function: cubic-bezier(.5, 0, .4, 1); }
  64%  { transform: translate(calc(var(--gx) * .56), -4px) rotate(-12deg) scale(1.06); }
  82%  { transform: translate(calc(var(--gx) * .54), -8px) rotate(-9deg) scale(1.06); animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
  100% { opacity: 1; transform: translate(var(--gx), 4px) rotate(0) scale(1); }
}
/* หางตอนบิน: ไฟส้มหลังน้องฮูก · ประกายม่วงหลังน้องไซ — สว่างแค่ช่วงบินเข้า */
/* หางเป็นดาวหาง: วงรีไล่สีจากตัวผีจางออกไป — ขอบนุ่มเองไม่ต้องเบลอ (แถบตรง ๆ ดูเป็นแผ่นสี่เหลี่ยม) */
.hb-gw::before { content: ""; position: absolute; top: 34%; height: 36%; width: 200%; opacity: 0; pointer-events: none; }
.hb-gw.l::before { right: 45%; transform-origin: 100% 50%; animation: hb-trail 1.25s .15s both;
  background: radial-gradient(farthest-side at 100% 50%, rgba(255, 200, 120, .9), rgba(255, 120, 30, .38) 45%, rgba(255, 90, 20, .1) 75%, transparent); }
.hb-gw.r::before { left: 45%; transform-origin: 0 50%; animation: hb-trail 1.15s .25s both;
  background: radial-gradient(farthest-side at 0 50%, rgba(225, 195, 255, .95), rgba(150, 90, 255, .4) 45%, rgba(124, 58, 237, .12) 75%, transparent); }
@keyframes hb-trail { 0% { opacity: 0; transform: scaleX(.4); } 12% { opacity: 1; transform: none; } 40% { opacity: .8; } 55%, 100% { opacity: 0; transform: scaleX(.3); } }
/* กะพริบตาเป็นระยะ */
.hb-eyes { transform-box: fill-box; transform-origin: 50% 60%; animation: hb-blink 3.6s 1.6s infinite; }
.hb-gw.r .hb-eyes { animation-delay: 2.4s; }
@keyframes hb-blink { 0%, 92%, 100% { transform: none; } 95% { transform: scaleY(.1); } }
.hb-pk { transform-box: fill-box; transform-origin: 30% 0; animation: hb-swing 1.4s ease-in-out infinite alternate; }
@keyframes hb-swing { from { transform: rotate(-7deg); } to { transform: rotate(7deg); } }

/* วงพลัง: วงแหวนไล่สีหมุนเป็นวงรีรอบไอคอน (บีบแนวตั้ง = มองเฉียงเหมือนในภาพ 3) */
.hb-swirl { z-index: 0; width: 300px; height: 300px; margin: -150px 0 0 -150px; border-radius: 50%; opacity: 0;
  background: conic-gradient(from 0deg, transparent 0 4%, #c084fc 16%, #f3e8ff 20%, transparent 33%, transparent 40%,
    #a855f7 54%, #e9d5ff 58%, transparent 70%, transparent 76%, #d8b4fe 88%, #fff 91%, transparent);
  -webkit-mask: radial-gradient(closest-side, transparent 50%, #000 62%, #000 76%, transparent 98%);
          mask: radial-gradient(closest-side, transparent 50%, #000 62%, #000 76%, transparent 98%);
  filter: blur(1.5px) brightness(1.15); animation: hb-swirl 1.3s .78s cubic-bezier(.3, .6, .4, 1) both; }
/* วงที่สองอยู่หน้าไอคอนแต่หลังผี — เคยอยู่หน้าผีแล้วแสงส้มพาดทับตาน้องไซ */
.hb-swirl.b { z-index: 1; width: 236px; height: 236px; margin: -118px 0 0 -118px;
  background: conic-gradient(from 90deg, transparent 0 8%, #ffb066 18%, #fff1dd 21%, transparent 32%, transparent 52%, #c99bff 64%, #f5ecff 67%, transparent 80%);
  animation-name: hb-swirl-b; animation-delay: .88s; }
@keyframes hb-swirl { 0% { opacity: 0; transform: rotate(-10deg) scaleY(.5) rotate(0) scale(.55); } 25%, 65% { opacity: 1; } 100% { opacity: 0; transform: rotate(-10deg) scaleY(.5) rotate(560deg) scale(1.15); } }
@keyframes hb-swirl-b { 0% { opacity: 0; transform: rotate(14deg) scaleY(.42) rotate(0) scale(.6); } 30%, 60% { opacity: .9; } 100% { opacity: 0; transform: rotate(14deg) scaleY(.42) rotate(-480deg) scale(1.2); } }
.hb-flash { z-index: 0; width: 280px; height: 200px; margin: -100px 0 0 -140px; border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .8), rgba(196, 140, 255, .6) 32%, rgba(124, 58, 237, .25) 62%, transparent);
  animation: hb-flash .65s .98s ease-out both; }
@keyframes hb-flash { 0% { opacity: 0; transform: scale(.3); } 30% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.7); } }

/* ประกายดาวสี่แฉกรอบไอคอน — เริ่มหลังรวมพลัง */
.hb-spark { z-index: 3; }
.hb-spark i { position: absolute; left: var(--x); top: var(--y); width: 12px; height: 12px; margin: -6px; opacity: 0;
  background: #f6ecff; clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
  filter: drop-shadow(0 0 4px #c084fc); animation: hb-tw 1.7s calc(1.1s + var(--d, 0s)) ease-in-out infinite both; }
@keyframes hb-tw { 0%, 100% { opacity: 0; transform: scale(calc(.3 * var(--s, 1))) rotate(0); } 50% { opacity: 1; transform: scale(var(--s, 1)) rotate(45deg); } }

/* เสร็จสิ้น: ผีย่อตัวรับแรงนิดหนึ่ง แล้วลอยขึ้นเป็นโค้งออกคนละฝั่ง ค่อย ๆ จางตอนท้าย
   (รอบแรกพุ่งออกใน 0.25 วิ แบบ ease-in พร้อมหมุน 24° และหด — เจ้าของ: "ผี 2 ตัวแปลก ๆ ให้มันสมูทหน่อย")
   ความยาวต้องเข้ากับ STORY_END ในสคริปต์ใต้ #boot — จอเริ่มจางตอนผีขึ้นไปเกือบพ้นแล้ว */
html:root.hw-season .boot.done .hb-gw.l { animation: hb-out-l .9s both; }
html:root.hw-season .boot.done .hb-gw.r { animation: hb-out-r .9s .06s both; }
@keyframes hb-out-l {
  0%   { opacity: 1; transform: translate(calc(var(--gx) * -1), 0) rotate(0) scale(1); animation-timing-function: cubic-bezier(.3, 0, .5, 1); }
  18%  { opacity: 1; transform: translate(calc(var(--gx) * -1 + 4px), 7px) rotate(3deg) scale(1.05, .93); animation-timing-function: cubic-bezier(.4, 0, .3, 1); }
  50%  { opacity: 1; transform: translate(calc(var(--gx) * -1 - 4vw), -14vh) rotate(-6deg) scale(.96, 1.04); animation-timing-function: cubic-bezier(.3, 0, .4, 1); }
  100% { opacity: 0; transform: translate(calc(var(--gx) * -1 - 22vw), -38vh) rotate(-12deg) scale(.78); }
}
@keyframes hb-out-r {
  0%   { opacity: 1; transform: translate(var(--gx), 4px) rotate(0) scale(1); animation-timing-function: cubic-bezier(.3, 0, .5, 1); }
  18%  { opacity: 1; transform: translate(calc(var(--gx) - 4px), 11px) rotate(-3deg) scale(1.05, .93); animation-timing-function: cubic-bezier(.4, 0, .3, 1); }
  50%  { opacity: 1; transform: translate(calc(var(--gx) + 4vw), -13vh) rotate(6deg) scale(.96, 1.04); animation-timing-function: cubic-bezier(.3, 0, .4, 1); }
  100% { opacity: 0; transform: translate(calc(var(--gx) + 22vw), -36vh) rotate(12deg) scale(.78); }
}
html:root.hw-season .boot.done .hb-spark { opacity: 0; transition: opacity .25s; }

/* ============================================================
   จอเข้าสู่ระบบ
   ------------------------------------------------------------
   เปลี่ยนโทเคนของธีมเฉพาะในจอนี้ — ปุ่ม ตัวหนังสือ ไอคอน ที่ใช้ --ink/--fill/--card อยู่แล้วเปลี่ยนตามเอง
   ใบพระเอกยังเป็นใบเดียวที่มีสีเต็ม (กฎ 1C13) แค่เปลี่ยนเป็นม่วงคืน → ส้มฟักทอง
   ============================================================ */
/* จอนี้สูงแค่เนื้อหา ส่วนที่เหลือคือพื้นของ .phone — พื้นกลางคืนจึงต้องทาที่ .phone (และ html/body ตอนเด้งสุดจอ)
   ไม่ใช่ที่ #scr-login ไม่งั้นเห็นแถบสว่างใต้การ์ด */
html:root.hw-season:has(#scr-login.on), html:root.hw-season:has(#scr-login.on) body { background: #0b0716; }
html:root.hw-season .phone:has(#scr-login.on) {
  background:
    radial-gradient(110% 45% at 85% 0%, rgba(124, 58, 237, .38), transparent 65%),
    radial-gradient(80% 35% at 0% 100%, rgba(255, 122, 24, .14), transparent 70%),
    linear-gradient(180deg, #170c2e 0%, #0e0820 55%, #0b0716 100%) !important;
}
html:root.hw-season #scr-login {
  --scr: #120a24; --card: #1d1433; --ink: #f6eefe; --muted: #b9a8d6; --line: rgba(190, 160, 255, .18);
  --fill: #ff8a1f; --on-fill: #fff; --blue: #ffad5c; --blue-soft: rgba(255, 138, 31, .14);
  /* ชิปข้อความผิดพลาด (.lg-note.bad) ใช้ --ink บน --alert-soft — --ink ตรงนี้สว่าง
     แต่ --alert-soft ยังเป็นชมพูอ่อนของธีมสว่าง ได้ตัวขาวบนพื้นชมพูอ่านไม่ออก · ใช้คู่ของธีมมืดแทน */
  --alert: #ff7a94; --alert-soft: rgba(255, 122, 148, .22);
  position: relative; isolation: isolate; color: var(--ink); background: transparent !important;
}
html:root.hw-season #scr-login .login-wrap { position: relative; z-index: 1; }

/* ชั้นตกแต่งทั้งจอสองชั้น: ดาวอยู่หลังการ์ด · ค้างคาวบินผ่านอยู่หน้าการ์ด (กดทะลุได้) */
html:root.hw-season .lg-hw { display: block; position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
html:root.hw-season .lg-hw.top { z-index: 2; }
.lg-hw > * { position: absolute; display: block; }
.lg-hw .lh-fly { inset: 0; }

/* ใบพระเอก: ม่วงคืนไล่ไปส้มฟักทอง ขอบเรืองส้ม */
html:root.hw-season #scr-login .lg-hero {
  background-image:
    radial-gradient(120% 90% at 100% 100%, rgba(255, 122, 24, .55), transparent 55%),
    linear-gradient(150deg, #2a1257 0%, #4c1d95 52%, #6b2a8a 100%);
  border: 1px solid rgba(255, 170, 90, .35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14), 0 18px 40px -18px rgba(255, 122, 24, .55), 0 0 0 1px rgba(0, 0, 0, .25);
}
/* วงกลมจางมุมขวาบนกลายเป็นพระจันทร์ */
html:root.hw-season #scr-login .lg-hero::after {
  right: 18px; top: 16px; width: 56px; height: 56px; clip-path: none; z-index: 1;
  background:
    radial-gradient(circle at 66% 30%, rgba(214, 170, 96, .55) 0 5px, transparent 6px),
    radial-gradient(circle at 34% 64%, rgba(214, 170, 96, .45) 0 7px, transparent 8px),
    radial-gradient(circle at 38% 34%, #fff8e3, #ffe2a1 55%, #f2b45a 100%);
  box-shadow: 0 0 26px 6px rgba(255, 196, 110, .4), 0 0 80px 20px rgba(255, 140, 50, .18);
  animation: hb-moon-glow-sm 3.2s ease-in-out infinite alternate;
}
@keyframes hb-moon-glow-sm { to { box-shadow: 0 0 34px 10px rgba(255, 196, 110, .5), 0 0 96px 28px rgba(255, 140, 50, .24); } }
html:root.hw-season #scr-login .lg-mark { background: transparent; padding: 0; box-shadow: 0 0 14px rgba(255, 138, 31, .45); }
html:root.hw-season #scr-login .lg-brand::after { content: " · Halloween"; color: #ffc078; }
html:root.hw-season #scr-login .lg-h { text-shadow: 0 0 22px rgba(255, 150, 60, .55), 0 2px 0 rgba(0, 0, 0, .25); }
html:root.hw-season #scr-login .lg-p { color: #f3e6ff; }

/* ค้างคาวสองตัวเกาะอยู่หน้าพระจันทร์ในใบพระเอก ลอยขึ้นลงเบา ๆ */
.lg-hero .lh-moonbats { display: none; }
html:root.hw-season #scr-login .lg-hero .lh-moonbats { display: block; position: absolute; right: 12px; top: 22px; width: 84px; height: 56px; z-index: 2; pointer-events: none; }
.lh-moonbats i { position: absolute; display: block; width: 30px; animation: lh-hover 2.4s ease-in-out infinite alternate; }
.lh-moonbats i:first-child { left: 4px; top: 22px; }
.lh-moonbats i:last-child { right: 0; top: 2px; width: 22px; animation-delay: -1.2s; }
@keyframes lh-hover { from { transform: translate(0, 0); } to { transform: translate(-6px, -8px); } }

/* มาสคอต: น้องฮูกชุดมัมมี่ (ชุดเดียวกับรางวัลฮาโลวีน · ย่อเหลือ 224px สำหรับวงนี้) */
.lg-sai-hw { display: none; }
html:root.hw-season #scr-login .lg-sai { display: none; }
html:root.hw-season #scr-login .lg-sai-hw { display: block; position: absolute; right: 16px; bottom: -32px; z-index: 3;
  width: 84px; height: 84px; border-radius: 50%; object-fit: contain; padding: 4px; pointer-events: none;
  background: radial-gradient(circle at 50% 40%, #3b1d6b, #150b2b 75%);
  border: 3px solid #ff9a3c;
  box-shadow: 0 0 0 4px #120a24, 0 0 24px rgba(255, 138, 31, .55);
  animation: lh-float 3s ease-in-out infinite alternate; }
@keyframes lh-float { to { transform: translateY(-5px) rotate(-3deg); } }

/* การ์ดล่าง: กระจกมืด ขอบม่วง · ใยแมงมุมจาง ๆ มุมซ้ายบน */
html:root.hw-season #scr-login .tx-card {
  position: relative;
  background: linear-gradient(180deg, rgba(42, 25, 76, .86), rgba(20, 12, 38, .92));
  box-shadow: 0 0 0 1px rgba(190, 150, 255, .22), inset 0 1px 0 rgba(255, 255, 255, .08), 0 20px 40px -20px rgba(0, 0, 0, .8);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.tx-card .lh-web { display: none; }
html:root.hw-season #scr-login .tx-card .lh-web { display: block; position: absolute; left: 0; top: 0; width: 92px; height: 92px; opacity: .3; pointer-events: none;
  stroke: #d9c8ff; stroke-width: 1; fill: none; }
html:root.hw-season #scr-login .lf-ic { background: rgba(255, 138, 31, .14); color: #ffad5c; box-shadow: inset 0 0 0 1px rgba(255, 160, 80, .28); }
html:root.hw-season #scr-login .lg-feat b { color: #f6eefe; }
html:root.hw-season #scr-login .tx-sep { border-top-color: rgba(0, 0, 0, .45); border-bottom-color: rgba(255, 255, 255, .07); }
html:root.hw-season #scr-login .tx-foot { background: rgba(8, 5, 16, .55); border-top-color: rgba(255, 255, 255, .06); box-shadow: none; }
html:root.hw-season #scr-login .login-what { color: #c9b6ea; }

/* ปุ่มหลัก: ฟักทองเรือง มีแสงวาบวิ่งผ่านเป็นระยะ */
html:root.hw-season #scr-login .lg-opts .btn.lg-go {
  position: relative; overflow: hidden; color: #fff;
  background: linear-gradient(180deg, #ffb04a, #ff7a18 55%, #e0560f);
  border: 1px solid #a8400c;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), inset 0 -2px 0 rgba(120, 30, 0, .35), 0 10px 26px -10px rgba(255, 122, 24, .9);
  text-shadow: 0 1px 1px rgba(120, 40, 0, .45);
}
html:root.hw-season #scr-login .lg-opts .btn.lg-go::after { content: ""; position: absolute; top: 0; bottom: 0; left: -40%; width: 30%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .45), transparent); transform: skewX(-18deg);
  animation: lh-shine 3.6s 1s ease-in-out infinite; pointer-events: none; }
@keyframes lh-shine { 0%, 55% { left: -40%; } 100% { left: 130%; } }
/* ปุ่ม Google คงพื้นสว่างตามแนวทางของ Google · ตัวหนังสือต้องตั้งเอง เพราะ --ink ของจอนี้เป็นสีสว่างแล้ว */
html:root.hw-season #scr-login .lg-opts .btn.lg-main {
  background: linear-gradient(180deg, #ffffff, #efe8fa); color: #1f1534;
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow: inset 0 1px 0 #fff, 0 8px 20px -12px rgba(0, 0, 0, .8);
}
html:root.hw-season #scr-login .lg-in { background: rgba(10, 6, 20, .6); color: var(--ink); border-color: rgba(190, 150, 255, .3); }

/* ============================================================
   เครื่องเบา / ลดการเคลื่อนไหว
   ============================================================ */
:root[data-lite] .hb-burst i:nth-child(even), :root[data-lite] .hb-fly i:nth-child(n+3),
:root[data-lite] .lg-hw .lh-fly i:nth-child(n+2), :root[data-lite] .hb-swirl.b, :root[data-lite] .hb-spark i:nth-child(even),
:root[data-lite] .hb-cloud.b { display: none; }
/* เครื่องเบา: เลิกเบลอ/เงาเรืองที่ต้องวาดใหม่ทุกเฟรม เหลือแค่การเคลื่อนที่ */
:root[data-lite] .hb-swirl, :root[data-lite] .hb-spark i { filter: none; }
:root[data-lite] .hb-g { filter: drop-shadow(0 0 6px rgba(196, 150, 255, .6)); }
html:root.hw-season[data-lite] #scr-login .tx-card { -webkit-backdrop-filter: none; backdrop-filter: none; }
@media (prefers-reduced-motion: reduce) {
  .hw-bat, .hb-stars, .lg-hw .lh-stars, .hb-moon, .hb-fog, .lh-moonbats i,
  html:root.hw-season .boot .boot-mid::before, html:root.hw-season .boot .boot-mark,
  html:root.hw-season #scr-login .lg-hero::after, html:root.hw-season #scr-login .lg-sai-hw { animation: none; }
  html:root.hw-season #scr-login .lg-opts .btn.lg-go::after { display: none; }
  /* ค้างคาวที่บินผ่าน/พุ่งออกต้องขยับถึงจะมีความหมาย — ลดการเคลื่อนไหวแล้วซ่อน ฉากที่เหลือยังเป็นฮาโลวีนครบ */
  .hb-burst, .hb-fly, .lg-hw .lh-fly { display: none !important; }
  /* ฉากผี: ภาพนิ่งของจังหวะ "กำลังโหลด" — ผีอยู่ข้างไอคอนเลย ไม่บินเข้า ไม่มีวงพลัง (สคริปต์ไม่รอจังหวะเมื่อลดการเคลื่อนไหว) */
  .hb-cloud, .hb-gw, .hb-g, .hb-eyes, .hb-pk, html:root.hw-season .boot .boot-bar,
  html:root.hw-season .boot .hp-track::after, html:root.hw-season .boot.done .boot-mark { animation: none; }
  .hb-gw { opacity: 1; }
  .hb-gw.l { transform: translateX(calc(var(--gx) * -1)); }
  .hb-gw.r { transform: translate(var(--gx), 4px); }
  .hb-gw::before, .hb-swirl, .hb-flash, .hb-spark { display: none; }
}
