/* ==========================================================================
   EMOI Production — Creative homepage
   Self-contained stylesheet (does not depend on styles.css) so the
   Professional pages (About/Services/Contact/Booking) are never affected by
   anything in here.
   ========================================================================== */

:root {
  /* Darkened back down per feedback that the lighter version lost contrast
     - noticeably darker/moodier than the previous round again, closer to
     the original near-black tone but still a plum-tinted charcoal rather
     than flat black. */
  --c-bg: #191316;
  --c-bg-soft: #251d20;
  --c-red: #ed1b45;
  --c-red-glow: rgba(237, 27, 69, 0.55);
  --c-amber: #f5a623;
  --c-amber-glow: rgba(245, 166, 35, 0.5);
  --c-cyan: #22d3ee;
  --c-cyan-glow: rgba(34, 211, 238, 0.5);
  --c-cream: #f7ede9;
  --c-gray: #9d9198;
  --c-line: rgba(247, 237, 233, 0.14);
  /* How much white tint sits over the glass tiles/cards - lower is more
     see-through, higher is more milky/opaque. Pages can override this with
     an inline style (the site-editor tool's Glass transparency slider
     writes it), so a fallback here is just the shipped default. Lowered
     again per feedback that the glass still didn't feel genuinely
     see-through into the background (paired with a lighter blur below). */
  --glass-tint: 0.05;
}

.creative-page {
  background: var(--c-bg);
  color: var(--c-cream);
  font-family: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  overflow-x: hidden;
}

/* Unlike styles.css (used by the other pages), this stylesheet never reset
   the browser's own default link underline - so every <a> on this page,
   including the top nav, was showing a plain underline the whole time,
   regardless of any custom hover effect added on top of it. */
.creative-page a { text-decoration: none; }

.creative-page * { box-sizing: border-box; }

/* ---------- Ambient drifting background ---------- */
.creative-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.creative-bg .blob {
  position: absolute;
  border-radius: 50%;
  /* filter:blur() is one of the most expensive things a browser can paint,
     roughly scaling with the square of the radius - this was 70px, on
     FIVE simultaneously-animating blobs, running on every single page
     (this background is shared site-wide), continuously, forever. That
     combination was almost certainly the main cause of the site feeling
     laggy/jerky in general, not just on any one page. Cut to 42px here
     (still a soft glow, just cheaper to render) and see below: only 3 of
     the 5 blobs still render, and will-change hints the browser to
     composite this on the GPU instead of repainting it. */
  filter: blur(42px);
  opacity: 0.35;
  animation: driftBlob 22s ease-in-out infinite;
  will-change: transform;
}
.creative-bg .blob:nth-child(1) { width: 420px; height: 420px; background: var(--c-red); top: -10%; left: -8%; animation-duration: 26s; }
.creative-bg .blob:nth-child(2) { width: 320px; height: 320px; background: #7a1630; top: 55%; right: -6%; animation-duration: 20s; animation-delay: -6s; }
.creative-bg .blob:nth-child(3) { width: 260px; height: 260px; background: #3a2a2f; bottom: -8%; left: 30%; animation-duration: 24s; animation-delay: -12s; }
/* The 4th and 5th blobs (amber/cyan accents, already the lowest-opacity
   ones) are switched off entirely rather than just shrunk - two fewer
   large blurred layers to composite every frame, on every page, adds up
   to a real chunk of the savings here. Left in the markup (not deleted)
   so this is a one-line revert if a lighter touch turns out to be enough. */
.creative-bg .blob:nth-child(4), .creative-bg .blob:nth-child(5) { display: none; }
@keyframes driftBlob {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33% { transform: translate(40px, 30px) scale(1.12); }
  66% { transform: translate(-30px, 20px) scale(0.94); }
}

/* A soft, slowly-drifting "aurora" of overlapping color pools - reads as
   atmospheric lighting moving through the scene rather than a single flat
   sweep, and stays smooth/blurred instead of showing hard gradient edges. */
.creative-bg .aurora {
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(ellipse 42% 32% at 22% 28%, rgba(34, 211, 238, 0.16), transparent 62%),
    radial-gradient(ellipse 36% 30% at 78% 18%, rgba(245, 166, 35, 0.13), transparent 62%),
    radial-gradient(ellipse 46% 36% at 58% 82%, rgba(237, 27, 69, 0.12), transparent 62%);
  /* Same reasoning as .blob above - this was blurring an element LARGER
     than the viewport (inset:-20%) by 60px, continuously animated,
     site-wide. Cut to 34px. */
  filter: blur(34px);
  animation: auroraDrift 36s ease-in-out infinite;
  mix-blend-mode: screen;
  will-change: transform;
}
@keyframes auroraDrift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25% { transform: translate(3%, -2%) scale(1.06); }
  50% { transform: translate(-2%, 3%) scale(0.97); }
  75% { transform: translate(2%, 2%) scale(1.03); }
}
@media (prefers-reduced-motion: reduce) {
  .creative-bg .blob, .creative-bg .aurora { animation: none; }
}

/* ---------- Minimal top nav ---------- */
.creative-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 22px 32px;
}
.creative-nav ul {
  list-style: none;
  display: flex;
  gap: 34px;
  margin: 0;
  padding: 0;
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: 0.01em;
}
.creative-nav a {
  color: var(--c-cream);
  opacity: 0.95;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55);
  transition: opacity 0.2s ease, color 0.2s ease;
}
.creative-nav a:hover { opacity: 1; color: var(--c-red); }
.creative-nav-toggle { display: none; background: none; border: none; color: var(--c-cream); font-size: 1.3rem; cursor: pointer; }
@media (max-width: 720px) {
  .creative-nav ul { position: fixed; top: 64px; right: 16px; left: 16px; background: var(--c-bg-soft); border-radius: 14px; flex-direction: column; gap: 4px; padding: 14px; display: none; border: 1px solid var(--c-line); }
  .creative-nav ul.open { display: flex; }
  .creative-nav ul a { display: block; padding: 8px 6px; }
  .creative-nav-toggle { display: block; }
}

