// dive-in.jsx — depth-scrolling immersive feature.
// Adaptation: dataset has no water-layer field, so layers are bucketed by habitat
// (Saltwater on top → Brackish in middle → Freshwater at depth). The metaphor is
// "different waters, descending in salinity" rather than literal depth.

function DiveBg({ depth }) {
  const top = `oklch(${0.42 - depth * 0.30} 0.10 ${220 - depth * 10})`;
  const mid = `oklch(${0.22 - depth * 0.18} 0.07 ${225 - depth * 8})`;
  const bot = `oklch(${0.08 - depth * 0.06} 0.03 230)`;
  return (
    <div style={{
      position: 'absolute', inset: 0, pointerEvents: 'none',
      background: `linear-gradient(180deg, ${top} 0%, ${mid} 55%, ${bot} 100%)`,
      transition: `background 1.2s ${VI.ease}`,
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        opacity: Math.max(0, 0.45 - depth * 0.7),
        background: `
          radial-gradient(ellipse 700px 140px at 28% -8%, rgba(255,255,255,0.5), transparent 70%),
          radial-gradient(ellipse 480px 90px at 70% -4%, rgba(180,230,240,0.35), transparent 70%),
          radial-gradient(ellipse 380px 70px at 50% 6%, rgba(220,250,255,0.25), transparent 70%)
        `,
        animation: 'ctx-pulse 5s infinite',
      }}/>
      {Array.from({ length: 28 }).map((_, i) => (
        <div key={i} style={{
          position: 'absolute',
          left: `${(i * 53) % 100}%`,
          top: `${(i * 37) % 100}%`,
          width: i % 5 === 0 ? 3 : 1.5,
          height: i % 5 === 0 ? 3 : 1.5,
          borderRadius: 99,
          background: `rgba(255,255,255,${0.15 + (i % 4) * 0.08})`,
          animation: `ctx-float ${5 + (i % 6)}s infinite ${VI.ease}`,
          animationDelay: `${(i * 0.27)}s`,
        }}/>
      ))}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse 100% 80% at 50% 50%, transparent 50%, rgba(0,0,0,0.35) 100%)',
      }}/>
    </div>
  );
}

function DiveSchools({ density = 1 }) {
  const all = [
    { y: 8,  dur: 26, delay: 0,    flip: false, scale: 0.45, opacity: 0.18 },
    { y: 22, dur: 32, delay: -10,  flip: true,  scale: 0.7,  opacity: 0.22 },
    { y: 36, dur: 28, delay: -4,   flip: false, scale: 0.55, opacity: 0.30 },
    { y: 48, dur: 42, delay: -22,  flip: true,  scale: 1.0,  opacity: 0.16 },
    { y: 60, dur: 30, delay: -8,   flip: false, scale: 0.5,  opacity: 0.25 },
    { y: 72, dur: 36, delay: -16,  flip: true,  scale: 0.8,  opacity: 0.18 },
    { y: 84, dur: 24, delay: -2,   flip: false, scale: 0.4,  opacity: 0.22 },
    { y: 92, dur: 44, delay: -28,  flip: true,  scale: 0.9,  opacity: 0.14 },
  ];
  const swimmers = all.slice(0, Math.max(2, Math.round(all.length * density)));
  return (
    <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'hidden' }}>
      {swimmers.map((s, i) => (
        <div key={i} style={{
          position: 'absolute', left: 0, right: 0, top: `${s.y}%`,
          height: 0,
          animation: `ctx-swim ${s.dur}s linear infinite`,
          animationDelay: `${s.delay}s`,
        }}>
          <div style={{
            transform: `scale(${s.scale}) ${s.flip ? 'scaleX(-1)' : ''}`,
            opacity: s.opacity, filter: 'blur(0.6px)',
          }}>
            <svg width="64" height="22" viewBox="0 0 64 22">
              <ellipse cx="22" cy="11" rx="22" ry="6.5" fill="rgba(255,255,255,0.55)"/>
              <path d="M 42 11 L 60 2 L 60 20 Z" fill="rgba(255,255,255,0.55)"/>
              <ellipse cx="14" cy="9" rx="4" ry="2.5" fill="rgba(255,255,255,0.18)"/>
              <circle cx="9" cy="9" r="1.2" fill="rgba(0,20,40,0.5)"/>
            </svg>
          </div>
        </div>
      ))}
    </div>
  );
}

