/* Nansen Aquarium — deep sea, bioluminescence, quietly cute. */

:root {
  --cyan: #4FD8FF;
  --mint: #6FF7D1;
  --lav:  #C77DFF;
  --pink: #FF8ED4;
  --gold: #FFD166;
  --text: #E8F1FF;
  --t2:   #9FC3E8;
  --t3:   #7FA3CC;
  --t4:   #55779E;
  --glass: rgba(10, 26, 51, 0.55);
  --line: rgba(79, 216, 255, 0.18);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #04070F;
}

body {
  font-family: 'Nunito', system-ui, sans-serif;
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

[hidden] { display: none !important; }

#stage {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: linear-gradient(180deg, #0E2242 0%, #0A1A33 34%, #071227 64%, #04070F 100%);

  /* Written per chain by src/backdrop.js. These are the fallbacks, and also
     what an unknown chain keeps: base blue water, a cyan motif that no chain
     has actually asked for. */
  --water-shallow: transparent;
  --water-deep: transparent;
  --motif-ink: var(--cyan);
  --motif-alpha: .06;
}

/* ── ambient ─────────────────────────────────────────────────────────── */

.godray {
  position: absolute;
  top: -180px;
  z-index: 1;
  pointer-events: none;
  filter: blur(8px);
  transform-origin: top center;
  animation: ray 20s ease-in-out infinite;
}
.godray.r1 { left: 26%; width: 130px; height: 78vh; background: linear-gradient(180deg, rgba(79,216,255,.14), rgba(79,216,255,0)); transform: rotate(14deg); }
.godray.r2 { left: 46%; width: 90px;  height: 70vh; background: linear-gradient(180deg, rgba(111,247,209,.11), rgba(111,247,209,0)); transform: rotate(9deg);  animation-delay: -7s; }
.godray.r3 { left: 68%; width: 70px;  height: 64vh; background: linear-gradient(180deg, rgba(79,216,255,.09), rgba(79,216,255,0)); transform: rotate(19deg); animation-delay: -14s; }
@keyframes ray { 0%, 100% { opacity: .6; } 50% { opacity: 1; } }

/* ── per-chain backdrop ───────────────────────────────────────────────────
   Above the god rays, below the seabed, a long way below anything alive. The
   whole layer rides the chain-swap fade with the tank, which is also what
   hides the moment the motif is swapped out. */

#backdrop {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  transition: opacity .4s ease;
}

/* Flat colour behind a fixed vertical mask rather than a gradient of its own:
   background-image never transitions, background-color always does, so this is
   the shape of wash that can actually cross-fade between chains. */
