/* ==========================================================================
   Animations CSS
   Three.js canvas layer, z-index stacking, reduced-motion, and
   GSAP animation helper classes.

   This file loads LAST on every page, so its rules take precedence
   over main.css for the selectors used here. The animation layer is
   fully self-contained — removing this file restores the original site.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Font fix: Override missing Calibre font to prevent 404 requests.
   main.css declares @font-face for Calibre-Semibold but the woff2/woff/ttf
   files do not exist. This override uses local() only, so the browser
   either finds it locally (unlikely) or falls back — no network request.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Calibre";
  src: local("Calibre Semibold"), local("Calibre-Semibold");
  font-weight: 600;
  font-display: swap;
  font-style: normal;
}

/* --------------------------------------------------------------------------
   1. Three.js Background Canvas
   -------------------------------------------------------------------------- */

#three-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* Dark fallback so the theme color is always present, even before
     Three.js loads. The canvas (alpha: true) renders particles on top. */
  background-color: #242943;
}

#three-bg canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* --------------------------------------------------------------------------
   2. Stacking: lift ALL page content above the canvas
   --------------------------------------------------------------------------
   #wrapper in main.css has NO position/z-index — it's static.
   We give it a stacking context so every child (header, main, footer)
   is guaranteed to paint above #three-bg (z-index: 0).

   #header (z-index: 10000) and #menu (z-index: 10002) are already set
   in main.css and sit above everything.
   -------------------------------------------------------------------------- */

#wrapper {
  position: relative;
  z-index: 1;
}

#footer {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   3. Background strategy — transparent #main, layered glass effect
   --------------------------------------------------------------------------
   body keeps the dark base color (#242943) so that when #three-bg canvas
   is reduced to 60%/40% opacity on mobile, the dark theme still shows
   through instead of the browser's default white.

   #main background is transparent so #three-bg (position: fixed, behind
   everything) shows through. Particle visibility is controlled per-section
   via their own semi-transparent backgrounds (e.g. 75% opacity on
   about-me sections, 75% on cert/research items).

   All direct children of #main are given position: relative and
   z-index: 2 so they paint above the #main:after preload overlay
   (z-index: 1). This replaces the template's #main > .inner rule
   which only covered elements with the .inner class.
   -------------------------------------------------------------------------- */

body {
  background: #242943;
}

/* -- #main: transparent to reveal canvas --
   main.css sets #main { background-color: #2a2f4a } (opaque).
   We override to transparent so particles show through the semi-
   transparent section backgrounds on about-me, experience, etc. */
#main {
  background-color: transparent;
}

/* All direct children of #main must sit above #main:after (z-index: 1).
   main.css only handles #main > .inner and #main > * > .inner — pages
   like about-me.html, experience.html use custom divs (profile-section,
   experience-grid, etc.) that would otherwise lack z-index. */
#main > * {
  position: relative;
  z-index: 2;
}

/* -- #header: frosted glass effect --
   The header is a thin 3.25em bar. A slight transparency + blur lets
   particles peek through without hurting readability. */
#header {
  background-color: rgba(42, 47, 74, 0.92);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* Banner pages: header starts transparent (overlays the banner image) */
#header.alt {
  background-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* -- Fix header flicker on scroll --
   When scrolling past the banner, main.js removes .alt (making the
   header instantly visible at position: fixed) and then adds .reveal
   (which runs a slide-down animation from top: -4em). Without
   animation-fill-mode: backwards, the header flashes visible for one
   frame BEFORE the animation starts. The backwards fill-mode applies
   the animation's 0% keyframe (top: -4em; opacity: 0) immediately
   when the class is added, eliminating the flash. */
#header.reveal {
  animation-fill-mode: backwards;
}

/* -- #banner:after overlay --
   Slightly reduce the overlay opacity so particles are faintly visible
   through the banner area on index.html and projects.html.
   We set it to the FINAL desired opacity (0.75) in both normal and preload
   states so there is no flash when is-preload is removed. */
#banner:after {
  opacity: 0.75;
  transition: none;
  transition-delay: 0s;
}

/* During preload, use the same opacity — no visual change on class removal */
body.is-preload #banner:after {
  opacity: 0.75;
}

/* --------------------------------------------------------------------------
   3c. Disable template CSS preload transitions — GSAP takes over
   --------------------------------------------------------------------------
   The Forty template has its own CSS transition-based reveal system that
   fires when body.is-preload is removed. GSAP also runs entrance
   animations on the same elements, causing a visible "double-load" flicker.

   Solution: kill the template's CSS transitions on page-entrance elements
   so GSAP is the SOLE orchestrator of the reveal. We set transition: none
   here (animations.css loads last, so these override main.css).
   -------------------------------------------------------------------------- */

/* Banner pages: header, banner overlay, banner content */
#header.alt {
  transition: none;
}

#banner:after {
  transition: none;
  transition-delay: 0s;
}

#banner > .inner {
  transition: none;
}

/* Non-banner pages: #main overlay and content.
   The :after pseudo-element is a dark overlay the template fades out during
   its CSS preload reveal. Since GSAP now controls content visibility directly,
   the overlay is redundant and causes a flash when is-preload is removed
   (it jumps from opacity:1 to opacity:0 instantly). Hide it completely. */
#main:after {
  display: none;
}

#main > .inner {
  transition: none;
}

/* Interests page: #main2 — same treatment */
#main2:after {
  display: none;
}

#main2 > .container {
  transition: none;
}

/* -- #footer --
   Give the footer a very slightly translucent background so particles
   are faintly visible, matching the subtle effect on index.html. */
#footer {
  background-color: rgba(36, 41, 67, 0.93);
}

