/* =========================================================
   NO JAZZ TODAY — EASTER EGGS

   One stylesheet for optional / playful scene interactions.
   Core layout and responsive rules stay in desktop.css/mobile.css.
   ========================================================= */

/* ---------------------------------------------------------
   ASTRONAUT HOVER — DESKTOP ONLY
   Existing full-scene alternate remains scene-bound.
   --------------------------------------------------------- */

.layer-foreground-gadget {
    position: absolute;
    inset: 0;
    z-index: 41;
    width: 1672px;
    height: 941px;
    max-width: none;
    pointer-events: none;
    user-select: none;
    opacity: 0;
    transition: opacity 180ms ease-out;
}

.scene-hotspot {
    position: absolute;
    z-index: 70;
    background: transparent;
}

.hotspot-astronaut {
    left: 158px;
    top: 380px;
    width: 255px;
    height: 255px;
    cursor: pointer;
}

.hotspot-astronaut:hover ~ .layer-foreground-gadget {
    opacity: 1;
}

.layer-bottle-gadget-soft,
.layer-bottle-gadget {
    position: absolute;
    inset: 0;
    width: 1672px;
    height: 941px;
    max-width: none;
    pointer-events: none;
    user-select: none;
    opacity: 0;
}

.layer-bottle-gadget-soft {
    z-index: 42;
    transition: opacity 150ms ease-out;
}

.layer-bottle-gadget {
    z-index: 43;
    transition: none;
}

/* Existing desktop bottle/hand hotspot — values intentionally preserved. */
.hotspot-bottle {
    left: 484px;
    top: 520px;
    width: 110px;
    height: 156px;
    margin: 0;
    padding: 0;
    border: 0;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
}

/* Desktop hover = soft visual hint only. No sound. */
.hotspot-bottle:hover ~ .layer-bottle-gadget-soft {
    opacity: 1;
}

/* Strong click/tap effect. JS holds it, then adds is-fading. */
.layer-bottle-gadget.is-active,
.mobile-layer-bottle-gadget.is-active {
    opacity: 1;
    transition: none;
}

.layer-bottle-gadget.is-fading,
.mobile-layer-bottle-gadget.is-fading {
    opacity: 0;
    transition: opacity var(--bottle-fade-duration, 2000ms) ease-out;
}

/* Mobile bottle target on the 941 × 1672 logical scene.
   Touch remains tap-only. A desktop/fine-pointer browser which happens to use
   this mobile artwork receives the dedicated soft hover overlay as well. */
.mobile-bottle-hotspot {
    position: absolute;
    z-index: 70;
    left: 252px;
    top: 1179px;
    width: 78px;
    height: 128px;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

.mobile-layer-bottle-gadget-soft,
.mobile-layer-bottle-gadget {
    position: absolute;
    inset: 0;
    width: 941px;
    height: 1672px;
    max-width: none;
    pointer-events: none;
    user-select: none;
    opacity: 0;
}

.mobile-layer-bottle-gadget-soft {
    z-index: 42;
    transition: opacity 150ms ease-out;
}

.mobile-layer-bottle-gadget {
    z-index: 43;
    transition: none;
}

@media (any-hover: hover) and (any-pointer: fine) {
    .mobile-bottle-hotspot:hover ~ .mobile-layer-bottle-gadget-soft {
        opacity: 1;
    }
}

/* Never let bottle controls interfere with open menus. */
.desktop-app.compact-nav:has(.holo.desktop-menu-open) .hotspot-bottle,
#mobile-app:has(.mobile-holo.mobile-menu-open) .mobile-bottle-hotspot {
    pointer-events: none;
}

#mobile-app:has(.mobile-holo.mobile-menu-open) .mobile-layer-bottle-gadget-soft {
    opacity: 0 !important;
}

.desktop-app.compact-nav:has(.holo.desktop-menu-open) .layer-bottle-gadget-soft {
    opacity: 0 !important;
}

