/* =============================================================================
   ShiftHawk — Feature diagrams (Swap requests · Handshake · Snap your schedule)
   Inline-SVG diagrams animated with CSS keyframes and revealed on scroll by
   assets/js/feature-diagrams.js (IntersectionObserver). Follows the site's
   animation conventions (team-invite.css / buddy-match.css): the JS "arms" a
   stage (pre-play hidden states), then adds .fd-play to run the sequence.
   Without JS — or under prefers-reduced-motion — the SVG renders fully
   composed as a static diagram (same fallback contract as the other stages).
   Namespaces: rq- (swap requests) · hs- (handshake) · oc- (schedule OCR).
   ========================================================================== */

.fd-stage { position: relative; }
.fd-stage .fd-svg { display: block; width: 100%; max-width: 1080px; height: auto; margin: var(--s-6) auto 0; }

/* replay affordance — same recipe as .stage-replay (team-invite.css) */
.fd-replay {
  position: absolute; right: var(--s-3); top: var(--s-3); z-index: 7;
  display: none; align-items: center; justify-content: center; gap: 6px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2);
  border-radius: var(--r-pill); padding: 0 var(--s-4); cursor: pointer;
  font-family: var(--font-mono); font-size: .7rem; font-weight: 600;
  min-height: 44px;
}
.fd-replay:hover { background: var(--surface); color: var(--text-1); border-color: var(--border-strong); }
.fd-replay.show { display: inline-flex; }
.fd-replay i { font-size: .95rem; }

/* ---- transient elements: visible only mid-animation, hidden at rest ------ */
.rq-fly, .rq-tap, .rq-sendring, .hs-beam, .hs-ring, .oc-beam, .oc-flash { opacity: 0; }

/* ---- centered transform origin for pop/scale elements --------------------
   (SVG children need fill-box so scale()/rotate() pivot on the element) */
.rq-bell, .rq-badge, .rq-note, .rq-done, .rq-fly, .rq-tap, .rq-sendring,
.hs-phoneL, .hs-phoneR, .hs-qr, .hs-ghost, .hs-agree, .hs-ring, .hs-agree-label,
.hs-okL, .hs-okR, .hs-pill,
.oc-paper, .oc-cam, .oc-flash, .oc-beam, .oc-eng1, .oc-eng2, .oc-cal, .oc-chip, .oc-confirm {
  transform-box: fill-box; transform-origin: 50% 50%;
}
.rq-bell { transform-origin: 50% 0; }   /* bell swings from its crown */

/* ---- armed (JS present, not yet scrolled into view): pre-play states ----- */
.fd-armed :is(.rq-path, .rq-badge, .rq-note, .rq-done,
  .hs-phoneL, .hs-phoneR, .hs-qr, .hs-ghost, .hs-link, .hs-agree, .hs-agree-label,
  .hs-okL, .hs-okR, .hs-pill,
  .oc-paper, .oc-cam, .oc-eng1, .oc-eng2, .oc-arr1, .oc-arr1b, .oc-arr2,
  .oc-cal, .oc-chip, .oc-confirm) { opacity: 0; }

