/* ===================================================================
   2026-09-01 home page 3D/animated redesign.
   Deliberately CSS-transform + vanilla-JS only (no WebGL/Three.js/canvas
   3D libraries) - every technique here has been broadly interoperable
   across Chrome/Edge/Firefox/Safari for a decade+, which matters given
   the cross-browser issues found and fixed earlier in this project.
   Every 3D transform uses the perspective() FUNCTION inline on a single
   element rather than an ancestor `perspective` property + child
   `transform-style:preserve-3d` - the latter pattern is the one with the
   more fragile cross-browser history (interacts badly with overflow/
   filter/stacking contexts on some engines); a self-contained transform
   on one element sidesteps that entirely.
   Content and layout are untouched: every rule below targets classes
   that already exist in pages/home.php - nothing here requires (or
   assumes) any markup change. All entrance/reveal effects are applied
   by home-3d.js adding classes at runtime, so with JS disabled the page
   renders exactly as it did before this file existed - nothing is ever
   hidden by CSS alone.
   =================================================================== */

/* ---------- Respect reduced-motion globally within the home page ---------- */
@media (prefers-reduced-motion: reduce) {
  .neo-home, .neo-home *, .neo-home *::before, .neo-home *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ---------- Scroll-reveal base (home-3d.js adds/removes these classes; never applied without JS) ---------- */
.reveal-3d {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .7s cubic-bezier(.22,.68,.32,1), transform .7s cubic-bezier(.22,.68,.32,1);
  will-change: transform, opacity;
}
.reveal-3d.is-revealed { opacity: 1; transform: translateY(0); }

/* ---------- Hero: ambient depth, ensure the parallax shift never spills past the section ---------- */
.neo-hero { overflow: hidden; }
.neo-hero-shade::before,
.neo-hero-shade::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  filter: blur(46px);
  opacity: .28;
  pointer-events: none;
}
.neo-hero-shade::before { width: 300px; height: 300px; background: #d5ad54; top: 8%; right: 6%; animation: neoOrbFloat 14s ease-in-out infinite; }
.neo-hero-shade::after { width: 220px; height: 220px; background: #791c2b; bottom: 12%; right: 22%; animation: neoOrbFloat 11s ease-in-out infinite reverse; }
@keyframes neoOrbFloat {
  0%, 100% { transform: translate3d(0,0,0) scale(1); }
  50% { transform: translate3d(-22px,-26px,0) scale(1.1); }
}

/* Hero copy: staggered entrance on load (always visible content, just animates in - not scroll-gated since it's the first thing on the page) */
.neo-hero-copy > * { opacity: 0; transform: translateY(22px); animation: neoHeroRise .75s cubic-bezier(.22,.68,.32,1) forwards; }
.neo-hero-copy > *:nth-child(1) { animation-delay: .05s; }
.neo-hero-copy > *:nth-child(2) { animation-delay: .18s; }
.neo-hero-copy > *:nth-child(3) { animation-delay: .32s; }
.neo-hero-copy > *:nth-child(4) { animation-delay: .46s; }
@keyframes neoHeroRise { to { opacity: 1; transform: translateY(0); } }

.neo-recognition {
  opacity: 0;
  transform: translateX(22px);
  animation: neoHeroRiseSide .8s .4s cubic-bezier(.22,.68,.32,1) forwards;
  transition: transform .25s ease-out;
  transform-style: flat;
}
@keyframes neoHeroRiseSide { to { opacity: 1; transform: translateX(0); } }
.neo-recognition > div { transition: transform .25s ease-out, background .2s ease; }
.neo-recognition > div:hover { transform: translateZ(0) scale(1.03); background: rgba(255,255,255,.05); }

.neo-scroll-cue i { animation: neoScrollBounce 1.8s ease-in-out infinite; }
@keyframes neoScrollBounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(5px); } }

/* ---------- Quick access tiles: a light lift only - the color/contrast/dropdown behaviour here was
   fixed across several rounds already and is deliberately left untouched. ---------- */
.neo-quick-tile > a { transition: transform .25s ease, background .18s ease, outline-color .18s ease; }
.neo-quick-tile > a:hover, .neo-quick-tile > a:focus { transform: translateY(-3px); }