@media (hover: none) {
    .scene-hotspot {
        display: none;
    }
}

/* Compact desktop: keep the existing hover, but never let its hotspot
   steal clicks while the Holo menu is open. */
.desktop-app.compact-nav .scene-hotspot {
    display: block;
}

.desktop-app.compact-nav:has(.holo.desktop-menu-open) .scene-hotspot {
    pointer-events: none;
}

.desktop-app.compact-nav .layer-foreground-gadget {
    pointer-events: none;
}

/* ---------------------------------------------------------
   BLUE MOON / JAZZ MODE
   Full-scene moon PNGs remain in scene/desktop and scene/mobile.
   --------------------------------------------------------- */

.moon-gadget-layer {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: fill;
    pointer-events: none;
    user-select: none;
    opacity: 0;
    z-index: 4;
    transition: opacity 220ms ease;
}

.moon-gadget-layer.is-visible {
    opacity: 1;
}

.moon-gadget-layer.is-pulsing {
    animation: moonGadgetStrongPulse 620ms ease-out forwards;
}

@keyframes moonGadgetStrongPulse {
    0%   { opacity: 0; }
    18%  { opacity: 1; }
    58%  { opacity: 0.92; }
    100% { opacity: 0; }
}

.jazz-moon-hotspot {
    position: absolute;
    z-index: 56;
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

.jazz-moon-hotspot:focus {
    outline: none;
}

/* Mobile artwork: the visible blue moon starts at the TOP scene edge,
   continues much farther right than the old 190 px patch and also remains
   visible behind the upper-left Holo edge. Keep the target elliptical so the
   enlarged area follows the moon instead of becoming a broad rectangular
   blocker over the Holo. Coordinates are on the fixed 941 × 1672 scene. */
.jazz-moon-hotspot.is-mobile-visible-moon {
    left: 0;
    top: 0;
    width: 340px;
    height: 165px;
    border-radius: 50% 50% 46% 42%;
}

.jazz-easter-host {
    position: absolute;
    inset: 14px 16px 16px;
    z-index: 120;
    overflow: hidden;
    pointer-events: none;
    border-radius: 18px;
    border: 1px solid rgba(151, 229, 255, 0.18);
    background: linear-gradient(
        180deg,
        rgba(3, 28, 62, 0.965),
        rgba(2, 21, 49, 0.975)
    );
    box-shadow:
        inset 0 0 24px rgba(92, 210, 255, 0.055),
        0 0 10px rgba(74, 198, 242, 0.08);
    opacity: 0;
    animation: jazzHostIn 0.18s linear forwards;
}

#mobile-holo > .jazz-easter-host {
    inset: 22px 24px 26px;
    border-radius: 26px;
}

.jazz-easter-host.is-closing {
    animation: jazzHostOut 0.22s linear forwards;
}

@keyframes jazzHostIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes jazzHostOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

#desktop-holo.jazz-mode-running > .holo-nav,
#desktop-holo.jazz-mode-running > .desktop-menu-toggle,
#desktop-holo.jazz-mode-running > .desktop-compact-menu,
#desktop-holo.jazz-mode-running > .desktop-compact-home-logo,
#mobile-holo.jazz-mode-running > .mobile-menu-toggle,
#mobile-holo.jazz-mode-running > .mobile-menu,
#mobile-holo.jazz-mode-running > .mobile-home-logo {
    visibility: hidden !important;
    pointer-events: none !important;
}

.desktop-app.jazz-mode-active .navigation-bar {
    pointer-events: none;
}

/* ---------------------------------------------------------
   LIVE TOUR BUS — DESKTOP + MOBILE

   Independent Easter Egg. Both source PNGs use the exact same 2048×875
   canvas and are therefore always registered at inset:0 inside one shared
   stack. The stack owns horizontal travel only. Bus and dust get separate,
   small vertical/scale motion so their prepared canvas registration is never
   replaced by ad-hoc left/top offsets.
   --------------------------------------------------------- */

