/* ──────────────────────────────────────────────────────────
   Duck cursor + flower-field chicks. Desktop/mouse only (see the
   (hover:hover) and (pointer:fine) guard in duck-cursor.js) — touch
   devices keep their native tap behavior and never get body.duck-
   cursor-active, so none of the cursor-hiding rules below apply there.
   The chicks themselves still walk on touch devices; only the duck
   cursor/fart/collision system is desktop-only.
   ────────────────────────────────────────────────────────── */

body.duck-cursor-active,
body.duck-cursor-active * {
  cursor: none !important;
}

/* At the farewell note the duck disperses into atoms that reform as the
   site's plain black-dot cursor — normally kept at opacity:0 while the
   duck is the pointer — which fades in to take over. */
body.outro-dot-cursor .site-cursor {
  opacity: 1;
}

/* The glowing fairy-dust specks the duck scatters into before coalescing
   onto the dot (see the disperse effect in duck-cursor.js). Each speck's
   colour + glow are set per-particle in JS. */
.duck-atom {
  position: fixed;
  top: 0;
  left: 0;
  border-radius: 50%;
  pointer-events: none;
  z-index: 9999;
  will-change: transform, opacity;
}

.duck-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 64px;
  height: auto;
  pointer-events: none;
  z-index: 9999;
  user-select: none;
  -webkit-user-select: none;
}

.duck-fart,
.duck-fart-fx {
  position: fixed;
  top: 0;
  left: 0;
  width: 34px;
  height: auto;
  pointer-events: none;
  z-index: 9998;
  opacity: 0;
  user-select: none;
  -webkit-user-select: none;
}
.duck-fart.is-visible,
.duck-fart-fx.is-visible {
  opacity: 1;
}

/* ─── Duck speech bubble ────────────────────────────────────
   Replaces both the old per-flower CSS tooltip and the old
   .site-cursor "view case study" pill — one consistent voice (the
   duck) reacts to hovering a planted flower or a project card instead.
   Position (translate) is written inline by duck-cursor.js every
   frame, same pattern as the duck/fart elements above. */
.duck-speech-bubble {
  position: fixed;
  top: 0;
  left: 0;
  max-width: 260px;
  width: max-content;
  padding: 10px 16px;
  border-radius: 16px;
  background: rgba(8, 12, 18, 0.92);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.2px;
  text-align: center;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
  pointer-events: none;
  z-index: 9998;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1.4);
}
.duck-speech-bubble.is-visible {
  opacity: 1;
}
.duck-speech-bubble::after {
  content: '';
  position: absolute;
  width: 10px;
  height: 10px;
  background: rgba(8, 12, 18, 0.92);
  border-radius: 2px;
}
/* Tail points down toward the duck when the bubble sits above it,
   flipped to point up when the duck is near the top of the screen and
   the bubble has to sit below instead (see duck-cursor.js). */
.duck-speech-bubble[data-tail="down"]::after {
  left: 50%;
  bottom: -4px;
  transform: translateX(-50%) rotate(45deg);
}
.duck-speech-bubble[data-tail="up"]::after {
  left: 50%;
  top: -4px;
  transform: translateX(-50%) rotate(45deg);
}

/* ─── Walking chicks ────────────────────────────────────────
   Two hosts share this base rule: .field-chicks-top is absolutely
   positioned within .guestbook-frame (left/top percentages relative to
   the flower field itself, near its top edge), while
   .field-chicks-global is fixed to the viewport bottom so the same
   chicks read as walking along the ground on every section, not just
   the guestbook. */
.field-chicks {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}
.field-chicks-global {
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: visible;
}
.field-chicks-global .field-chick {
  position: fixed;
}
.field-chick {
  position: absolute;
  width: 46px;
  height: 46px;
  /* object-fit:contain rather than height:auto — the two walk-cycle
     frames (chick-walk-01/02.png) have noticeably different aspect
     ratios (~0.89 vs ~1.01), so height:auto made the box itself resize
     by a few px every time the frame swapped, reading as a flicker/
     blink every 220ms instead of a smooth walk cycle. A fixed box lets
     each frame scale to fit without changing the box's own size. */
  object-fit: contain;
  will-change: transform;
  user-select: none;
  -webkit-user-select: none;
}
.field-chick.is-dead {
  width: 50px;
  height: 50px;
}

/* The walking duck that joins the chick flock along the bottom when the
   duck isn't acting as the pointer cursor (mobile). Bigger than a chick
   and portrait (duck art is ~353x503, ~0.70), with a fixed box +
   object-fit:contain so the two walk frames' slightly different aspect
   ratios don't resize the box on each swap (same fix as the chicks). */
.field-duck {
  width: 48px;
  height: 68px;
}
