/* ══════════════════════════════════════════
   PLANET JOURNEY — funnel-embedded (v2)
   Planets live ON the funnel: positioned children of
   #funnelContainer, mapped via FunnelUtils.svgToScreen.
   Tokens from shared.css. Illustrative scene colors
   (Earth, ship, portal) are hardcoded, consistent with
   the funnel's own SVG/legend.
   ══════════════════════════════════════════ */

/* Declutter the funnel mouth so Earth + Kontext planets sit clean on the spine */
.funnel-container [class*="idea-drift"] { display: none; }

/* Overlay for webinar spurs (lane stays implied by the funnel's flow arrows) */
.pl-svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2;
}

/* Phase → planet color binding (tokens) */
.pl-conv { --pc: var(--orange); }
.pl-p1   { --pc: var(--p1); }
.pl-p2a  { --pc: var(--p2); }
.pl-p2b  { --pc: var(--p2); }
.pl-p3   { --pc: var(--p3); }

/* Terminator shadow darkness — tuned for dark space; on the light-mode page
   background the same 0.42 alpha reads as a harsh smudge rather than a
   night-side shading, so it's lighter there. */
:root { --pl-shadow: rgba(0,0,0,0.42); }
[data-theme="light"] { --pl-shadow: rgba(0,0,0,0.22); }

/* Planets — a lit sphere: crisp terminator (day→night), bright limb highlight,
   faint atmospheric halo in the zone colour. Gently drifts (var(--float-*)). */