.water-wash,
.water-floor {
  position: absolute;
  inset: 0;
  transition: background-color .9s ease;
}
.water-wash {
  background-color: var(--water-shallow);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .45) 46%, transparent 78%);
  mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .45) 46%, transparent 78%);
}
.water-floor {
  background-color: var(--water-deep);
  -webkit-mask-image: linear-gradient(180deg, transparent 34%, rgba(0, 0, 0, .5) 70%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 34%, rgba(0, 0, 0, .5) 70%, #000 100%);
}

.motif {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Two shadows, not one: the tight pass keeps the strokes from washing out at
   this opacity, the wide one is the halo that makes the motif read as something
   luminous a long way off instead of a decal on the glass. */
.motif-art {
  opacity: var(--motif-alpha);
  color: var(--motif-ink);
  filter: drop-shadow(0 0 9px currentColor) drop-shadow(0 0 38px currentColor);
}

/* Both drifts are slower than anything else on screen — a full cycle outlasts
   several feedings, so the motif never reads as motion, only as never quite
   being where you left it. */
.motif-feather {
  height: 68%;
  width: auto;
  aspect-ratio: 310 / 790;
  transform-origin: 50% 40%;
  animation: featherDrift 28s ease-in-out infinite;
}
@keyframes featherDrift {
  0%, 100% { transform: rotate(-13deg) translate3d(-10px, -14px, 0); }
  50%      { transform: rotate(-5deg)  translate3d(16px, 18px, 0); }
}

/* Square art on a landscape stage, so it is sized off the short edge and left
   to keep its own proportion. The tilt lives in the keyframes rather than the
   resting transform: a square sitting perfectly level reads as a UI panel, and
   a few degrees off is the whole difference between that and something hanging
   in a current. */
.motif-block {
  height: 62%;
  width: auto;
  aspect-ratio: 1 / 1;
  animation: blockDrift 31s ease-in-out infinite;
}
/* the pane blooms, the outlines stay sharp — the same trick the beams use, and
   the reason this reads as light through a block instead of a filled tile */
.motif-block .block-core { filter: blur(18px); }
@keyframes blockDrift {
  0%, 100% { transform: rotate(-4deg) translate3d(-13px, 11px, 0) scale(1.01); opacity: var(--motif-alpha); }
  50%      { transform: rotate(2deg)  translate3d(14px, -12px, 0) scale(1.05); opacity: calc(var(--motif-alpha) * 1.18); }
}

.motif-beams {
  width: 76%;
  height: 64%;
  animation: beamDrift 34s ease-in-out infinite;
}
/* the bodies bloom, the leading edges stay sharp — that contrast is the whole
   difference between a shaft of light and a painted bar */
.motif-beams .beam-body { filter: blur(7px); }
.motif-beams .beam-edge { opacity: .9; }
@keyframes beamDrift {
  0%, 100% { transform: translate3d(-18px, 10px, 0) scale(1.02); opacity: var(--motif-alpha); }
  50%      { transform: translate3d(20px, -12px, 0) scale(1.06); opacity: calc(var(--motif-alpha) * 1.15); }
}

#seabed {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  z-index: 3;
  pointer-events: none;
  line-height: 0;
}
#seabed svg { display: block; }
/* faint rim light so the ridge reads against the gradient's bottom stop */
#seabed .ridge { filter: drop-shadow(0 0 6px rgba(79, 216, 255, .3)); }

#ambient { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

.snow {
  position: absolute;
  top: -10px;
  border-radius: 50%;
  background: #9FC3E8;
  animation: snowfall linear infinite;
}
@keyframes snowfall {
  from { transform: translate3d(0, -20px, 0); }
  to   { transform: translate3d(18px, 105vh, 0); }
}

.bubble {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(180, 226, 255, .5);
  background: rgba(180, 226, 255, .12);
  animation: bubbleRise 8s ease-in forwards;
}
@keyframes bubbleRise {
  from { transform: translate3d(0, 0, 0); opacity: 0; }
  12%  { opacity: .75; }
  to   { transform: translate3d(var(--drift, 0px), -85vh, 0); opacity: 0; }
}

.jelly {
  position: absolute;
  width: 80px;
  opacity: .55;
  transform: scale(var(--s, 1));
  filter: drop-shadow(0 0 14px rgba(199, 125, 255, .5));
  animation: drift 10s ease-in-out infinite;
}
.jelly img { display: block; width: 100%; height: auto; }
@keyframes drift {
  0%, 100% { transform: translateY(0) scale(var(--s, 1)); }
  50%      { transform: translateY(-22px) scale(var(--s, 1)); }
}

/* ── tank + creatures ────────────────────────────────────────────────── */

#tank {
  position: absolute;
  inset: 0;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
}

.creature {
  position: absolute;
  left: 0;
  top: 0;
  cursor: pointer;
  pointer-events: auto;
  will-change: transform;
  z-index: 2;
}
.creature .body { position: relative; width: 100%; height: 100%; }

/* The bioluminescence is painted into the art, so there is no drop-shadow to
   pulse. Exposure carries the data instead: --b0/--b1 are set per creature
   from its win rate (see setGlow in tank.js) and it breathes between them. */
.sprite {
  display: block;
  width: 100%;
  height: 100%;
  animation: glowPulse 4s ease-in-out infinite;
}
@keyframes glowPulse {
  0%, 100% { filter: brightness(var(--b0, .92)); }
  50%      { filter: brightness(var(--b1, 1.08)); }
}

/* top-volume whale only — the gold art has no crown of its own */
.crown {
  position: absolute;
  left: 12%;
  top: 16%;
  width: 17%;
  filter: drop-shadow(0 0 8px rgba(255, 209, 102, .85));
  pointer-events: none;
}