/* =========================== shared keyframes ============================ */
@keyframes fdFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fdPop {
  0%   { opacity: 0; transform: scale(.4); }
  70%  { opacity: 1; transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes fdRise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes fdDrop { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
@keyframes fdSlideL { from { opacity: 0; transform: translateX(-36px); } to { opacity: 1; transform: none; } }
@keyframes fdSlideR { from { opacity: 0; transform: translateX(36px); } to { opacity: 1; transform: none; } }
@keyframes fdRing {
  0%   { opacity: .85; transform: scale(.4); }
  100% { opacity: 0;   transform: scale(2.2); }
}

/* =========================== rq — swap requests ========================== */
@keyframes rqFly {
  0%   { opacity: 0; transform: translate(0, 0) rotate(6deg); }
  10%  { opacity: 1; }
  50%  { transform: translate(240px, -84px) rotate(0deg); }
  90%  { opacity: 1; }
  100% { opacity: 0; transform: translate(480px, -2px) rotate(8deg); }
}
@keyframes rqBell {
  0%, 100% { transform: rotate(0); }
  20% { transform: rotate(14deg); }
  40% { transform: rotate(-12deg); }
  60% { transform: rotate(8deg); }
  80% { transform: rotate(-5deg); }
}
.fd-play .rq-path     { animation: fdFadeIn .5s ease .15s both; }
.fd-play .rq-sendring { animation: fdRing .6s ease .2s both; }
.fd-play .rq-fly      { animation: rqFly 1.5s ease-in-out .35s both; }
.fd-play .rq-bell     { animation: rqBell .9s ease 1.75s both; }
.fd-play .rq-badge    { animation: fdPop .45s ease 1.85s both; }
.fd-play .rq-note     { animation: fdRise .5s ease 2.05s both; }
.fd-play .rq-tap      { animation: fdRing .7s ease 2.7s both; }
.fd-play .rq-done     { animation: fdPop .5s ease 3.15s both; }

/* ============================= hs — handshake ============================ */
@keyframes hsBeam {
  0%   { opacity: 0; transform: translateY(0); }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(100px); }
}
.fd-play .hs-phoneL      { animation: fdSlideL .6s ease 0s both; }
.fd-play .hs-phoneR      { animation: fdSlideR .6s ease .15s both; }
.fd-play .hs-qr          { animation: fdPop .5s ease .65s both; }
.fd-play .hs-beam        { animation: hsBeam .9s ease-in-out 1.05s 2 both; }
.fd-play .hs-ghost       { animation: fdFadeIn .8s ease 1.7s both; }
.fd-play .hs-link        { animation: fdFadeIn .5s ease 2.6s both; }
.fd-play .hs-agree       { animation: fdPop .55s ease 2.95s both; }
.fd-play .hs-ring        { animation: fdRing .8s ease 3.05s both; }
.fd-play .hs-agree-label { animation: fdRise .45s ease 3.2s both; }
.fd-play .hs-okL         { animation: fdPop .4s ease 3.45s both; }
.fd-play .hs-okR         { animation: fdPop .4s ease 3.6s both; }
.fd-play .hs-pill        { animation: fdDrop .5s ease 3.8s both; }

/* ========================= oc — snap your schedule ====================== */
@keyframes ocFlash { 0%, 100% { opacity: 0; } 30% { opacity: .85; } }
@keyframes ocBeam {
  0%   { opacity: 0; transform: translateY(0); }
  10%  { opacity: .45; }
  90%  { opacity: .45; }
  100% { opacity: 0; transform: translateY(252px); }
}
.fd-play .oc-paper   { animation: fdRise .6s ease 0s both; }
.fd-play .oc-cal     { animation: fdRise .55s ease .25s both; }
.fd-play .oc-cam     { animation: fdPop .45s ease .5s both; }
.fd-play .oc-flash   { animation: ocFlash .5s ease .85s both; }
.fd-play .oc-beam    { animation: ocBeam 1.4s ease-in-out 1.05s both; }
.fd-play .oc-arr1,
.fd-play .oc-arr1b   { animation: fdFadeIn .4s ease 1.35s both; }
.fd-play .oc-eng1    { animation: fdPop .5s ease 1.5s both; }
.fd-play .oc-eng2    { animation: fdPop .5s ease 1.7s both; }
.fd-play .oc-arr2    { animation: fdFadeIn .4s ease 2s both; }
.fd-play .oc-chip    { animation: fdPop .4s ease both; animation-delay: calc(2.3s + var(--d, 0s)); }
.fd-play .oc-confirm { animation: fdPop .5s ease 3.4s both; }

/* ================= static fallback (reduced motion / no IO) ==============
   The composed end-state, forced. .fd-static is added by the JS; the media
   query covers the CSS-only path (JS missing entirely is already static
   because nothing is armed). */
.fd-static :is(.rq-path, .rq-badge, .rq-note, .rq-done,
  .hs-phoneL, .hs-phoneR, .hs-qr, .hs-ghost, .hs-link, .hs-agree, .hs-agree-label,
  .hs-okL, .hs-okR, .hs-pill,
  .oc-paper, .oc-cam, .oc-eng1, .oc-eng2, .oc-arr1, .oc-arr1b, .oc-arr2,
  .oc-cal, .oc-chip, .oc-confirm) { opacity: 1 !important; transform: none !important; animation: none !important; }
.fd-static :is(.rq-fly, .rq-tap, .rq-sendring, .hs-beam, .hs-ring, .oc-beam, .oc-flash) { opacity: 0 !important; animation: none !important; }
.fd-static .fd-replay { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  .fd-stage * { animation: none !important; transition: none !important; }
  .fd-stage :is(.rq-path, .rq-badge, .rq-note, .rq-done,
    .hs-phoneL, .hs-phoneR, .hs-qr, .hs-ghost, .hs-link, .hs-agree, .hs-agree-label,
    .hs-okL, .hs-okR, .hs-pill,
    .oc-paper, .oc-cam, .oc-eng1, .oc-eng2, .oc-arr1, .oc-arr1b, .oc-arr2,
    .oc-cal, .oc-chip, .oc-confirm) { opacity: 1 !important; transform: none !important; }
  .fd-stage :is(.rq-fly, .rq-tap, .rq-sendring, .hs-beam, .hs-ring, .oc-beam, .oc-flash) { opacity: 0 !important; }
  .fd-replay { display: none !important; }
}