.pl-planet {
  position: absolute; z-index: 4; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; cursor: pointer; color: #050510;
  font-family: var(--font-mono); font-weight: 500;
  background: radial-gradient(circle at var(--hl-x, 34%) var(--hl-y, 28%),
    rgba(255,255,255,0.66) 0%,
    color-mix(in srgb, var(--pc) 88%, #fff) 24%,
    var(--pc) 50%,
    color-mix(in srgb, var(--pc) 66%, #000) 84%,
    color-mix(in srgb, var(--pc) 46%, #000) 100%);
  box-shadow:
    inset -3px -4px 8px var(--pl-shadow),
    0 0 0 1px var(--glass-8),
    0 0 16px 1px color-mix(in srgb, var(--pc) 22%, transparent);
  transition: box-shadow 0.2s ease, opacity 0.2s ease;
  animation: pl-float var(--float-dur, 9s) ease-in-out infinite;
  animation-delay: var(--float-delay, 0s);
}
/* Hover/focus = the rocket is scanning this planet: a rotating dashed radar ring
   sweeps it (no size change — we only present here). */
.pl-planet::before {
  content: ''; position: absolute; inset: -7px; border-radius: 50%;
  border: 1.5px dashed color-mix(in srgb, var(--pc) 72%, #fff);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.pl-planet:hover { z-index: 7; }
.pl-planet:hover::before, .pl-planet:focus-visible::before {
  opacity: 0.9; animation: pl-scan 3.5s linear infinite;
}
.pl-planet:hover { box-shadow:
  inset -3px -4px 8px var(--pl-shadow), 0 0 0 1px var(--glass-12),
  0 0 22px 4px color-mix(in srgb, var(--pc) 38%, transparent); }
.pl-planet:focus-visible { outline: 2px solid var(--pc); outline-offset: 4px; }
.pl-planet.is-active { box-shadow:
  inset -3px -4px 8px var(--pl-shadow), 0 0 0 2px var(--glass-15), 0 0 22px 4px var(--pc); }
.pl-planet.is-webinar { opacity: 0.45; --float-amp: 7px; --float-dur: 6s; }
.pl-planet.is-webinar:hover { opacity: 1; }

/* ── Exploration marker (premium feature) ──────────────────────────────
   A quiet residual "scan ring" left on a planet once its detail view has
   been opened (state comes from app.js's VisitedModule via localStorage,
   flipped on live by planet.js's 'bwv:planet-visited' listener). It's its
   own element — not a transform on .pl-planet/.pl-star — so it never fights
   the fixed-centering transform or the pl-float drift on the body itself.
   Its inset (-4px) also differs from the hover radar ring (::before, -7px)
   so the two read as distinct concentric rings instead of colliding when a
   visited planet is hovered/focused. Subtle by design: a faint solid ring,
   no badge/checkmark look, no layout impact (position: absolute). */
.pl-visited-mark {
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--pc) 60%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}
.pl-planet.is-visited .pl-visited-mark,
.pl-star.is-visited .pl-visited-mark {
  opacity: 0.55;
}
.pl-star .pl-visited-mark { inset: -5px; }

/* Active-phase dimming — mirrors the funnel-line dimming in style.css
   (.funnel-container.has-active .funnel-phase) so planets/stars outside the
   selected phase recede too, instead of staying full-bright while the funnel
   art behind them dims (the "leak" that broke the focus effect). */
.funnel-container.has-active .pl-planet,
.funnel-container.has-active .pl-star {
  opacity: 0.35;
  transition: opacity 0.3s ease;
}
.funnel-container.has-active .pl-planet:hover,
.funnel-container.has-active .pl-planet:focus-visible,
.funnel-container.has-active .pl-star:hover,
.funnel-container.has-active .pl-star:focus-visible {
  opacity: 0.7;
}
.funnel-container.has-active[data-milestone-phase="base"] .pl-conv,
.funnel-container.has-active[data-milestone-phase="conv"] .pl-conv,
.funnel-container.has-active[data-milestone-phase="p1"] .pl-p1,
.funnel-container.has-active[data-milestone-phase="p2a"] .pl-p2a,
.funnel-container.has-active[data-milestone-phase="p2b"] .pl-p2b,
.funnel-container.has-active[data-milestone-phase="p3"] .pl-p3 {
  opacity: 1;
}
.pl-planet .pl-num { position: relative; z-index: 2; line-height: 1; opacity: 0.5; font-weight: 500; }
@keyframes pl-scan { to { transform: rotate(360deg); } }
@keyframes pl-float {
  0%, 100% { transform: translate(-50%, -50%); }
  50%      { transform: translate(-50%, calc(-50% - var(--float-amp, 3px))); }
}

/* Per-planet surface variety — each planet looks individual but keeps its zone
   color (--pc). The ::after carries the texture and sits below the number. */
.pl-planet[class*="pl-surf-"]::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
}
.pl-planet.pl-surf-0::after { display: none; }          /* smooth */
.pl-planet.pl-surf-1::after {                            /* cratered */
  background:
    radial-gradient(circle at 64% 38%, color-mix(in srgb, var(--pc) 32%, #000) 0 11%, transparent 12%),
    radial-gradient(circle at 38% 64%, color-mix(in srgb, var(--pc) 38%, #000) 0 8%, transparent 9%),
    radial-gradient(circle at 72% 70%, color-mix(in srgb, var(--pc) 26%, #000) 0 6%, transparent 7%);
  opacity: 0.5;
}
.pl-planet.pl-surf-2::after {                            /* banded (gas giant) */
  background: repeating-linear-gradient(var(--surf-rot, 16deg),
    transparent 0 4px,
    color-mix(in srgb, var(--pc) 34%, #000) 4px 7px,
    transparent 7px 12px);
  opacity: 0.38; mix-blend-mode: soft-light;
}
.pl-planet.pl-surf-3::after {                            /* ringed */
  inset: auto; left: 50%; top: 50%; width: 165%; height: 44%;
  transform: translate(-50%, -50%) rotate(var(--surf-rot, -22deg));
  border: 2px solid color-mix(in srgb, var(--pc) 60%, transparent);
  border-bottom-color: transparent; background: none; opacity: 0.75;
}

/* Earth (home) — illustrative */
.pl-planet.is-home {
  color: #eaf6ff;
  background: radial-gradient(circle at 36% 30%, #d8f3ff, #4aa8e6 32%, #1d6fae 62%, #0c4474 100%);
  box-shadow: inset -3px -4px 9px rgba(0,0,0,0.4), 0 0 18px 3px rgba(94,160,224,0.45);
}
.pl-launch-rocket {
  position: absolute;
  z-index: 4;
  left: 64%;
  top: 14%;
  width: 132%;
  aspect-ratio: 72 / 43;
  pointer-events: none;
  transform: translate(-50%, -50%) rotate(-68deg);
  transform-origin: 50% 50%;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5));
  /* Only reveal the launch rocket while hovering/focusing Planet 1 */
  opacity: 0;
  transition: opacity 0.25s ease;
}
.pl-planet.is-home:hover .pl-launch-rocket,
.pl-planet.is-home:focus-visible .pl-launch-rocket {
  opacity: 1;
}
.pl-launch-rocket-flight {
  position: absolute;
  inset: 0;
  animation: pl-launch-idle 3.4s ease-in-out infinite;
}
.pl-launch-rocket img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.pl-launch-rocket-flame {
  position: absolute;
  left: -34%;
  top: 50%;
  height: 18%;
  transform: translateY(-50%);
  border-radius: 999px 0 0 999px;
  clip-path: polygon(0 50%, 100% 0, 86% 50%, 100% 100%);
  opacity: 0.82;
  transform-origin: right center;
  animation: pl-launch-flame 210ms ease-in-out infinite alternate;
}
.pl-launch-rocket-flame-outer {
  width: 44%;
  background: linear-gradient(90deg, transparent 0%, #ffcf6b 44%, var(--orange) 100%);
  filter: blur(0.2px) drop-shadow(0 0 7px rgba(255,130,24,0.72));
}
.pl-launch-rocket-flame-inner {
  left: -22%;
  width: 28%;
  height: 10%;
  background: linear-gradient(90deg, transparent 0%, #fff4bf 52%, #ffd06a 100%);
  opacity: 0.92;
}
.pl-planet.is-home:hover .pl-launch-rocket-flight,
.pl-planet.is-home:focus-visible .pl-launch-rocket-flight {
  animation: pl-launch-lift 620ms ease-in-out infinite alternate;
}
@keyframes pl-launch-idle {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(2px, -1px); }
}
@keyframes pl-launch-lift {
  from { transform: translate(0, 0); }
  to   { transform: translate(7px, 0); }
}
@keyframes pl-launch-flame {
  from { transform: translateY(-50%) scaleX(0.82); opacity: 0.55; }
  to   { transform: translateY(-50%) scaleX(1.08); opacity: 0.96; }
}
/* Off-lane labels (webinar pill) */
.pl-tag {
  position: absolute; z-index: 4; transform: translate(-50%, 0);
  font-family: var(--font-heading); font-weight: 700; font-size: 0.52rem;
  text-transform: uppercase; letter-spacing: 0.07em; white-space: nowrap; pointer-events: none;
  color: var(--p2); background: color-mix(in srgb, var(--p2) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--p2) 25%, transparent);
  padding: 2px 7px; border-radius: 20px;
}
.pl-tag.pl-tag-muted {
  color: var(--text-faint); background: transparent; border: none;
  font-weight: 600; font-size: 0.5rem;
}
/* Webinar pill: sits ABOVE the cluster and only fades in while a webinar planet
   is hovered (the planets themselves stay dim until then). */
.pl-tag-webinar { transform: translate(-50%, -100%); opacity: 0; transition: opacity 0.2s ease; }
#funnelContainer:has(.pl-planet.is-webinar:hover) .pl-tag-webinar { opacity: 1; }

/* Slot 17 — Your AI Base: a space station (hub, structural ring, modules),
   clearly larger than the planets and the upgrade docks. No corona, no pulse. */
.pl-star {
  position: absolute; z-index: 5; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; cursor: pointer; color: #f4ecff;
  font-family: var(--font-mono); font-weight: 600;
}
.pl-ai-base-art {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; transition: transform var(--ease-fast);
}
[data-theme="light"] .pl-ai-base-art { filter: brightness(0.82) contrast(1.15); }
.pl-star:is(:hover, :focus-visible) .pl-ai-base-art { transform: scale(1.05); }
.pl-star:hover { z-index: 8; }
.pl-star:focus-visible { outline: 2px solid var(--p3); outline-offset: 4px; }
.pl-star .pl-num { position: relative; z-index: 2; line-height: 1; opacity: 0.9; }
.pl-star-label {
  position: absolute; left: 50%; bottom: -16px; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 0.55rem; color: var(--p3); white-space: nowrap;
}

/* Ship — single travelling craft on the spine, reusing the funnel ship art
   (swaps per phase, see planet.js). Art points right; planet.js tilts it. */
.pl-ship {
  position: absolute; z-index: 6; transform: translate(-50%, -50%); pointer-events: none;
  transition: left 0.5s cubic-bezier(0.5, 0, 0.3, 1), top 0.5s cubic-bezier(0.5, 0, 0.3, 1);
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.55));
}
.pl-ship img { width: 72px; height: auto; display: block; transition: transform 0.4s ease; }
.pl-ship .pl-ship-glow {
  position: absolute; inset: -6px; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(255,85,0,0.28), transparent 68%);
}

/* Engine trail — small particles sampled off the ship's real position while
   it's mid-flight (see setShip/spawnTrail in planet.js). transform + opacity
   only; each particle removes itself from the DOM on animationend. */
.pl-ship-trail {
  position: absolute; z-index: 5; border-radius: 50%; pointer-events: none;
  transform: translate(-50%, -50%);
  animation: pl-ship-trail-fade 380ms ease-out forwards;
}
.pl-ship-trail-a {
  background: var(--orange);
  box-shadow: 0 0 4px 1px color-mix(in srgb, var(--orange) 55%, transparent);
}
.pl-ship-trail-b {
  background: var(--glass-30);
  box-shadow: 0 0 3px 1px var(--glass-15);
}
@keyframes pl-ship-trail-fade {
  0%   { opacity: 0.85; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--tdx, 0px)), calc(-50% + var(--tdy, 0px))) scale(0.4); }
}

/* Tooltip (appended to body) — a phase-tinted "scan readout" panel: glassy, blurred,
   with a coloured scan-edge and a corner bracket, to match the cockpit/scanner feel. */
.pl-tip {
  position: fixed; z-index: 60; pointer-events: none; opacity: 0;
  transition: opacity 0.14s ease; max-width: 250px;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: blur(11px) saturate(1.15); backdrop-filter: blur(11px) saturate(1.15);
  color: var(--text);
  border: 1px solid var(--glass-12);
  border-left: 2px solid color-mix(in srgb, var(--pc, var(--orange)) 72%, transparent);
  border-radius: 4px 11px 11px 4px; padding: 9px 13px 10px;
  font-size: 0.74rem; line-height: 1.36;
  box-shadow: 0 10px 34px rgba(0,0,0,0.55), 0 0 0 1px var(--glass-4),
    inset 0 0 20px color-mix(in srgb, var(--pc, var(--orange)) 7%, transparent);
}
.pl-tip::after {  /* top-right scan bracket */
  content: ''; position: absolute; top: 6px; right: 6px; width: 9px; height: 9px;
  border-top: 1.5px solid color-mix(in srgb, var(--pc, var(--orange)) 55%, transparent);
  border-right: 1.5px solid color-mix(in srgb, var(--pc, var(--orange)) 55%, transparent);
  opacity: 0.7;
}
.pl-tip .pl-tip-meta {
  font-family: var(--font-mono); font-size: 0.57rem; letter-spacing: 0.05em;
  text-transform: uppercase; display: block; margin-bottom: 3px;
  color: color-mix(in srgb, var(--pc, var(--text-faint)) 70%, var(--text-faint));
}
.pl-tip .pl-tip-phase {
  font-family: var(--font-mono); font-size: 0.6rem; font-weight: 600;
  margin-top: 5px; display: block; color: var(--pc);
}

/* Route trail — a soft dashed curve threading BEHIND the planets (replaces the old
   straight centre flow-arrow). Drawn in screen space through the lane positions. */
.pl-trail { position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2; overflow: visible; }
.pl-trail-path {
  fill: none; stroke: var(--glass-30); stroke-width: 1.5;
  stroke-dasharray: 2 9; stroke-linecap: round; opacity: 0.5;
}

/* ── Ambient gimmick: an occasional meteor ── */
.pl-deco { position: absolute; pointer-events: none; z-index: 3; }
/* Meteor: a thin bright streak that shoots across every so often. Origin +
   direction are re-rolled each cycle by planet.js (--mt/--ml start, --mrot angle,
   --mmx/--mmy travel) so the streak appears at varied positions, not one fixed
   spot. Catchable mid-flight → easter egg (a wish). */
.pl-meteor { top: var(--mt, 8%); left: var(--ml, 16%); width: 90px; height: 2px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--orange) 85%, #fff));
  border-radius: 2px; opacity: 0; transform: rotate(var(--mrot, 24deg));
  /* Base none; the keyframe flips pointer-events to `auto` only while the streak
     is bright, so it's catchable mid-flight but never a dead click-zone otherwise. */
  pointer-events: none; cursor: pointer;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--orange) 60%, transparent));
  animation: pl-meteor-shoot 13s linear infinite; }
