/* 3Q Thần Tướng landing.
   Desktop: every element is placed with PSD coordinates (1920px wide design),
   --x/--y/--w are pixels in the PSD, relative to the top of their section.
   --u is the size of one PSD pixel on screen (set in JS, CSS fallback here). */
:root {
  --u: calc(min(100vw, 1920px) / 1920);
  --gold: #f2d38b;
  --text: #c9c2b4;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { overflow-x: hidden; }
body {
  background: #0d0c0b;
  color: var(--text);
  font-family: 'Roboto', Arial, sans-serif;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

/* ---------- sections ---------- */
.sec {
  position: relative;
  width: calc(1920 * var(--u));
  height: calc(var(--h) * var(--u));
  margin: 0 auto;
  background: var(--bg) top center / 100% auto no-repeat;
}
.sec + .sec { margin-top: -1px; } /* hide sub-pixel seams between background slices */
.sec--hero { --h: 1250; --bg: url(bg/hero.jpg); }
.sec--news { --h: 830; --bg: url(bg/news.jpg); }
.sec--rank { --h: 910; --bg: url(bg/rank.jpg); }
.sec--general { --h: 970; --bg: url(bg/general.jpg); }
.sec--feature { --h: 834; --bg: url(bg/feature.jpg); }
.sec--footer { --h: 227; --bg: url(footer/bg.jpg); background-color: #000; }

.abs {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
}
.abs > img { width: 100%; height: auto; }
img.abs { height: auto; max-width: none; }
.wrap { display: contents; }

.btn { transition: transform .2s, filter .2s; }
.btn:hover { transform: translateY(calc(-4 * var(--u))); filter: brightness(1.15); }

/* ---------- hero effects (hero-fx.js) ---------- */
.hero__fx { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.fx-canvas { position: absolute; left: 0; top: 0; }
/* heat haze: same background, displaced by an SVG noise filter, faded at top/bottom */
.fx-heat {
  position: absolute;
  left: 0;
  width: 100%;
  background: url(bg/hero.jpg) no-repeat;
  filter: url(#fx-heat);
  -webkit-mask: linear-gradient(transparent, #000 35%, #000 70%, transparent);
  mask: linear-gradient(transparent, #000 35%, #000 70%, transparent);
}
.fx-aura, .fx-rays { position: absolute; border-radius: 50%; mix-blend-mode: screen; will-change: transform, opacity; }
.fx-aura {
  background: radial-gradient(closest-side, rgba(255, 190, 100, .10), rgba(255, 170, 70, .30) 50%, rgba(255, 140, 40, 0) 100%);
  animation: fx-breathe 7s ease-in-out infinite;
}
.fx-rays {
  opacity: calc(.22 * var(--k));
  background: repeating-conic-gradient(from 0deg, rgba(255, 196, 110, .9) 0deg 1deg, rgba(255, 196, 110, 0) 3.5deg 12deg);
  /* hollow center: rays start behind the silhouette, faces stay crisp */
  -webkit-mask: radial-gradient(closest-side, transparent 30%, #000 45%, rgba(0, 0, 0, .4) 70%, transparent 100%);
  mask: radial-gradient(closest-side, transparent 30%, #000 45%, rgba(0, 0, 0, .4) 70%, transparent 100%);
  animation: fx-spin 160s linear infinite;
}
.fx-rays--rev { animation-direction: reverse; }
/* faint fire glow over the burning battlefield */
.hero__fx::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0; height: 38%;
  background: radial-gradient(60% 70% at 50% 85%, rgba(255, 110, 30, .16), transparent 70%);
  mix-blend-mode: screen;
  animation: fx-flicker 4.5s ease-in-out infinite;
}
.hero__fx.is-paused *, .hero__fx.is-paused::after { animation-play-state: paused; }
@keyframes fx-breathe {
  0%, 100% { opacity: calc(.55 * var(--k)); transform: scale(.96); }
  50% { opacity: var(--k); transform: scale(1.04); }
}
@keyframes fx-spin { to { transform: rotate(360deg); } }
@keyframes fx-flicker {
  0%, 100% { opacity: .7; }
  30% { opacity: 1; }
  55% { opacity: .8; }
  75% { opacity: .95; }
}

/* ---------- Hổ Tướng Bảng fire + heat haze (general-fx.js) ---------- */
.gfx-canvas { position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none; }
.gfx-heat {
  position: absolute;
  pointer-events: none;
  background: url(bg/general.jpg) no-repeat;
  /* fade in from the top and at the sides so the distorted copy blends into the original */
  -webkit-mask: linear-gradient(transparent, #000 45%), linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, #000 45%), linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
  mask-composite: intersect;
}
.gfx-heat-art { pointer-events: none; }

/* ---------- animated logo (logo-fx.js) ---------- */
.logo-gl, .warp-gl, .logo-bolt { position: absolute; pointer-events: none; }
.logo-bolt { mix-blend-mode: screen; }
.is-gl > img { visibility: hidden; }

/* section titles float gently up and down (~10px), each on its own phase */
h2.title { animation: title-float 4.2s ease-in-out infinite; }
.sec--rank h2.title { animation-delay: -1.1s; }
.sec--general h2.title { animation-delay: -2.2s; }
.sec--feature h2.title { animation-delay: -3.1s; }
@keyframes title-float {
  0%, 100% { transform: translateY(5px); }
  50% { transform: translateY(-5px); }
}
@media (prefers-reduced-motion: reduce) { h2.title { animation: none; } }

/* whole hero logo drifts slowly up and down (uses `translate` so it stacks on any transform) */
.hero__logo { animation: logo-float 6s ease-in-out infinite; will-change: translate; }
@keyframes logo-float {
  0%, 100% { translate: 0 7px; }
  50% { translate: 0 -7px; }
}
@media (prefers-reduced-motion: reduce) { .hero__logo { animation: none; } }

/* ---------- side bar ---------- */
.side {
  position: fixed;
  z-index: 50;
  right: 0;
  top: calc(134 * var(--u));
  width: calc(227 * var(--u));
}
.side__bar { width: 100%; }
.side__link {
  position: absolute;
  left: 50%;
  width: 31%;
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translateX(-3%);
}
.side__link:hover { box-shadow: 0 0 calc(18 * var(--u)) rgba(255, 210, 120, .8); }
.side__gift {
  position: absolute;
  left: 45.4%;
  top: 75.9%;
  width: 38.8%;
}
/* swings like a hanging tag, pivot = top center (the hook) */
.gift__img { width: 100%; transform-origin: 50% 0; }
.gift__img.is-swing { animation: gift-swing 1.1s cubic-bezier(.36, .07, .19, .97); }
@keyframes gift-swing {
  0% { transform: rotate(0); }
  15% { transform: rotate(14deg); }
  32% { transform: rotate(-10deg); }
  50% { transform: rotate(6deg); }
  68% { transform: rotate(-3.5deg); }
  84% { transform: rotate(1.5deg); }
  100% { transform: rotate(0); }
}
/* twinkling 4-point stars around / over the tag.
   ::after = soft round glow, ::before = sharp star (clip-path would clip a filter glow,
   so the glow is a separate layer) */
.spark {
  position: absolute;
  z-index: 1;
  width: 56%;
  aspect-ratio: 1;
  pointer-events: none;
  opacity: 0;
  animation: spark 2.6s ease-in-out infinite;
}
.spark::before, .spark::after { content: ''; position: absolute; inset: 0; }
.spark::after {
  inset: 22%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 236, 170, .95), rgba(255, 190, 70, .45) 45%, rgba(255, 160, 40, 0) 72%);
}
.spark::before {
  z-index: 1;
  background: radial-gradient(circle, #fff 0 10%, #fff3c2 22%, #ffd36b 42%, rgba(255, 190, 70, .2) 70%);
  clip-path: polygon(50% 0, 55% 45%, 100% 50%, 55% 55%, 50% 100%, 45% 55%, 0 50%, 45% 45%);
}
.spark--1 { left: -30%; top: 0; }
.spark--2 { right: -32%; top: 28%; width: 46%; animation-delay: .55s; }
.spark--3 { left: -24%; top: 60%; width: 42%; animation-delay: 1.1s; }
.spark--4 { right: -20%; top: 72%; width: 36%; animation-delay: 1.6s; }
.spark--5 { left: 34%; top: 18%; width: 34%; animation-delay: 2.05s; } /* over the gift box */
@keyframes spark {
  0%, 100% { opacity: 0; transform: scale(.15) rotate(0); }
  18% { opacity: 1; transform: scale(1.1) rotate(30deg); }
  30% { opacity: 1; transform: scale(.9) rotate(50deg); }
  45% { opacity: 0; transform: scale(.25) rotate(90deg); }
}

/* ---------- news carousel ---------- */
.news__view { overflow: hidden; height: calc(442 * var(--u)); }
.news__track { display: flex; gap: calc(11 * var(--u)); width: max-content; }
.news__track img { height: calc(442 * var(--u)); width: auto; max-width: none; }
.arrow { cursor: pointer; background: none; border: 0; }

/* ---------- generals ---------- */
.tab { cursor: pointer; background: none; border: 0; filter: brightness(.8); transition: filter .2s, transform .2s; }
.tab:hover { filter: brightness(1); }
.tab.is-active { filter: brightness(1.15) drop-shadow(0 0 calc(10 * var(--u)) rgba(255, 200, 90, .7)); }

.gen__art, .gen__flag { transition: opacity .35s; }
.gen__art { pointer-events: none; }
.is-hidden { opacity: 0; visibility: hidden; }

.gen__panel { display: grid; grid-template-columns: calc(98 * var(--u)) 1fr; grid-template-rows: auto auto 1fr; column-gap: calc(2 * var(--u)); }
.gen__banner { grid-row: span 3; width: 100%; }
.gen__name { height: calc(92 * var(--u)); margin: calc(12 * var(--u)) 0 calc(21 * var(--u)); display: flex; align-items: center; }
.gen__name img { height: 100%; width: auto; max-width: none; }
.gen__name span {
  font: 700 calc(64 * var(--u)) / 1 'Oswald', 'Roboto', sans-serif;
  text-transform: uppercase;
  letter-spacing: calc(2 * var(--u));
  background: linear-gradient(#fff3c4, #d9a94a 60%, #9a6a22);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.gen__desc { font-size: calc(15 * var(--u)); line-height: 1.55; }
.gen__meta { margin-top: calc(14 * var(--u)); font-size: calc(15 * var(--u)); line-height: 1.9; }
.gen__meta b { color: var(--gold); font-size: calc(19 * var(--u)); font-weight: 700; margin-left: calc(6 * var(--u)); }

/* ---------- feature slider ---------- */
.feat__frame > img { width: 100%; }
.feat__slides { position: absolute; inset: 9% 2.2% 9.6% 2.2%; }
.feat__slide { position: absolute; inset: 0; opacity: 0; transition: opacity .5s; }
.feat__slide.is-active { opacity: 1; }
.feat__slide img { width: 100%; height: 100%; }

/* light sweep over banner text: a bright band slides across, masked to the gold letters.
   All shines share one 14s cycle (3s sweep each); --d staggers them so they never overlap.
   The feature slider changes every 7s so each slide's shine lands while it is shown. */
.news__track a { position: relative; display: block; outline: none; }
/* keyboard focus drawn inside the card: .news__view clips anything outside it */
.news__track a:focus-visible::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 3px var(--gold);
}
.shine {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* mask-image is set inline on each element (path relative to the page) */
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  background:
    linear-gradient(100deg, transparent 43%, rgba(255, 252, 235, 1) 50%, transparent 57%),
    linear-gradient(100deg, transparent 28%, rgba(255, 210, 120, .85) 50%, transparent 72%);
  background-size: 250% 100%;
  background-repeat: no-repeat;
  background-position: 140% 0;
  mix-blend-mode: screen;
  animation: shine 14s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes shine {
  0% { background-position: 140% 0; }
  21.4% { background-position: -40% 0; }  /* 3s slow sweep, then wait */
  100% { background-position: -40% 0; }
}
@media (prefers-reduced-motion: reduce) { .shine { display: none; } }

/* ---------- news popup: same gold frame + paper as the Đặc Sắc box (9-slice of feature/frame.webp) ---------- */
html.is-modal { overflow: hidden; }
.modal {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px 16px;
  opacity: 0; transition: opacity .25s ease;
}
.modal[hidden] { display: none; }
.modal.is-open { opacity: 1; }
.modal__backdrop {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(30,12,6,.72), rgba(0,0,0,.9));
}
.modal__box {
  --fw: 56px; /* frame thickness on screen */
  position: relative;
  display: flex; flex-direction: column;
  width: min(880px, 100%);
  max-height: min(860px, 100%);
  border: var(--fw) solid transparent;
  border-image: url(feature/frame.webp) 56 fill / var(--fw) stretch;
  filter: drop-shadow(0 12px 40px rgba(0,0,0,.7));
  transform: translateY(18px) scale(.96);
  transition: transform .3s cubic-bezier(.2,.8,.3,1.2);
}
.modal.is-open .modal__box { transform: none; }
.modal__body {
  min-height: 0; /* let it shrink inside the box so it scrolls instead of spilling over the frame */
  overflow-y: auto; overscroll-behavior: contain;
  margin: -14px -18px; padding: 10px 22px 18px; /* use the paper inside the gold bar */
  color: #3d2615; font-size: 16px; line-height: 1.7;
  scrollbar-width: thin; scrollbar-color: #b8893a transparent;
}
.modal__body::-webkit-scrollbar { width: 8px; }
.modal__body::-webkit-scrollbar-thumb { background: linear-gradient(#e2bd6b, #9c6d26); border-radius: 4px; }
.modal__cover {
  width: 100%; aspect-ratio: 700 / 442; object-fit: cover;
  margin-bottom: 18px; /* the news art already has its own gold frame */
  filter: drop-shadow(0 6px 14px rgba(60,30,10,.35));
}
.modal__title {
  font-family: 'Oswald', sans-serif; font-weight: 700;
  font-size: 30px; line-height: 1.2; text-transform: uppercase; text-align: center;
  color: #8e1b10;
  text-shadow: 0 1px 0 #f6e3b4;
}
.modal__meta {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin: 6px 0 18px; white-space: nowrap; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: #8a6a3c;
}
.modal__meta::before, .modal__meta::after {
  content: ''; flex: 0 1 120px; height: 1px;
  background: linear-gradient(90deg, transparent, #b8893a);
}
.modal__meta::after { transform: scaleX(-1); }
.modal__content h4 {
  margin: 0 0 14px; font-size: 19px; text-align: center; color: #8e1b10; text-transform: uppercase;
}
.modal__content h5 {
  margin: 20px 0 8px; padding-left: 12px; border-left: 4px solid #b8893a;
  font-size: 16px; text-transform: uppercase; color: #6e3a12;
}
.modal__content p { margin: 0 0 12px; }
.modal__content ul { margin: 0 0 12px 22px; }
.modal__content li { margin-bottom: 6px; }
.modal__content b { color: #8e1b10; }
.modal__content .modal__cta {
  margin-top: 20px; padding: 12px 16px; text-align: center; font-weight: 700; color: #fff4d6;
  background: linear-gradient(90deg, transparent, #8e1b10 15%, #8e1b10 85%, transparent);
}
.modal__close {
  position: absolute; top: calc(var(--fw) * -1 - 6px); right: calc(var(--fw) * -1 - 6px); z-index: 1;
  width: 46px; height: 46px; border-radius: 50%;
  border: 2px solid #e8c472; cursor: pointer;
  background: radial-gradient(circle at 50% 35%, #7a1a10, #2a0805);
  box-shadow: 0 0 0 2px #5b3a12, 0 4px 12px rgba(0,0,0,.6);
  color: #f6dc97; font-size: 30px; line-height: 1;
  transition: transform .2s ease, filter .2s ease;
}
.modal__close:hover, .modal__close:focus-visible { transform: rotate(90deg); filter: brightness(1.25); outline: none; }
@media (max-width: 767px) {
  .modal { padding: 16px 10px; }
  .modal__box { --fw: 34px; border-image-slice: 56 fill; }
  .modal__body { margin: -6px -8px; padding: 6px 10px 12px; font-size: 15px; }
  .modal__title { font-size: 22px; }
  .modal__close { width: 40px; height: 40px; font-size: 26px; top: -30px; right: -26px; }
}
@media (prefers-reduced-motion: reduce) { .modal, .modal__box { transition: none; } }

/* ---------- mobile: stacked layout ---------- */
@media (max-width: 767px) {
  :root { --u: calc(100vw / 1920); }
  .sec {
    width: 100%;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 28px 16px;
    background-size: cover;
  }
  .abs { position: relative; left: auto; top: auto; width: var(--mw, 90%); }
  .wrap { display: flex; }

  .sec--hero { padding-top: 46vw; background-position: 50% 0; background-size: cover; min-height: 150vw; }
  .hero__logo { --mw: 96%; }
  .hero__frame, .hero__qr { display: none; }
  .hero__dl { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%; max-width: 420px; }
  .hero__dl .abs { width: 100%; }
  .hero__dl .hero__pay { grid-column: 1 / -1; width: 62%; justify-self: center; }

  .side { top: auto; bottom: 12px; right: 18px; width: 52px; } /* room for the right stars */
  .side__bar, .side__link { display: none; }
  .side__gift { position: relative; left: auto; top: auto; display: block; width: 100%; }

  .title { --mw: 78%; max-width: 380px; }
  /* this image is half transparent padding (artwork = 50% of its width): double it so it matches */
  .sec--rank .title { --mw: 156%; max-width: 760px; flex-shrink: 0; }

  .news__view { height: auto; width: 100%; overflow-x: auto; scroll-snap-type: x mandatory; }
  .news__track { gap: 10px; }
  .news__track a { scroll-snap-align: center; }
  .news__track img { height: 52vw; }
  .arrow { display: none; }

  .rank__board { --mw: 100%; overflow-x: auto; }
  .rank__board img { width: 760px; max-width: none; }

  .sec--general { background-position: center; }
  .gen__tabs { width: 100%; overflow-x: auto; align-items: flex-start; justify-content: center; gap: 2px; padding-bottom: 4px; }
  /* tab images have different cloud decorations; --pc = plate centre in the image (px).
     Shift each down so every plate centre lines up with the tallest one (Thục, 88px). */
  .gen__tabs .tab { flex: 0 0 auto; width: 84px; margin-top: calc((88 - var(--pc, 88)) * 84px / var(--w)); }
  .gen__stage { position: relative; width: 100%; aspect-ratio: 803 / 619; }
  .gen__stage .gen__art { position: absolute; left: 50%; top: 0; width: 88%; transform: translateX(-50%); }
  .gen__stage .gen__art[data-art='thuc'] { width: 100%; }
  .gen__stage .gen__flag { position: absolute; left: auto; right: 0; top: 0; width: 30%; }
  .gen__panel { --mw: 100%; display: grid; grid-template-columns: 52px 1fr; column-gap: 12px; }
  .gen__panel .gen__banner { grid-row: span 3; width: 52px; }
  .gen__name { height: 40px; }
  .gen__name span { font-size: 30px; }
  .gen__desc, .gen__meta { font-size: 14px; }
  .gen__meta b { font-size: 16px; }

  .feat__frame { --mw: 100%; }

  .sec--footer { background-size: 280% auto; background-position: 50% 100%; padding: 14px 16px 0; min-height: 230px; justify-content: flex-start; }
  .footer__logo { --mw: 44%; }
}