.live-bus-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    overflow: hidden;
}

.live-bus-overlay--desktop {
    z-index: 60;
}

.live-bus-overlay--mobile {
    z-index: 28;
}

.live-bus-motion {
    position: absolute;
    aspect-ratio: 2048 / 875;
    transform: translateX(-118%);
    transform-origin: 50% 100%;
    will-change: transform;
}

.live-bus-overlay--desktop .live-bus-motion {
    left: 30px;
    bottom: -70px;
    width: 900px;
}

.live-bus-overlay--mobile .live-bus-motion {
    left: -20px;
    bottom: -50px;
    width: 800px;
}

.live-bus-image,
.live-bus-dust {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: contain;
    pointer-events: none;
    user-select: none;
    transform-origin: 50% 72%;
}

.live-bus-image {
    z-index: 2;
    opacity: 1;
    filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.25));
}

.live-bus-dust {
    z-index: 3;
    opacity: 1;
}

.live-bus-overlay.is-playing {
    opacity: 1;
}

.live-bus-overlay.is-playing .live-bus-motion {
    animation: liveBusTravel 6600ms linear forwards;
}

.live-bus-overlay.is-playing .live-bus-image {
    animation: liveBusBounce 6600ms ease-in-out forwards;
}

.live-bus-overlay.is-playing .live-bus-dust {
    animation: liveBusDust 6600ms ease-in-out forwards;
}

/* Smooth travel: enter -> stand still -> leave. The horizontal movement is
   deliberately independent from the small vertical motion below. */
@keyframes liveBusTravel {
    0% {
        transform: translateX(-118%);
        animation-timing-function: cubic-bezier(.20,.70,.24,1);
    }
    30% {
        transform: translateX(0);
        animation-timing-function: linear;
    }
    68% {
        transform: translateX(0);
        animation-timing-function: cubic-bezier(.30,.03,.25,1);
    }
    100% {
        transform: translateX(120%);
    }
}

/* Bus body: small road/suspension movement while driving; perfectly still
   during the pause. No horizontal component lives here. */
@keyframes liveBusBounce {
    0%   { opacity: 1; transform: translateY(1.5px); }
    6%   { opacity: 1; transform: translateY(-1px); }
    12%  { opacity: 1; transform: translateY(1px); }
    18%  { opacity: 1; transform: translateY(-0.7px); }
    24%  { opacity: 1; transform: translateY(0.6px); }
    30%  { opacity: 1; transform: translateY(0); }
    68%  { opacity: 1; transform: translateY(0); }
    75%  { opacity: 1; transform: translateY(-1px); }
    82%  { opacity: 1; transform: translateY(1px); }
    89%  { opacity: 1; transform: translateY(-0.7px); }
    95%  { opacity: 1; transform: translateY(0.6px); }
    100% { opacity: 1; transform: translateY(0); }
}

/* Dust: travels on the same registered canvas, but breathes faster and with a
   slightly different vertical rhythm. At the stop it fades slowly to 25%,
   drifts a little, then comes back to 100% more quickly as the bus departs. */
@keyframes liveBusDust {
    0%   { opacity: 1;    transform: translateY(1px) scale(1.000, 1.000); }
    6%   { opacity: 1;    transform: translateY(-2.5px) scale(1.010, 1.016); }
    12%  { opacity: 1;    transform: translateY(1.8px) scale(1.002, 1.009); }
    18%  { opacity: 1;    transform: translateY(-2px) scale(1.013, 1.020); }
    24%  { opacity: 1;    transform: translateY(1.2px) scale(1.006, 1.012); }
    30%  { opacity: 1;    transform: translateY(0) scale(1.000, 1.000); }
    42%  { opacity: .78;  transform: translateY(-1px) scale(1.006, 1.010); }
    55%  { opacity: .52;  transform: translateY(.7px) scale(1.010, 1.014); }
    68%  { opacity: .25;  transform: translateY(-1px) scale(1.014, 1.018); }
    76%  { opacity: 1;    transform: translateY(1.8px) scale(1.007, 1.013); }
    82%  { opacity: 1;    transform: translateY(-2.5px) scale(1.015, 1.021); }
    88%  { opacity: 1;    transform: translateY(1.8px) scale(1.004, 1.011); }
    94%  { opacity: 1;    transform: translateY(-1.5px) scale(1.012, 1.018); }
    100% { opacity: 1;    transform: translateY(0) scale(1.006, 1.012); }
}

