/* =============================================================================
   Dark Island — Link Tree · DEFERRED styles
   Loaded without blocking first paint. Everything here is an enhancement:
   custom fonts, the ember effect layer, depth & glow. Nothing here hides
   content that is already visible, so it is safe if it arrives late.
   ========================================================================== */

/* ---- Self-hosted brand fonts (Latin subset, swap so text is never hidden) - */
@font-face{
  font-family:'Cinzel';font-style:normal;font-weight:600 700;font-display:swap;
  src:url('../fonts/cinzel-700-normal-2.woff2') format('woff2');
}
@font-face{
  font-family:'EB Garamond';font-style:normal;font-weight:400 600;font-display:swap;
  src:url('../fonts/eb-garamond-400-normal-7.woff2') format('woff2');
}
@font-face{
  font-family:'EB Garamond';font-style:italic;font-weight:400;font-display:swap;
  src:url('../fonts/eb-garamond-400-italic-7.woff2') format('woff2');
}

/* ---- Depth: faint red glow up top, cool blue below (red+blue on black) ---- */
body::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:
    /* warm "fire" glow at the BOTTOM, where the embers rise from */
    radial-gradient(140% 95% at 50% 118%, rgba(255,59,59,.18), transparent 62%),
    /* faint cool tint up top */
    radial-gradient(130% 80% at 50% -15%, rgba(61,169,255,.06), transparent 55%);
}

/* ---- Ember particle layer (canvas injected by embers.js) ------------------ */
.embers-layer{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none;background:transparent}
.embers-layer #particles-js{position:absolute;inset:0;width:100%;height:100%}
.embers-layer canvas{position:absolute;inset:0;display:block}

/* ---- Ember burst on click / tap -------------------------------------------
   Driven by assets/js/click-burst.js (enabled by $GAME['clickBurst']). The JS
   sets --s / --ember / --glow / --o and the transform per particle; everything
   here is static. The layer never intercepts input (pointer-events:none), so
   links and buttons keep working normally underneath. */
.burst-layer{position:fixed;inset:0;z-index:40;overflow:hidden;pointer-events:none}
.burst-p{
  position:absolute;left:0;top:0;
  width:var(--s);height:var(--s);
  border-radius:12%;                       /* + the JS 45° rotate = diamond */
  background:var(--ember);
  box-shadow:0 0 6px var(--glow),0 0 14px var(--glow);
  opacity:var(--o,1);
  mix-blend-mode:screen;                   /* glows against the dark page */
  will-change:transform,opacity;
}
@media (prefers-reduced-motion:reduce){    /* belt-and-suspenders (JS also skips) */
  .burst-layer{display:none}
}

/* ---- Ornate corner ornaments on buttons (from the game page's cards) ------
   Two diagonal corners like the reference: ::before = top-right (mirrored),
   ::after = bottom-left. One light-silver filigree PNG, purely decorative. */
.link-row{position:relative}
.link-row > *{position:relative;z-index:2}      /* keep icon/label/chevron above */
.link-row::before,.link-row::after,
.link-banner::before,.link-banner::after{
  content:"";position:absolute;width:40px;height:42px;
  background:url('../img/borda.png') center/contain no-repeat;
  opacity:.9;pointer-events:none;
}
.link-row::before,.link-banner::before{top:-5px;right:-5px;transform:scale(-1,-1)} /* top-right */
.link-row::after,.link-banner::after{bottom:-5px;left:-5px}                        /* bottom-left */
.link-row::before,.link-row::after{z-index:1}       /* behind the row's own content */
.link-banner::before,.link-banner::after{z-index:3} /* on top of the full-bleed image + caption */

/* ---- Polish + animation on the primary CTA ------------------------------- */
/* Pulsing ember glow, plus a gentle "go" nudge on the chevron. */
@keyframes ctaGlow{
  0%,100%{box-shadow:0 6px 26px rgba(255,59,59,.12)}
  50%    {box-shadow:0 10px 42px rgba(255,59,59,.40)}
}
@keyframes ctaChev{
  0%,100%{transform:translateX(0)}
  50%    {transform:translateX(5px)}
}
.link-primary{box-shadow:0 8px 30px rgba(255,59,59,.10);animation:ctaGlow 2.4s ease-in-out infinite}
.link-primary .link-chev{animation:ctaChev 1.6s ease-in-out infinite}
.ic-img{transition:filter .15s ease, transform .15s ease}
@media (hover:hover){
  .link-primary:hover{box-shadow:0 10px 42px rgba(255,59,59,.34)}
  .link-row:hover .link-chev{color:var(--accent)}
  .link-row:hover .link-ic{color:var(--accent)}
  /* Image icons (the affiliate logos) ignore `color`, so the SVG hover recolor
     above never touches them. Give them an accent glow + slight lift instead;
     the white-filtered logo keeps its recolor while it glows. */
  .link-row:hover .ic-img{filter:drop-shadow(0 0 6px var(--accent));transform:scale(1.1)}
  .link-row:hover .ic-white{filter:brightness(0) invert(1) drop-shadow(0 0 6px var(--accent));transform:scale(1.1)}
}
@media (prefers-reduced-motion:reduce){
  .link-primary,.link-primary .link-chev{animation:none}
}