.creature.gulp   .body { animation: gulp .3s ease-out; }
.creature.shiver .body { animation: shiver .45s ease-in-out; }
@keyframes gulp   { 0% { transform: scale(1); } 40% { transform: scale(1.12); } 100% { transform: scale(1); } }
@keyframes shiver {
  0%, 100% { transform: rotate(0deg); }
  16% { transform: rotate(3deg); }  33% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }  66% { transform: rotate(-3deg); }
  83% { transform: rotate(3deg); }
}

/* ── event FX ────────────────────────────────────────────────────────── */

.coin {
  position: absolute;
  left: 0;
  top: 0;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  z-index: 5;
  pointer-events: none;
  filter: drop-shadow(0 0 10px rgba(255, 209, 102, .7));
  transition: opacity .42s ease-out;
}
.coin svg { display: block; width: 100%; height: 100%; transition: transform .2s ease-in; }
.coin.eaten svg { transform: scale(0); }
/* nobody made the interception — the coin dissolves instead of hitting the floor */
.coin.lost { opacity: 0; }
.coin.lost svg { transform: scale(.6); }

.sparkle {
  position: absolute;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 9px rgba(255, 209, 102, .9);
  z-index: 6;
  pointer-events: none;
  animation: sparkle .62s ease-out forwards;
}
@keyframes sparkle {
  from { transform: translate(0, 0) scale(1); opacity: 1; }
  to   { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

.trail {
  position: absolute;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: rgba(255, 142, 212, .5);
  box-shadow: 0 0 12px rgba(255, 142, 212, .7);
  z-index: 4;
  pointer-events: none;
  animation: trailFade 1.1s ease-out forwards;
}
@keyframes trailFade {
  from { transform: scale(1); opacity: .8; }
  to   { transform: scale(.25); opacity: 0; }
}

.amt-pop {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  white-space: nowrap;
  font-family: 'Space Mono', monospace;
  font-size: 15px;
  font-weight: 700;
  text-shadow: 0 0 14px rgba(4, 7, 15, .95);
  animation: popUp 1.2s ease-out forwards;
}
.amt-pop.buy  { color: var(--mint); }
.amt-pop.sell { color: var(--pink); }
@keyframes popUp {
  0%   { transform: translate(-50%, 4px); opacity: 0; }
  18%  { opacity: 1; }
  100% { transform: translate(-50%, -54px); opacity: 0; }
}

/* ── top bar ─────────────────────────────────────────────────────────── */

/* Three columns, the outer two equal, so the tabs sit on the true centre line
   of the bar no matter how wide the brand gets. Which tank you are in is the
   one thing the header exists to say, so it says it in the middle. The third
   column is deliberately empty — it is the counterweight. */
#topbar {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 7;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  padding: 26px 40px;
}

.brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
.brand-icon { display: block; line-height: 0; filter: drop-shadow(0 0 8px rgba(79, 216, 255, .6)); }
.brand-name {
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 24px;
  font-weight: 700;
  text-shadow: 0 0 18px rgba(79, 216, 255, .5);
}

#chains { display: flex; gap: 8px; justify-self: center; }
.chain {
  padding: 10px 22px;
  border-radius: 999px;
  border: 1px solid rgba(79, 216, 255, .2);
  background: transparent;
  color: var(--t3);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: color .2s, border-color .2s, background .2s;
}
.chain:hover { color: var(--text); border-color: rgba(79, 216, 255, .4); }
.chain.active {
  border-color: rgba(79, 216, 255, .5);
  background: rgba(79, 216, 255, .12);
  color: var(--text);
  font-weight: 700;
  box-shadow: 0 0 16px rgba(79, 216, 255, .25);
  cursor: default;
}
.chain:disabled { cursor: progress; }

/* ── chain swap ───────────────────────────────────────────────────────────
   Switching chains empties the tank and refills it. Rather than let creatures
   blink out mid-stroke, the two things that carry the chain's data — the tank
   and the feed panel — fade down together, are rebuilt while nothing is on
   screen, and come back up: 400ms out, 400ms in. The backdrop goes with them:
   its motif is swapped outright, and this is the darkness it happens in. */
#tank, #feedpanel {
  transition: opacity .4s ease;
}
#stage.swapping #tank,
#stage.swapping #feedpanel,
#stage.swapping #backdrop {
  opacity: 0;
}

