/* ═══ Section headings with an icon that charge — one kit for every section page ═══
   owner: /tournaments 2026-09-29 ("รูปถ้วยรางวัลอยู่หน้าตารางแข่ง และ hover จะมีเอฟเฟคสายฟ้าแบบหน้า
   login"); 2026-09-30 /decks ("อยากให้มีไอคอนจัดเด็คเหมือนตารางแข่ง และทำเอฟเฟคคล้ายกัน") and then
   the other section pages ("ทำกับหน้าอื่นๆ ด้วย"). Markup = storefront/partials/charge-head, icons =
   storefront/partials/head-icons/<icon>. pkg-fx-charge.js drives the host's data-charge="1…4" /
   .is-strike / .is-discharge and draws the bolts (pkg-fx-charge.css, which also has the
   sf-p5-* keyframes). The login's choreography: tilt + hard shadow → jitter → red slab, white
   letters → black slab too.

   Icons move through ONE number, --lift on .sf-charge-icon: 0 at rest, 1 on hover, 2 at charge
   levels 1–2, 3 at levels 3–4. Each icon's parts compute their pose from it (see the icon
   blocks at the end), so hover gating / reduced motion / effects-off live here once. --glow =
   the icon's own light colour. */
.sf-charge-head { isolation: isolate; }
.sf-charge-head > .sf-kicker { position: relative; z-index: 1; } /* stays readable over the red slab */
.sf-charge-head h1 { margin: 0; }
.sf-charge-sub { position: relative; z-index: 1; margin: 8px 0 0; font: 600 13px/1.6 'Noto Sans Thai', sans-serif; color: var(--v2-muted); } /* above the focus lines */
.sf-charge-title { position: relative; display: inline-flex; align-items: center; gap: .26em; isolation: isolate; transform-origin: 20% 60%; transition: text-shadow .2s steps(2), transform .25s cubic-bezier(.3, 1.6, .5, 1), color .15s, scale .06s; }
.sf-charge-icon { --lift: 0; --glow: #00efff; flex: 0 0 auto; width: 1.12em; height: 1.19em; margin: -.08em 0 -.04em; overflow: visible; transform-origin: 50% 90%;
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--glow) 35%, transparent));
  transition: filter .2s, rotate .25s cubic-bezier(.3, 1.6, .5, 1), scale .25s cubic-bezier(.3, 1.6, .5, 1); }