.pl-meteor::before { /* transparent hit-pad — fattens the 2px streak into a ~28px
  catchable band so a fast-moving streak can actually be clicked */
  content: ''; position: absolute; top: -13px; bottom: -13px; left: -8px; right: -10px; }
.pl-meteor::after { content: ''; position: absolute; right: -2px; top: -1.5px;
  width: 5px; height: 5px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 8px 2px color-mix(in srgb, var(--orange) 70%, #fff); }
@keyframes pl-meteor-shoot {
  0%        { opacity: 0; pointer-events: none; transform: translate(0, 0) rotate(var(--mrot, 24deg)); }
  4%        { opacity: 0.9; pointer-events: auto; }
  16%       { opacity: 0.9; pointer-events: auto; }
  22%, 100% { opacity: 0; pointer-events: none; transform: translate(var(--mmx, 360px), var(--mmy, 160px)) rotate(var(--mrot, 24deg)); }
}
/* Caught! Fade the streak out (important beats the running animation's opacity)
   and lock it for the wish's duration. */
.pl-meteor.is-caught { opacity: 0 !important; pointer-events: none; transition: opacity 260ms ease; }
/* While a planet/star is being scanned, kill the meteor (animation:none reverts
   it to its base opacity:0) so a streak can't shoot past and distract. */
#funnelContainer:has(.pl-planet:hover, .pl-star:hover) .pl-meteor { animation: none; }

/* ── Easter-egg overlay: wish burst/bubble ──
   Appended to #funnelContainer by planet.js; self-remove after their animation. */
.pl-wish-burst {
  position: absolute; z-index: 7; transform: translate(-50%, -50%);
  font-size: 22px; line-height: 1; pointer-events: none;
  filter: drop-shadow(0 0 9px rgba(255, 200, 90, 0.95));
  animation: pl-wish-burst-pop 950ms ease-out forwards; }
@keyframes pl-wish-burst-pop {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.2) rotate(-30deg); }
  25%  { opacity: 1; transform: translate(-50%, -50%) scale(1.5) rotate(12deg); }
  60%  { opacity: 1; transform: translate(-50%, -50%) scale(1.12) rotate(0deg); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.3) rotate(0deg); }
}
.pl-wish-bubble {
  position: absolute; z-index: 7; transform: translate(-50%, -100%);
  padding: 6px 12px; border-radius: 10px;
  background: rgba(34, 22, 10, 0.94); border: 1px solid rgba(255, 190, 110, 0.6);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45), 0 0 14px rgba(255, 160, 60, 0.4);
  color: #ffe6bf; font-size: 12px; font-weight: 600; white-space: nowrap;
  pointer-events: none; opacity: 0; animation: pl-wish-bubble-pop 2.6s ease forwards; }