#toast {
  position: absolute;
  top: 74px;
  right: 40px;
  z-index: 8;
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(6, 14, 28, .92);
  border: 1px solid rgba(79, 216, 255, .3);
  color: var(--t2);
  font-size: 13px;
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
}
#toast.show { opacity: 1; transform: translateY(0); }

/* ── live feed ───────────────────────────────────────────────────────── */

#feedpanel {
  position: absolute;
  top: 100px;
  right: 40px;
  z-index: 7;
  width: 330px;
  padding: 20px 22px;
  border-radius: 20px;
  background: var(--glass);
  border: 1px solid var(--line);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.feed-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.livedot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--mint);
  box-shadow: 0 0 10px rgba(111, 247, 209, .9);
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: .9; } 50% { opacity: .3; } }

.feed-title { font-size: 12px; font-weight: 800; letter-spacing: 2px; color: var(--mint); }
.replay-badge {
  margin-left: auto;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid rgba(159, 195, 232, .22);
  color: var(--t4);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 1.4px;
  cursor: help;
}

#feed-rows { display: flex; flex-direction: column; }

.feed-row {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(79, 216, 255, .08);
  max-height: 110px;
  overflow: hidden;
  transition: transform .3s ease-out, opacity .3s ease-out, max-height .3s ease-out, padding .3s ease-out;
}
.feed-row:last-child { border-bottom: none; }
.feed-row.in  { transform: translateX(24px); opacity: 0; }
.feed-row.out { max-height: 0; opacity: 0; padding: 0; }

.feed-ico {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.feed-ico svg { display: block; }
.feed-txt { flex-grow: 1; min-width: 0; }
.feed-line { font-size: 13.5px; color: var(--text); overflow-wrap: anywhere; }
.feed-line b { font-weight: 800; }
.amt { font-weight: 700; }
.amt.buy  { color: var(--mint); }
.amt.sell { color: var(--pink); }
.feed-sub { margin-top: 2px; font-size: 11.5px; color: var(--t3); }
/* the timestamp doubles as the link to the trade on its own block explorer */
.feed-tx {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted rgba(159, 195, 232, .35);
  transition: color .18s, border-color .18s;
}
.feed-tx:hover { color: var(--cyan); border-bottom-color: rgba(79, 216, 255, .7); }

/* Every creature's bioluminescence is its realized PnL, so the panel says so —
   under its breath, at the same weight as the REPLAY badge. */
.feed-legend {
  display: flex;
  gap: 14px;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid rgba(79, 216, 255, .08);
  font-size: 10px;
  color: var(--t4);
}
.pnl-key { display: inline-flex; align-items: center; gap: 5px; }
.pnl-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.pnl-dot.up   { background: var(--mint); box-shadow: 0 0 5px rgba(111, 247, 209, .55); }
.pnl-dot.down { background: var(--pink); box-shadow: 0 0 5px rgba(255, 142, 212, .55); }

/* ── hover chip ──────────────────────────────────────────────────────── */

#hoverchip {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 8;
  max-width: 260px;
  padding: 11px 15px;
  border-radius: 14px;
  background: rgba(6, 14, 28, .93);
  border: 1px solid rgba(79, 216, 255, .35);
  box-shadow: 0 0 24px rgba(79, 216, 255, .15);
  pointer-events: none;
  will-change: transform;
}
.chip-1 { font-family: 'Space Mono', monospace; font-size: 13px; color: var(--text); }
.chip-2 { margin-top: 4px; font-size: 12px; font-weight: 700; color: var(--mint); }
.chip-3 {
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  color: var(--mint);
  opacity: .72;
  overflow-wrap: anywhere;
}

/* ── CTA ─────────────────────────────────────────────────────────────── */

