/* Timelapse Maestro — shared "live demo" stage styles.
 *
 * The phone (real Flutter app in an iframe) + the CSS-3D NMX rig that animates
 * from the app's simulated motor telemetry. Used by BOTH the dedicated demo
 * page (try.html) and the embedded demo section on the landing page
 * (index.html), so this is the single source of truth for the stage — edit
 * here, not inline. Paired with demo.js (markup wiring + telemetry bridge).
 * Relies on the color tokens from style.css. */

/* The stage holds the phone + the external rig, side by side. */
.stage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 48px;
  padding: 40px 24px 72px;
  max-width: var(--maxw);
  margin: 0 auto;
}
/* On a narrow screen the two columns stack. Float the rig ABOVE the phone
   and let its tripod base overlap the phone's top edge, so the two read
   as one tight unit — the rig "stands on" the phone, with no gap. The rig
   label rides above the rig so nothing sits in the overlap zone. */
@media (max-width: 760px) {
  .stage {
    flex-direction: column;
    gap: 0;
    padding-top: 24px;
  }
  /* Scoped under .stage so these beat the single-class base rules defined
     later in the file (equal specificity → source order would win). */
  .stage .rig-stage {
    order: -1;
    /* In a column the flex-basis maps to HEIGHT — the base `flex: 1 1 380px`
       would inflate the block and open a gap. Reset to content height and
       stretch to full width so the rig reads big. */
    flex: 0 0 auto;
    align-self: stretch;
    max-width: none;
    width: 100%;
    display: flex;
    flex-direction: column;
    /* Tuck the rig's empty footroom down over the phone's top edge. */
    margin-bottom: -48px;
    position: relative;
    z-index: 5;
    /* Touches in the overlap fall through to the phone underneath. */
    pointer-events: none;
  }
  /* "Move the joystick →" hint is desktop-only — the → and green cue don't
     read stacked, and the hero copy already prompts the action. */
  .stage .rig-stage .hint-row {
    display: none;
  }
  /* Label above the rig so nothing sits between the rig and the phone. */
  .stage .rig-stage .rig-caption {
    order: 1;
    margin: 0 0 14px;
  }
  /* Tall enough to hold the camera head (it reaches ~216px up from the
     rig base) with headroom, so the label clears it instead of colliding.
     The extra height grows upward — the bottom overlap is unchanged. */
  .stage .rig3d {
    order: 2;
    height: 240px;
    max-width: none;
  }
  .stage .phone {
    position: relative;
    z-index: 1;
  }
}

/* ── Phone bezel wrapping the real Flutter app ───────────── */
.phone {
  /* --w: phone outer width (unitless px). --lw/--lh: the app's logical
     viewport — rendering it larger than the bezel and scaling down means
     more room for the UI (so "Go To" fits and pages don't overflow). */
  --w: 340;
  --lw: 420;
  --lh: 910;
  position: relative;
  width: calc(var(--w) * 1px);
  height: calc((var(--w) - 28) * var(--lh) / var(--lw) * 1px + 28px);
  background: #0a0a0a;
  border: 2px solid var(--border-light);
  border-radius: 44px;
  padding: 14px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.7),
    inset 0 0 0 2px #000;
  flex: 0 0 auto;
}
@media (max-width: 430px) {
  .phone {
    --w: 300;
  }
}
.phone .screen {
  position: absolute;
  inset: 14px;
  border-radius: 32px;
  overflow: hidden;
  background: #000;
}
.phone .screen iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(var(--lw) * 1px);
  height: calc(var(--lh) * 1px);
  border: 0;
  transform: scale(calc((var(--w) - 28) / var(--lw)));
  transform-origin: top left;
  display: block;
}
.phone-loading {
  position: absolute;
  inset: 14px;
  border-radius: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.9rem;
  pointer-events: none;
}

/* ── External rig ────────────────────────────────────────── */
.rig-stage {
  flex: 1 1 380px;
  min-width: 300px;
  max-width: 560px;
}
.rig-stage .rig-caption {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.88rem;
  margin-top: 14px;
}

/* ── 3D rig ───────────────────────────────────────────────
   Pan = yaw (rotateY) and tilt = pitch (rotateX) so they read as
   genuinely different axes — not two in-plane leans. A slight downward
   look (perspective + tilted floor) gives the head depth. */
