/* ===== pb52: FX layer — attractive but fast.
   Rules of the layer: animate ONLY transform/opacity (compositor thread),
   every loop is slow & rare, prefers-reduced-motion kills it all (base css
   has the global * override). No libraries. ============================== */

/* ---------- view transition: quick fade for the page, rise for children ---------- */
.view.active { animation: viewIn .18s ease both; }
@keyframes viewIn { from { opacity: 0; } to { opacity: 1; } }

.content > .fx-c {
  animation: fxRise .52s cubic-bezier(.22, 1, .36, 1) var(--d, 0ms) both;
}
@keyframes fxRise {
  from { opacity: 0; transform: translateY(16px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ---------- dynamically rendered list items (MutationObserver) ---------- */
.fx-i {
  animation: fxItem .45s cubic-bezier(.22, 1, .36, 1) var(--d, 0ms) both;
}
@keyframes fxItem {
  from { opacity: 0; transform: translateY(12px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

/* ---------- press spring on every tappable control ---------- */
.btn, .prod-buy, .disc-btn, .topup-cta, .pay-cta, .svc-act, .amt,
.quick, .cat-pill, .copy-btn, .appbar-add, .invite-strip {
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1);
}
.btn:active, .prod-buy:active, .disc-btn:active, .topup-cta:active, .pay-cta:active,
.svc-act:active, .amt:active, .quick:active, .cat-pill:active, .copy-btn:active,
.appbar-add:active { transform: scale(.94); }

/* ripple (JS injects .ripple into .pressable) */
.pressable { position: relative; overflow: hidden; }
.ripple {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(255,255,255,.45), rgba(255,255,255,.1) 60%, transparent 72%);
  transform: translate(-50%, -50%) scale(0);
  animation: rip .55s ease-out forwards;
}
@keyframes rip { to { transform: translate(-50%, -50%) scale(1); opacity: 0; } }

/* ---------- wallet hero: slow shine sweep + waving purse ---------- */
.wallet-hero::before {
  content: ""; position: absolute; top: -60%; bottom: -60%; left: -55%; width: 36%;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.30), transparent);
  transform: translateX(0) skewX(-18deg);
  animation: shine 6s ease-in-out 1.2s infinite;
  pointer-events: none;
}
@keyframes shine {
  0%, 60%  { transform: translateX(0) skewX(-18deg); }
  100%     { transform: translateX(390%) skewX(-18deg); }
}
.wh-icon {
  position: relative; z-index: 1;
  animation: wig 6.5s ease-in-out infinite;
}
@keyframes wig {
  0%, 86%, 100% { transform: none; }
  90% { transform: rotate(-12deg) scale(1.12); }
  94% { transform: rotate(9deg) scale(1.06); }
  97% { transform: rotate(-4deg); }
}

/* ---------- quick-grid icons pop in sequence (delay set by .fx-c) ---------- */
.quick .q-icon { transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
.quick:active .q-icon { transform: scale(1.25) rotate(-8deg); }

/* ---------- tab bar: bounce the active icon ---------- */
.tab .t-icon { transition: transform .2s cubic-bezier(.34,1.56,.64,1); }
.tab.on .t-icon { animation: tabPop .55s cubic-bezier(.34,1.56,.64,1); }
@keyframes tabPop {
  0%   { transform: translateY(0) scale(1); }
  35%  { transform: translateY(-7px) scale(1.22); }
  70%  { transform: translateY(1px) scale(.96); }
  100% { transform: translateY(0) scale(1); }
}
.tab-plus.on .plus { animation: plusPop .5s cubic-bezier(.34,1.56,.64,1); }
@keyframes plusPop {
  0% { transform: scale(1); } 40% { transform: scale(1.22) rotate(90deg); }
  100% { transform: scale(1.06) rotate(0); }
}

/* ---------- selection pops (radio-like controls) ---------- */
.cat-pill.on { animation: selPop .35s cubic-bezier(.34,1.56,.64,1); }
.amt.sel { animation: selPop .35s cubic-bezier(.34,1.56,.64,1); }
.pay-opt.sel { animation: selPop .35s cubic-bezier(.34,1.56,.64,1); }
@keyframes selPop {
  0% { transform: scale(.95); } 60% { transform: scale(1.045); } 100% { transform: scale(1); }
}

/* ---------- modal: backdrop fade + sheet spring ---------- */
.modal-back { animation: bdIn .22s ease both !important; }
@keyframes bdIn { from { opacity: 0; } to { opacity: 1; } }
.modal { animation: sheetIn .4s cubic-bezier(.22, 1.15, .36, 1) both !important; }
@keyframes sheetIn {
  from { transform: translateY(70px) scale(.97); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ---------- toast: spring in ---------- */
#toast { transition: opacity .2s ease, transform .38s cubic-bezier(.34,1.56,.64,1) !important; }

/* ---------- empty state: floating icon ---------- */
.empty .e-icon { display: inline-block; animation: bob 2.8s ease-in-out infinite; }
@keyframes bob { 0%,100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-7px) rotate(-4deg); } }

/* ---------- usage bar: shimmer flowing through the fill ---------- */
.usage-fill { position: relative; overflow: hidden; transition: width .9s cubic-bezier(.22,1,.36,1); }
.usage-fill::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.38), transparent);
  transform: translateX(-100%);
  animation: flowline 2.6s ease-in-out .4s infinite;
}
@keyframes flowline { 0% { transform: translateX(-100%); } 65%, 100% { transform: translateX(100%); } }