function DiveLightShafts({ depth }) {
  if (depth > 0.65) return null;
  const op = Math.max(0, 0.3 - depth * 0.45);
  return (
    <div style={{
      position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'hidden',
      opacity: op, mixBlendMode: 'screen',
    }}>
      {[20, 42, 66, 84].map((x, i) => (
        <div key={i} style={{
          position: 'absolute', top: -60, left: `${x}%`,
          width: 80, height: '60%',
          transform: `rotate(${(i % 2 ? 8 : -10)}deg)`,
          background: 'linear-gradient(180deg, rgba(180,230,240,0.5) 0%, transparent 100%)',
          filter: 'blur(14px)',
          animation: `ctx-pulse ${6 + i}s infinite ${VI.ease}`,
        }}/>
      ))}
    </div>
  );
}

function DiveTransition({ intensity = 'strong', onDone }) {
  const [phase, setPhase] = React.useState(0);
  React.useEffect(() => {
    if (intensity === 'off') { onDone?.(); return; }
    const dur = intensity === 'strong' ? [60, 480, 800] : [40, 280, 480];
    const t1 = setTimeout(() => setPhase(1), dur[0]);
    const t2 = setTimeout(() => setPhase(2), dur[0] + dur[1]);
    const t3 = setTimeout(() => { setPhase(3); onDone?.(); }, dur[0] + dur[1] + dur[2]);
    return () => { clearTimeout(t1); clearTimeout(t2); clearTimeout(t3); };
  }, [intensity]);

  if (intensity === 'off' || phase === 3) return null;
  const big = intensity === 'strong';

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 200, pointerEvents: 'none', overflow: 'hidden',
    }}>
      {phase >= 1 && (
        <>
          {[0, 1, 2].map(i => (
            <div key={i} style={{
              position: 'absolute',
              left: '50%', top: '38%',
              width: 30, height: 30, marginLeft: -15, marginTop: -15,
              borderRadius: '50%',
              border: `1px solid ${VI.accent}`,
              animation: `dv-ripple ${big ? 1.3 : 0.7}s ${VI.ease} ${i * 0.13}s forwards`,
              opacity: 0,
            }}/>
          ))}
        </>
      )}

      {phase >= 1 && (
        <div style={{
          position: 'absolute', inset: 0,
          background: `
            linear-gradient(180deg,
              oklch(0.42 0.10 220) 0%,
              oklch(0.22 0.07 225) 55%,
              oklch(0.08 0.03 230) 100%)
          `,
          transform: phase >= 2 ? 'translateY(0)' : 'translateY(-100%)',
          transition: `transform ${big ? 0.7 : 0.4}s cubic-bezier(.55,0,.25,1)`,
        }}>
          {phase >= 2 && Array.from({ length: big ? 18 : 8 }).map((_, i) => (
            <div key={i} style={{
              position: 'absolute',
              left: `${(i * 17) % 100}%`,
              bottom: '-10%',
              width: 4 + (i % 4) * 2, height: 4 + (i % 4) * 2,
              borderRadius: 99,
              background: 'rgba(255,255,255,0.5)',
              boxShadow: '0 0 4px rgba(255,255,255,0.6)',
              animation: `dv-bubble ${0.6 + (i % 5) * 0.15}s ${VI.ease} ${i * 0.04}s forwards`,
              opacity: 0,
            }}/>
          ))}
        </div>
      )}

      {phase === 1 && (
        <div style={{
          position: 'absolute', inset: 0,
          background: `radial-gradient(ellipse 60% 30% at 50% 38%, ${VI.accent}55, transparent 70%)`,
          animation: `ctx-fadeIn .2s ${VI.ease}, dv-fadeOut .4s ${VI.ease} .2s forwards`,
        }}/>
      )}

      <style>{`
        @keyframes dv-ripple {
          0%   { transform: scale(1);  opacity: 0.9; }
          100% { transform: scale(${big ? 28 : 16}); opacity: 0; }
        }
        @keyframes dv-bubble {
          0%   { transform: translateY(0) scale(0.6); opacity: 0; }
          20%  { opacity: 0.9; }
          100% { transform: translateY(-120%) scale(1); opacity: 0; }
        }
        @keyframes dv-fadeOut { to { opacity: 0; } }
      `}</style>
    </div>
  );
}