/* ---------- Numbers: card lift + count-up target (home-3d.js animates the digits themselves) ---------- */
.neo-numbers article { transition: transform .3s ease; }
.neo-numbers article:hover { transform: translateY(-4px); }
.neo-numbers article.reveal-3d { transform: translateY(26px) rotateX(8deg); transform-origin: bottom; }
.neo-numbers article.reveal-3d.is-revealed { transform: translateY(0) rotateX(0); }

/* ---------- Programme cards: fixed-angle 3D tilt on hover/focus (single transform, no preserve-3d) ---------- */
.neo-programme {
  transition: transform .45s cubic-bezier(.22,.68,.32,1), background .22s ease, box-shadow .3s ease;
  transform: perspective(900px) rotateX(0) rotateY(0) translateZ(0);
}
.neo-programme:hover, .neo-programme:focus {
  transform: perspective(900px) rotateX(3deg) rotateY(-4deg) translateY(-6px) translateZ(0);
  box-shadow: 0 24px 46px rgba(0,0,0,.28);
}
.neo-programme.reveal-3d { transform: perspective(900px) translateY(30px) rotateX(10deg); }
.neo-programme.reveal-3d.is-revealed { transform: perspective(900px) translateY(0) rotateX(0); }

/* ---------- News / events: slide in from either side, gentle lift on hover ---------- */
.neo-news-list article, .neo-events article { transition: transform .3s ease, box-shadow .3s ease; }
.neo-news-list article:hover, .neo-events article:hover { transform: translateX(4px); }
.neo-news.reveal-3d, .neo-news-list article.reveal-3d { transform: translateX(-30px); }
.neo-news.reveal-3d.is-revealed, .neo-news-list article.reveal-3d.is-revealed { transform: translateX(0); }
.neo-events.reveal-3d, .neo-events article.reveal-3d { transform: translateX(30px); }
.neo-events.reveal-3d.is-revealed, .neo-events article.reveal-3d.is-revealed { transform: translateX(0); }

/* ---------- Campus: parallax image (home-3d.js sets transform on scroll; container already clips via existing overflow:hidden) ---------- */
.neo-campus-image img { will-change: transform; transform: scale(1.08) translate3d(0,0,0); }
.neo-campus-copy.reveal-3d { transform: translateY(30px); }
.neo-campus-copy.reveal-3d.is-revealed { transform: translateY(0); }

/* ---------- MDP grid: same tilt language as programme cards, for a consistent "3D card" feel ---------- */
.neo-mdp-grid > article {
  transition: transform .45s cubic-bezier(.22,.68,.32,1), box-shadow .3s ease;
  transform: perspective(900px) rotateX(0) rotateY(0);
}
.neo-mdp-grid > article:hover, .neo-mdp-grid > article:focus-within {
  transform: perspective(900px) rotateX(2deg) rotateY(-3deg) translateY(-5px);
  box-shadow: 0 20px 40px rgba(9,37,54,.14);
}
.neo-mdp-grid > article.reveal-3d { transform: perspective(900px) translateY(28px) rotateX(8deg); }
.neo-mdp-grid > article.reveal-3d.is-revealed { transform: perspective(900px) translateY(0) rotateX(0); }

/* ---------- Image slider: crossfade becomes a subtle 3D swing - the JS class-toggle logic is untouched,
   this only extends what CSS properties change between the two states. ---------- */
.neo-image-slide {
  transform: scale(1.05) rotateY(5deg);
  transition: opacity .55s ease, transform .85s cubic-bezier(.22,.68,.32,1);
}
.neo-image-slide.is-active { transform: scale(1) rotateY(0deg); }

/* ---------- Reduced motion: disable the interactive/ambient extras entirely, keep content static and visible ---------- */
@media (prefers-reduced-motion: reduce) {
  .neo-hero-shade::before, .neo-hero-shade::after { animation: none; opacity: .15; }
  .neo-scroll-cue i { animation: none; }
  .neo-programme, .neo-mdp-grid > article, .neo-recognition, .neo-recognition > div { transform: none !important; }
}

/* ---------- Small screens: skip the tilt/parallax intensity, keep entrance fades only ---------- */
@media (max-width: 760px) {
  .neo-programme:hover, .neo-programme:focus,
  .neo-mdp-grid > article:hover, .neo-mdp-grid > article:focus-within {
    transform: translateY(-4px);
  }
  .neo-hero-shade::before, .neo-hero-shade::after { display: none; }
}