#cta {
  position: absolute;
  bottom: 92px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
  width: 640px;
  text-align: center;
}
.cta-caption {
  margin-bottom: 12px;
  font-size: 15px;
  color: var(--t2);
  text-shadow: 0 0 12px rgba(10, 26, 51, .9);
}
#cta-form { display: flex; gap: 10px; }

#cta-input {
  flex-grow: 1;
  min-width: 0;
  padding: 16px 22px;
  border-radius: 999px;
  background: rgba(6, 14, 28, .82);
  border: 1px solid rgba(79, 216, 255, .4);
  color: var(--text);
  font-family: 'Space Mono', monospace;
  font-size: 14px;
  outline: none;
  box-shadow: 0 0 20px rgba(79, 216, 255, .12);
  transition: border-color .2s, box-shadow .2s;
}
#cta-input::placeholder { color: #6E93BF; }
#cta-input:focus { border-color: rgba(79, 216, 255, .8); box-shadow: 0 0 24px rgba(79, 216, 255, .28); }
#cta-input.bad {
  border-color: var(--pink);
  box-shadow: 0 0 24px rgba(255, 142, 212, .35);
  animation: shake .5s ease-in-out;
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-9px); } 30% { transform: translateX(9px); }
  45% { transform: translateX(-6px); } 60% { transform: translateX(6px); }
  80% { transform: translateX(-2px); }
}

#cta-btn {
  padding: 16px 30px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(180deg, #FFD166, #F2B23E);
  color: #2A1E05;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 17px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 0 28px rgba(255, 209, 102, .45);
  transition: transform .15s ease, box-shadow .2s ease;
}
#cta-btn:hover { transform: translateY(-1px); box-shadow: 0 0 36px rgba(255, 209, 102, .6); }
#cta-btn:active { transform: translateY(1px); }

#credit {
  position: absolute;
  right: 24px;
  bottom: 18px;
  z-index: 7;
  font-size: 12px;
  color: var(--t4);
}
#credit b { color: var(--t3); font-weight: 700; }
#credit a { color: inherit; text-decoration: none; transition: color .18s ease; }
#credit a:hover b { color: var(--cyan); }

/* ── egg modal / hatchery ────────────────────────────────────────────────
   One card, four faces: the pre-launch note, the drifting egg, the read, and
   the reveal. src/hatch.js only ever toggles `data-phase` and `hidden` — every
   piece of chrome below is already in index.html. */

#egg-modal {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(4, 7, 15, .75);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .26s ease;
}
#egg-modal.show { opacity: 1; }

.egg-card {
  position: relative;
  width: 380px;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  padding: 34px 32px 30px;
  border-radius: 24px;
  text-align: center;
  background: rgba(10, 26, 51, .82);
  border: 1px solid rgba(79, 216, 255, .28);
  box-shadow: 0 0 60px rgba(79, 216, 255, .18);
  outline: none;
  transform: translateY(10px) scale(.97);
  transition: transform .26s cubic-bezier(.2, .8, .3, 1), width .3s ease;
}
#egg-modal.show .egg-card { transform: translateY(0) scale(1); }
/* the reveal carries a portrait and a stat table, so it earns more room */
.egg-card[data-phase="reveal"] { width: 500px; }

.egg-x {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(79, 216, 255, .25);
  background: transparent;
  color: var(--t3);
  cursor: pointer;
  transition: color .2s, border-color .2s, background .2s;
}
.egg-x:hover { color: var(--text); border-color: rgba(79, 216, 255, .6); background: rgba(79, 216, 255, .1); }

.egg-steps { display: flex; gap: 11px; justify-content: center; margin-bottom: 20px; }
.egg-steps i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(79, 216, 255, .2);
  transition: background .3s ease, box-shadow .3s ease;
}
.egg-steps i.done { background: rgba(79, 216, 255, .38); }
.egg-steps i.on { background: var(--cyan); box-shadow: 0 0 10px rgba(79, 216, 255, .9); }
.egg-card[data-phase="reveal"] .egg-steps i.on { background: var(--gold); box-shadow: 0 0 10px rgba(255, 209, 102, .9); }