function DiveDepthGauge({ depth, layer }) {
  const meters = Math.round(depth * 200);
  return (
    <div style={{
      position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)',
      zIndex: 6, height: 240, width: 44, pointerEvents: 'none',
      display: 'flex', flexDirection: 'column', alignItems: 'center',
    }}>
      <div style={{
        fontFamily: VI.fontMono, fontSize: 8.5, color: 'rgba(255,255,255,0.65)',
        letterSpacing: '0.16em', marginBottom: 6,
      }}>0m</div>
      <div style={{
        flex: 1, width: 2, background: 'rgba(255,255,255,0.16)', borderRadius: 99,
        position: 'relative',
      }}>
        {[0.05, 0.30, 0.85].map((t, i) => (
          <div key={i} style={{
            position: 'absolute', left: -3, top: `${t * 100}%`,
            width: 8, height: 1, background: 'rgba(255,255,255,0.35)',
          }}/>
        ))}
        <div style={{
          position: 'absolute', left: -7, top: `${depth * 100}%`,
          transform: 'translateY(-50%)',
          width: 16, height: 16, borderRadius: 99, background: VI.accent,
          boxShadow: `0 0 14px ${VI.accent}, 0 0 0 2px rgba(255,255,255,0.18)`,
          transition: `top .25s ${VI.ease}`,
        }}/>
        <div style={{
          position: 'absolute', right: 16, top: `${depth * 100}%`,
          transform: 'translateY(-50%)',
          padding: '2px 6px', borderRadius: 4,
          background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(6px)',
          border: '0.5px solid rgba(255,255,255,0.18)',
          fontFamily: VI.fontMono, fontSize: 9, color: '#fff',
          letterSpacing: '0.06em', whiteSpace: 'nowrap',
        }}>{meters}m</div>
      </div>
      <div style={{
        fontFamily: VI.fontMono, fontSize: 8.5, color: 'rgba(255,255,255,0.65)',
        letterSpacing: '0.16em', marginTop: 6,
      }}>200m</div>
      <div style={{
        marginTop: 8, fontFamily: VI.fontMono, fontSize: 8, color: VI.accent,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        writingMode: 'vertical-rl', transform: 'rotate(180deg)',
        position: 'absolute', right: -18, top: '50%',
      }}>{layer}</div>
    </div>
  );
}

function DiveSoundIndicator({ depth }) {
  const labels = [
    [0.25, 'Wave wash · gulls'],
    [0.55, 'Muffled current'],
    [0.85, 'Deep rumble'],
    [1.01, 'Silent · pressure'],
  ];
  const cur = labels.find(([t]) => depth < t)?.[1] || 'Silent';
  return (
    <div style={{
      position: 'absolute', left: 14, top: 14, zIndex: 6,
      display: 'flex', alignItems: 'center', gap: 7,
      padding: '6px 10px', borderRadius: 99,
      background: 'rgba(0,0,0,0.42)', backdropFilter: 'blur(12px)',
      border: '0.5px solid rgba(255,255,255,0.18)',
      pointerEvents: 'none',
    }}>
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.2" strokeLinecap="round">
        <path d="M11 5 L6 9 H3 V15 H6 L11 19 Z"/>
        <path d="M16 9 Q18 12 16 15" opacity="0.7"/>
        <path d="M19 6 Q22 12 19 18" opacity="0.4"/>
      </svg>
      <span style={{
        fontFamily: VI.fontMono, fontSize: 8.5, color: 'rgba(255,255,255,0.85)',
        letterSpacing: '0.1em', textTransform: 'uppercase',
      }}>{cur}</span>
    </div>
  );
}