/* ---------- Hero: EMOI wordmark ---------- */
.creative-hero {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 140px 20px 60px;
}
/* Rebuilt to use the ACTUAL logo artwork from frame one, not plain website
   text standing in for it. images/logo-E.png, -M.png, -O.png, -I.png are
   crops of the real uploaded logo (see EMOI-Site-Editor.html's auto-slice
   step, which splits an uploaded logo image into per-letter pieces plus an
   isolated "tittle" accent whenever it can cleanly detect that shape - E/M/
   O/I here are that real artwork, not a font). font-size is still set (to
   the same clamp() as height) purely so js/creative.js's existing
   getBoundingClientRect()+fontSize math keeps working unchanged - nothing
   here actually renders as text anymore. */
.creative-mark {
  font-size: clamp(3.2rem, 12vw, 7.5rem);
  height: clamp(3.2rem, 12vw, 7.5rem);
  position: relative;
  display: inline-flex;
  align-items: flex-end;
  animation: markFadeUp 0.9s cubic-bezier(.2,.8,.2,1) both;
}
/* height:100% here needs .ml itself to have an explicit height to resolve
   against - .creative-mark's own height is explicit (the clamp() above),
   but .ml is a flex item with align-items:flex-end (not the default
   stretch), so its height would otherwise be "auto" (sized by its own
   content, i.e. the image) - and a percentage height can't resolve against
   an auto-height parent, so it silently falls back to the image's raw
   native pixel size instead. Same bug class as .hero-logo-img hit earlier
   in this file's history; this is why the wordmark rendered oversized
   until this explicit height was added. */
.creative-mark .ml {
  height: 100%;
}
.creative-mark .ml-img {
  display: block;
  height: 100%;
  width: auto;
}
/* .dot wraps the real O artwork (a ring shape in this logo, not a filled
   letterform) plus the floating "tittle" accent that hops across the
   wordmark - see initLogoIntro() in js/creative.js. height:100% here
   (rather than leaving it to size from content) is what lets
   .mark-tittle's percentage-free, em-based position below resolve
   correctly and consistently regardless of viewport width. */
.creative-mark .dot {
  position: relative;
  display: inline-flex;
  align-items: flex-end;
  height: 100%;
}
.creative-mark .mark-tittle {
  position: absolute;
  /* Exact values measured directly from the real logo file's pixels (the
     tittle dot's true position/size relative to the O ring), not guessed -
     left is the dot's own center, top is its top edge, both in em relative
     to this same wordmark's font-size - reused identically as the hop's
     landing spot in js/creative.js (targetForLetter's O_LEFT_PCT/
     TOUCH_TOP_PCT) so there's no pop when the animation hands control back
     to this CSS default. em units (not %) on purpose: the hop temporarily
     switches this element to position:fixed, and percentage sizes/offsets
     don't survive that switch the way em units do. */
  left: 0.9031em;
  top: -0.2722em;
  width: 0.3093em;
  height: 0.3093em;
  transform: translateX(-50%);
  pointer-events: none;
  filter: drop-shadow(0 0 14px rgba(247, 237, 233, 0.5));
}
.creative-mark .mark-tittle img {
  display: block;
  width: 100%;
  height: 100%;
}
@keyframes markFadeUp {
  from { opacity: 0; transform: translateY(26px); }
  to { opacity: 1; transform: translateY(0); }
}