.pl-wish-bubble::after { content: ''; position: absolute; left: 50%; bottom: -5px;
  margin-left: -5px; width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 6px solid rgba(34, 22, 10, 0.94); }
@keyframes pl-wish-bubble-pop {
  0%   { opacity: 0; transform: translate(-50%, -100%) scale(0.6); }
  10%  { opacity: 1; transform: translate(-50%, -100%) scale(1.06); }
  16%  { opacity: 1; transform: translate(-50%, -100%) scale(1); }
  88%  { opacity: 1; transform: translate(-50%, -100%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -100%) scale(0.95); }
}

/* Sprinkled starfield — faint twinkling dots behind the whole scene (z below
   the trail). Positions/timings set per-dot in planet.js. */
.pl-starfield { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.pl-star-dot {
  position: absolute; border-radius: 50%; background: #fff;
  box-shadow: 0 0 3px 0.5px rgba(255,255,255,0.55);
  animation: pl-twinkle var(--tw-dur, 3.4s) ease-in-out infinite;
  animation-delay: var(--tw-delay, 0s);
}
@keyframes pl-twinkle {
  0%, 100% { opacity: 0.22; transform: scale(0.7); }
  50%      { opacity: 0.85; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .pl-star, .pl-planet, .pl-meteor, .pl-star-dot,
  .pl-launch-rocket-flight, .pl-launch-rocket-flame { animation: none; }
  .pl-planet:hover::before, .pl-planet:focus-visible::before { animation: none; }
  .pl-meteor { display: none; }
  .pl-ship, .pl-ship img, .pl-planet, .pl-ai-base-art { transition: none; }
  /* planet.js already gates emitTrailParticle() behind the same query, so
     this is a defensive no-op net, not the primary switch. */
  .pl-ship-trail { display: none; }
  /* Marker still shows/hides instantly via the opacity rule above — just
     without the fade-in transition. */
  .pl-visited-mark { transition: none; }
}