function DiveLayerBand({ layer, fish, idx, onOpen, accent }) {
  return (
    <section style={{ padding: '60px 0 40px', position: 'relative' }}>
      <div className="ctx-fadeUp" style={{ padding: '0 24px', marginBottom: 28 }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8,
        }}>
          <div style={{ width: 24, height: 1, background: accent }}/>
          <span style={{
            fontFamily: VI.fontMono, fontSize: 9.5, color: accent,
            letterSpacing: '0.22em', textTransform: 'uppercase',
          }}>0{idx + 1} / {layer.depth}</span>
        </div>
        <h2 style={{
          margin: 0, fontFamily: VI.fontDisp, fontWeight: 300, fontSize: 44,
          color: '#fff', letterSpacing: '-0.02em', lineHeight: 1,
        }}>
          The <em style={{ fontWeight: 300 }}>{layer.name}</em>
        </h2>
        <p style={{
          margin: '12px 0 0', maxWidth: 280,
          fontFamily: VI.fontDisp, fontStyle: 'italic', fontWeight: 300,
          fontSize: 15, color: 'rgba(255,255,255,0.65)', lineHeight: 1.5,
        }}>{layer.blurb}</p>
      </div>

      <div style={{ padding: '0 16px', display: 'flex', flexDirection: 'column', gap: 14 }}>
        {fish.map((f, i) => (
          <DiveFishCard key={f.id} fish={f} accent={accent} delay={i * 60} onClick={() => onOpen(f)} />
        ))}
        {fish.length === 0 && (
          <div style={{
            padding: '40px 8px', textAlign: 'center',
            fontFamily: VI.fontDisp, fontStyle: 'italic', fontWeight: 300,
            fontSize: 14, color: 'rgba(255,255,255,0.4)',
          }}>No specimens drift through this layer · adjust filters</div>
        )}
      </div>
    </section>
  );
}

