/*
 * Ink graphics — the drawing system shared by the service page illustrations
 * -------------------------------------------------------------------------
 * One language across every page: line art drawn on with a staggered
 * stroke-dasharray cascade, then a short loop. White strokes on the navy
 * heroes, #1e293b strokes on the white how-it-works scenes.
 *
 * Spec: docs/Redesign/design_handoff_service_pages/ANIMATIONS.md
 *
 * Two rules from that doc that must not be undone:
 *
 *   1. Closed round shapes must NOT take the dash-draw. <circle> and two-arc
 *      paths render with a visible seam in some rasterizers even at
 *      stroke-dashoffset 0, so coins and seals get .ink-dN for the fade
 *      WITHOUT .ink-draw.
 *   2. Looping groups need `both` fill mode, or an element holds its base
 *      position through the draw-in instead of its 0% keyframe — a pen parked
 *      mid-frame, or a seal visible before it is stamped.
 *
 * Restart: every animation rule sits behind .ink-anim on the scene root.
 * how_it_works_controller removes that class, forces a reflow, and re-adds it,
 * so a scene shown a second time draws again instead of appearing finished.
 *
 * Currently carries the Insure hero and the four Insure how-it-works scenes.
 * The escrow / finance / manage loops belong here too as those pages land.
 */

/* ======================= draw-in cascade (hd1–hd6) =======================
   Each path carries pathLength="1", so one normalized keyframe set draws
   paths of any length. Group by visual depth: ground and major silhouettes on
   hd1/hd2, detail on hd5/hd6. */