.rig3d {
  position: relative;
  width: 100%;
  max-width: 520px;
  height: 340px;
  margin: 0 auto;
  perspective: 900px;
  /* Shape/colors/depth come from rig-model.js (the single source of truth);
     hide until RigModel.applyRig() has styled + extruded the parts so the
     pre-JS placeholder shape never flashes. applyRig sets visibility:visible. */
  visibility: hidden;
}
.floor {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(12deg);
}
/* Tripod feet */
.leg {
  position: absolute;
  bottom: 30px;
  width: 6px;
  height: 38px;
  background: #1d1d1d;
  border-radius: 3px;
}
.leg.l {
  left: 27%;
  transform: rotate(20deg);
}
.leg.r {
  right: 27%;
  transform: rotate(-20deg);
}
/* Rear tripod leg — drops straight down behind the rail (foreshortened). */
.leg.c {
  left: 50%;
  margin-left: -3px;
  bottom: 34px;
  height: 24px;
  background: #161616;
}
/* Slider rail */
.rail {
  position: absolute;
  left: 8%;
  right: 8%;
  height: 18px;
  border-radius: 10px;
  background: linear-gradient(#3a3a3a, #141414 55%, #050505);
  bottom: 64px;
  box-shadow: inset 0 2px 3px rgba(255, 255, 255, 0.07),
    0 8px 16px rgba(0, 0, 0, 0.6);
}
/* Drive-motor end blocks — blue anodised, one on each end of the rail. */
.rail::before,
.rail::after {
  content: "";
  position: absolute;
  top: -8px;
  width: 18px;
  height: 34px;
  border-radius: 5px;
  background: linear-gradient(#2a8ad0, #0c4a7d 60%, #093a63);
  border: 1px solid #062a49;
}
.rail::before {
  left: -16px;
}
.rail::after {
  right: -16px;
}
/* Carriage rides the rail (sled = translateX) */
.carriage {
  position: absolute;
  left: 50%;
  bottom: 73px;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transform: translateX(-50%);
  transition: transform 0.09s linear;
}
/* Carriage base — the blue NMX motor block riding the rail. Stays planted
   on the rail; the pan/tilt head turns above it, about the lens. */
.base {
  position: absolute;
  left: -44px;
  bottom: 5px;
  width: 88px;
  height: 20px;
  border-radius: 7px;
  background: linear-gradient(#2a8ad0, #0c4a7d 60%, #093a63);
  border: 1px solid #062a49;
  box-shadow: inset 0 2px 2px rgba(255, 255, 255, 0.18),
    0 10px 18px rgba(0, 0, 0, 0.5);
}
/* Pan pivot (yaw): anchored at the LENS CENTRE. rotateY turns the WHOLE
   head — the L-arm, the L-bracket and the camera — about the lens. */
.yaw {
  position: absolute;
  left: -5px;
  bottom: 85px;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transition: transform 0.09s linear;
}
/* L-arm — one piece, clipped from a blue block into an L (20px leg +
   18px foot). Child of #pan, so it swings with the pan about the lens. */
.arm {
  position: absolute;
  left: -73px;
  bottom: -59px;
  width: 96px;
  height: 85px;
  background: linear-gradient(90deg, #0c4a7d, #3a96da 46%, #0c4a7d);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 85' preserveAspectRatio='none'%3E%3Cpath d='M5 0 L9 0 Q14 0 14 5 L14 67 Q14 72 19 72 L91 72 Q96 72 96 77 L96 80 Q96 85 91 85 L5 85 Q0 85 0 80 L0 5 Q0 0 5 0 Z' fill='%23000'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 85' preserveAspectRatio='none'%3E%3Cpath d='M5 0 L9 0 Q14 0 14 5 L14 67 Q14 72 19 72 L91 72 Q96 72 96 77 L96 80 Q96 85 91 85 L5 85 Q0 85 0 80 L0 5 Q0 0 5 0 Z' fill='%23000'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
/* Tilt pivot (pitch): also at the lens centre (same point as #pan).
   rotateX pitches the L-bracket + camera about the lens; the L-arm
   stays put. */
.pitch {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transition: transform 0.09s linear;
}
/* L-bracket — one piece, the blue camera cradle (14px leg + 13px foot the
   camera sits on). Sized so the foot top meets the camera's underside and
   the leg top meets the camera top. Child of #tilt, tilts with the camera. */
.bracket {
  position: absolute;
  left: -59px;
  bottom: -36px;
  width: 107px;
  height: 59px;
  background: linear-gradient(90deg, #0c4a7d, #3a96da 46%, #0c4a7d);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 107 59' preserveAspectRatio='none'%3E%3Cpath d='M5 0 L9 0 Q14 0 14 5 L14 41 Q14 46 19 46 L102 46 Q107 46 107 51 L107 54 Q107 59 102 59 L5 59 Q0 59 0 54 L0 5 Q0 0 5 0 Z' fill='%23000'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 107 59' preserveAspectRatio='none'%3E%3Cpath d='M5 0 L9 0 Q14 0 14 5 L14 41 Q14 46 19 46 L102 46 Q107 46 107 51 L107 54 Q107 59 102 59 L5 59 Q0 59 0 54 L0 5 Q0 0 5 0 Z' fill='%23000'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
/* Camera — centred on the lens (the pan + tilt pivot). Original dark
   machined body. */
.camera {
  position: absolute;
  left: -46px;
  bottom: -24px;
  width: 92px;
  height: 48px;
  border-radius: 10px;
  background: linear-gradient(155deg, #3a3a3a, #161616);
  border: 1px solid #000;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
  transform-style: preserve-3d;
}
/* Flat, transparent tap target floated over the camera's projected
   position (see script). The camera lives in a preserve-3d subtree where
   touch/click hit-testing is unreliable, so taps were missing it; a flat
   fixed element always hit-tests cleanly. Tracks the camera every frame. */
.cam-hit {
  position: fixed;
  z-index: 50;
  background: transparent;
  cursor: pointer; /* tap-to-shoot easter egg */
  touch-action: manipulation; /* no 300ms tap delay / double-tap zoom */
  -webkit-tap-highlight-color: transparent; /* no blue tap flash */
  -webkit-touch-callout: none;
  user-select: none;
  -webkit-user-select: none;
  outline: none;
}
/* Lens — centred on the camera face (also the tilt pivot point). */
.lens {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 38%, #3a3a3a, #050505 72%);
  border: 3px solid #1a1a1a;
}
.rec {
  position: absolute;
  left: 8px;
  top: 8px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary-bright);
  box-shadow: 0 0 6px var(--primary-bright);
}
/* Continuous run with no shutter: the camera is rolling video, so blink
   the record light for the duration of the move. */
.camera.recording .rec {
  animation: rec-blink 1s steps(1, end) infinite;
}
@keyframes rec-blink {
  0%,
  50% {
    background: var(--primary-bright);
    box-shadow: 0 0 7px var(--primary-bright);
  }
  50.01%,
  100% {
    background: #3a1414;
    box-shadow: none;
  }
}
/* Green focus-assist lamp — lights while the camera is focusing. */
.focuslamp {
  position: absolute;
  left: 8px;
  top: 22px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #1c3a2a;
  transition: background 0.06s, box-shadow 0.06s;
}
.camera.focus .focuslamp {
  background: var(--green);
  box-shadow: 0 0 8px var(--green);
}
.camera.focus .lens {
  border-color: var(--green);
  box-shadow: 0 0 12px rgba(127, 220, 160, 0.7);
}
/* White shutter flash — a burst at the lens on each frame's trigger
   (not a whiteout of the whole camera body). */
.flash {
  position: absolute;
  left: 50%;
  top: 50%;
  margin: -25px 0 0 -25px;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    #ffffff 0%,
    rgba(255, 255, 255, 0.85) 38%,
    rgba(255, 255, 255, 0) 72%
  );
  opacity: 0;
  pointer-events: none;
}
.camera.shoot .flash {
  opacity: 1;
}
.camera.shoot .lens {
  background: #ffffff;
  border-color: #ffffff;
  box-shadow: 0 0 16px 5px rgba(255, 255, 255, 0.85);
}
.hint-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.hint {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 auto;
  padding: 8px 16px;
  border: 1px solid var(--border-light);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 0.9rem;
}
.hint .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 8px var(--green);
}
