/* =====================================================================
   askNils — third.asknils.ch
   A one-act animation: the fish swims in, Martin's giant "Ja" surfaces,
   a fishing hook reels it out of the water, and it ends up on a stick
   over a campfire — reading "Nein".
   ===================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  background: #000;
  overflow: hidden;
  font-family: Georgia, "Times New Roman", serif;
  color: #fff;
}

#stage {
  position: fixed;
  inset: 0;
  isolation: isolate;
}

/* ---------------------------------------------------------------------
   No-JS / progressive-enhancement baseline.
   By default only the final scene is visible, so a visitor without
   JavaScript still gets the punchline (a roasted fish reading "Nein").
   As soon as JS runs, <html> gets `.js` and we hide the finale until
   the timeline reveals it.
   --------------------------------------------------------------------- */
#shark, #ja, #rig { opacity: 0; }
#fire { opacity: 1; }

.js #fire { opacity: 0; }

/* =====================================================================
   Phase 1 — the shark swims in (reused from Martin's last page)
   ===================================================================== */
#shark {
  position: absolute;
  top: 50%;
  left: 100%;
  width: 46vw;
  transform: translateY(-50%);
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.5));
  will-change: left, transform, opacity;
  z-index: 2;
}
#shark svg { width: 100%; height: auto; display: block; }

#shark.swim { animation: sharkSwim 2.2s cubic-bezier(0.3, 0, 0.4, 1) forwards; }
@keyframes sharkSwim {
  0%   { left: 108%; opacity: 0; transform: translateY(-50%) scale(1); }
  10%  { opacity: 1; }
  42%  { left: 44%;  opacity: 1; transform: translateY(-50%) scale(1); }
  50%  { left: 40%;  opacity: 1; transform: translateY(-50%) scale(1.06); }
  100% { left: -60%; opacity: 1; transform: translateY(-50%) scale(1); }
}

/* =====================================================================
   Phase 2 — the giant "Ja" surfaces (white page, black word)
   ===================================================================== */
#ja {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  color: #000;
  z-index: 3;
  pointer-events: none;
}
#ja .word {
  font-size: 30vw;
  line-height: 1;
  font-weight: 700;
  letter-spacing: -0.02em;
}
/* The white page (the "water surface") stays up through the whole catch so
   the dark line and the fish read against it; only the WORD gets snatched. */
#ja.show { animation: jaIn 0.8s ease-out forwards; }
@keyframes jaIn { to { opacity: 1; } }
#ja.caught .word { animation: wordSnatch 0.5s ease-in forwards; }
@keyframes wordSnatch {
  0%   { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(0.2) translateY(-42vh); }
}

/* =====================================================================
   Phase 3 — the fishing rig: line, hook, and the thrashing catch
   ===================================================================== */
#rig {
  position: absolute;
  left: 50%;
  top: 0;
  height: 100%;
  transform: translateX(-50%);
  z-index: 4;
  pointer-events: none;
}
#rig .rig-inner {
  position: relative;
  width: 20vmin;
  height: 100vh;
  transform: translateY(-100%);        /* parked fully above the viewport */
  will-change: transform;
}
.js #rig.drop { opacity: 1; }          /* reveal the rig once it starts dropping */
.js #rig.drop .rig-inner {
  transition: transform 1s cubic-bezier(0.25, 0.7, 0.35, 1.05);
  transform: translateY(0);            /* drop so the hook reaches the "Ja" */
}
.js #rig.reel .rig-inner {
  animation: reelUp 2.7s cubic-bezier(0.45, 0.02, 0.5, 1) 0.15s forwards;
}
/* reeled up, but it fights the whole way — up, slip back, up again */
@keyframes reelUp {
  0%   { transform: translateY(0); }
  12%  { transform: translateY(-5%); }
  20%  { transform: translateY(0%); }
  40%  { transform: translateY(-17%); }
  50%  { transform: translateY(-10%); }
  72%  { transform: translateY(-45%); }
  80%  { transform: translateY(-38%); }
  100% { transform: translateY(-125%); }
}

#rig .line {
  position: absolute;
  left: 50%;
  top: 0;
  width: 2px;
  height: 32vh;                        /* from the top down to the hook */
  margin-left: -1px;
  background: linear-gradient(180deg, rgba(40,45,50,0.2), rgba(30,34,38,0.9));
}
#rig .hook {
  position: absolute;
  left: 50%;
  top: 30vh;
  width: 6vmin;
  transform: translateX(-50%);
}
#rig .hook svg { width: 100%; height: auto; display: block;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.35)); }

/* the caught fish rides just under the hook */
#rig .catch {
  position: absolute;
  left: 50%;
  top: 40vh;
  width: 34vmin;
  transform: translateX(-50%);
  opacity: 0;
}
.js #rig.reel .catch {
  opacity: 1;
  animation: thrash 0.19s steps(2, end) infinite;
}
/* the fish yanks against the line as it comes up */
@keyframes thrash {
  0%   { transform: translateX(-50%) rotate(-9deg) translateY(0); }
  50%  { transform: translateX(-52%) rotate(10deg) translateY(-4px); }
  100% { transform: translateX(-48%) rotate(-7deg) translateY(2px); }
}