function DiveFishCard({ fish, accent, delay, onClick }) {
  return (
    <button className="ctx-btn ctx-fadeUp" onClick={onClick} style={{
      width: '100%', height: 168, borderRadius: 18, overflow: 'hidden',
      position: 'relative', textAlign: 'left',
      border: '0.5px solid rgba(255,255,255,0.10)',
      background: VI.bgCard, animationDelay: `${delay}ms`,
      boxShadow: '0 8px 32px rgba(0,0,0,0.3)',
    }}>
      {fish.coverImg ? (
        <img src={fish.coverImg} alt={fish.name} loading="lazy" style={{
          position: 'absolute', inset: 0,
          width: '100%', height: '100%', objectFit: 'cover',
        }}/>
      ) : (
        <FishGradient fish={fish} height={168} radius={0} intensity={1.4}/>
      )}
      <div style={{
        position: 'absolute', inset: 0, padding: 18,
        background: 'linear-gradient(110deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.05) 55%, rgba(0,0,0,0.35) 100%)',
        display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          {fish.family && (
            <span style={{
              padding: '4px 10px', borderRadius: 99,
              background: 'rgba(0,0,0,0.45)', backdropFilter: 'blur(10px)',
              fontFamily: VI.fontMono, fontSize: 9, color: '#fff',
              letterSpacing: '0.14em', textTransform: 'uppercase',
              border: '0.5px solid rgba(255,255,255,0.18)',
            }}>{fish.family}</span>
          )}
          <span style={{
            fontFamily: VI.fontMono, fontSize: 8.5, color: 'rgba(255,255,255,0.7)',
            letterSpacing: '0.1em', textTransform: 'uppercase',
            display: 'flex', alignItems: 'center', gap: 5,
          }}>
            <span style={{
              width: 6, height: 6, borderRadius: 99, background: accent,
              boxShadow: `0 0 8px ${accent}`,
            }}/>
            {fish.water}
          </span>
        </div>

        <div>
          <div style={{
            fontFamily: VI.fontDisp, fontWeight: 500, fontSize: 24,
            color: '#fff', lineHeight: 1.05, letterSpacing: '-0.01em',
            textShadow: '0 1px 8px rgba(0,0,0,0.6)',
          }}>{fish.name}</div>
          <div style={{
            fontFamily: VI.fontDisp, fontStyle: 'italic', fontWeight: 300,
            fontSize: 12.5, color: 'rgba(255,255,255,0.85)', marginTop: 3,
            textShadow: '0 1px 6px rgba(0,0,0,0.6)',
          }}>{fish.latin}</div>
          {(fish.regions?.length > 0 || fish.methods?.length > 0) && (
            <div style={{
              marginTop: 10, display: 'flex', gap: 10, alignItems: 'center',
              fontFamily: VI.fontMono, fontSize: 8.5, color: 'rgba(255,255,255,0.7)',
              letterSpacing: '0.1em', textTransform: 'uppercase',
            }}>
              {fish.regions?.[0] && <span>{REGION_LABEL[fish.regions[0]] || fish.regions[0]}</span>}
              {fish.methods?.[0] && fish.regions?.[0] && <span style={{ opacity: 0.4 }}>·</span>}
              {fish.methods?.[0] && <span style={{ color: accent }}>{METHOD_LABEL[fish.methods[0]] || fish.methods[0]}</span>}
            </div>
          )}
        </div>
      </div>
    </button>
  );
}

function DiveSurfacePull({ pulling, progress }) {
  if (!pulling) return null;
  const ready = progress >= 1;
  return (
    <div style={{
      position: 'absolute', top: 0, left: 0, right: 0, zIndex: 8,
      height: 80, display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
      paddingBottom: 8, pointerEvents: 'none',
      opacity: Math.min(1, progress * 1.4),
    }}>
      <div style={{
        display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
        transform: `scale(${0.85 + Math.min(1, progress) * 0.15})`,
        transition: `transform .2s ${VI.ease}`,
      }}>
        <div style={{
          width: 28, height: 28, borderRadius: 99,
          border: `1.5px solid ${ready ? VI.accent : 'rgba(255,255,255,0.6)'}`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: ready ? VI.accent : '#fff',
          transition: `all .18s ${VI.ease}`,
        }}>↑</div>
        <div style={{
          fontFamily: VI.fontMono, fontSize: 8.5, letterSpacing: '0.2em',
          color: ready ? VI.accent : 'rgba(255,255,255,0.7)',
          textTransform: 'uppercase',
        }}>{ready ? 'Release to surface' : 'Pull to surface'}</div>
      </div>
    </div>
  );
}

// Main Dive In screen
function DiveIn({ species, onClose, onOpen, intensity = 'strong' }) {
  const scrollRef = React.useRef(null);
  const [depth, setDepth] = React.useState(0);
  const [transitioning, setTransitioning] = React.useState(intensity !== 'off');
  const [waterFilter, setWaterFilter] = React.useState('All');
  const [pulling, setPulling] = React.useState(false);
  const [pullProgress, setPullProgress] = React.useState(0);
  const pullStart = React.useRef(null);

  // Layers: bucket by habitat (since dataset has no water-layer field).
  // Saltwater = surface/upper, Brackish = mid (estuaries), Freshwater = depth (rivers/lakes inland).
  // The fourth "Abyss" layer collects rare/uncommon species (is_common === false).
  const layers = React.useMemo(() => [
    {
      name: 'Saltwater',
      depth: 'Open ocean',
      blurb: 'Where light dapples open water and predators chase bait through current seams.',
      accent: '#7BD3C8',
      filter: f => f.water === 'Saltwater',
    },
    {
      name: 'Brackish',
      depth: 'Estuaries',
      blurb: 'Where rivers meet the sea — tidal mouths, oyster bars, mangrove roots.',
      accent: '#6BB8D8',
      filter: f => f.water === 'Brackish',
    },
    {
      name: 'Freshwater',
      depth: 'Rivers · Lakes',
      blurb: 'Inland waters. Cold streams, slow rivers, still ponds — each its own world.',
      accent: '#4A8EC8',
      filter: f => f.water === 'Freshwater',
    },
    {
      name: 'Rare',
      depth: 'Records · Wrecks',
      blurb: 'Uncommon catches — species rarely landed, catalogued from records and reports.',
      accent: '#7B6BC8',
      filter: f => f.is_common === false,
    },
  ], []);

  const filteredFish = React.useCallback((layer) => {
    let arr = (species || []).filter(layer.filter);
    if (waterFilter !== 'All') arr = arr.filter(f => f.water === waterFilter);
    // Prefer species with cover photos and shuffle slightly per layer
    arr = arr.filter(f => f.coverImg).slice(0, 6);
    if (arr.length < 4) {
      // backfill without strict photo requirement
      arr = (species || []).filter(layer.filter)
        .filter(f => waterFilter === 'All' || f.water === waterFilter)
        .slice(0, 6);
    }
    return arr;
  }, [waterFilter, species]);

  const currentLayer =
    depth < 0.25 ? 'Saltwater' :
    depth < 0.55 ? 'Brackish' :
    depth < 0.85 ? 'Freshwater' : 'Rare';

  const onScroll = (e) => {
    const t = e.target;
    const max = t.scrollHeight - t.clientHeight;
    const d = Math.min(1, Math.max(0, t.scrollTop / Math.max(1, max)));
    setDepth(d);
    if (t.scrollTop > 0 && pulling) {
      setPulling(false);
      setPullProgress(0);
    }
  };

  const onTouchStart = (e) => {
    const t = scrollRef.current;
    if (t && t.scrollTop <= 0) {
      pullStart.current = e.touches[0].clientY;
    }
  };
  const onTouchMove = (e) => {
    if (pullStart.current == null) return;
    const dy = e.touches[0].clientY - pullStart.current;
    if (dy > 0) {
      setPulling(true);
      setPullProgress(Math.min(1.4, dy / 90));
    }
  };
  const onTouchEnd = () => {
    if (pullProgress >= 1) onClose?.();
    setPulling(false);
    setPullProgress(0);
    pullStart.current = null;
  };

  return (
    <div className="ctx-fadeIn" style={{
      width: '100%', height: '100dvh', position: 'fixed', inset: 0,
      overflow: 'hidden', background: '#050608', zIndex: 100,
    }}>
      <DiveBg depth={depth}/>
      <DiveLightShafts depth={depth}/>
      <DiveSchools density={0.85}/>

      <div
        ref={scrollRef}
        onScroll={onScroll}
        onTouchStart={onTouchStart}
        onTouchMove={onTouchMove}
        onTouchEnd={onTouchEnd}
        style={{
          position: 'relative', zIndex: 2,
          width: '100%', height: '100%', overflowY: 'auto',
          paddingBottom: 80,
        }}
      >
        <div className="ctx-fadeUp" style={{
          padding: '60px 24px 40px', position: 'relative', minHeight: 380,
        }}>
          <div style={{
            fontFamily: VI.fontMono, fontSize: 10, color: VI.accent,
            letterSpacing: '0.28em', textTransform: 'uppercase', marginBottom: 18,
          }}>Dive In</div>
          <h1 style={{
            margin: 0, fontFamily: VI.fontDisp, fontWeight: 300, fontSize: 56,
            color: '#fff', letterSpacing: '-0.025em', lineHeight: 0.92,
          }}>
            <em style={{ fontWeight: 300 }}>Descend</em><br/>
            into the<br/>
            <span style={{
              background: `linear-gradient(135deg, ${VI.accent}, #B8E5DD)`,
              WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
              fontStyle: 'italic',
            }}>column.</span>
          </h1>
          <p style={{
            margin: '22px 0 0', maxWidth: 280,
            fontFamily: VI.fontBody, fontWeight: 300, fontSize: 14.5,
            lineHeight: 1.55, color: 'rgba(255,255,255,0.72)',
          }}>
            Scroll to descend through the waters of the field guide. Each layer
            holds species adapted to its salinity and habitat.
          </p>

          <div style={{
            marginTop: 28, display: 'flex', gap: 6, flexWrap: 'wrap',
          }}>
            {['All', 'Saltwater', 'Freshwater', 'Brackish'].map(w => {
              const on = waterFilter === w;
              return (
                <button key={w} className="ctx-btn" onClick={() => setWaterFilter(w)} style={{
                  padding: '7px 13px', borderRadius: 99,
                  background: on ? VI.accent : 'rgba(255,255,255,0.06)',
                  color: on ? VI.bg : '#fff',
                  border: `0.5px solid ${on ? VI.accent : 'rgba(255,255,255,0.16)'}`,
                  fontFamily: VI.fontMono, fontSize: 10, letterSpacing: '0.14em',
                  textTransform: 'uppercase', fontWeight: 500,
                  boxShadow: on ? `0 0 16px ${VI.accent}55` : 'none',
                  transition: `all .2s ${VI.ease}`,
                }}>{w}</button>
              );
            })}
          </div>

          <div style={{
            marginTop: 40, display: 'flex', alignItems: 'center', gap: 12,
            fontFamily: VI.fontMono, fontSize: 9.5, color: 'rgba(255,255,255,0.55)',
            letterSpacing: '0.18em', textTransform: 'uppercase',
          }}>
            <span style={{ display: 'inline-block', animation: 'dv-bob 2s infinite ease-in-out' }}>↓</span>
            Scroll to descend
          </div>
        </div>

        {layers.map((l, i) => (
          <DiveLayerBand
            key={l.name}
            layer={l}
            idx={i}
            fish={filteredFish(l)}
            onOpen={onOpen}
            accent={l.accent}
          />
        ))}

        <div style={{ padding: '60px 24px 80px', textAlign: 'center' }}>
          <div style={{
            fontFamily: VI.fontDisp, fontStyle: 'italic', fontWeight: 300,
            fontSize: 18, color: 'rgba(255,255,255,0.45)', lineHeight: 1.4,
          }}>The seabed.<br/>Time to surface.</div>
          <button className="ctx-btn" onClick={onClose} style={{
            marginTop: 24, padding: '10px 22px', borderRadius: 99,
            background: 'rgba(255,255,255,0.08)',
            border: '0.5px solid rgba(255,255,255,0.2)',
            color: '#fff', fontFamily: VI.fontMono, fontSize: 10,
            letterSpacing: '0.18em', textTransform: 'uppercase',
            backdropFilter: 'blur(12px)',
          }}>↑ Surface</button>
        </div>
      </div>

      <DiveDepthGauge depth={depth} layer={currentLayer}/>
      <DiveSoundIndicator depth={depth}/>
      <DiveSurfacePull pulling={pulling} progress={pullProgress}/>

      <button className="ctx-btn" onClick={onClose} style={{
        position: 'absolute', top: 14, right: 14, zIndex: 7,
        width: 36, height: 36, borderRadius: 99,
        background: 'rgba(0,0,0,0.42)', backdropFilter: 'blur(14px)',
        border: '0.5px solid rgba(255,255,255,0.18)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: '#fff',
      }} aria-label="Close Dive In">{Icon.close(17)}</button>

      {transitioning && (
        <DiveTransition intensity={intensity} onDone={() => setTransitioning(false)}/>
      )}

      <style>{`
        @keyframes dv-bob {
          0%, 100% { transform: translateY(0); }
          50%      { transform: translateY(4px); }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { DiveIn });