.egg-art { position: relative; }
.egg-art svg { display: block; margin: 0 auto 14px; position: relative; z-index: 1; }
.egg-core { animation: pulse 2.6s ease-in-out infinite; }
/* the shell only gives once something inside is trying to get out */
.egg-crack { opacity: 0; transition: opacity .7s ease; }
.egg-card[data-phase="reading"] .egg-crack { opacity: .9; }

/* halo behind the egg while the wallet is being read */
.egg-art::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 46%;
  width: 230px;
  height: 230px;
  margin: -115px 0 0 -115px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(79, 216, 255, .22), rgba(79, 216, 255, 0));
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease;
}
.egg-card[data-phase="reading"] .egg-art::before { opacity: 1; animation: pulse 2.5s ease-in-out infinite; }

.egg-card[data-phase="egg"] .egg-art {
  animation: eggFall .9s cubic-bezier(.2, .8, .3, 1) both, eggFloat 7s ease-in-out .9s infinite;
}
.egg-card[data-phase="reading"] .egg-art { animation: eggShiver 1.7s ease-in-out infinite; }
@keyframes eggFall {
  from { transform: translateY(-46px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes eggFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
@keyframes eggShiver {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-2deg); }
  75% { transform: rotate(2deg); }
}

.egg-addr {
  margin-bottom: 12px;
  font-family: 'Space Mono', monospace;
  font-size: 13px;
  letter-spacing: 1.5px;
  color: var(--t4);
  overflow-wrap: anywhere;
}
.egg-title {
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.3;
  text-shadow: 0 0 18px rgba(79, 216, 255, .45);
}
.egg-sub { margin-top: 8px; font-size: 14px; line-height: 1.5; color: var(--t2); }
.egg-sub b { color: var(--mint); }

/* what the read actually found, in the wallet's own numbers */
.egg-teasers {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
}
.egg-teasers li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: 'Space Mono', monospace;
  font-size: 13px;
  color: var(--mint);
  animation: teaseIn .35s ease-out both;
}
.egg-teasers li + li { animation-delay: .2s; }
.egg-teasers svg { display: block; flex-shrink: 0; }
@keyframes teaseIn {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* ── reveal ──────────────────────────────────────────────────────────── */

.egg-reveal { display: flex; flex-direction: column; align-items: center; }

.egg-portrait {
  position: relative;
  max-width: 100%;
  margin-bottom: 6px;
  filter: drop-shadow(0 0 22px var(--sg, rgba(79, 216, 255, .35)));
}
.egg-portrait img { display: block; width: 100%; height: 100%; }

.egg-you { font-size: 15px; color: var(--t2); }
.egg-species {
  margin-top: 2px;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 38px;
  font-weight: 800;
  letter-spacing: 2px;
  line-height: 1.15;
  color: var(--gold);
  text-shadow: 0 0 28px rgba(255, 209, 102, .55);
}
.egg-legend {
  margin-top: 8px;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  text-shadow: 0 0 18px rgba(79, 216, 255, .4);
}
.egg-wallet {
  margin-top: 2px;
  font-family: 'Space Mono', monospace;
  font-size: 13px;
  color: var(--t3);
  overflow-wrap: anywhere;
}
/* which tank and how far back the numbers below reach — quiet, but never
   optional: the read is one chain over 90 days, not the whole wallet */
.egg-scope {
  margin-top: 5px;
  font-size: 12px;
  letter-spacing: .3px;
  color: var(--t4);
}
.egg-blank {
  margin-top: 18px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--t3);
}
/* the stat table, the "Loves" line and the epithet are the legend card's, so
   a fish reads the same before and after it is released */
.egg-reveal .legend-stats { margin-top: 18px; }
.egg-reveal .legend-flavor { margin-bottom: 0; }

/* the eggshell that marks the visitor's own fish, in the tank and on the card */
.hatch-mark {
  position: absolute;
  right: 5%;
  top: 5%;
  width: 15%;
  min-width: 13px;
  max-width: 26px;
  height: auto;
  opacity: .92;
  filter: drop-shadow(0 0 6px rgba(255, 209, 102, .7));
  pointer-events: none;
}

/* ── hatchery buttons ────────────────────────────────────────────────── */