/* =====================================================================
   Shared fish look — recoloured raw vs cooked through custom props
   ===================================================================== */
.fish .fish-svg { width: 100%; height: auto; display: block; overflow: visible; }
.fish-label {
  position: absolute;
  left: 50%;
  top: 52%;
  transform: translate(-50%, -50%) rotate(-4deg);
  font-weight: 700;
  color: #10171d;
  text-shadow: 0 1px 0 rgba(255,255,255,0.35);
  pointer-events: none;
  white-space: nowrap;
}

/* Fills come from plain CSS rules (not SVG presentation-attribute var(),
   which Safari/older engines don't substitute) so the fish colours render
   in every browser. */
.fish .fs-gill { fill: none; stroke-width: 3; stroke-linecap: round; }

/* Raw catch — darker so it reads against the white "water" page */
.fish--raw { filter: drop-shadow(0 6px 10px rgba(0,0,0,0.35)); }
.fish--raw .fs-body  { fill: #5f7d92; stroke: rgba(18,28,36,0.6); stroke-width: 2; }
.fish--raw .fs-belly { fill: #b7ccd8; }
.fish--raw .fs-fin   { fill: #405b6d; }
.fish--raw .fs-gill  { stroke: rgba(18,28,36,0.6); }
.fish--raw .fs-eye   { fill: #0d1519; }
.fish--raw .fs-shine { fill: #ffffff; }
.fish--raw .fish-label { font-size: 6vmin; color: #f4f8fb; text-shadow: 0 1px 2px rgba(0,0,0,0.55); }

/* Cooked catch — browned, the answer */
.fish--cooked { filter: drop-shadow(0 8px 14px rgba(0,0,0,0.55)); }
.fish--cooked .fs-body  { fill: #b6793d; stroke: rgba(48,28,10,0.5); stroke-width: 2; }
.fish--cooked .fs-belly { fill: #e0ab68; }
.fish--cooked .fs-fin   { fill: #8a5a2c; }
.fish--cooked .fs-gill  { stroke: rgba(48,28,10,0.5); }
.fish--cooked .fs-eye   { fill: #1c130c; }
.fish--cooked .fs-shine { fill: #f6d9a8; }
.fish--cooked .fish-label {
  font-size: 7vmin;
  color: #fff4e0;
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}

/* =====================================================================
   Phase 4 — night, the campfire, and the fish on a stick reading "Nein"
   ===================================================================== */
#fire {
  position: absolute;
  inset: 0;
  z-index: 5;
  background:
    radial-gradient(120% 90% at 50% 118%, #4a2a12 0%, #2a1a12 22%, #100b16 55%, #05060c 100%);
  overflow: hidden;
}
.js #fire.show { animation: fireIn 1s ease-out forwards; }
@keyframes fireIn { from { opacity: 0; } to { opacity: 1; } }

#fire .stars { position: absolute; inset: 0; pointer-events: none; }
#fire .star {
  position: absolute;
  width: 2px; height: 2px;
  border-radius: 50%;
  background: #fdf6d8;
  opacity: 0.7;
  animation: twinkle 3.4s ease-in-out infinite;
}
@keyframes twinkle { 0%,100% { opacity: 0.2; } 50% { opacity: 0.85; } }

#fire .scene {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(92vw, 560px);
  height: min(88vh, 640px);
}

/* --- the spit --------------------------------------------------------- */
.support {
  position: absolute;
  bottom: 8%;
  width: 12px;
  height: 50%;
  border-radius: 6px;
  background: linear-gradient(180deg, #6f4c2b, #40290f);
  transform-origin: bottom center;
  box-shadow: 0 2px 4px rgba(0,0,0,0.4);
}
.support--left  { left: 15%;  transform: rotate(12deg); }
.support--right { right: 15%; transform: rotate(-12deg); }

.skewer {
  position: absolute;
  top: 41%;
  left: 9%;
  width: 82%;
  height: 9px;
  border-radius: 6px;
  background: linear-gradient(90deg, #5a3d20, #855a30 50%, #5a3d20);
  transform: rotate(-1.5deg);
  box-shadow: 0 3px 5px rgba(0,0,0,0.45);
  z-index: 6;
}

/* --- the cooked fish, straddling the skewer --------------------------- */
.catch-fire {
  position: absolute;
  left: 50%;
  top: 41%;
  width: 62%;
  transform: translate(-50%, -50%);
  z-index: 7;
  animation: roast 5.5s ease-in-out infinite;
}
@keyframes roast {
  0%,100% { transform: translate(-50%, -50%) rotate(-3deg); }
  50%     { transform: translate(-50%, -50%) rotate(3deg); }
}
.catch-fire .grill { display: block; }
.catch-fire .heat {
  position: absolute;
  left: 12%;
  right: 12%;
  top: 62%;
  height: 70%;
  background: radial-gradient(60% 100% at 50% 100%, rgba(255,170,60,0.25), transparent 70%);
  filter: blur(3px);
  animation: shimmer 1.6s ease-in-out infinite;
  pointer-events: none;
  z-index: -1;
}
@keyframes shimmer {
  0%,100% { transform: scaleY(1) translateY(0); opacity: 0.6; }
  50%     { transform: scaleY(1.12) translateY(-4px); opacity: 0.9; }
}

/* --- the campfire ----------------------------------------------------- */
.campfire {
  position: absolute;
  left: 50%;
  bottom: 4%;
  transform: translateX(-50%);
  width: 42%;
  height: 30%;
}
.campfire .glow {
  position: absolute;
  left: 50%;
  bottom: -20%;
  width: 240%;
  height: 220%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(255,150,45,0.55), rgba(255,90,20,0.18) 55%, transparent 75%);
  filter: blur(6px);
  animation: pulse 2.6s ease-in-out infinite;
  z-index: 0;
}
@keyframes pulse { 0%,100% { opacity: 0.75; } 50% { opacity: 1; } }

.campfire .logs { position: absolute; left: 50%; bottom: 0; width: 100%; height: 34%; transform: translateX(-50%); z-index: 2; }
.campfire .log {
  position: absolute;
  bottom: 6%;
  left: 50%;
  width: 78%;
  height: 26%;
  border-radius: 8px;
  background: linear-gradient(180deg, #6b4a2c, #34210f);
  box-shadow: inset 0 2px 3px rgba(255,180,90,0.25);
}
.campfire .log--a { transform: translateX(-50%) rotate(18deg); }
.campfire .log--b { transform: translateX(-50%) rotate(-18deg); }

.campfire .flames {
  position: absolute;
  left: 50%;
  bottom: 18%;
  width: 100%;
  height: 100%;
  transform: translateX(-50%);
  z-index: 1;
}
.flame {
  position: absolute;
  left: 50%;
  bottom: 0;
  border-radius: 50% 50% 50% 50% / 72% 72% 30% 30%;
  transform-origin: 50% 90%;
  will-change: transform;
}
.flame--outer {
  width: 58%; height: 96%;
  margin-left: -29%;
  background: radial-gradient(60% 80% at 50% 78%, #ffb02e 0%, #ff6a00 48%, #d63a00 82%, rgba(214,58,0,0) 100%);
  filter: blur(1px);
  animation: flicker 0.9s ease-in-out infinite;
}
.flame--mid {
  width: 40%; height: 74%;
  margin-left: -20%;
  background: radial-gradient(60% 80% at 50% 78%, #ffe07a 0%, #ffab2e 55%, rgba(255,120,0,0) 100%);
  animation: flicker 0.66s ease-in-out infinite reverse;
}
.flame--inner {
  width: 22%; height: 48%;
  margin-left: -11%;
  background: radial-gradient(60% 80% at 50% 80%, #fff7e0 0%, #ffe27a 60%, rgba(255,210,80,0) 100%);
  animation: flicker 0.5s ease-in-out infinite;
}
@keyframes flicker {
  0%,100% { transform: scaleY(1)    scaleX(1)    skewX(0deg);   opacity: 0.95; }
  25%     { transform: scaleY(1.1)  scaleX(0.92) skewX(-3deg);  opacity: 1;    }
  50%     { transform: scaleY(0.94) scaleX(1.05) skewX(2deg);   opacity: 0.9;  }
  75%     { transform: scaleY(1.06) scaleX(0.96) skewX(-1deg);  opacity: 1;    }
}

.campfire .sparks { position: absolute; inset: -30% 0 0 0; z-index: 3; pointer-events: none; }
.campfire .spark {
  position: absolute;
  bottom: 20%;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: #ffd06a;
  box-shadow: 0 0 6px 1px rgba(255,170,60,0.8);
  animation: rise linear infinite;
  opacity: 0;
}
@keyframes rise {
  0%   { transform: translateY(0) scale(1);      opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: translateY(-220px) scale(0.2); opacity: 0; }
}

/* --- corner wordmark -------------------------------------------------- */
#fire .wordmark {
  position: absolute;
  left: 0; right: 0;
  bottom: 3.2vh;
  text-align: center;
  font-size: 3vmin;
  letter-spacing: 0.35em;
  text-transform: lowercase;
  color: rgba(255, 228, 190, 0.6);
}

/* --- misc ------------------------------------------------------------- */
.fallback-note {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 4vw;
  text-align: center;
  padding: 0 6vw;
}

/* =====================================================================
   Reduced motion — skip the whole thing, hold the final tableau still
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  #shark { display: none; }
  #rig   { display: none; }
  #ja     { opacity: 0 !important; }
  #fire   { opacity: 1 !important; }
  .catch-fire,
  .flame, .campfire .glow, #fire .star, .campfire .spark, .catch-fire .heat {
    animation: none !important;
  }
}