@keyframes hd1 {
  0% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  10% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

@keyframes hd2 {
  0%,
  7% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  17% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

@keyframes hd3 {
  0%,
  14% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  24% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

@keyframes hd4 {
  0%,
  21% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  31% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

@keyframes hd5 {
  0%,
  28% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  38% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

@keyframes hd6 {
  0%,
  35% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
  }
  45% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
}

/* Hand-drawn wobble on the white scenes. steps(1) keeps it a jitter, not a
   slide. */
@keyframes inkBoil2 {
  0% {
    transform: translate(0, 0);
  }
  33% {
    transform: translate(0.4px, -0.3px);
  }
  66% {
    transform: translate(-0.3px, 0.4px);
  }
  100% {
    transform: translate(0, 0);
  }
}

/* ======================= how-it-works scene loops ======================= */

@keyframes hcursor {
  0%,
  46% {
    opacity: 0;
    transform: translate(-16px, 12px);
  }
  52% {
    opacity: 1;
    transform: translate(0, 0);
  }
  58% {
    opacity: 1;
    transform: translate(0, 2px);
  }
  64% {
    opacity: 1;
    transform: translate(0, 0);
  }
  78%,
  100% {
    opacity: 0;
    transform: translate(0, 0);
  }
}

@keyframes hclick {
  0%,
  52% {
    transform: scale(0.2);
    opacity: 0;
  }
  58% {
    transform: scale(1);
    opacity: 0.9;
  }
  68% {
    transform: scale(2.3);
    opacity: 0;
  }
  100% {
    transform: scale(2.3);
    opacity: 0;
  }
}

@keyframes hmailOut {
  0%,
  64% {
    transform: translate(0, 0);
    opacity: 0;
  }
  70% {
    transform: translate(6px, -5px);
    opacity: 1;
  }
  88% {
    transform: translate(62px, -34px);
    opacity: 1;
  }
  100% {
    transform: translate(96px, -50px);
    opacity: 0;
  }
}

@keyframes hmailIn {
  0% {
    transform: translate(-92px, -46px);
    opacity: 0;
  }
  8% {
    transform: translate(-72px, -36px);
    opacity: 1;
  }
  26% {
    transform: translate(-8px, -4px);
    opacity: 1;
  }
  34%,
  100% {
    transform: translate(0, 0);
    opacity: 0;
  }
}

@keyframes hcheck {
  0%,
  62% {
    stroke-dashoffset: 1;
    opacity: 0;
  }
  66% {
    opacity: 1;
  }
  74% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

@keyframes hcheck2 {
  0%,
  72% {
    stroke-dashoffset: 1;
    opacity: 0;
  }
  76% {
    opacity: 1;
  }
  84% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

@keyframes hpenWork {
  0%,
  40% {
    transform: translate(0, 0) rotate(0deg);
  }
  52% {
    transform: translate(11px, 2px) rotate(-5deg);
  }
  64% {
    transform: translate(3px, 5px) rotate(3deg);
  }
  76% {
    transform: translate(14px, 3px) rotate(-4deg);
  }
  88%,
  100% {
    transform: translate(6px, 1px) rotate(0deg);
  }
}

@keyframes hmergeL {
  0%,
  44% {
    transform: translate(-34px, 0);
    opacity: 1;
  }
  68% {
    transform: translate(0, 0);
    opacity: 1;
  }
  74%,
  100% {
    transform: translate(0, 0);
    opacity: 0;
  }
}

@keyframes hmergeR {
  0%,
  44% {
    transform: translate(34px, 0);
    opacity: 1;
  }
  68% {
    transform: translate(0, 0);
    opacity: 1;
  }
  74%,
  100% {
    transform: translate(0, 0);
    opacity: 0;
  }
}

@keyframes hmergeOne {
  0%,
  72% {
    opacity: 0;
    transform: scale(0.9);
  }
  80% {
    opacity: 1;
    transform: scale(1.05);
  }
  86%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes hdollar1 {
  0%,
  76% {
    opacity: 0;
    transform: translate(0, 6px);
  }
  84% {
    opacity: 1;
    transform: translate(0, -8px);
  }
  100% {
    opacity: 0;
    transform: translate(0, -20px);
  }
}

@keyframes hdollar2 {
  0%,
  82% {
    opacity: 0;
    transform: translate(0, 6px);
  }
  90% {
    opacity: 1;
    transform: translate(0, -8px);
  }
  100% {
    opacity: 0;
    transform: translate(0, -20px);
  }
}

@keyframes hsign {
  0%,
  58% {
    stroke-dashoffset: 1;
  }
  84% {
    stroke-dashoffset: 0;
  }
  100% {
    stroke-dashoffset: 0;
  }
}

@keyframes hsmile {
  0%,
  84% {
    stroke-dashoffset: 1;
  }
  92% {
    stroke-dashoffset: 0;
  }
  100% {
    stroke-dashoffset: 0;
  }
}

/* ======================== escrow-signing (hero) ========================
   Three documents fall and sway, a pen signs the top sheet, the signed pile
   slides into the finished stack. 7s loop, 2.8s delay so the draw-in lands
   first. */

@keyframes escSheet0 {
  0% {
    transform: translate(-26px, -196px) rotate(-17deg);
    opacity: 0;
  }
  3% {
    opacity: 1;
  }
  9% {
    transform: translate(-13px, -104px) rotate(11deg);
    opacity: 1;
  }
  17%,
  62% {
    transform: translate(0, 0) rotate(-1deg);
    opacity: 1;
  }
  74% {
    transform: translate(96px, 40px) rotate(2deg);
    opacity: 0.55;
  }
  80%,
  100% {
    transform: translate(100px, 46px) rotate(2deg);
    opacity: 0;
  }
}

@keyframes escSheet1 {
  0%,
  7% {
    transform: translate(22px, -196px) rotate(15deg);
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  16% {
    transform: translate(11px, -104px) rotate(-9deg);
    opacity: 1;
  }
  24%,
  62% {
    transform: translate(-6px, -5px) rotate(0deg);
    opacity: 1;
  }
  74% {
    transform: translate(99px, 49px) rotate(3deg);
    opacity: 0.55;
  }
  80%,
  100% {
    transform: translate(103px, 55px) rotate(3deg);
    opacity: 0;
  }
}

@keyframes escSheet2 {
  0%,
  14% {
    transform: translate(-14px, -196px) rotate(-9deg);
    opacity: 0;
  }
  17% {
    opacity: 1;
  }
  23% {
    transform: translate(-7px, -104px) rotate(7deg);
    opacity: 1;
  }
  31%,
  62% {
    transform: translate(-12px, -10px) rotate(1deg);
    opacity: 1;
  }
  74% {
    transform: translate(102px, 58px) rotate(4deg);
    opacity: 0.55;
  }
  80%,
  100% {
    transform: translate(106px, 64px) rotate(4deg);
    opacity: 0;
  }
}

@keyframes escSignDraw {
  0%,
  40% {
    stroke-dashoffset: 1;
  }
  58%,
  68% {
    stroke-dashoffset: 0;
  }
  69%,
  100% {
    stroke-dashoffset: 1;
  }
}

@keyframes escPenMove {
  0%,
  34% {
    transform: translate(-54px, 34px);
    opacity: 0;
  }
  40% {
    transform: translate(-42px, 16px);
    opacity: 1;
  }
  58% {
    transform: translate(6px, 4px);
    opacity: 1;
  }
  68% {
    transform: translate(14px, 0);
    opacity: 1;
  }
  73%,
  100% {
    transform: translate(46px, -18px);
    opacity: 0;
  }
}

/* ====================== finance-piggy-bank (hero) ====================== */

@keyframes coinDrop0 {
  0% {
    transform: translateY(-96px);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  62% {
    transform: translateY(0);
    opacity: 1;
  }
  72%,
  100% {
    transform: translateY(4px);
    opacity: 0;
  }
}

@keyframes coinDrop1 {
  0% {
    transform: translate(-8px, -96px);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  62% {
    transform: translate(0, 0);
    opacity: 1;
  }
  72%,
  100% {
    transform: translateY(4px);
    opacity: 0;
  }
}

@keyframes coinDrop2 {
  0% {
    transform: translate(9px, -96px);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  62% {
    transform: translate(0, 0);
    opacity: 1;
  }
  72%,
  100% {
    transform: translateY(4px);
    opacity: 0;
  }
}

@keyframes billFall0 {
  0% {
    transform: translate(-30px, -108px) rotate(-16deg);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  60% {
    transform: translate(-4px, -6px) rotate(4deg);
    opacity: 1;
  }
  70%,
  100% {
    transform: translate(0, 2px) rotate(6deg);
    opacity: 0;
  }
}

@keyframes billFall1 {
  0% {
    transform: translate(26px, -104px) rotate(14deg);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  60% {
    transform: translate(4px, -6px) rotate(-5deg);
    opacity: 1;
  }
  70%,
  100% {
    transform: translate(0, 2px) rotate(-7deg);
    opacity: 0;
  }
}

/* ====================== manage-beachfront (hero) ====================== */

@keyframes mgSwing {
  0% {
    transform: rotate(-5deg);
  }
  50% {
    transform: rotate(5deg);
  }
  100% {
    transform: rotate(-5deg);
  }
}

/* ===================== notary-counter (Escrow scene) =====================
   Visitor walks in, hands a document across the counter, the notary stamps it,
   an orange seal appears. All four loop groups need `backwards` fill mode so
   during the draw-in the visitor sits off-screen and the seal is invisible. */

@keyframes notArrive {
  0% {
    transform: translateX(-150px);
  }
  16%,
  100% {
    transform: translateX(0);
  }
}

@keyframes notHandOff {
  0%,
  28% {
    transform: translate(0, 0);
  }
  44%,
  100% {
    transform: translate(42px, 3px);
  }
}

@keyframes notStampPress {
  0%,
  52% {
    transform: rotate(0deg);
  }
  62%,
  70% {
    transform: rotate(-18deg);
  }
  80%,
  100% {
    transform: rotate(0deg);
  }
}

@keyframes notSeal {
  0%,
  64% {
    opacity: 0;
  }
  72%,
  94% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* ============================ applying it ============================ */

/* Any stroked path taking the dash-draw. Never put this on a <circle>. */
.ink-draw {
  stroke-dasharray: 1;
}

/* Duration and easing differ between the heroes and the white scenes, so the
   six cascade classes read them from the scene root rather than duplicating. */
.ink-hero {
  --ink-dur: 2.6s;
  --ink-ease: cubic-bezier(0.4, 0, 0.2, 1);
}

.ink-scene {
  --ink-dur: 2.8s;
  --ink-ease: ease-out;
}

.ink-anim .ink-d1 {
  animation: hd1 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-d2 {
  animation: hd2 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-d3 {
  animation: hd3 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-d4 {
  animation: hd4 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-d5 {
  animation: hd5 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-d6 {
  animation: hd6 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-boil {
  animation: inkBoil2 0.42s steps(1) infinite;
}

/* ---- insure hero: umbrella sway ----
   Pivots at the ferrule, 170,196 — the bottom of the pole in this SVG's 320x230
   viewBox. Rotate about anything above it and the umbrella slides across the
   ground instead of pivoting on it. transform-box: view-box is what makes those
   user-space coordinates mean anything; without it the origin resolves against
   the element's own bounding box.

   0.65s clears the canopy draw — hd3 finishes at 24% of --ink-dur — so it starts
   moving the moment it is drawn rather than standing still first. */
@keyframes insSway {
  0% {
    transform: rotate(-3.4deg);
  }
  50% {
    transform: rotate(3.4deg);
  }
  100% {
    transform: rotate(-3.4deg);
  }
}

.ink-anim .ins-sway {
  transform-box: view-box;
  transform-origin: 170px 196px;
  animation: insSway 6s ease-in-out 0.65s infinite;
}

.ink-anim .ink-cursor {
  animation: hcursor var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-click {
  animation: hclick var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-mail-out {
  animation: hmailOut var(--ink-dur) cubic-bezier(0.4, 0, 0.3, 1) 1 both;
}

.ink-anim .ink-mail-in {
  animation: hmailIn var(--ink-dur) cubic-bezier(0.4, 0, 0.3, 1) 1 both;
}

.ink-anim .ink-check {
  animation: hcheck var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-check2 {
  animation: hcheck2 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-pen {
  animation: hpenWork var(--ink-dur) ease-in-out 1 both;
}

.ink-anim .ink-merge-l {
  animation: hmergeL var(--ink-dur) cubic-bezier(0.3, 0.7, 0.3, 1) 1 both;
}

.ink-anim .ink-merge-r {
  animation: hmergeR var(--ink-dur) cubic-bezier(0.3, 0.7, 0.3, 1) 1 both;
}

.ink-anim .ink-merge-one {
  animation: hmergeOne var(--ink-dur) cubic-bezier(0.3, 0.7, 0.3, 1) 1 both;
}

.ink-anim .ink-dollar-1 {
  animation: hdollar1 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-dollar-2 {
  animation: hdollar2 var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-sign {
  animation: hsign var(--ink-dur) var(--ink-ease) 1 both;
}

.ink-anim .ink-smile {
  animation: hsmile var(--ink-dur) var(--ink-ease) 1 both;
}

/* transform-origin is geometry, so it is per-scene rather than per-class.
   transform-box: view-box makes the percentages resolve against the viewBox
   instead of the element's own bounding box. */
.ink-click,
.ink-pen,
.ink-merge-one {
  transform-box: view-box;
}

.ink-scene--address .ink-click {
  transform-origin: 146px 106px;
}

.ink-scene--carriers .ink-pen {
  transform-origin: 84px 112px;
}

.ink-scene--bundle .ink-click {
  transform-origin: 168px 82px;
}

.ink-scene--bundle .ink-merge-one {
  transform-origin: 169px 80px;
}

.ink-scene--renewal .ink-pen {
  transform-origin: 86px 106px;
}

/* ---- hero loops ----
   These run on their own timing rather than the shared cascade duration, so
   each carries its own full declaration. Every one is offset past the 2.6s
   draw-in so the drawing finishes before it starts moving.

   **The escrow five start at 0s on purpose.** They used to wait 2.8s for the
   hd1-hd6 cascade — the desk, the books and the stamp in the right corner — to
   finish drawing, which meant the hero's first three seconds were a still. The
   paper now falls the moment the page loads and the scene draws in behind it.
   All five share one 7s cycle, so the delay has to be identical across them or
   the pen signs a sheet that has not landed.

   `backwards` stays. It does nothing at a 0s delay, but the moment anyone
   reintroduces one it is what stops the browser painting the element's natural
   state — a full stack and a drawn signature — through the wait and then
   snapping to empty. That is exactly the bug this had. */

.ink-anim .esc-sheet-0 {
  animation: escSheet0 7s cubic-bezier(0.42, 0, 0.5, 1) 0s infinite backwards;
}

.ink-anim .esc-sheet-1 {
  animation: escSheet1 7s cubic-bezier(0.42, 0, 0.5, 1) 0s infinite backwards;
}

.ink-anim .esc-sheet-2 {
  animation: escSheet2 7s cubic-bezier(0.42, 0, 0.5, 1) 0s infinite backwards;
}

.ink-anim .esc-sign {
  animation: escSignDraw 7s linear 0s infinite backwards;
}

.ink-anim .esc-pen {
  animation: escPenMove 7s cubic-bezier(0.42, 0, 0.5, 1) 0s infinite backwards;
}

/* Same fill-mode bug the escrow sheets had, and the same fix. The coins and
   bills are authored at cx 210, cy 110 — which is on the pig's back, right by
   the slot — and only leave it once their animation starts. With a bare 3-5s
   delay the browser painted that natural position the whole time, so the hero
   opened with the money already sitting on the pig and then jumping up to fall.
   `backwards` holds frame zero instead, where they are 96px above the frame at
   opacity 0.

   Delays pulled in from 3/3.9/4.8s and 3.5/5.1s so the first coin drops almost
   immediately and the money reads as continuous, rather than waiting for the
   pig to finish drawing before anything falls. */
.ink-anim .fin-coin-0 {
  animation: coinDrop0 2.8s cubic-bezier(0.45, 0, 0.7, 1) 0.35s infinite backwards;
}

.ink-anim .fin-coin-1 {
  animation: coinDrop1 2.8s cubic-bezier(0.45, 0, 0.7, 1) 1.65s infinite backwards;
}

.ink-anim .fin-coin-2 {
  animation: coinDrop2 2.8s cubic-bezier(0.45, 0, 0.7, 1) 3.1s infinite backwards;
}

.ink-anim .fin-bill-0 {
  animation: billFall0 3.4s cubic-bezier(0.45, 0, 0.7, 1) 1.1s infinite backwards;
}

.ink-anim .fin-bill-1 {
  animation: billFall1 3.4s cubic-bezier(0.45, 0, 0.7, 1) 2.6s infinite backwards;
}

.mg-sign-board {
  transform-box: view-box;
  transform-origin: 68px 74px;
}

.ink-anim .mg-sign-board {
  animation: mgSwing 4.6s ease-in-out 2.6s infinite;
}

/* ---- notary counter ----
   `backwards` on all four is load-bearing: without it the visitor stands at the
   counter and the seal is already stamped during the 2.8s draw-in. */

.ink-figure {
  --ink-dur: 2.8s;
  --ink-ease: ease-out;
}

.ink-anim .not-visitor {
  animation: notArrive 9s cubic-bezier(0.3, 0.7, 0.3, 1) 2.8s infinite backwards;
}

.ink-anim .not-doc {
  animation: notHandOff 9s cubic-bezier(0.4, 0, 0.3, 1) 2.8s infinite backwards;
}

.not-stamp {
  transform-box: view-box;
  transform-origin: 208px 102px;
}

.ink-anim .not-stamp {
  animation: notStampPress 9s cubic-bezier(0.45, 0, 0.3, 1) 2.8s infinite backwards;
}

.ink-anim .not-seal {
  animation: notSeal 9s ease-out 2.8s infinite backwards;
}

/* ============================ scene staging ============================ */

.ink-stage {
  position: relative;
  overflow: hidden;
  background: linear-gradient(150deg, #f8fafc 0%, #ffffff 70%);
  border: 1px solid #e8eef7;
  border-radius: 16px;
}

.ink-stage-frame {
  position: relative;
  aspect-ratio: 260 / 172;
}

.ink-scene {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

.ink-scene.is-active {
  z-index: 2;
  opacity: 1;
}

.ink-scene svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ============================ reduced motion ============================
   ANIMATIONS.md asks the build to go further than the prototype here: freeze
   the loops and leave the drawings in their final state. The transient
   elements are hidden rather than parked, so the frozen frame is a coherent
   finished drawing instead of a cursor and two pre-merge documents stacked on
   top of the merged one. */

@media (prefers-reduced-motion: reduce) {
  .ink-boil,
  .ink-anim *,
  .ink-hero * {
    animation: none !important;
  }

  .ink-cursor,
  .ink-click,
  .ink-mail-out,
  .ink-mail-in,
  .ink-dollar-1,
  .ink-dollar-2,
  .ink-merge-l,
  .ink-merge-r {
    opacity: 0;
  }

  /* Frozen, the three coins and two bills all land on the slot at once and read
     as mud. One of each is enough to say "deposit". */
  .fin-coin-1,
  .fin-coin-2,
  .fin-bill-1 {
    opacity: 0;
  }

  /* Same for the falling sheets — the signed one on the desk tells the story. */
  .esc-sheet-0,
  .esc-sheet-1 {
    opacity: 0;
  }
}