/* Firefox Desktop uses the accepted smaller 760×370 Holo plane. Keep the
   same registered PNG stack, only adapt the shared box to that Holo size. */
.desktop-app.firefox-old-holo-test #desktop-holo .live-bus-overlay--desktop {
    z-index: 120;
}

.desktop-app.firefox-old-holo-test #desktop-holo .live-bus-overlay--desktop .live-bus-motion {
    left: 0;
    bottom: -61px;
    width: 760px;
}

@media (prefers-reduced-motion: reduce) {
    .live-bus-overlay.is-playing .live-bus-motion,
    .live-bus-overlay.is-playing .live-bus-image,
    .live-bus-overlay.is-playing .live-bus-dust {
        animation-duration: 1ms !important;
    }
}

/* ---------------------------------------------------------
   CPT. JELLYFISH — DESKTOP + MOBILE

   Trigger = Cpt. Jellyfish name plate in the scene.
   Visual = Holo-level overlay so the character is clipped by the screen and
   automatically follows the existing desktop/mobile perspective.

   The three PNGs are deliberately registered in one identical box. The
   wrapper owns all travel; the frames only cross-fade. This keeps the notes,
   tie and office props stable while the bell/tentacles pulse subtly.
   --------------------------------------------------------- */

.hotspot-jellyfish,
.mobile-jellyfish-hotspot {
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* Desktop logical scene 1672 × 941. This sits over the actual Cpt. Jellyfish
   name plate and is intentionally much smaller than the astronaut hover area. */
.hotspot-jellyfish {
    /* Corrected against the accepted desktop master: the plate itself sits
       around x 387–463 / y 558–603 on the 1672×941 logical scene. */
    left: 382px;
    top: 548px;
    width: 92px;
    height: 62px;
    z-index: 90;
    pointer-events: auto;
}

/* Preserve the existing astronaut hover effect while the pointer is directly
   over the name plate hotspot. */
.hotspot-jellyfish:hover ~ .layer-foreground-gadget {
    opacity: 1;
}

/* Portrait mobile logical scene 941 × 1672. The plate sits immediately left
   of the bottle/hand area in the current artwork, so the two touch targets do
   not overlap. */
.mobile-jellyfish-hotspot {
    position: absolute;
    z-index: 72;
    left: 132px;
    top: 1124px;
    width: 106px;
    height: 72px;
}

#mobile-app:has(.mobile-holo.mobile-menu-open) .mobile-jellyfish-hotspot {
    pointer-events: none;
}

.jellyfish-easter-egg {
    position: absolute;
    inset: 0;
    z-index: 54;
    overflow: hidden;
    pointer-events: none;
    opacity: 0;
}

.jellyfish-easter-egg.is-playing {
    opacity: 1;
}

.jellyfish-motion {
    position: absolute;
    aspect-ratio: 560 / 700;
    transform-origin: 50% 58%;
    will-change: transform;
}

.jellyfish-easter-egg--desktop .jellyfish-motion {
    left: 590px;
    top: 520px;
    width: 318px;
    --jelly-mid-x: 34px;
    --jelly-mid-y: -445px;
    --jelly-late-y: -710px;
    --jelly-end-x: 92px;
    --jelly-end-y: -1035px;
}

.jellyfish-easter-egg--mobile .jellyfish-motion {
    left: 212px;
    top: 1025px;
    width: 350px;
    --jelly-mid-x: 38px;
    --jelly-mid-y: -665px;
    --jelly-late-y: -1120px;
    --jelly-end-x: 92px;
    --jelly-end-y: -1585px;
}

