/* ===== Home page extra 3D depth layer =====
   Scoped to home only (linked when $page==='home').
   Pure CSS/JS, no library. Respects prefers-reduced-motion via JS gate. */

/* Depth stage + raised planes: DESKTOP ONLY. On touch there is no tilt, so
   preserve-3d/translateZ would just add GPU cost + risk clipping. Gate it. */
@media (hover: hover) and (pointer: fine) {
  /* Give cards a 3D stage so JS tilt has perspective + depth */
  .fish-card,
  .combo-card {
    transform-style: preserve-3d;
    will-change: transform;
  }

  /* When JS is tilting a card, kill the slow transition so it tracks the pointer,
     then a smooth spring-back on leave (class toggled by JS). */
  .fish-card.tilt-active,
  .combo-card.tilt-active {
    transition: transform .05s linear !important;
  }
  .fish-card.tilt-reset,
  .combo-card.tilt-reset {
    transition: transform .5s cubic-bezier(.22,.61,.36,1) !important;
  }

  /* Lift inner pieces onto raised planes so tilt reads as real depth (parallax) */
  .fish-card .fish-media { transform: translateZ(28px); }
  .fish-card .fish-tag,
  .fish-card .oos-badge { transform: translateZ(46px); }
  .fish-card .fish-name { transform: translateZ(34px); }
  .fish-card .add-cart-btn { transform: translateZ(30px); }

  .combo-card .combo-img-wrap { transform: translateZ(30px); }
  .combo-card .combo-save-badge { transform: translateZ(52px); }
  .combo-card .combo-name { transform: translateZ(30px); }
}

/* Soft dynamic shadow driven by a CSS var the JS updates on tilt */
.fish-card.tilt-active,
.combo-card.tilt-active {
  box-shadow:
    calc(var(--tiltX, 0) * -14px) calc(var(--tiltY, 0) * 14px + 20px) 40px rgba(7, 34, 51, .28);
}

/* A moving glare sheen that follows the cursor across the card */
.fish-card::after,
.combo-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
  background: radial-gradient(
    circle at var(--glareX, 50%) var(--glareY, 0%),
    rgba(255, 255, 255, .35),
    rgba(255, 255, 255, 0) 45%
  );
  z-index: 3;
}
.fish-card.tilt-active::after,
.combo-card.tilt-active::after { opacity: 1; }

[data-theme="dark"] .fish-card::after,
[data-theme="dark"] .combo-card::after {
  background: radial-gradient(
    circle at var(--glareX, 50%) var(--glareY, 0%),
    rgba(120, 220, 205, .22),
    rgba(120, 220, 205, 0) 45%
  );
}

/* ===== Floating bubbles behind the catalog ===== */
.bubble-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.bubble-layer .bubble {
  position: absolute;
  bottom: -60px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%,
    rgba(255, 255, 255, .85),
    rgba(148, 214, 205, .35) 45%,
    rgba(47, 181, 163, .12) 70%);
  border: 1px solid rgba(255, 255, 255, .35);
  animation: bubbleRise linear infinite;
  opacity: 0;
}
[data-theme="dark"] .bubble-layer .bubble {
  background: radial-gradient(circle at 32% 28%,
    rgba(180, 240, 230, .5),
    rgba(47, 181, 163, .18) 55%,
    rgba(10, 55, 79, .05) 75%);
  border-color: rgba(120, 220, 205, .22);
}
@keyframes bubbleRise {
  0%   { transform: translateY(0) scale(.6); opacity: 0; }
  12%  { opacity: .7; }
  85%  { opacity: .5; }
  100% { transform: translateY(-115vh) scale(1); opacity: 0; }
}

/* Keep real content above the bubble layer */
.catalog .section-title,
.catalog .section-sub,
.catalog .search-row,
.catalog .filter-row,
.catalog .combo-grid,
.catalog .grid { position: relative; z-index: 1; }

/* Combo cards fade+rise in like the fish cards already do */
.combo-card.reveal-3d {
  opacity: 0;
  transform: translateY(26px) scale(.97);
  transition: opacity .6s ease, transform .6s cubic-bezier(.22,.61,.36,1);
}
.combo-card.reveal-3d.in-view {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .bubble-layer { display: none; }
  .combo-card.reveal-3d { opacity: 1; transform: none; }
}

/* ============================================================
   Hero character (default theme) — fisherman landing a catch.
   ONLY adds the character. The hero keeps its original height and its
   original text position: no min-height, no flex centring, no extra
   padding on wide screens — so the headline wraps exactly as before.
   Geometry from the reference (1536x727 hero):
     width 39% of hero  ·  right gap 1.37%  ·  bottom flush
   Sized off hero WIDTH so the ratio holds on Windows, macOS,
   iPhone and Android alike.
   ============================================================ */
.hero-character {
  position: absolute;
  right: 1.37%;              /* reference right gap */
  bottom: 0;                 /* stands on the hero floor */
  /* Anchored to hero HEIGHT, not width: the real hero is shorter than the
     reference mock, and a width-based size would push his head past the
     top edge and get clipped by .hero's overflow:hidden. 92% of the hero
     height matches the reference's 86% share and can never overflow. */
  height: 92%;
  width: auto;
  max-width: 46%;            /* never crowd the copy on short, wide heroes */
  min-height: 200px;
  z-index: 1;                /* under .tide-line so the wave laps his legs */
  pointer-events: none;
  animation: castBob 5.5s ease-in-out infinite;
}
@keyframes castBob {
  0%, 100% { transform: translateY(0)     rotate(0deg); }
  50%      { transform: translateY(-10px) rotate(-.6deg); }
}

/* Only guard the copy from him once the hero gets narrow enough for them
   to actually collide. Wide screens are left exactly as they were. */
@media (max-width: 1180px) {
  .hero-with-character .hero-inner { padding-right: min(34%, 300px); }
}
@media (max-width: 820px) {
  .hero-with-character .hero-inner { padding-right: min(30%, 220px); }
  .hero-character { width: 44%; right: 1%; }
}

/* Phones: side-by-side stops working — he moves below the copy. */
@media (max-width: 640px) {
  .hero-with-character .hero-inner { padding-right: 0; }
  .hero-character {
    position: static;
    display: block;
    margin: 18px auto 0;
    height: auto;            /* stacked: size by width again */
    width: min(72%, 300px);
    max-width: none;
    min-width: 0;
    min-height: 0;
    animation: castBobMobile 5.5s ease-in-out infinite;
  }
  @keyframes castBobMobile {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-7px); }
  }
}

/* Landscape phones: hero is very short — keep him beside the copy, capped. */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 500px) {
  .hero-character {
    position: absolute; margin: 0; right: 1%; bottom: 0;
    height: 94%; width: auto; max-width: 38%; min-height: 0;
  }
  .hero-with-character .hero-inner { padding-right: min(32%, 240px); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-character { animation: none; }
}