/* ---------- payment CTA: rare sheen so it never goes unnoticed ---------- */
.pay-cta, .topup-cta { position: relative; overflow: hidden; }
.pay-cta::after, .topup-cta::after {
  content: ""; position: absolute; top: -40%; bottom: -40%; left: -60%; width: 34%;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.35), transparent);
  transform: translateX(0) skewX(-18deg);
  animation: shine 7s ease-in-out 2s infinite;
  pointer-events: none;
}

/* ---------- success hero: ring pulse around the check ---------- */
.sh-check { animation: pop .45s cubic-bezier(.2,1.6,.4,1), ringPulse 1.5s ease-out .35s 2 both; }
@keyframes ringPulse {
  0%   { box-shadow: 0 0 0 0 rgba(46,204,113,.5); }
  100% { box-shadow: 0 0 0 22px rgba(46,204,113,0); }
}

/* ---------- role chip: breathing green dot energy ---------- */
.role-chip { animation: fadein .6s ease both; }

/* ---------- home invoice banner: slide down entrance ---------- */
.home-inv-banner { animation: dropIn .5s cubic-bezier(.22,1,.36,1) both; }
@keyframes dropIn { from { opacity: 0; transform: translateY(-14px) scale(.97); } to { opacity: 1; transform: none; } }

/* ---------- count-up numbers shouldn't jitter width ---------- */
.wh-amount, .total-amount, .mc-value, .th-balance { font-variant-numeric: tabular-nums; }

/* ---------- success confetti ---------- */
.fx-conf { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 5; border-radius: inherit; }
.fx-conf i {
  position: absolute; top: -14px; border-radius: 2px; opacity: 0;
  animation: fall 1.9s linear forwards;
}
@keyframes fall {
  0%   { opacity: 1; transform: translateY(0) rotate(0); }
  100% { opacity: .9; transform: translateY(340px) translateX(14px) rotate(var(--rz, 360deg)); }
}

/* ---------- pb52b: service card accents ---------- */
/* press lift — the whole card reacts under the finger */
.svc-card { transition: transform .25s cubic-bezier(.22, 1, .36, 1); }
.svc-card:active { transform: scale(.985); }
/* "رو به اتمام" badge breathes so it never blends in */
.svc-status.soon { animation: breathe 2.2s ease-in-out infinite; }
@keyframes breathe { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(.96); } }
/* traffic bar grows from the RTL start edge on first paint */
.svc-card .usage-fill { animation: growW 1s cubic-bezier(.22, 1, .36, 1) .15s both; transform-origin: right; }
@keyframes growW { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* expiry chip slides a hair later than the card */
.svc-card .svc-info span { animation: fxItem .45s cubic-bezier(.22, 1, .36, 1) calc(var(--d, 0ms) + 120ms) both; }