.jellyfish-easter-egg--mobile {
    z-index: 28;
}

.jellyfish-frame {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: contain;
    pointer-events: none;
    user-select: none;
    opacity: 0;
    filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.18));
    will-change: opacity;
}

.jellyfish-frame--base {
    opacity: 1;
}

.jellyfish-easter-egg.is-playing .jellyfish-motion {
    animation: jellyfishRise 8000ms linear forwards;
}

.jellyfish-easter-egg.is-playing .jellyfish-frame--base {
    animation: jellyfishBaseFrames 8000ms ease-in-out forwards;
}

.jellyfish-easter-egg.is-playing .jellyfish-frame--pulse1 {
    animation: jellyfishPulseOne 8000ms ease-in-out forwards;
}

.jellyfish-easter-egg.is-playing .jellyfish-frame--pulse2 {
    animation: jellyfishPulseTwo 8000ms ease-in-out forwards;
}

/* The consultant rises more slowly into the Holo, pauses slightly lower than
   before and then continues upward. During the stop the DRAWING itself remains
   the base frame only; there is no pulse-frame cross-fade. The wrapper performs
   just a very small, slow local hover so the character does not look frozen.

   43% -> 57% of 8.0 s = ~1.1 s hover window. Pulse1 belongs to the first
   ascent. Pulse2 begins only AFTER the stop, synchronized with the second ascent. */
@keyframes jellyfishRise {
    0% {
        transform: translate3d(0, 0, 0) rotate(-1.10deg) scale(.965);
    }
    16% {
        transform: translate3d(8px, -150px, 0) rotate(-.55deg) scale(.982);
    }
    30% {
        transform: translate3d(23px, -345px, 0) rotate(.42deg) scale(1.000);
    }
    43% {
        transform: translate3d(var(--jelly-mid-x), var(--jelly-mid-y), 0)
                   rotate(.55deg) scale(1.006);
    }

    /* ~1.1 second stop: base artwork stays fixed; only a tiny slow hover. */
    48% {
        transform: translate3d(var(--jelly-mid-x), var(--jelly-mid-y), 0)
                   translate3d(1px, 1px, 0) rotate(.48deg) scale(1.006);
    }
    52% {
        transform: translate3d(var(--jelly-mid-x), var(--jelly-mid-y), 0)
                   translate3d(-1px, -2px, 0) rotate(.60deg) scale(1.006);
    }
    57% {
        transform: translate3d(var(--jelly-mid-x), var(--jelly-mid-y), 0)
                   translate3d(1px, 0, 0) rotate(.52deg) scale(1.006);
    }

    76% {
        transform: translate3d(62px, var(--jelly-late-y), 0)
                   rotate(-.30deg) scale(1.016);
    }
    100% {
        transform: translate3d(var(--jelly-end-x), var(--jelly-end-y), 0)
                   rotate(.70deg) scale(1.024);
    }
}

/* Smooth A -> B -> A before the stop. During the entire stop only A/base is
   visible. After the stop the second ascent starts A -> C -> A. */
@keyframes jellyfishBaseFrames {
    0%, 10%   { opacity: 1; }
    18%, 27%  { opacity: 0; }
    36%, 58%  { opacity: 1; }
    66%, 75%  { opacity: 0; }
    84%, 100% { opacity: 1; }
}

@keyframes jellyfishPulseOne {
    0%, 10%   { opacity: 0; }
    18%, 27%  { opacity: 1; }
    36%, 100% { opacity: 0; }
}

@keyframes jellyfishPulseTwo {
    0%, 58%   { opacity: 0; }
    66%, 75%  { opacity: 1; }
    84%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .jellyfish-easter-egg.is-playing .jellyfish-motion,
    .jellyfish-easter-egg.is-playing .jellyfish-frame {
        animation-duration: 1ms !important;
    }
}

