/* ==========================================================================
   AutoSmile logo motion system — single source of truth for all logo/emblem
   animation. Loaded by BOTH the marketing pages (alongside styles.css) and
   the app pages (panel.html/dashboard.html/admin.html, which do NOT load
   styles.css at all) — so every token and keyframe here is self-contained.

   Two motion modes:
     - idle pulse:  a continuous "heartbeat" on persistent marks (header nav,
       standalone emblem showcases). Applied directly to .brand-logo-full /
       .brand-logo-mark — no wrapper, no class needed in HTML.
     - reveal:      a one-shot entrance (soft scale/fade-in, no wipe, no glow)
       that hands off into the idle pulse once it completes. Wrap the <img>
       in <span class="as-reveal is-armed">. `is-armed` can be present in
       the static HTML (auto-plays on load) or added by JS (scroll-into-view,
       session-gated first visit).

   SAFETY RULE — read this before touching anything below:
   The resting state must always be fully visible. Every clip-path/opacity/
   transform tied to these animations lives ONLY inside
   `@media (prefers-reduced-motion: no-preference)`, never as a base style.
   A reduced-motion visitor must see a plain, static, fully-visible mark —
   never a permanently clipped-away or zero-opacity one.
   ========================================================================== */

:root{
  --as-pulse-dur:3.2s;
  --as-pulse-ease:ease-in-out;
  --as-pulse-scale:1.06;
  --as-pulse-scale-2:1.03;
  --as-reveal-dur:1100ms;
  --as-reveal-ease:cubic-bezier(.2,.7,.3,1);
}

@keyframes asBrandPulse{
  0%,100%{transform:scale(1);}
  15%{transform:scale(var(--as-pulse-scale));}
  30%{transform:scale(1);}
  45%{transform:scale(var(--as-pulse-scale-2));}
  60%{transform:scale(1);}
}

@keyframes asRevealLift{
  from{opacity:0;transform:scale(.92);}
  to{opacity:1;transform:scale(1);}
}

@media(prefers-reduced-motion:no-preference){
  /* header nav logo: idle pulse only, applied directly — no HTML changes
     anywhere this is used (22 pages share the same header markup). */
  .brand-logo-full,.brand-logo-mark{animation:asBrandPulse var(--as-pulse-dur) var(--as-pulse-ease) infinite;transform-origin:center;}

  /* generic idle-pulse utility for any other standalone mark (e.g. a
     showcase image that never gets the reveal treatment). */
  .as-mark-pulse{animation:asBrandPulse var(--as-pulse-dur) var(--as-pulse-ease) infinite;transform-origin:center;}

  .as-reveal{position:relative;display:inline-block;}
  .as-reveal.is-armed{opacity:0;animation:asRevealLift var(--as-reveal-dur) var(--as-reveal-ease) 1 both;}
  .as-reveal.is-armed img{
    transform-origin:center;
    animation:asBrandPulse var(--as-pulse-dur) var(--as-pulse-ease) var(--as-reveal-dur) infinite;
  }
}

@media(prefers-reduced-motion:reduce){
  /* Belt & suspenders: styles.css has a global reduced-motion kill-switch,
     but panel.html/dashboard.html/admin.html don't load styles.css at all,
     so this system carries its own reset — otherwise a reveal element on an
     app page could be stuck at opacity:0/clipped with no animation left to
     ever un-clip it. */
  .brand-logo-full,.brand-logo-mark,.as-mark-pulse,
  .as-reveal,.as-reveal img{
    animation:none !important;opacity:1 !important;transform:none !important;clip-path:none !important;-webkit-clip-path:none !important;
  }
}

/* ---------- app boot splash (panel.html / dashboard.html / admin.html) ----------
   A brief full-screen overlay shown while the app page settles in. Dismissed
   by the inline script each page carries — see the script comment there for
   why dismissal uses a hard timeout rather than animationend. */
.as-boot{
  position:fixed;inset:0;z-index:2000;display:grid;place-items:center;
  background:#fff;transition:opacity .35s ease;
}
.as-boot img{width:72px;height:auto;}
.as-boot.is-done{opacity:0;pointer-events:none;}