.egg-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-top: 22px;
}
.egg-buttons button {
  padding: 12px 26px;
  border-radius: 999px;
  border: 1px solid rgba(79, 216, 255, .4);
  background: rgba(79, 216, 255, .1);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background .2s, border-color .2s, transform .15s ease, box-shadow .2s;
}
.egg-buttons button:hover { background: rgba(79, 216, 255, .2); border-color: rgba(79, 216, 255, .7); }

#egg-release {
  border: none;
  background: linear-gradient(180deg, #FFD166, #F2B23E);
  color: #2A1E05;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 16px;
  box-shadow: 0 0 26px rgba(255, 209, 102, .45);
}
#egg-release:hover {
  background: linear-gradient(180deg, #FFD166, #F2B23E);
  transform: translateY(-1px);
  box-shadow: 0 0 34px rgba(255, 209, 102, .6);
}
#egg-release:active { transform: translateY(1px); }

/* Turnstile stays out of the layout until Cloudflare puts something in it */
#egg-captcha:not(:empty) { margin-top: 16px; display: flex; justify-content: center; }

/* ── legend modal ────────────────────────────────────────────────────── */

#legend-modal {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(4, 7, 15, .75);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .15s ease;
}
#legend-modal.show { opacity: 1; }

.legend-card {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 600px;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  padding: 28px 36px 30px;
  border-radius: 28px;
  border: 1.5px solid rgba(79, 216, 255, .35);
  background: radial-gradient(ellipse at 50% 12%, #0E2242 0%, #081226 60%, #060D1C 100%);
  box-shadow: 0 0 40px rgba(79, 216, 255, .1);
  outline: none;
  transform: translateY(10px) scale(.98);
  transition: transform .15s cubic-bezier(.2, .8, .3, 1);
}
#legend-modal.show .legend-card { transform: none; }

.legend-close {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 34px;
  height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(79, 216, 255, .25);
  background: transparent;
  color: var(--t3);
  cursor: pointer;
  transition: color .2s, border-color .2s, background .2s;
}
.legend-close:hover { color: var(--text); border-color: rgba(79, 216, 255, .6); background: rgba(79, 216, 255, .1); }

.legend-body {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  min-width: 0;
}

.legend-kicker {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 3px;
  color: var(--lav);
}

.legend-sprite {
  position: relative;
  margin-top: 18px;
  max-width: 100%;
  filter: drop-shadow(0 0 22px var(--sg, rgba(79, 216, 255, .35)));
}
.legend-sprite img { display: block; width: 100%; height: 100%; }

.legend-name {
  margin-top: 10px;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-size: 32px;
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  text-shadow: 0 0 20px rgba(79, 216, 255, .4);
}
.legend-addr {
  margin-top: 2px;
  font-family: 'Space Mono', monospace;
  font-size: 14px;
  color: var(--t3);
  overflow-wrap: anywhere;
}

.legend-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
}
.legend-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 13px;
  font-weight: 700;
}
.legend-pill svg { display: block; }

.legend-stats { width: 100%; margin-top: 22px; }
.legend-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 4px;
  border-bottom: 1px solid rgba(79, 216, 255, .1);
}
.legend-row:last-child { border-bottom: none; }
.legend-k { font-size: 14px; color: var(--t2); }
.legend-v {
  font-family: 'Space Mono', monospace;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
}
.legend-v.pos { color: var(--mint); }
.legend-v.neg { color: var(--pink); }

.legend-loves {
  margin-top: 16px;
  font-size: 13px;
  font-weight: 700;
  color: var(--mint);
  opacity: .8;
  text-align: center;
  overflow-wrap: anywhere;
}
.legend-flavor {
  margin: 18px 0 24px;
  font-size: 15px;
  font-style: italic;
  line-height: 1.5;
  color: var(--t2);
  text-align: center;
}

.legend-btn {
  width: 100%;
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 15px 0;
  border: 1.5px solid rgba(79, 216, 255, .5);
  border-radius: 999px;
  color: var(--cyan);
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 0 18px rgba(79, 216, 255, .15);
  transition: background .2s, border-color .2s, box-shadow .2s;
}
.legend-btn:hover {
  background: rgba(79, 216, 255, .12);
  border-color: rgba(79, 216, 255, .85);
  box-shadow: 0 0 26px rgba(79, 216, 255, .3);
}