/* When the intro's dot lands back on the O (see initLogoIntro() in
   js/creative.js), the canvas sparks themselves flare up bigger/brighter
   for a beat (see particleField.flare() in js/creative.js - it reads a
   flareIntensity value every frame and boosts each spark's radius/alpha/
   glow) while every OTHER moving element (drifting blobs/aurora, any
   mid-hover tile animation) freezes for that same beat - "everything is
   connected" - before continuing normally. An earlier version of this used
   a full-screen white overlay flash instead; that read as the whole screen
   flashing rather than the sparks lighting up, so it was replaced. Only
   ever added on the Home page (the JS gates the whole intro on
   .creative-mark existing, which only this page has). */
.creative-page.logo-lit .creative-bg .blob,
.creative-page.logo-lit .creative-bg .aurora,
.creative-page.logo-lit .service-tile.is-animating * {
  animation-play-state: paused !important;
}
.creative-tagline {
  margin-top: 18px;
  font-size: clamp(0.95rem, 2vw, 1.15rem);
  color: var(--c-gray);
  max-width: 520px;
  animation: markFadeUp 0.9s cubic-bezier(.2,.8,.2,1) 0.15s both;
}
/* ---------- Service icon tiles ---------- */
.creative-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 22px;
  max-width: 1100px;
  width: 100%;
  margin: 64px auto 100px;
  padding: 0 20px;
}
@media (max-width: 900px) {
  .creative-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .creative-grid { grid-template-columns: 1fr; }
}