/* --------------------------------------------------------------------------
   3b. WebP image overrides
   --------------------------------------------------------------------------
   Override main.css background-image references (which use .jpg) to serve
   WebP for ~50-90% smaller file sizes. Also blocks the external
   photographylife.com URL and the missing media.jpg reference.
   -------------------------------------------------------------------------- */

/* Banner background (main.css line 3711 sets banner.jpg; main.js then
   overrides it at runtime with the portrait <img> src via inline style).
   We do NOT use !important here because main.js sets background-image
   via inline style to show the portrait photo — !important would block
   that override. */
#banner {
  background-image: url("../../images/banner.webp");
}

/* Interests page: property card images (main.css lines 4532-4558) */
/* Block the external photographylife.com default — override with none */
.property-image1 {
  background-image: none !important;
}
.col.span_1_of_3:nth-child(1) .property-image1 {
  background-image: url("../../images/art.webp") !important;
}
.col.span_1_of_3:nth-child(2) .property-image1 {
  background-image: url("../../images/music.webp") !important;
}
.col.span_1_of_3:nth-child(3) .property-image1 {
  background-image: url("../../images/botw.webp") !important;
}
.col.span_1_of_3:nth-child(1) .property-image {
  background-image: url("../../images/elden.webp") !important;
}
.col.span_1_of_3:nth-child(2) .property-image {
  background-image: url("../../images/panya_fish.webp") !important;
}
.col.span_1_of_3:nth-child(3) .property-image {
  background-image: url("../../images/food.webp") !important;
}

/* Block missing media.jpg reference (main.css line 4558) */
.property-image:nth-child(2) {
  background-image: none !important;
}

/* --------------------------------------------------------------------------
   4. Reduced Motion
   --------------------------------------------------------------------------
   Hide the canvas entirely and restore all original backgrounds for
   users who prefer reduced motion. GSAP scripts also check this
   internally, but CSS provides a guaranteed fallback.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  #three-bg {
    display: none !important;
  }

  /* Restore original backgrounds when canvas is hidden */
  body {
    background: #242943;
  }

  #main {
    background-color: #2a2f4a;
  }

  #header {
    background-color: #2a2f4a;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  #banner:after {
    opacity: 0.85;
  }

  #footer {
    background-color: transparent;
  }

  /* Ensure all content is immediately visible (no animation delays) */
  #wrapper,
  #header,
  #footer,
  #main > section,
  #main > div,
  #main2 > .container,
  #banner > .inner,
  #banner h1,
  #banner .content p,
  #banner .actions,
  .experience-card,
  .education-card,
  .cert-item,
  .research-item,
  .property-card,
  .spotlight,
  .achievements li,
  .skill-tag,
  .tag,
  .filter-btn,
  .project-card,
  .progress-card {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* --------------------------------------------------------------------------
   5. GSAP Animation Helper Classes
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   5a. Pre-animation hidden states
   --------------------------------------------------------------------------
   Hide page-entrance elements via CSS so they are invisible from first paint.
   This prevents the "content flash" where content renders visibly before
   GSAP's window.load handler can set them to opacity:0.

   GSAP's gsap.set() and timeline .to() apply inline styles that override
   these CSS rules, so once GSAP runs, it fully controls visibility.

   The noscript.css stylesheet (loaded inside <noscript>) overrides these
   back to visible for users without JavaScript.
   -------------------------------------------------------------------------- */

/* Non-banner pages: header, main sections, footer start hidden */
body.is-preload #header:not(.alt) {
  opacity: 0;
}

body.is-preload #main > section,
body.is-preload #main > div:not(#footer),
body.is-preload #main2 > .container {
  opacity: 0;
}

body.is-preload #footer {
  opacity: 0;
}

/* Banner pages: individual banner children start hidden
   (the .inner wrapper is made visible so the dark overlay isn't
   the only thing showing; GSAP animates individual children) */
body.is-preload #banner > .inner {
  opacity: 1;
  filter: none;
  transform: none;
}

body.is-preload #banner h1,
body.is-preload #banner > .inner > p,
body.is-preload #banner .content p,
body.is-preload #banner .actions {
  opacity: 0;
}

/* Elements hidden before GSAP reveals them */
.gsap-hidden {
  opacity: 0;
  visibility: hidden;
}

/* Smooth will-change hints for elements that will be animated */
.will-animate {
  will-change: transform, opacity;
}

/* --------------------------------------------------------------------------
   6. Enhanced visual polish
   -------------------------------------------------------------------------- */

/* Focus-visible states for keyboard navigation */
.button:focus-visible,
a:focus-visible,
.filter-btn:focus-visible {
  outline: 2px solid #9bf1ff;
  outline-offset: 3px;
}

/* Smooth transitions for interactive elements */
.cert-item,
.research-item,
.experience-card,
.education-card,
.achievements li,
.property-card {
  transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              box-shadow 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              background-color 0.3s ease;
}

/* Tags and pills */
.skill-tag,
.tag {
  cursor: default;
  transition: transform 0.2s ease, background-color 0.2s ease;
}

/* --------------------------------------------------------------------------
   7. Mobile adjustments
   --------------------------------------------------------------------------
   Reduce canvas opacity on smaller screens for readability.
   -------------------------------------------------------------------------- */

@media screen and (max-width: 736px) {
  #three-bg {
    opacity: 0.6;
  }
}

@media screen and (max-width: 480px) {
  #three-bg {
    opacity: 0.4;
  }

  #header {
    background-color: rgba(42, 47, 74, 0.95);
  }
}

/* --------------------------------------------------------------------------
   8. Mobile tile tap-to-reveal
   --------------------------------------------------------------------------
   Mirrors the desktop :hover effect via a JS-toggled class so that
   first tap reveals the image, second tap navigates.
   -------------------------------------------------------------------------- */

.tiles article.is-hovered:before {
  opacity: 0.25;
}
