/* styles/page-decor.css — site-wide decorative DNA helix (left margin) and
   vine (right margin), grown in once each page's intro banner (.hero or
   .page-header) scrolls up behind the sticky navbar — see
   js/components/page-decor.js, which also sets top/height inline once it
   knows the page's real length (capped at the footer's top edge, so the
   strand never runs behind the footer) and sets transition-duration inline
   on the backbone/stem so the draw SPEED is constant across pages of any
   length, rather than the total draw time. position: absolute (not fixed)
   so once grown, the strand is part of the page itself — it scrolls out of
   view like normal content, rather than staying pinned to the viewport. Only
   shows once the viewport is wide enough to have real margin space outside
   the 1200px container (>=1500px) — narrower than that, including actual
   mobile, neither strand renders at all. Purely decorative: aria-hidden, no
   pointer events. */

.page-decor {
  display: none;
}

.page-decor svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

@media (min-width: 1500px) {
  .page-decor {
    display: block;
    position: absolute;
    top: 0;
    /* height set inline by page-decor.js once it knows how tall the page
       actually is — nothing to show before that anyway, since the SVG
       itself isn't built until the grow-in trigger fires. */
    width: 90px;
    pointer-events: none;
    z-index: 1;
  }
  .page-decor-left {
    left: 0;
  }
  .page-decor-right {
    right: 0;
  }
}

/* ---- DNA helix ---- */
.decor-dna-backbone {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 3;
  stroke-linecap: round;
  /* Duration is set inline by page-decor.js (constant px/ms speed across
     pages of any length) — only the property/easing live here. */
  transition-property: stroke-dashoffset;
  transition-timing-function: ease-out;
}

.decor-dna-rung {
  stroke: var(--color-accent);
  stroke-width: 3;
  stroke-linecap: round;
  opacity: 0;
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 250ms ease, transform 250ms ease;
}

.decor-dna-rung.is-revealed {
  opacity: 1;
  transform: scaleX(1);
}

/* ---- Vine ---- */
.decor-vine-stem {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 3;
  stroke-linecap: round;
  transition-property: stroke-dashoffset;
  transition-timing-function: ease-out;
}

.decor-vine-leaf {
  fill: var(--color-accent);
  opacity: 0;
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 300ms ease, transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.decor-vine-leaf.is-revealed {
  opacity: 1;
  transform: scale(1);
}

/* Tiny colorful flowers interspersed along the vine — each is a static
   outer <g> (position, set via a transform attribute in JS) wrapping this
   inner group, which CSS reveals with its own scale-in transform. Color
   comes from a --flower-color custom property set per-instance in JS,
   cycling through a small palette. */
.decor-vine-flower-small {
  opacity: 0;
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 300ms ease, transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.decor-vine-flower-small.is-revealed {
  opacity: 1;
  transform: scale(1);
}

.decor-vine-flower-small ellipse {
  fill: var(--flower-color, #fff);
}

.decor-vine-flower-small-center {
  fill: var(--color-primary-dark);
}

/* ---- Methylation enzyme (DNA side) ---- */
.decor-enzyme-body {
  fill: var(--color-primary-dark);
}

.decor-enzyme-notch {
  fill: var(--color-bg);
}

/* Rest state sits at the anchor point, away from the strand, invisible. */
.decor-dna-enzyme {
  opacity: 0;
  transform: translate(0, 0);
}

.decor-methyl-dot {
  fill: #d98c2b;
  opacity: 0;
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 500ms ease, transform 500ms ease;
}

.decor-dna-enzyme.is-docking {
  animation: decor-enzyme-dock 6s ease-in-out forwards;
}

.decor-methyl-dot.is-active {
  animation: decor-methyl-pop 6s ease-in-out forwards;
}

/* Played instead of .is-active when the enzyme comes back to a mark it left
   earlier — the mark only ever disappears as a visible result of this, never
   on its own timer. */
.decor-methyl-dot.is-removing {
  animation: decor-methyl-remove 6s ease-in-out forwards;
}

/* The enzyme slides in from the anchor to translate(-40px, 0) — actually
   touching the strand — pulses there, then slides back out. */
@keyframes decor-enzyme-dock {
  0% {
    opacity: 0;
    transform: translate(0, 0);
  }
  20% {
    opacity: 1;
    transform: translate(-40px, 0);
  }
  25%,
  60% {
    opacity: 1;
    transform: translate(-40px, 0) scale(1.08);
  }
  80% {
    opacity: 1;
    transform: translate(0, 0);
  }
  100% {
    opacity: 0;
    transform: translate(0, 0);
  }
}

/* Stays hidden until well after the enzyme has arrived and started
   pulsing (20-25%) — the mark only appears once it's actually touched
   down, not before. */
@keyframes decor-methyl-pop {
  0%,
  30% {
    opacity: 0;
    transform: scale(0);
  }
  45% {
    opacity: 1;
    transform: scale(1.3);
  }
  55% {
    transform: scale(1);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Mirrors decor-methyl-pop in reverse — stays put while the enzyme travels
   in, shrinks away once it's docked and pulsing (same 25-60% window as
   decor-enzyme-dock's own pulse), then stays gone. */
@keyframes decor-methyl-remove {
  0%,
  20% {
    opacity: 1;
    transform: scale(1);
  }
  45% {
    transform: scale(1.3);
  }
  60%,
  100% {
    opacity: 0;
    transform: scale(0);
  }
}

/* ---- Spider (vine side) ---- */
/* Not a permanent resident — invisible except during its own visit, which
   fades the whole assembly (thread + spider + legs) in just before the
   thread starts growing and back out just after the spider's climbed back
   up, wrapping the drop/climb animations below. */
.decor-spider-anchor {
  opacity: 0;
}

.decor-spider-anchor.is-visiting {
  animation: decor-spider-anchor-visit 8s ease-in-out forwards;
}

@keyframes decor-spider-anchor-visit {
  0%,
  100% {
    opacity: 0;
  }
  8%,
  92% {
    opacity: 1;
  }
}

.decor-spider-thread {
  stroke: var(--color-text-muted);
  stroke-width: 1;
  transform: scaleY(0);
  transform-box: fill-box;
  transform-origin: top;
}

.decor-spider-body {
  fill: var(--color-text);
}

.decor-spider-leg {
  stroke: var(--color-text);
  stroke-width: 1.5;
}

.decor-spider-thread.is-dropping {
  animation: decor-thread-grow 8s ease-in-out forwards;
}

.decor-spider.is-dropping {
  animation: decor-spider-drop 8s ease-in-out forwards;
}

@keyframes decor-thread-grow {
  0%,
  100% {
    transform: scaleY(0);
  }
  25%,
  70% {
    transform: scaleY(1);
  }
}

@keyframes decor-spider-drop {
  0% {
    transform: translateY(0);
  }
  25%,
  60% {
    transform: translateY(90px);
  }
  66% {
    transform: translateY(90px) translateX(4px);
  }
  72% {
    transform: translateY(90px) translateX(-4px);
  }
  78% {
    transform: translateY(90px);
  }
  100% {
    transform: translateY(0);
  }
}