.service-tile {
  position: relative;
  /* Real, bright, see-through glass: a faint top-to-bottom highlight gradient
     plus a strong blur/saturation boost so the drifting background color and
     particles clearly show through, with a bright inset rim on the top edge
     like light catching the edge of an actual glass panel. The white tint's
     strength comes from --glass-tint (see :root above) so it's adjustable
     per page from the site-editor tool's Glass transparency slider, instead
     of a fixed baked-in number. */
  background: linear-gradient(165deg,
    rgba(255, 255, 255, calc(var(--glass-tint) * 1)),
    rgba(255, 255, 255, calc(var(--glass-tint) * 0.15)) 45%,
    rgba(255, 255, 255, calc(var(--glass-tint) * 0.45)));
  /* Lighter blur than before (was 22px) so the background's actual shapes
     and colors genuinely read through the glass instead of dissolving
     into a plain frosted haze - paired with the lower --glass-tint above. */
  backdrop-filter: blur(10px) saturate(190%) brightness(1.12);
  -webkit-backdrop-filter: blur(10px) saturate(190%) brightness(1.12);
  border: 1px solid rgba(255, 255, 255, 0.3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 0 32px rgba(255, 255, 255, 0.04), 0 8px 28px rgba(0, 0, 0, 0.25);
  border-radius: 20px;
  padding: 36px 20px 28px;
  cursor: pointer;
  overflow: hidden;
  text-align: center;
  transition: border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease, background 0.3s ease;
  animation: markFadeUp 0.9s cubic-bezier(.2,.8,.2,1) both;
}
.service-tile:nth-child(1) { animation-delay: 0.35s; }
.service-tile:nth-child(2) { animation-delay: 0.42s; }
.service-tile:nth-child(3) { animation-delay: 0.49s; }
.service-tile:nth-child(4) { animation-delay: 0.56s; }

.service-tile:hover, .service-tile:focus-visible {
  border-color: var(--c-red);
  background: linear-gradient(165deg,
    rgba(255, 255, 255, calc(var(--glass-tint) * 1.5)),
    rgba(255, 255, 255, calc(var(--glass-tint) * 0.25)) 45%,
    rgba(255, 255, 255, calc(var(--glass-tint) * 0.7)));
  transform: translateY(-6px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 18px 40px rgba(237, 27, 69, 0.22);
  outline: none;
}

/* Small particles appear while hovering, instead of any cursor-tracking
   glow/light effect (both the earlier spotlight and the jellyfish version
   were rejected). js/creative.js spawns tiny .hover-particle spans inside
   the hovered element at a steady trickle while the pointer is over it;
   this just styles/animates each one (rise + fade + gentle drift), shared
   with .service-option/.btn/.services-quicknav a in css/styles.css so the
   effect is consistent everywhere. */
.hover-particle {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  border-radius: 50%;
  width: 5px;
  height: 5px;
  opacity: 0;
  animation: hoverParticleRise 0.9s ease-out forwards;
}
@keyframes hoverParticleRise {
  0% { opacity: 0; transform: translate(0, 0) scale(0.4); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--drift-x, 0), -34px) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .hover-particle { display: none; }
}

.service-tile .tile-icon-wrap {
  position: relative;
  width: 76px;
  height: 76px;
  margin: 0 auto 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.service-tile svg { width: 42px; height: 42px; position: relative; z-index: 2; }
.service-tile svg * { transition: all 0.35s ease; }

.service-tile h3 {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 6px;
  color: var(--c-cream);
}
.service-tile p.tile-sub {
  font-size: 0.78rem;
  color: var(--c-gray);
  margin: 0;
  line-height: 1.4;
}

/* Tile 1: Event & Marketing Coordinator — checklist draws in, then the
   marketing (megaphone) and external-liaison (people) badges pop in */
.service-tile[data-service="coordinator"] .plan-line {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.35s ease;
}
.service-tile[data-service="coordinator"].is-animating .plan-line { transform: scaleX(1); }
.service-tile[data-service="coordinator"].is-animating .plan-line:nth-of-type(1) { transition-delay: 0s; }
.service-tile[data-service="coordinator"].is-animating .plan-line:nth-of-type(2) { transition-delay: 0.1s; }
.service-tile[data-service="coordinator"].is-animating .plan-line:nth-of-type(3) { transition-delay: 0.2s; }
.service-tile[data-service="coordinator"] .coord-badge {
  opacity: 0;
  transform: scale(0.4);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(.2,.8,.2,1);
}
.service-tile[data-service="coordinator"].is-animating .coord-badge { opacity: 1; transform: scale(1); }
.service-tile[data-service="coordinator"].is-animating .coord-badge-marketing { transition-delay: 0.3s; }
.service-tile[data-service="coordinator"].is-animating .coord-badge-people { transition-delay: 0.4s; }

/* Tile 2: Music / Entertainment — equalizer bars pulse */
.service-tile[data-service="music"] .eq-bar {
  transform-origin: bottom;
  transition: transform 0.3s ease;
}
.service-tile[data-service="music"].is-animating .eq-bar { animation: eqBounce 0.7s ease-in-out infinite; }
.service-tile[data-service="music"].is-animating .eq-bar:nth-child(1) { animation-delay: 0s; }
.service-tile[data-service="music"].is-animating .eq-bar:nth-child(2) { animation-delay: 0.12s; }
.service-tile[data-service="music"].is-animating .eq-bar:nth-child(3) { animation-delay: 0.24s; }
.service-tile[data-service="music"].is-animating .eq-bar:nth-child(4) { animation-delay: 0.06s; }
@keyframes eqBounce {
  0%, 100% { transform: scaleY(0.4); }
  50% { transform: scaleY(1); }
}
.music-note-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid var(--c-red);
  opacity: 0;
  transform: scale(0.7);
}
.service-tile[data-service="music"].is-animating .music-note-ring {
  animation: ringPulse 1.1s ease-out infinite;
}
@keyframes ringPulse {
  0% { opacity: 0.6; transform: scale(0.7); }
  100% { opacity: 0; transform: scale(1.6); }
}

/* Tile 3: AV Production — speaker thumps to a beat, stage light sweeps in */
.service-tile[data-service="av"] .speaker-cone {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.2s ease;
}
.service-tile[data-service="av"].is-animating .speaker-cone { animation: speakerThump 0.6s ease-in-out infinite; }
.service-tile[data-service="av"].is-animating .speaker-cone:nth-of-type(2) { animation-delay: 0.15s; }
@keyframes speakerThump {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.16); }
}
.service-tile[data-service="av"] .stage-light {
  transform-box: fill-box;
  transform-origin: 70% 15%;
  transition: transform 0.4s ease;
}
.service-tile[data-service="av"].is-animating .stage-light { animation: stageLightSweep 1.4s ease-in-out infinite; }
@keyframes stageLightSweep {
  0%, 100% { transform: rotate(-8deg); }
  50% { transform: rotate(10deg); }
}
.service-tile[data-service="av"] .light-beam {
  opacity: 0;
  transition: opacity 0.3s ease;
}
.service-tile[data-service="av"].is-animating .light-beam {
  opacity: 0.55;
  animation: beamFlicker 1.4s ease-in-out infinite;
}
@keyframes beamFlicker {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.65; }
}