/* every named part of an icon eases between its poses */
.sf-charge-icon [class] { transition: rotate .3s cubic-bezier(.3, 1.6, .5, 1), translate .3s cubic-bezier(.3, 1.6, .5, 1), scale .3s cubic-bezier(.3, 1.6, .5, 1), opacity .25s; }
/* hover (mouse only, motion allowed): the icon lifts and wakes up. :where keeps it at the same
   weight as the charge levels below, which come later and win while it charges. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  :where(body:not(.effects-off)) .sf-charge-title:hover .sf-charge-icon { --lift: 1; rotate: -8deg; scale: 1.06; }
}
/* red + black slabs behind the icon and word (wipe in at level 3 / 4) */
.sf-charge-title::before, .sf-charge-title::after { content: ''; position: absolute; z-index: -1; pointer-events: none; transform-origin: left center; transition: transform .22s cubic-bezier(.3, 1.4, .5, 1); }
.sf-charge-title::before { left: -16px; right: -26px; top: 8%; bottom: -8%; background: var(--p5-red); border: 4px solid var(--p5-ink); box-shadow: 10px 10px 0 var(--p5-ink); transform: skewX(-14deg) rotate(-2.5deg) scaleX(0); clip-path: polygon(0 8%, 97% 0, 100% 88%, 3% 100%); }
.sf-charge-title::after { left: 10%; right: -8px; top: 55%; bottom: -16%; background: var(--p5-ink); transform: skewX(18deg) rotate(3deg) scaleX(0); transform-origin: right center; }
/* level 1: hard offset shadow + tilt, the icon lifts and glows */
.sf-charge-head[data-charge="1"] .sf-charge-title { transform: rotate(-2deg) skewX(-4deg); text-shadow: 3px 3px 0 var(--p5-ink), 6px 6px 0 var(--p5-red); }
.sf-charge-head[data-charge] .sf-charge-icon { --lift: 2; rotate: -10deg; scale: 1.1; filter: drop-shadow(3px 3px 0 var(--p5-ink)) drop-shadow(0 0 14px color-mix(in srgb, var(--glow) 80%, transparent)); }
/* level 2: bigger offsets, stepped jitter */
.sf-charge-head[data-charge="2"] .sf-charge-title { transform: rotate(-3deg) skewX(-6deg); text-shadow: 4px 4px 0 var(--p5-ink), 8px 8px 0 var(--p5-red), -2px -2px 0 #fff3; animation: sf-p5-jitter .14s steps(2) infinite; }
/* level 3: the red slab lands, letters go white, the icon white-hot */
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-charge-title { color: #fff; text-shadow: 4px 4px 0 var(--p5-ink), 7px 7px 0 var(--p5-ink); }
.sf-charge-head[data-charge="3"] .sf-charge-title { transform: rotate(-4deg) skewX(-8deg); animation: sf-p5-shake .1s steps(2) infinite; }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-charge-title::before { transform: skewX(-14deg) rotate(-2.5deg) scaleX(1); }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-charge-icon { --lift: 3; scale: 1.16; filter: drop-shadow(3px 3px 0 var(--p5-ink)) drop-shadow(0 0 6px #fff) drop-shadow(0 0 18px var(--glow)); }
/* level 4: black slab too, heavier shake */
.sf-charge-head[data-charge="4"] .sf-charge-title { transform: rotate(-5deg) skewX(-10deg) scale(1.04); animation: sf-p5-shake .06s steps(2) infinite; }
.sf-charge-head[data-charge="4"] .sf-charge-title::after { transform: skewX(18deg) rotate(3deg) scaleX(1); }
/* impact: the heading recoils, the icon quakes */
.sf-charge-title.is-hit { scale: 1.06; }
.sf-charge-icon.is-quake { animation: sf-p5-quake .22s steps(4); }
/* halftone flash behind the heading on a strike */
.sf-charge-head::before { content: ''; position: absolute; inset: -40px -30px -30px; z-index: -1; pointer-events: none; opacity: 0;
  background: radial-gradient(circle, var(--p5-red) 32%, transparent 34%) 0 0 / 13px 13px;
  -webkit-mask-image: radial-gradient(ellipse at 30% 60%, #000 0%, #000a 30%, transparent 64%); mask-image: radial-gradient(ellipse at 30% 60%, #000 0%, #000a 30%, transparent 64%); }
.sf-charge-head.is-strike::before { animation: sf-p5-flash .22s steps(2) forwards; }
/* leaving: a red/black slash sweeps across it */
.sf-charge-head::after { content: ''; position: absolute; left: -12%; top: 34%; width: 72%; height: 52%; z-index: 6; pointer-events: none; background: linear-gradient(180deg, var(--p5-ink) 0 14%, var(--p5-red) 14% 86%, var(--p5-ink) 86%); transform: skewY(-9deg) translateX(-140%); opacity: 0; }
.sf-charge-head.is-discharge::after { animation: sf-p5-slash .5s cubic-bezier(.7, 0, .3, 1) forwards; }
@media (prefers-reduced-motion: reduce) { .sf-charge-head::after { display: none; } .sf-charge-icon, .sf-charge-icon [class] { transition: none; } }
.effects-off .sf-charge-head::after { display: none; }

/* ---------- the icons' own parts ---------- */
.sf-hi-trophy { --glow: #ffd24a; }

/* deck: a hand of three cards, each turning about a point below the hand */
.sf-hi-deck { --glow: #00efff; }
.sf-hi-deck-card { transform-box: view-box; transform-origin: 32px 74px; }
.sf-hi-deck-card.is-l { rotate: calc(-15deg - var(--lift) * 5deg); }
.sf-hi-deck-card.is-r { rotate: calc(15deg + var(--lift) * 5deg); }
.sf-hi-deck-card.is-c { translate: 0 calc(var(--lift) * -2px); }

/* gavel: raised about its grip a little more each level; slammed onto the block on a hit */
.sf-hi-gavel { --glow: #ff9f1c; }
.sf-hi-gavel-hammer { transform-box: view-box; transform-origin: 57px 44px; rotate: calc(16deg + var(--lift) * 9deg); }
.sf-hi-gavel.is-quake .sf-hi-gavel-hammer { animation: sf-hi-slam .26s ease-out; }
@keyframes sf-hi-slam { 0%, 30% { rotate: -1deg; } }

/* coins: the standing coin hops, then spins */
.sf-hi-coins { --glow: #3ee8a0; }
.sf-hi-coins-top { transform-box: fill-box; transform-origin: center; translate: 0 calc(var(--lift) * -2.5px); }
.sf-hi-coins-card { translate: calc(var(--lift) * -1px) 0; }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-hi-coins-top { animation: sf-hi-spin .45s linear infinite; }
@keyframes sf-hi-spin { 50% { scale: .12 1; } }

/* gacha: the knob turns a quarter each level, a capsule drops in the chute, the capsules rattle */
.sf-hi-gacha { --glow: #ff4fbc; }
.sf-hi-gacha-knob { transform-box: fill-box; transform-origin: center; rotate: calc(var(--lift) * 90deg); }
.sf-hi-gacha-drop { opacity: clamp(0, var(--lift), 1); translate: 0 calc((1 - clamp(0, var(--lift), 1)) * -5px); }
.sf-hi-gacha-balls { transform-box: view-box; transform-origin: 32px 22px; }
.sf-charge-head[data-charge] .sf-hi-gacha-balls { animation: sf-hi-rattle .16s steps(2) infinite; }
@keyframes sf-hi-rattle { 0% { translate: -1.4px .8px; rotate: -5deg; } 100% { translate: 1.4px -.8px; rotate: 5deg; } }

/* pack: the top crimp tears open from the right, light pours out of the gap */
.sf-hi-pack { --glow: #a78bfa; }
.sf-hi-pack-top { transform-box: view-box; transform-origin: 14px 13px; rotate: calc(var(--lift) * -7deg); }
.sf-hi-pack-light { opacity: calc(var(--lift) * .33); }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-hi-pack-light { animation: sf-hi-flicker .2s steps(2) infinite; }
@keyframes sf-hi-flicker { 50% { opacity: .55; } }

/* shop: window + door light up, the neon sign flickers while it charges */
.sf-hi-shop { --glow: #00efff; }
.sf-hi-shop-light { opacity: calc(var(--lift) * .3); }
.sf-charge-head[data-charge] .sf-hi-shop-sign { animation: sf-hi-flicker .3s steps(2) infinite; }

/* news: one wave at rest, a second and third join, then they pulse */
.sf-hi-news { --glow: #ffe45e; }
.sf-hi-news-waves .is-1 { opacity: clamp(.35, var(--lift), 1); }
.sf-hi-news-waves .is-2 { opacity: clamp(0, var(--lift) - .6, 1); }
.sf-hi-news-waves .is-3 { opacity: clamp(0, var(--lift) - 1.6, 1); }
.sf-charge-head[data-charge] .sf-hi-news-waves { animation: sf-hi-wave .24s steps(2) infinite; }
@keyframes sf-hi-wave { 50% { translate: 2.5px 0; } }

/* bag: the cards rise out of it */
.sf-hi-bag { --glow: #00efff; }
.sf-hi-bag-card.is-a { translate: calc(var(--lift) * -.8px) calc(var(--lift) * -2.4px); }
.sf-hi-bag-card.is-b { translate: calc(var(--lift) * .8px) calc(var(--lift) * -3.6px); }

/* cart (2026-10-10, owner: "ตะกร้า ที่เป็นหัวข้ออาจต้องมีรูปหรือไอคอน"): the cards pop up, the cart rolls
   forward and its wheels turn; at the top levels the wheels keep spinning */
.sf-hi-cart { --glow: #00efff; }
.sf-hi-cart-roll { translate: calc(var(--lift) * 1.4px) 0; }
.sf-hi-cart-card.is-a { translate: calc(var(--lift) * -.6px) calc(var(--lift) * -2.6px); }
.sf-hi-cart-card.is-b { translate: calc(var(--lift) * .6px) calc(var(--lift) * -3.8px); }
.sf-hi-cart-wheel { transform-box: fill-box; transform-origin: center; rotate: calc(var(--lift) * 120deg); }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-hi-cart-wheel { animation: sf-hi-wheel .45s linear infinite; }
@keyframes sf-hi-wheel { to { rotate: 360deg; } }

/* tag: swings out on its string, sways at the top levels */
.sf-hi-tag { --glow: #ff2e88; }
.sf-hi-tag-tag { transform-box: view-box; transform-origin: 32.4px 14.6px; rotate: calc(var(--lift) * -6deg); }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-hi-tag-tag { animation: sf-hi-sway .5s ease-in-out infinite alternate; }
@keyframes sf-hi-sway { from { rotate: -26deg; } to { rotate: -6deg; } }

/* gem: tilts, the sparkles grow, then twinkle */
.sf-hi-gem { --glow: #c89bff; }
.sf-hi-gem-stone { transform-box: fill-box; transform-origin: center; rotate: calc(var(--lift) * 5deg); translate: 0 calc(var(--lift) * -1.5px); }
.sf-hi-gem-spark { transform-box: fill-box; transform-origin: center; scale: clamp(.35, var(--lift) * .45, 1.2); }
.sf-hi-gem-spark.is-2 { scale: clamp(0, var(--lift) * .45 - .2, 1.2); }
.sf-hi-gem-spark.is-3 { scale: clamp(0, var(--lift) * .45 - .5, 1.2); }
.sf-charge-head[data-charge] .sf-hi-gem-spark { animation: sf-hi-twinkle .3s steps(2) infinite; }
@keyframes sf-hi-twinkle { 50% { rotate: 45deg; } }

/* lens: slides up the card, then scans across it */
.sf-hi-lens { --glow: #00efff; }
.sf-hi-lens-glass { translate: calc(var(--lift) * -2.5px) calc(var(--lift) * -3px); }
.sf-charge-head:is([data-charge="3"], [data-charge="4"]) .sf-hi-lens-glass { animation: sf-hi-scan .5s ease-in-out infinite alternate; }
@keyframes sf-hi-scan { from { translate: -13px -8px; } to { translate: -2px -12px; } }

/* bug (/play/{game}/report): legs wiggle, antenna sparks light up */
.sf-hi-bug { --glow: #ff2e88; }
/* scarab in a hex shield (2026-10-16): legs spread, eyes flare, glitch slices tear across while it charges */
.sf-hi-bug-legs .is-l { rotate: calc(var(--lift) * -5deg); transform-origin: 21px 40px; }
.sf-hi-bug-legs .is-r { rotate: calc(var(--lift) * 5deg); transform-origin: 43px 40px; }
.sf-hi-bug-eye { filter: drop-shadow(0 0 calc(var(--lift) * 1.5px) #ff2e88); }
.sf-hi-bug-glitch { opacity: 0; mix-blend-mode: screen; }
.sf-charge-head[data-charge] .sf-hi-bug-legs { animation: sf-hi-legs .2s steps(2) infinite; }
.sf-charge-head[data-charge] .sf-hi-bug-eye { animation: sf-hi-bug-eye .35s steps(2) infinite; }
.sf-charge-head[data-charge] .sf-hi-bug-glitch.is-a { animation: sf-hi-bug-glitch .9s steps(1) infinite; }
.sf-charge-head[data-charge] .sf-hi-bug-glitch.is-b { animation: sf-hi-bug-glitch .9s steps(1) -.45s infinite reverse; }
@keyframes sf-hi-legs { 50% { translate: 0 -1.5px; } }
@keyframes sf-hi-bug-eye { 50% { fill: #fff; } }
@keyframes sf-hi-bug-glitch { 0% { opacity: .85; translate: -4px 0; } 20% { opacity: 0; } 55% { opacity: .7; translate: 5px 3px; } 70% { opacity: 0; } }