/* ---------------------------------------------------------
   CONTACT ALIEN
   Scene-level overlay, not clipped by the Holo top edge.
   It sits above the scene / Holo graphics but below menu controls,
   and pointer-events:none guarantees that navigation stays clickable.
   --------------------------------------------------------- */

.contact-easter-egg {
    position: absolute;
    z-index: 54;
    display: block;
    height: auto;
    max-width: none;
    pointer-events: none;
    user-select: none;
    opacity: 0;
    transform: translate3d(0, -118%, 0);
    transform-origin: top center;
    transition:
        transform 760ms cubic-bezier(0.22, 0.78, 0.24, 1.08),
        opacity 140ms linear;
    will-change: transform, opacity;
}

.contact-easter-egg.is-visible {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}

/* Desktop: right-biased, but safely left of the hamburger rail. */
#desktop-scene > .contact-easter-egg {
    top: -16px;
    right: 232px;
    width: 298px;
}

/* Compact desktop: move the Contact alien into the free lane left of
   hamburger/menu/scroll rail. Normal desktop positioning stays untouched. */
.desktop-app.compact-nav #desktop-scene > .contact-easter-egg {
    right: 560px;
}

/* Mobile: right-biased with a fixed safety lane for the hamburger. */
#mobile-scene > .contact-easter-egg {
    top: -10px;
    right: 250px;
    width: 262px;
}

/* Menus stay visually dominant if open. */
.desktop-app.compact-nav:has(.holo.desktop-menu-open) #desktop-scene > .contact-easter-egg,
#mobile-app:has(.mobile-holo.mobile-menu-open) #mobile-scene > .contact-easter-egg {
    opacity: 0.26;
}

@media (prefers-reduced-motion: reduce) {
    .layer-foreground-gadget,
    .layer-bottle-gadget-soft,
    .layer-bottle-gadget,
    .mobile-layer-bottle-gadget-soft,
    .mobile-layer-bottle-gadget,
    .moon-gadget-layer,
    .moon-gadget-layer.is-pulsing,
    .jazz-easter-host,
    .jazz-easter-host.is-closing,
    .contact-easter-egg {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

/* =========================================================
   TOUCH EQUIVALENT FOR DESKTOP-SCENE HOVER GAGS
   Phone landscape uses the desktop scene, so hover-only astronaut feedback
   receives a short tap state. Fine-pointer desktop hover remains unchanged.
   ========================================================= */

.layer-foreground-gadget.is-touch-active {
    opacity: 1;
}

.desktop-app.phone-landscape-scroll .hotspot-astronaut {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

@media (hover: none) {
    /* Prevent sticky :hover states after taps on touch browsers. */
    .hotspot-astronaut:hover ~ .layer-foreground-gadget,
    .hotspot-bottle:hover ~ .layer-bottle-gadget-soft {
        opacity: 0;
    }

    .layer-foreground-gadget.is-touch-active {
        opacity: 1;
    }
}


/* =========================================================
   V38 — DESKTOP EASTER EGGS STAY ACTIVE WITH COMPACT MENU OPEN

   The hotspots are on the scene, outside the Holo DOM. The compact menu
   occupies the right-hand Holo area; the playful scene hotspots remain
   usable instead of being globally disabled by menu state.
   Mobile menu blocking is intentionally unchanged.
   ========================================================= */
.desktop-app.compact-nav:has(.holo.desktop-menu-open) .scene-hotspot,
.desktop-app.compact-nav:has(.holo.desktop-menu-open) .hotspot-bottle,
.desktop-app.compact-nav:has(.holo.desktop-menu-open) .jazz-moon-hotspot {
    pointer-events: auto !important;
}

/* Keep the existing desktop bottle hover hint available as well. */
.desktop-app.compact-nav:has(.holo.desktop-menu-open)
.hotspot-bottle:hover ~ .layer-bottle-gadget-soft {
    opacity: 1 !important;
}