/* ---- On-sale row (opt-in via 'sale' => '50% OFF' in config.php) -----------
   Looks like a normal filigree-framed row; the differences are a small
   '50% OFF' tag pinned to the top-right corner (which takes over that corner's
   ornament) and the bottom-left filigree ornament glowing orange + pulsing
   ("blink"). Holds a static glow under reduced motion. */
.link-row.is-sale::before{display:none}   /* the tag owns the top-right corner */
.link-row.is-sale::after{
  animation:saleOrnament 1.1s ease-in-out infinite;
}
@keyframes saleOrnament{
  0%,100%{filter:drop-shadow(0 0 2px rgba(255,106,18,.3))}
  50%    {filter:drop-shadow(0 0 5px #ff9a3c) drop-shadow(0 0 13px rgba(255,106,18,.95)) drop-shadow(0 0 26px rgba(255,90,10,.6))}
}
.link-row .sale-tag{
  position:absolute;top:0;right:0;z-index:4;
  font-family:var(--font-body);font-weight:700;font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;background:linear-gradient(135deg,#ff8a1e,#b81000);
  padding:.18rem .5rem;border-radius:0 0 0 9px;
  box-shadow:0 1px 6px rgba(0,0,0,.5),0 0 12px rgba(255,106,18,.55);
}
@media (prefers-reduced-motion:reduce){
  .link-row.is-sale::after{animation:none;filter:drop-shadow(0 0 6px rgba(255,106,18,.85))}
}

/* ---- Slow-spinning radial ornament on the hero CTA ----------------------
   Copied from the game page's Steam "wishlist band": a large filigree disc
   that peeks from the bottom-right corner and rotates once every 90s. The
   .link-radial span is an inner clip (inset:0 + overflow:hidden) so the disc
   stays inside the button and never adds horizontal scroll — and because the
   clip is a child, the corner ornaments (which sit slightly OUTSIDE the button
   on ::before/::after) are left untouched. */
@keyframes radial-spin{to{transform:rotate(360deg)}}
.link-primary .link-radial{
  position:absolute;inset:0;z-index:0;     /* below ornaments (1) and content (2) */
  overflow:hidden;pointer-events:none;
}
.link-primary .link-radial::before{
  content:"";position:absolute;
  right:-160px;bottom:-125px;
  width:300px;height:300px;
  /* The original golden filigree mandala, recolored to a white silhouette.
     Re-encoded at display resolution (~58 KB vs the 141 KB source) so it stays
     faithful at the 300px it renders, without the full-size asset weight. */
  background:url('../img/radial.webp?v=17') center/contain no-repeat;
  /* brightness(0) flattens the golden art to black, invert(1) → white; alpha kept. */
  filter:brightness(0) invert(1);
  opacity:.8;
  animation:radial-spin 90s linear infinite;
}
@media (prefers-reduced-motion:reduce){
  .link-primary .link-radial::before{animation:none}
}

/* ---- Brand logo fade-in (JS adds .logo-ready once the image loads) -------- */
@keyframes brandIn{from{opacity:0}to{opacity:1}}
.brand.logo-ready .brand-logo{animation:brandIn .5s ease both}

/* ---- A touch more character on the tabs ---------------------------------- */
.tab.is-active{box-shadow:inset 0 -2px 0 var(--accent)}

@media (prefers-reduced-motion:reduce){
  .brand.logo-ready .brand-logo{animation:none}
}

/* ---- Popups (Main Questions / Patreon) --------------------------------- */
.modal{
  position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;
  padding:max(1.6rem,env(safe-area-inset-top)) 1.35rem max(1.6rem,env(safe-area-inset-bottom));
}
.modal[hidden]{display:none}
.modal-backdrop{position:absolute;inset:0;background:#0000007d;opacity:0;transition:opacity .25s ease}
.modal.open .modal-backdrop{opacity:1}
.modal-sheet{
  position:relative;width:100%;max-width:520px;max-height:86vh;
  overflow-y:auto;overflow-x:hidden;                 /* never scroll sideways */
  background:var(--bg-soft);border:1px solid var(--card-edge);border-top:3px solid var(--accent);
  padding:1.5rem 1.15rem 1.6rem;-webkit-overflow-scrolling:touch;
  opacity:0;transform:translateY(10px) scale(.97);transition:opacity .25s ease,transform .25s ease;
}
.modal.open .modal-sheet{opacity:1;transform:none}
.modal-head{position:relative;text-align:center;padding:0 2.2rem .85rem;border-bottom:1px solid var(--card-edge);margin-bottom:.5rem}
.modal-title{font-family:var(--font-head);font-weight:700;letter-spacing:.03em;font-size:1.3rem;line-height:1.2}
.modal-sub{color:var(--muted);font-size:.78rem;letter-spacing:.09em;text-transform:uppercase;margin-top:.3rem}
.modal-x{
  position:absolute;top:.15rem;right:.15rem;z-index:2;width:44px;height:44px;
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:0;color:var(--muted);font-size:1.9rem;line-height:1;
  cursor:pointer;touch-action:manipulation;transition:color .15s;
}
.modal-x:hover,.modal-x:active{color:var(--text)}
.modal-body{font-size:1.02rem;overflow-wrap:break-word;word-break:break-word}
.modal-body p{margin:0 0 .85rem}
.modal-body p:last-child{margin-bottom:0}
.modal-list{list-style:none;margin:.2rem 0 .2rem;padding:0}
.modal-list li{position:relative;padding:.2rem 0 .2rem 1.1rem}
.modal-list li::before{content:"";position:absolute;left:0;top:.85em;width:6px;height:6px;background:var(--accent)}
.modal-foot{margin-top:1.4rem}
.modal-cta{
  display:inline-flex;align-items:center;gap:.5rem;
  background:var(--accent);color:#140a0a;font-family:var(--font-head);font-weight:700;letter-spacing:.03em;
  padding:.8rem 1.5rem;text-decoration:none;border:0;cursor:pointer;transition:background .15s;touch-action:manipulation;
}
.modal-cta:hover{color:#140a0a}
.modal-cta:active{background:var(--accent-press)}

/* FAQ accordion */
.faq-item{border-bottom:1px solid var(--card-edge)}
.faq-item summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:1rem .15rem;font-family:var(--font-head);font-weight:600;letter-spacing:.01em;font-size:1rem;
  touch-action:manipulation;transition:color .15s;
}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{
  content:"";flex:0 0 auto;width:10px;height:10px;margin-right:.25rem;
  border-right:2px solid var(--accent-2);border-bottom:2px solid var(--accent-2);
  transform:rotate(45deg);transition:transform .2s ease;
}
.faq-item[open] summary{color:var(--accent-2)}
.faq-item[open] summary::after{transform:rotate(-135deg)}
.faq-a{color:var(--muted);padding:0 .15rem 1.1rem;line-height:1.55}
/* Smooth open/close. Modern browsers animate the height via ::details-content;
   everywhere else the answer still fades in on open. Degrades to an instant
   toggle if neither is supported. */
:root{interpolate-size:allow-keywords}
.faq-item::details-content{
  block-size:0;overflow:hidden;
  transition:block-size .28s ease,content-visibility .28s allow-discrete;
}
.faq-item[open]::details-content{block-size:auto}
.faq-item[open] .faq-a{animation:faqReveal .3s ease both}
@keyframes faqReveal{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){
  .faq-item::details-content{transition:none}
  .faq-item[open] .faq-a{animation:none}
}

@media (min-width:600px){
  .modal{padding:1.5rem}
  .modal-sheet{max-height:85vh}
}
@media (prefers-reduced-motion:reduce){
  .modal-backdrop,.modal-sheet{transition:none}
  .modal-sheet{opacity:1;transform:none}
}

/* ============================================================================
   LOGO IGNITE  ·  optional molten intro for the brand logo
   ----------------------------------------------------------------------------
   Enabled by $GAME['logoIgnite'] (config.php), which loads
   assets/js/logo-ignite.js. That script adds `.logo-ignite` to `.brand` once,
   on open — it injects the crack SVG and starts the ambient background embers
   (only AFTER the burst). Self-disables under reduced
   motion.
   Sequence (3 beats): dim grey stone -> BURST at 0.2 (fully cracked + in flames,
   the background embers surge to 5x) -> cools back to the white logo.
   Tweak the look with the --ig-* vars below; duration is the single source of
   truth (the JS reads --ig-dur). To remove: delete this block, that JS file,
   and the config flag.
   NOTE: the mask URL must match $GAME['logo'] (relative to THIS file).
   ========================================================================== */
:root{
  --ig-dur:4s;          /* total length; the JS reads this for the burst/ember beats */
  --ig-amber:#ff6a12;   /* THE single fire hue — depth comes from brightness, not more hues */
}
.brand-logo{position:relative}   /* anchor for the molten/crack/ember layers */

/* (1) MOLTEN body — logo shape filled with lava. Snaps bright at the burst, then
   the brightness filter cools it to dark molten rock, then it fades so the plain
   white base logo remains. */
.brand.logo-ignite .brand-logo::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  -webkit-mask:url('../img/logo.svg') center/contain no-repeat;
          mask:url('../img/logo.svg') center/contain no-repeat;
  /* Same amber hue top-to-bottom, only lightness varies -> no hue seams. */
  background:linear-gradient(0deg,#d2560e,var(--ig-amber) 55%,#ff8f3a);
  background-size:100% 240%;
  animation:igMolten var(--ig-dur) ease-out both,
            igLava calc(var(--ig-dur) * .8) linear both;
}
@keyframes igLava{ from{background-position:50% 100%} to{background-position:50% 20%} }
@keyframes igMolten{
  0%,15% {opacity:0;filter:brightness(1.8) saturate(1.3)}  /* no flames during the grey hold */
  20%    {opacity:1;filter:brightness(1.9) saturate(1.4)}  /* BURST: full flames, snapped on */
  45%    {opacity:1;filter:brightness(1.1) saturate(1.1)}  /* cooling */
  100%   {opacity:0;filter:brightness(.6) saturate(.9)}    /* fade -> white base */
}

/* (2) CRACKS — bright lava fissures glinting through the cooling rock. The JS
   injects + measures the paths (each gets --len); masked to the logo shape.
   Drawn on just after the burst, then dimmed as everything cools. */
.logo-cracks{
  position:absolute;inset:0;z-index:3;pointer-events:none;
  -webkit-mask:url('../img/logo.svg') center/contain no-repeat;
          mask:url('../img/logo.svg') center/contain no-repeat;
  animation:igCrackShow var(--ig-dur) ease-out both;
}
.logo-cracks svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.logo-crack{
  fill:none;stroke:#ff8f3a;stroke-width:4;   /* lighter amber so the crack glints */
  stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
  filter:drop-shadow(0 0 3px var(--ig-amber)) drop-shadow(0 0 6px var(--ig-amber));
  animation:igCrack calc(var(--ig-dur) * .17) ease-out both;
  animation-delay:calc(var(--ig-dur) * .04);          /* fully cracked by the 0.2 burst */
}
@keyframes igCrack{ to{stroke-dashoffset:0} }          /* draw the crack on */
@keyframes igCrackShow{ 0%,4%{opacity:0} 12%{opacity:1} 55%{opacity:.8} 100%{opacity:0} }

/* (3) GLOW — the whole-logo arc: dim grey stone -> heat -> burst pop/flash -> white. */
.brand.logo-ignite .brand-logo{ animation:igGlow var(--ig-dur) ease-out both }
@keyframes igGlow{
  0%,12% {transform:scale(1);    filter:brightness(.32) saturate(.35)}   /* dim grey stone (held) */
  16%    {transform:scale(1.04); filter:brightness(1) saturate(1) drop-shadow(0 0 12px var(--ig-amber))}   /* fast ignite */
  20%    {transform:scale(1.16); filter:brightness(2.6) drop-shadow(0 0 40px #fff) drop-shadow(0 0 84px var(--ig-amber))}   /* BURST: white-hot core, amber halo */
  28%    {transform:scale(1);    filter:brightness(1.15) drop-shadow(0 0 18px var(--ig-amber))}
  55%    {transform:scale(1);    filter:drop-shadow(0 0 8px var(--ig-amber))}
  100%   {transform:scale(1);    filter:none}   /* white */
}

@media (prefers-reduced-motion:reduce){   /* belt-and-suspenders (JS also skips) */
  .brand.logo-ignite .brand-logo,
  .brand.logo-ignite .brand-logo::before,
  .logo-cracks,.logo-crack{animation:none}
  .brand.logo-ignite .brand-logo::before,.logo-cracks{opacity:0}
}
