/* ==========================================================================
   anim.css — shared, site-wide attention + annotation layer for Businessily.
   Loaded after every page's own CSS. Pairs with anim.js.

   HARD RULES honored here:
   - Only transform / opacity are animated (plus stroke-dashoffset for draw-on).
   - EVERY motion rule is gated behind @media (prefers-reduced-motion: no-preference).
   - With reduced motion (or no JS) all content is fully visible + usable:
     annotations show statically, reveals are visible, nothing is hidden.
   - No layout thrash: transforms/opacity only, GPU-friendly.
   - Annotations never cover text/CTAs (pointer-events:none, sit in the margin).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1 · ANNOTATIONS — hand-drawn-style inline-SVG marks + short callout labels.
   The host element gets .annot and contains an .annot-mark (the SVG) and an
   optional .annot-label. Marks are absolutely positioned and decorative, so
   they never intercept clicks or block the underlying text/CTA.
   -------------------------------------------------------------------------- */
.annot { position: relative; }

.annot-mark {
  position: absolute;
  pointer-events: none;
  color: var(--accent);
  z-index: 2;
  overflow: visible;
}
.annot-mark path,
.annot-mark line,
.annot-mark ellipse,
.annot-mark circle,
.annot-mark polyline {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The little human callout label. Calm, confident, set in the rounded face. */
.annot-label {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  font-family: var(--font);
  font-weight: 800;
  font-size: clamp(.72rem, 1.6vw, .84rem);
  line-height: 1.15;
  color: var(--accent);
  letter-spacing: .1px;
  max-width: 11.5rem;
  text-wrap: balance;
  /* a faint chip so the label reads over any background without a hard box */
  background: color-mix(in srgb, var(--accent) 9%, var(--card));
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-radius: 999px;
  padding: 3px 11px;
  box-shadow: 0 6px 18px -12px color-mix(in srgb, var(--accent) 60%, transparent);
}
[data-theme="dark"] .annot-label { color: var(--accent-2); }
[data-theme="dark"] .annot-mark { color: var(--accent-2); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .annot-label { color: var(--accent-2); }
  :root:not([data-theme="light"]) .annot-mark { color: var(--accent-2); }
}

/* Positioning helpers (the host sets one of these on the label/mark) */
.annot-label.al-tr { top: -.4rem; right: 0; }
.annot-label.al-br { bottom: -.4rem; right: 0; }
.annot-label.al-bl { bottom: -.4rem; left: 0; }
.annot-label.al-tl { top: -.4rem; left: 0; }

/* Draw-on: stroke starts hidden, then draws when scrolled into view.
   Gated behind no-preference; with reduced motion the stroke is fully drawn. */
@media (prefers-reduced-motion: no-preference) {
  .annot-mark path,
  .annot-mark line,
  .annot-mark ellipse,
  .annot-mark circle,
  .annot-mark polyline {
    stroke-dasharray: var(--dash, 240);
    stroke-dashoffset: var(--dash, 240);
    transition: stroke-dashoffset .9s cubic-bezier(.45,.05,.2,1);
  }
  .annot.drawn .annot-mark path,
  .annot.drawn .annot-mark line,
  .annot.drawn .annot-mark ellipse,
  .annot.drawn .annot-mark circle,
  .annot.drawn .annot-mark polyline {
    stroke-dashoffset: 0;
  }
  /* label fades up just after the stroke begins */
  .annot-label {
    opacity: 0;
    transform: translateY(4px);
    transition: opacity .5s ease .25s, transform .5s cubic-bezier(.2,.7,.2,1) .25s;
  }
  .annot.drawn .annot-label { opacity: 1; transform: none; }
}

/* On narrow screens, annotations could crowd the text — keep them, but make
   them quieter and ensure labels never push off-canvas. */
@media (max-width: 640px) {
  .annot-label { max-width: 9rem; font-size: .72rem; padding: 2px 9px; }
}

/* --------------------------------------------------------------------------
   Per-spot breathing room for robust annotations whose target sits in a dense
   stack. We open a small, clean band so the engine can drop the label there
   instead of crowding a neighbouring line or the CTA. Cosmetic only.
   -------------------------------------------------------------------------- */
@media (min-width: 641px) {
  /* Pricing card: give the comparison block room below "You keep all of it."
     so "and they keep raising it" lands in clear space, well above the CTA. */
  .pt-price-card .pt-vs { margin-bottom: 40px; }

  /* How-it-works Apple block: open a clean band between the paragraph and the
     data-flow diagram so "yes — literally never us" lands clear of both. */
  .hiw-apple-p { margin-bottom: 72px; }
}
/* Smallest phones: a couple of marks are decorative enough to hide so they
   never overlap copy. Anything tagged .annot-hide-sm is purely ornamental. */
@media (max-width: 460px) {
  .annot-hide-sm { display: none !important; }
}

/* --------------------------------------------------------------------------
   2 · RICHER ENTRANCE MOTION — extends the existing .reveal system.
   Base .reveal (opacity + translateY) already lives in styles.css and is
   driven by the IntersectionObserver in app.js. Here we add:
     - directional variants  (data-reveal="left|right|up|scale")
     - staggered children     (data-reveal="stagger")
   All gated; with reduced motion everything is simply visible.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {

  /* Directional reveal variants. The host keeps .reveal so app.js toggles .in */
  .reveal[data-reveal="left"]  { transform: translateX(-26px); }
  .reveal[data-reveal="right"] { transform: translateX(26px); }
  .reveal[data-reveal="up"]    { transform: translateY(26px); }
  .reveal[data-reveal="scale"] { transform: scale(.96); }
  .reveal.in[data-reveal="left"],
  .reveal.in[data-reveal="right"],
  .reveal.in[data-reveal="up"],
  .reveal.in[data-reveal="scale"] { transform: none; }

  /* Staggered children: the container is .reveal[data-reveal="stagger"]; its
     direct children fade/slide in sequence once the container gets .in.
     The container itself does NOT animate as a block (the children carry the
     motion), so we neutralize the base .reveal transform/opacity on it to
     avoid a double fade. Delays handled by --i set in JS, with a CSS fallback
     ramp for the first several children. */
  .reveal[data-reveal="stagger"] { opacity: 1; transform: none; transition: none; }
  .reveal[data-reveal="stagger"] > * {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity .55s cubic-bezier(.2,.7,.2,1),
                transform .55s cubic-bezier(.2,.7,.2,1);
    transition-delay: calc(var(--i, 0) * 70ms);
  }
  .reveal.in[data-reveal="stagger"] > * { opacity: 1; transform: none; }

  /* CSS-only fallback ramp (covers cases where JS hasn't set --i yet) */
  .reveal[data-reveal="stagger"] > *:nth-child(1) { --i: 0; }
  .reveal[data-reveal="stagger"] > *:nth-child(2) { --i: 1; }
  .reveal[data-reveal="stagger"] > *:nth-child(3) { --i: 2; }
  .reveal[data-reveal="stagger"] > *:nth-child(4) { --i: 3; }
  .reveal[data-reveal="stagger"] > *:nth-child(5) { --i: 4; }
  .reveal[data-reveal="stagger"] > *:nth-child(6) { --i: 5; }
  .reveal[data-reveal="stagger"] > *:nth-child(7) { --i: 6; }
  .reveal[data-reveal="stagger"] > *:nth-child(8) { --i: 7; }
}