/* ── responsive ──────────────────────────────────────────────────────── */

@media (max-width: 800px) {
  #feedpanel { display: none; }
  #topbar { padding: 18px 20px; gap: 10px; }
  .brand { gap: 10px; }
  .brand-name { font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .brand-icon svg { width: 30px; height: 20px; }
  #chains { gap: 6px; }
  .chain { padding: 7px 14px; font-size: 12.5px; }
  /* the motif is a landscape shape on a portrait screen; let it fill instead */
  .motif-beams { width: 96%; height: 44%; }
  .motif-feather { height: 56%; }
  /* the square one is the other way round: sized off the short edge again, and
     on a portrait screen that is the width */
  .motif-block { height: auto; width: 84%; }
  #cta { width: 90%; bottom: 48px; }
  #cta-form { flex-direction: column; }
  #cta-btn { padding: 14px 22px; }
  #credit { display: none; }
  #toast { right: 20px; }
  #egg-modal { padding: 14px; }
  .egg-card, .egg-card[data-phase="reveal"] { width: 100%; padding: 26px 18px 22px; }
  .egg-species { font-size: 30px; }
  .egg-buttons button { padding: 12px 20px; }
  #legend-modal { padding: 14px; }
  .legend-card { padding: 24px 20px 22px; border-radius: 22px; }
  .legend-name { font-size: 26px; }
  .legend-stats { margin-top: 16px; }
  .legend-row { padding: 10px 2px; }
}

/* Raised from 560px when the tabs moved to the centre: the wordmark now has to
   fit in half of what is left over, not all of it. */
@media (max-width: 640px) {
  .brand-name { display: none; }
}

/* ── reduced motion ──────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .godray, .snow, .jelly, .bubble, .livedot, .egg-core, .sprite, .motif-art,
  .egg-art, .egg-art::before, .egg-teasers li { animation: none !important; }
  /* the drift is the only thing that moved; the motif itself still belongs */
  .motif-feather { transform: rotate(-9deg); }
  .motif-block { transform: rotate(-3deg); }
  .sprite { filter: brightness(var(--b1, 1.08)); }
  .feed-row { transition-duration: .01ms; }
  #egg-modal, .egg-card, .egg-crack, .egg-art::before { transition-duration: .01ms; }
  #legend-modal, .legend-card { transition-duration: .01ms; }
}

/* ── poster mode (?og=1) ─────────────────────────────────────────────────
   Only ever seen by the screenshot run that produces public/og/card.png:
   the interactive chrome goes away, the wordmark takes the stage, and the
   attribution footer stays — the fish are still Nansen's data. */
#og-hero { display: none; }
body.og-mode #topbar,
body.og-mode #feedpanel,
body.og-mode #cta,
body.og-mode #hoverchip { display: none !important; }
/* The wordmark needs water nobody is swimming in. Every creature's range is
   measured off #tank's own height (see tank.js), so raising its floor to 58%
   herds the whole roster into the upper water without touching the steering
   itself — and leaves the lower third to the type and the attribution. */
body.og-mode #tank { bottom: 42%; }
body.og-mode #og-hero {
  display: block;
  position: absolute;
  top: 74%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 8;
  text-align: center;
  pointer-events: none;
}
.og-name {
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 96px;
  line-height: 1.05;
  letter-spacing: .5px;
  white-space: nowrap;
  background: linear-gradient(180deg, #FFFFFF 12%, #9FE8FF 58%, #4FD8FF 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 18px rgba(79, 216, 255, .5)) drop-shadow(0 8px 34px rgba(4, 7, 15, .9));
}
.og-tag {
  margin-top: 10px;
  font-family: 'Baloo 2', 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 31px;
  color: #BFE2FF;
  opacity: .92;
  text-shadow: 0 0 14px rgba(79, 216, 255, .45), 0 2px 16px rgba(4, 7, 15, .85);
}
body.og-mode #credit { font-size: 15px; }