/* Tile 4: Recording Studio — tape reels spin, REC light blinks */
.service-tile[data-service="studio"] .tape-reel {
  transform-box: fill-box;
  transform-origin: center;
}
.service-tile[data-service="studio"].is-animating .tape-reel { animation: reelSpin 1.8s linear infinite; }
@keyframes reelSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.service-tile[data-service="studio"] .rec-blink {
  opacity: 0.35;
  transition: opacity 0.2s ease;
}
.service-tile[data-service="studio"].is-animating .rec-blink { animation: recBlink 1s steps(2) infinite; }
@keyframes recBlink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* ---------- Click-to-navigate: a fast wormhole dive, no iframe ---------- */
/* Clicking a tile no longer pre-loads the destination in a hidden iframe
   and cross-fades into it - waiting on that second page to actually load
   was the real source of the "took a second" lag complaint, since the
   reveal could only look smooth if the destination happened to load fast
   enough to keep up with our animation timeline. Instead, this plays a
   short, self-contained "diving into a tunnel" effect entirely on the
   CURRENT page - the clicked tile rushes toward the viewer while a dark
   radial vignette rockets outward from the exact point clicked (see
   body.wormhole-active::after below, positioned via --wh-x/--wh-y) - then
   the browser does a completely normal navigation to the destination,
   which fades in from black on arrival (see .creative-page's
   pageEnterFade animation) to read as "exiting the tunnel" on the other
   side. Every animated property here is transform/opacity/filter only
   (never a layout-triggering property), so it stays GPU-composited and
   smooth at 60fps, and it's kicked off on the very next animation frame
   after the click (see navigateWithZoom() in js/creative.js) - no
   artificial startup delay before anything visibly happens. */
.service-tile.is-growing {
  transition: transform 0.5s cubic-bezier(.6, 0, .4, 1), filter 0.5s cubic-bezier(.6, 0, .4, 1), opacity 0.45s ease 0.1s;
  transform: scale(var(--grow-scale, 6));
  filter: blur(18px) brightness(1.7);
  opacity: 0;
  z-index: 501;
}
body.is-zooming > *:not(:has(.service-tile.is-growing)) {
  transition: opacity 0.35s ease;
  opacity: 0.6;
}
body.wormhole-active::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 500;
  pointer-events: none;
  background: radial-gradient(circle at var(--wh-x, 50%) var(--wh-y, 50%),
    transparent 0%,
    rgba(10, 7, 8, 0.55) 40%,
    rgba(10, 7, 8, 0.98) 75%);
  opacity: 0;
  animation: wormholeRush 0.55s cubic-bezier(.6, 0, .4, 1) forwards;
}
@keyframes wormholeRush {
  0% { opacity: 0; transform: scale(0.25); }
  35% { opacity: 1; transform: scale(1.3); }
  100% { opacity: 1; transform: scale(3); }
}
/* Every page (not just Home) fades in from black on arrival - a cheap,
   self-contained "emerging on the other side" beat that doesn't need to
   coordinate with the departure animation on the page you clicked from,
   since that page has no way of knowing how fast this one will load. */
@keyframes pageEnterFade {
  from { opacity: 0; }
  to { opacity: 1; }
}
.creative-page {
  animation: pageEnterFade 0.35s ease both;
}

/* ---------- Sparky particle constellation (see js/creative.js) ---------- */
/* A canvas-drawn field of glowing red/amber/cyan/cream sparks that drift
   slowly and connect with faint lines when they pass near each other -
   more of an actual "art piece" than a handful of floating CSS dots. */
.creative-particles-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .creative-particles-canvas { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  /* js/creative.js already skips the whole wormhole visual entirely when
     reduced motion is requested and navigates immediately - these are
     just a defensive fallback in case any of these classes end up in the
     DOM some other way. */
  .service-tile, .service-tile *, .creative-mark, .creative-tagline,
  body.is-zooming > *, body.wormhole-active::after {
    animation: none !important;
    transition: none !important;
  }
  body.wormhole-active::after { display: none !important; }
  body.is-zooming > * { opacity: 1 !important; filter: none !important; transform: none !important; }
  .creative-page { animation: none !important; }
}