/* --------------------------------------------------------------------------
   3 · ATTENTION CUES
   -------------------------------------------------------------------------- */

/* 3a · One-time gentle pulse/glow on the PRIMARY CTA when it first appears.
   anim.js adds .cta-pulse for the duration of one pulse, then removes it. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes bz-cta-pulse {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
    60%  { box-shadow: 0 0 0 14px color-mix(in srgb, var(--accent) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
  }
  .cta-pulse { animation: bz-cta-pulse 1.4s cubic-bezier(.3,.7,.3,1) 1; }
}

/* 3b · Hero scroll cue — a soft chevron that fades after the first scroll.
   Rendered by anim.js into the first .hero on the page. */
.bz-scrollcue {
  position: absolute;
  left: 50%;
  bottom: clamp(14px, 3vh, 30px);
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  color: var(--text-2);
  opacity: .72;
  pointer-events: none;
  z-index: 3;
  transition: opacity .5s ease;
}
.bz-scrollcue svg { display: block; }
.bz-scrollcue.bz-cue-gone { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  @keyframes bz-cue-bob {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50%      { transform: translateX(-50%) translateY(6px); }
  }
  .bz-scrollcue { animation: bz-cue-bob 1.9s ease-in-out infinite; }
}
/* With reduced motion the cue is static (no bob); we also hide it on very
   short viewports where it could overlap the hero CTA. */
@media (max-height: 620px) { .bz-scrollcue { display: none; } }

/* 3c · Underline-sweep on a key hero/section phrase.
   Wrap the phrase in <span class="sweep">…</span>. The underline draws once
   when scrolled into view. Static (already drawn) under reduced motion. */
.sweep { position: relative; white-space: nowrap; }
.sweep::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: -.08em;
  height: .14em;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transform-origin: left center;
}
@media (prefers-reduced-motion: no-preference) {
  .sweep::after { transform: scaleX(0); transition: transform .7s cubic-bezier(.2,.7,.2,1); }
  .sweep.swept::after { transform: scaleX(1); }
}
