/* =====================================================================
   Alo Link — hệ thống chuyển động (motion design system)
   Nguyên tắc: chuyển động có chủ đích, chỉ dùng transform + opacity cho mượt,
   cùng một bộ tốc độ & đường cong ở mọi nơi, tôn trọng "giảm chuyển động".
   ===================================================================== */

/* ---------- 1. Motion tokens ---------- */
@property --sidebar { syntax: '<length>'; inherits: true; initial-value: 248px; }
:root {
  --m-instant: 90ms;   /* phản hồi bấm */
  --m-fast: 150ms;     /* hover, đổi màu */
  --m-base: 240ms;     /* mở menu, tooltip, toast */
  --m-slow: 380ms;     /* modal, vào trang */
  --m-reveal: 640ms;   /* hiện khi cuộn */
  --m-hero: 900ms;     /* trang chủ */
  --e-out: cubic-bezier(.16, 1, .3, 1);       /* ra nhanh, dừng êm (mặc định) */
  --e-in-out: cubic-bezier(.65, .05, .36, 1); /* đổi trạng thái qua lại */
  --e-in: cubic-bezier(.5, 0, .75, 0);        /* biến mất */
  --e-spring: cubic-bezier(.34, 1.4, .64, 1); /* nảy nhẹ (dự phòng khi trình duyệt chưa hỗ trợ linear()) */
  /* Lò xo vật lý (tính sẵn từ độ cứng/giảm chấn): mỗi loại một vai trò rõ ràng */
  --spring-snappy: cubic-bezier(.2, .9, .3, 1);   /* phản hồi thao tác: 345ms, không nảy */
  --spring-smooth: cubic-bezier(.16, 1, .3, 1);   /* vào trang, mở khối: 690ms, không nảy */
  --spring-bouncy: cubic-bezier(.3, 1.25, .5, 1); /* thứ vừa xuất hiện: nảy 6% */
  --spring-pop: cubic-bezier(.3, 1.5, .5, 1);     /* icon nhỏ xác nhận: nảy 13% */
  --sh-1: 0 1px 2px rgba(20, 26, 51, .05), 0 2px 6px -2px rgba(20, 26, 51, .06);
  --sh-2: 0 1px 2px rgba(20, 26, 51, .05), 0 8px 18px -8px rgba(20, 26, 51, .14), 0 18px 36px -24px rgba(20, 26, 51, .18);
  --sh-3: 0 2px 4px rgba(20, 26, 51, .05), 0 14px 28px -12px rgba(20, 26, 51, .2), 0 32px 64px -32px rgba(20, 26, 51, .28);
  --stagger: 55ms;
  --lift: -2px;
  --press: .97;
  --shadow-lift: 0 14px 30px -16px rgba(20, 26, 51, .28);
  --shadow-pop: 0 24px 48px -20px rgba(20, 26, 51, .35);
  transition: --sidebar var(--m-slow) var(--e-in-out);
}
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring-snappy: linear(0, 0.0458, 0.1529, 0.2757, 0.3999, 0.5151, 0.6217, 0.7063, 0.7757, 0.8312, 0.8771, 0.9103, 0.9355, 0.9543, 0.9689, 0.9788, 0.9859, 0.9909, 0.9945, 0.9967, 0.9982, 0.9992, 0.9998, 1.0001, 1);
    --spring-smooth: linear(0, 0.0527, 0.1687, 0.2987, 0.4291, 0.5416, 0.6374, 0.7189, 0.7822, 0.834, 0.873, 0.9033, 0.9274, 0.9451, 0.959, 0.9692, 0.9769, 0.9829, 0.9872, 0.9904, 0.9929, 0.9947, 0.9961, 0.9971, 0.9978, 0.9984, 0.9988, 0.9991, 1);
    --spring-bouncy: linear(0, 0.0569, 0.1875, 0.3503, 0.5164, 0.6677, 0.7992, 0.897, 0.9676, 1.0144, 1.0418, 1.0544, 1.0566, 1.0523, 1.0443, 1.0349, 1.0252, 1.0169, 1.0101, 1.0049, 1.0012, 0.9988, 0.9974, 0.9968, 0.9968, 0.9971, 0.9976, 0.9982, 0.9987, 0.9991, 0.9995, 0.9998, 1);
    --spring-pop: linear(0, 0.0869, 0.2738, 0.5059, 0.7261, 0.8988, 1.0262, 1.1008, 1.1308, 1.1302, 1.1096, 1.0811, 1.0502, 1.0233, 1.0037, 0.9905, 0.9837, 0.9821, 0.9838, 0.9872, 0.9913, 0.9953, 0.9983, 1.0005, 1.0018, 1.0024, 1.0023, 1.0019, 1.0014, 1.0009, 1.0004, 1.0001, 1);
    --e-spring: var(--spring-pop);
  }
}

/* ---------- 2. Keyframes dùng chung ---------- */
@keyframes m-enter { from { opacity: 0; transform: translate3d(0, 6px, 0); } to { opacity: 1; transform: none; } }
@keyframes m-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-fade-up { from { opacity: 0; transform: translate3d(0, 18px, 0); } to { opacity: 1; transform: none; } }
@keyframes m-fade-down { from { opacity: 0; transform: translate3d(0, -12px, 0); } to { opacity: 1; transform: none; } }
@keyframes m-scale-in { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: none; } }
@keyframes m-pop { 0% { opacity: 0; transform: scale(.85); } 60% { opacity: 1; transform: scale(1.04); } 100% { transform: none; } }
@keyframes m-slide-in-right { from { opacity: 0; transform: translate3d(24px, 0, 0) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes m-spin { to { transform: rotate(360deg); } }
@keyframes m-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@keyframes m-shake { 0%, 100% { transform: none; } 20% { transform: translateX(-4px); } 40% { transform: translateX(4px); } 60% { transform: translateX(-2px); } 80% { transform: translateX(2px); } }
@keyframes m-ring-pulse { 0% { box-shadow: 0 3px 0 var(--coin-dark), 0 0 0 0 rgba(255, 197, 49, .55); } 100% { box-shadow: 0 3px 0 var(--coin-dark), 0 0 0 16px rgba(255, 197, 49, 0); } }
@keyframes m-draw { to { stroke-dashoffset: 0; } }
@keyframes m-dot { 0%, 80%, 100% { opacity: .25; transform: scale(.8); } 40% { opacity: 1; transform: none; } }

/* ---------- 3. Chuyển trang (View Transitions giữa các trang, trình duyệt hỗ trợ) ----------
   Mờ chéo nhanh, không nhòe, không trượt: nhẹ cho máy yếu. Thanh trên và menu đứng yên;
   ô xanh của mục đang chọn trượt sang mục mới. */
@view-transition { navigation: auto; }
.topbar { view-transition-name: topbar; }
@media (min-width: 992px) {
  .sidebar { view-transition-name: sidebar; }
  .sidebar .nav-link.active { view-transition-name: nav-active; }
}
.main-area, .site-main { view-transition-name: page; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
::view-transition-group(page) { animation-duration: 0s; }
::view-transition-old(page) { animation: vt-out 120ms ease-in both; }
::view-transition-new(page) { animation: vt-in 200ms ease-out both; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; } to { opacity: 1; } }
::view-transition-group(nav-active) { animation-duration: 260ms; animation-timing-function: var(--e-out); }
::view-transition-group(topbar), ::view-transition-group(sidebar) { animation-duration: 0s; }

/* ---------- 4. Vào trang: các khối hiện nhanh, lệch nhau rất ít ---------- */
.js .main-area > :not(.row):not(.modal),
.js .site-main > :not(.row):not(.hero-wrap):not(.modal):not([data-reveal]),
.js .main-area > .row:not([data-reveal-stagger]) > :not(.modal),
.js .site-main > .row:not([data-reveal-stagger]) > :not(.modal) { animation: m-enter 320ms var(--e-out) both; }
/* đến bằng chuyển trang: cả trang đã mờ chéo, các khối bên trong không chạy thêm */
.vt-in .main-area > *, .vt-in .site-main > *, .vt-in .main-area > .row > *, .vt-in .site-main > .row > * { animation: none !important; }
.main-area > :nth-child(2), .site-main > :nth-child(2) { animation-delay: 30ms; }
.main-area > :nth-child(3), .site-main > :nth-child(3) { animation-delay: 60ms; }
.main-area > :nth-child(n+4), .site-main > :nth-child(n+4) { animation-delay: 90ms; }

/* ---------- 5. Hiện khi cuộn: data-reveal="up|down|left|right|scale|blur|clip" ---------- */
[data-reveal] { --rv-x: 0; --rv-y: 22px; --rv-s: 1; --rv-blur: 0; transition: opacity var(--m-reveal) var(--e-out), transform var(--m-reveal) var(--e-out), clip-path var(--m-reveal) var(--e-out); transition-delay: calc(var(--i, 0) * var(--stagger)); }
[data-reveal='down'] { --rv-y: -22px; }
[data-reveal='left'] { --rv-x: 28px; --rv-y: 0; }
[data-reveal='right'] { --rv-x: -28px; --rv-y: 0; }
[data-reveal='scale'] { --rv-y: 0; --rv-s: .94; }
[data-reveal='blur'] { --rv-y: 10px; }
.js [data-reveal]:not(.is-in) { opacity: 0; transform: translate3d(var(--rv-x), var(--rv-y), 0) scale(var(--rv-s)); }
.js [data-reveal='clip']:not(.is-in) { opacity: 1; transform: none; clip-path: inset(0 0 100% 0 round 12px); }
[data-reveal='clip'].is-in { clip-path: inset(0 0 0 0 round 12px); }
[data-reveal].is-in { opacity: 1; transform: none; }
/* con của data-reveal-stagger cũng hiện lần lượt */
.js [data-reveal-stagger] > * { transition: opacity var(--m-reveal) var(--e-out), transform var(--m-reveal) var(--e-out); transition-delay: calc(var(--i, 0) * var(--stagger)); }
.js [data-reveal-stagger]:not(.is-in) > * { opacity: 0; transform: translate3d(0, 16px, 0); }
.motion-fallback [data-reveal], .motion-fallback [data-reveal-stagger] > *, .motion-fallback [data-split] { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }

/* ---------- 6. Nút ---------- */
.btn { transition: color var(--m-fast) ease, background-color var(--m-fast) ease, border-color var(--m-fast) ease, box-shadow var(--m-base) var(--e-out), transform var(--m-fast) var(--e-out); }
.btn:active:not(:disabled) { transform: scale(var(--press)); transition-duration: var(--m-instant); }
.input-group > .btn:hover, .btn-group > .btn:hover, .btn-link:hover { transform: none !important; box-shadow: none !important; }
.btn-primary:not(.btn-link) { background-image: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0) 60%); }
.btn-primary:hover:not(:disabled), .btn-ink:hover, .btn-coin:hover { transform: translateY(var(--lift)); }
.btn-primary:hover:not(:disabled) { box-shadow: 0 1px 2px rgba(43, 89, 255, .3), 0 10px 22px -10px rgba(43, 89, 255, .65); }
.btn-ink:hover { box-shadow: 0 8px 18px -8px rgba(20, 26, 51, .55); }
.btn-coin:hover { box-shadow: 0 5px 0 var(--coin-dark), 0 10px 20px -10px rgba(229, 168, 0, .6); }
.btn-coin:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 var(--coin-dark); }
.btn i { display: inline-block; transition: transform 420ms var(--spring-pop); }
.btn:hover i.bi-plus-lg { transform: rotate(90deg); }
.btn:hover i.bi-box-arrow-up-right, .btn:hover i.bi-chevron-right { transform: translate(2px, -1px); }
.btn:hover i.bi-download { transform: translateY(2px); }
/* đang xử lý */
.btn.is-loading { pointer-events: none; cursor: progress; opacity: .92; }
.btn.is-loading > i { display: none; }
.btn.is-loading::before { content: ''; display: inline-block; width: 1em; height: 1em; margin-right: .45em; vertical-align: -.15em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: m-spin .65s linear infinite; }
.btn:disabled:not(.is-loading) { transform: none; box-shadow: none; }
/* sao chép thành công */
.copy-ok { color: var(--mint) !important; }
.btn.copy-ok.btn-primary, .btn.copy-ok.btn-success { color: #fff !important; background-color: var(--mint); border-color: var(--mint); }
.copy-ok i { animation: m-icon-morph 520ms var(--spring-pop) both; }
@keyframes m-icon-morph { 0% { opacity: 0; transform: scale(.4) rotate(-45deg); } 100% { opacity: 1; transform: none; } }
.copy-ripple { position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; pointer-events: none; border: 2px solid currentColor; opacity: 0; }

/* ---------- 7. Thẻ, liên kết, icon ---------- */
.card { transition: box-shadow var(--m-base) var(--e-out), transform var(--m-base) var(--e-out), border-color var(--m-base) ease; }
.card-hover:hover, .plan-card:hover, .feature-card:hover { transform: translateY(var(--lift)); box-shadow: var(--sh-2); border-color: #d3daf0; }
.stat-money { position: relative; overflow: hidden; }
.stat-money::after { content: ''; position: absolute; inset: -40% -10% auto auto; width: 180px; height: 180px; border-radius: 50%; background: radial-gradient(closest-side, rgba(255, 197, 49, .22), transparent); pointer-events: none; }
.stat .value { font-variant-numeric: tabular-nums; }
.link-u, .site-foot a { text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat; transition: background-size var(--m-base) var(--e-out), color var(--m-fast) ease; }
.link-u:hover, .site-foot a:hover { background-size: 100% 1px; }
.table-hover > tbody > tr > * { transition: background-color var(--m-fast) ease; }
.table > tbody > tr:hover > * { --bs-table-bg-state: rgba(43, 89, 255, .035); }
.feature .ico, .empty i { transition: transform var(--m-base) var(--e-spring), background-color var(--m-base) ease; }
.feature:hover .ico { transform: rotate(-8deg) scale(1.08); background: #dfe6ff; }
.badge { transition: background-color var(--m-fast) ease, color var(--m-fast) ease; }

/* ---------- 8. Thanh trên & menu ---------- */
.topbar { transition: background-color var(--m-base) ease, box-shadow var(--m-base) ease, border-color var(--m-base) ease; }
.topbar.is-scrolled { background: rgba(255, 255, 255, .97); border-bottom-color: rgba(226, 230, 240, .7); box-shadow: 0 8px 24px -18px rgba(20, 26, 51, .4); }
.brand-mark { transition: transform var(--m-base) var(--e-spring); }
.brand-logo { transition: transform var(--m-base) var(--e-spring); transform-origin: left center; }
.brand:hover .brand-logo { transform: scale(1.04); }
.balance-chip { transition: background-color var(--m-fast) ease, transform var(--m-fast) var(--e-out), box-shadow var(--m-base) var(--e-out); }
.balance-chip:hover { transform: translateY(-1px); box-shadow: 0 6px 14px -8px rgba(229, 168, 0, .6); }
.sidebar .nav-link { transition: background-color var(--m-fast) ease, color var(--m-fast) ease; position: relative; z-index: 1; }
.sidebar .offcanvas-body { position: relative; }
.sidebar .nav-link i { transition: transform var(--m-base) var(--e-out), opacity var(--m-fast) ease; }
.sidebar .nav-link:hover i { transform: translateX(2px) scale(1.06); opacity: 1; }
.sidebar .nav-link.active { box-shadow: 0 8px 18px -10px rgba(43, 89, 255, .9); }
.sidebar .nav-link.active::before { content: ''; position: absolute; left: -.4rem; top: 22%; bottom: 22%; width: 3px; border-radius: 0 3px 3px 0; background: var(--coin); animation: m-scale-in var(--m-slow) var(--e-spring) both; }
.offcanvas-lg, .offcanvas { --bs-offcanvas-transition: transform var(--m-slow) var(--e-out); }
.offcanvas-backdrop.show { opacity: .4; }
.dropdown-menu { --bs-dropdown-border-color: var(--line); --bs-dropdown-border-radius: var(--radius-m); box-shadow: var(--shadow-pop); padding: .35rem; }
.dropdown-menu.show { animation: m-dd-in 160ms var(--e-out) both; transform-origin: top left; }
.dropdown-menu-end.show { transform-origin: top right; }
@keyframes m-dd-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.dropdown-item { border-radius: 8px; transition: background-color var(--m-fast) ease, color var(--m-fast) ease; }
.nav-tabs .nav-link, .nav-pills .nav-link { transition: color var(--m-fast) ease, background-color var(--m-base) var(--e-out), border-color var(--m-base) ease, box-shadow var(--m-base) ease; }
.nav-pills .nav-link.active { box-shadow: 0 6px 16px -8px rgba(43, 89, 255, .7); }
.tab-pane.fade { transition: opacity 180ms ease; }
/* ô trắng trượt sang mục đang chọn của nhóm tab (motion.js) */
.has-ind { position: relative; isolation: isolate; }
.has-ind > .nav-ind { position: absolute; z-index: 0; left: 0; top: 0; border-radius: 9px; background: var(--card); box-shadow: 0 1px 2px rgba(20, 26, 51, .08), 0 2px 8px rgba(20, 26, 51, .06); pointer-events: none; transition: transform 480ms var(--spring-smooth), width 480ms var(--spring-smooth), height 480ms var(--spring-smooth); }
.has-ind.no-anim > .nav-ind { transition: none; }
.seg-tabs.has-ind .nav-link.active { background: transparent; box-shadow: none; }
.seg-tabs.has-ind > li, .seg-tabs.has-ind > .nav-link { position: relative; z-index: 1; }
.page-link { transition: background-color var(--m-fast) ease, color var(--m-fast) ease, transform var(--m-fast) var(--e-out); }
.page-link:hover { transform: translateY(-1px); }
.collapsing { transition: height var(--m-slow) var(--e-out); }

/* Thu gọn menu bên trái (máy tính) */
.sb-toggle { display: none; }
@media (min-width: 992px) {
  .sidebar .offcanvas-body { display: flex !important; flex-direction: column; min-height: 100%; }
  .sb-toggle { display: flex; align-items: center; gap: .7rem; margin: auto .4rem 0; padding: .55rem .75rem; border: 0; background: transparent; color: #8f97bd; border-radius: var(--radius-s); font-size: .85rem; font-weight: 500; transition: background-color var(--m-fast) ease, color var(--m-fast) ease; white-space: nowrap; }
  .sb-toggle:hover { background: rgba(255, 255, 255, .06); color: #fff; }
  .sb-toggle i { transition: transform var(--m-slow) var(--e-in-out); font-size: 1.05rem; }
  .nav-label, .qa-label, .who-text, .sidebar .group, .sb-toggle span { transition: opacity var(--m-base) ease, max-width var(--m-slow) var(--e-in-out); white-space: nowrap; }
  .qa-label, .sb-toggle span { display: inline-block; vertical-align: top; max-width: 160px; overflow: hidden; }
  html.sb-mini { --sidebar: 76px; }
  .sb-mini .sidebar { overflow-x: hidden; }
  .sb-mini .sidebar .nav-link { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
  .sb-mini .nav-label, .sb-mini .qa-label, .sb-mini .who-text, .sb-mini .sb-toggle span { opacity: 0; max-width: 0; width: 0; overflow: hidden; }
  .sb-mini .sidebar .group { opacity: 0; height: 1px; padding: 0; margin: .7rem 1.1rem; background: rgba(255, 255, 255, .08); overflow: hidden; }
  .sb-mini .quick-actions { padding-left: .55rem; padding-right: .55rem; }
  .sb-mini .quick-actions .btn { padding-left: 0; padding-right: 0; }
  .sb-mini .quick-actions .btn i { margin: 0 !important; }
  .sb-mini .sidebar .who { display: flex; justify-content: center; padding-left: 0; padding-right: 0; }
  .sb-mini .sb-toggle { justify-content: center; gap: 0; }
  .sb-mini .sb-toggle i { transform: rotate(180deg); }
  .sb-mini .sidebar .nav-link.active::before { left: 0; }
}
.who { display: flex; align-items: center; gap: .65rem; }
.who-avatar { flex: none; width: 34px; height: 34px; border-radius: 10px; background: var(--ink-2); color: var(--coin); display: grid; place-items: center; font-weight: 800; transition: transform var(--m-base) var(--e-spring); }
.who:hover .who-avatar { transform: rotate(-6deg) scale(1.05); }
.who-text { min-width: 0; }
.author-card .avatar, .shop-head .brand-mark { transition: transform var(--m-base) var(--e-spring); }
.author-card:hover .avatar { transform: rotate(-6deg) scale(1.05); }

/* ---------- 9. Form ---------- */
.form-control, .form-select { transition: border-color var(--m-fast) ease, box-shadow 420ms var(--spring-snappy), background-color var(--m-fast) ease; }
.form-control:focus, .form-select:focus { box-shadow: 0 0 0 1px rgba(43, 89, 255, .35), 0 0 0 4px rgba(43, 89, 255, .12), 0 6px 16px -10px rgba(43, 89, 255, .45); }
.form-label { transition: color var(--m-fast) ease; }
.form-label:has(+ .form-control:focus, + .form-select:focus, + .input-group:focus-within, + .pw-wrap:focus-within, + .bank-trigger:focus) { color: var(--cobalt); }
.form-control:user-invalid:not(:focus), .form-select:user-invalid:not(:focus) { border-color: var(--rose); animation: m-shake 360ms var(--e-out) 1; }
.form-check-input { transition: background-color 220ms ease, border-color 220ms ease, background-position 420ms var(--spring-bouncy), box-shadow var(--m-base) ease, transform 160ms var(--spring-snappy); }
.form-switch .form-check-input:active { transform: scale(.94); }
.form-check-input[type=checkbox]:not([role=switch]):checked { animation: m-pop 300ms var(--e-spring); }
.form-switch .form-check-input:active { filter: brightness(.95); }
.input-group-text { transition: border-color var(--m-fast) ease, color var(--m-fast) ease; }
.input-group:focus-within .input-group-text { border-color: var(--cobalt); color: var(--cobalt); }
.pw-wrap { position: relative; }
.pw-wrap .form-control { padding-right: 2.75rem; }
.pw-toggle { position: absolute; right: .35rem; top: 50%; transform: translateY(-50%); width: 2.1rem; height: 2.1rem; border: 0; border-radius: 8px; background: transparent; color: var(--ink-soft); display: grid; place-items: center; transition: background-color var(--m-fast) ease, color var(--m-fast) ease; }
.pw-toggle:hover { background: var(--paper); color: var(--ink); }
.pw-toggle i { grid-area: 1 / 1; transition: opacity var(--m-base) ease, transform var(--m-base) var(--e-out); }
.pw-toggle .bi-eye-slash { opacity: 0; transform: scale(.6) rotate(-20deg); }
.pw-toggle.is-on .bi-eye { opacity: 0; transform: scale(.6) rotate(20deg); }
.pw-toggle.is-on .bi-eye-slash { opacity: 1; transform: none; }
.type-card { transition: border-color var(--m-fast) ease, background-color var(--m-fast) ease, transform var(--m-base) var(--e-out), box-shadow var(--m-base) var(--e-out); }
.type-card:hover { transform: translateY(var(--lift)); box-shadow: var(--shadow-lift); }
.btn-check:checked + .type-card i { animation: m-pop 420ms var(--e-spring); }
.type-card i { transition: color var(--m-fast) ease; }

/* ---------- 10. Thông báo, cảnh báo, toast ---------- */
.js .alert:not(.alert-static) { animation: m-fade-down var(--m-slow) var(--e-out) both; }
.alert.fade:not(.show) { transform: translateY(-6px); transition: opacity var(--m-base) ease, transform var(--m-base) var(--e-out); }
.alert-check { flex: none; width: 1.25rem; height: 1.25rem; margin-right: .5rem; vertical-align: -.25rem; }
.alert-check circle { stroke: currentColor; opacity: .25; }
.alert-check path { stroke: currentColor; stroke-dasharray: 24; stroke-dashoffset: 24; animation: m-draw 520ms var(--e-out) 260ms forwards; }
.alo-toasts { position: fixed; z-index: 1090; right: 1rem; bottom: 1rem; display: flex; flex-direction: column; align-items: flex-end; gap: .5rem; pointer-events: none; max-width: calc(100vw - 2rem); }
.alo-toast { --toast-ms: 2600ms; position: relative; overflow: hidden; pointer-events: auto; display: flex; align-items: center; gap: .6rem; min-width: 220px; max-width: 380px; padding: .75rem .95rem; border-radius: var(--radius-m); background: var(--ink); color: #fff; box-shadow: 0 0 0 1px rgba(255, 255, 255, .06) inset, var(--sh-3); font-weight: 500; font-size: .9rem; animation: m-toast-in 260ms var(--e-out) both; touch-action: pan-y; cursor: pointer; }
@keyframes m-toast-in { from { opacity: 0; transform: translate3d(0, 16px, 0) scale(.94); } 40% { opacity: 1; } to { opacity: 1; transform: none; } }
.alo-toast i { font-size: 1.1rem; animation: m-icon-morph 520ms var(--spring-pop) 120ms both; }
.alo-toast::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: currentColor; opacity: .28; transform-origin: left; animation: m-toast-time var(--toast-ms) linear both; }
.alo-toast:hover::after { animation-play-state: paused; }
@keyframes m-toast-time { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.alo-toast.is-success i { color: #5ee0b4; }
.alo-toast.is-error i { color: #ff8a8e; }
.alo-toast.is-info i { color: var(--coin); }
.alo-toast.is-leaving { transition: opacity 220ms ease, transform 300ms var(--e-in); opacity: 0; transform: translate3d(var(--swipe, 12px), 0, 0) scale(.97); }
@media (max-width: 575.98px) { .alo-toasts { left: 1rem; right: 1rem; align-items: stretch; } .alo-toast { max-width: none; } }

/* ---------- 11. Modal & hộp xác nhận ---------- */
.modal { --bs-modal-border-radius: var(--radius-l); --bs-modal-border-color: transparent; --bs-modal-box-shadow: var(--shadow-pop); }
.modal-content { box-shadow: var(--shadow-pop); }
.modal.fade { transition: opacity 240ms ease; }
.modal.fade:not(.show) .modal-dialog { transition-duration: 200ms; transition-timing-function: var(--e-in); }
.modal.fade .modal-dialog { transform: translate3d(0, 10px, 0) scale(.98); transition: transform 240ms var(--e-out); }
.modal.show .modal-dialog { transform: none; }
.modal.modal-static .modal-dialog { transform: scale(1.02); }
.modal-backdrop { --bs-backdrop-opacity: .4; }
.modal-backdrop.fade { transition: opacity var(--m-base) ease; }
@media (max-width: 575.98px) { .modal.fade .modal-fullscreen-sm-down { transform: translateY(40px); } .modal.show .modal-fullscreen-sm-down { transform: none; } }
.alo-confirm .modal-dialog { max-width: 400px; }
.alo-confirm .modal-body { padding: 1.6rem 1.5rem 1rem; text-align: center; }
.alo-confirm .confirm-ico { width: 52px; height: 52px; margin: 0 auto .9rem; border-radius: 16px; display: grid; place-items: center; font-size: 1.5rem; background: var(--cobalt-tint); color: var(--cobalt); }
.alo-confirm.is-danger .confirm-ico { background: #fde8e9; color: var(--rose); }
.alo-confirm.show .confirm-ico { animation: m-pop 480ms var(--e-spring) 80ms both; }
.alo-confirm .confirm-msg { font-weight: 600; font-size: 1.02rem; white-space: pre-line; }
.alo-confirm .modal-footer { border-top: 0; padding: 0 1.5rem 1.4rem; display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.alo-confirm .modal-footer > * { margin: 0; }
.btn-danger-soft { background: var(--rose); color: #fff; border: 0; }
.btn-danger-soft:hover { background: #c93a3f; color: #fff; transform: translateY(var(--lift)); box-shadow: 0 8px 18px -8px rgba(229, 72, 77, .6); }

/* Tooltip */
.alo-tip { position: fixed; z-index: 1095; pointer-events: none; background: var(--ink); color: #fff; font-size: .8rem; font-weight: 500; padding: .35rem .6rem; border-radius: 8px; box-shadow: var(--shadow-lift); opacity: 0; transform: translate3d(-4px, 0, 0) scale(.96); transition: opacity var(--m-fast) ease, transform var(--m-base) var(--e-out); white-space: nowrap; }
.alo-tip.is-top { transform: translate3d(0, 4px, 0) scale(.96); }
.alo-tip.is-on { opacity: 1; transform: none; }

/* ---------- 12. Chờ tải & khung xương ---------- */
.skeleton { position: relative; overflow: hidden; background: #e9edf6; border-radius: var(--radius-s); }
.skeleton::after { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .65), transparent); animation: m-shimmer 1.2s ease-in-out infinite; }
.dots-wait { display: inline-flex; gap: 4px; vertical-align: middle; }
.dots-wait span { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: m-dot 1.2s ease-in-out infinite; }
.dots-wait span:nth-child(2) { animation-delay: .15s; }
.dots-wait span:nth-child(3) { animation-delay: .3s; }
.qr-dialog { max-width: 360px; }
.qr-frame { width: 220px; height: 220px; margin: 0 auto; border-radius: 16px; background: #fff; border: 1px solid var(--line); padding: 10px; display: grid; place-items: center; }
.qr-frame { position: relative; overflow: hidden; }
.qr-frame img { width: 100%; height: 100%; opacity: 0; }
.qr-frame img.is-loaded { opacity: 1; animation: m-qr-scan 900ms cubic-bezier(.45, .05, .25, 1) both; }
@keyframes m-qr-scan { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
.qr-frame:has(img.is-loaded)::after { content: ''; position: absolute; left: 6px; right: 6px; top: 0; height: 26px; pointer-events: none; background: linear-gradient(180deg, rgba(43, 89, 255, 0), rgba(43, 89, 255, .22) 80%, rgba(43, 89, 255, .7)); border-radius: 2px; animation: m-qr-line 900ms cubic-bezier(.45, .05, .25, 1) both; }
@keyframes m-qr-line { 0% { transform: translateY(-26px); opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(var(--qr-h, 220px)); opacity: 0; } }
.qr-frame.skeleton img.is-loaded { position: relative; z-index: 1; }

/* ---------- 13. Rút gọn link ---------- */
#quickLink [data-step='done']:not(.d-none) { animation: m-scale-in var(--m-slow) var(--e-out) both; }
#quickLink [data-step='done'] .bi-check-circle-fill { display: inline-block; animation: m-pop 560ms var(--e-spring) 80ms both; }
#ql-result, #created { transition: background-color var(--m-slow) ease; }
.flash-ok { animation: m-flash 900ms var(--e-out); }
@keyframes m-flash { 0% { background-color: var(--mint-tint); } 100% { background-color: #fff; } }
.form-control-lg:focus { box-shadow: 0 0 0 .3rem rgba(43, 89, 255, .14); }

/* ---------- 14. Trang chủ ---------- */
body { overflow-x: clip; }
.hero-wrap { position: relative; isolation: isolate; }
.hero-bg { position: absolute; z-index: -1; top: -2rem; bottom: -6rem; left: 50%; width: 100vw; transform: translateX(-50%); overflow: hidden; pointer-events: none; -webkit-mask-image: linear-gradient(#000 55%, transparent); mask-image: linear-gradient(#000 55%, transparent); }
.hero-bg .grid { position: absolute; inset: 0; background-image: linear-gradient(rgba(20, 26, 51, .045) 1px, transparent 1px), linear-gradient(90deg, rgba(20, 26, 51, .045) 1px, transparent 1px); background-size: 44px 44px; -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 35%, #000 30%, transparent 75%); mask-image: radial-gradient(ellipse 70% 60% at 50% 35%, #000 30%, transparent 75%); }
.hero-bg .layer { position: absolute; inset: 0; }
.hero-bg .blob { position: absolute; border-radius: 50%; }
.hero-bg .b1 { width: 520px; height: 520px; left: 8%; top: -120px; background: radial-gradient(closest-side, rgba(43, 89, 255, .16), transparent); }
.hero-bg .b2 { width: 420px; height: 420px; right: 6%; top: 40px; background: radial-gradient(closest-side, rgba(255, 197, 49, .2), transparent); }
.hero-bg .b3 { width: 360px; height: 360px; left: 42%; bottom: -120px; background: radial-gradient(closest-side, rgba(18, 163, 122, .12), transparent); }
.hero h1 { animation: m-fade-up 520ms var(--e-out) both; }
.hero .lead, .hero .hero-cta { animation: m-fade-up var(--m-hero) var(--e-out) both; }
.hero .lead { animation-delay: 90ms; }
.hero .hero-cta { animation-delay: 160ms; }
.hero .hero-cta .btn-primary { box-shadow: 0 10px 24px -12px rgba(43, 89, 255, .7); }
.stub-wrap { animation: m-fade-up 520ms var(--e-out) 200ms both; }
.stub .short { position: relative; }
.stub .short::after { content: ''; position: absolute; left: 0; right: 0; bottom: -4px; height: 2px; border-radius: 2px; background: var(--coin); transform-origin: left; transform: scaleX(0); animation: m-underline 600ms var(--e-out) 600ms forwards; }
@keyframes m-underline { to { transform: scaleX(1); } }
.feature-card { height: 100%; padding: 1.25rem; border-radius: var(--radius-m); border: 1px solid transparent; transition: transform var(--m-base) var(--e-out), box-shadow var(--m-base) var(--e-out), border-color var(--m-base) ease, background-color var(--m-base) ease; }
.feature-card:hover { background: var(--card); border-color: var(--line); }
.bank-strip-list li { transition: transform var(--m-base) var(--e-spring); }
.bank-strip-list li:hover { transform: translateY(-3px) scale(1.06); }
.js [data-reveal-stagger].bank-strip-list:not(.is-in) > * { transform: translate3d(0, 10px, 0) scale(.9); }

/* ---------- 15. Trang vượt link ---------- */
.ticket { animation: m-fade-up var(--m-slow) var(--e-out) 60ms both; }
.ticket-head h1 { animation: m-enter var(--m-slow) var(--e-out) 200ms both; }
.buy-box { transition: box-shadow var(--m-base) var(--e-out), transform var(--m-base) var(--e-out); }
.buy-box:hover { box-shadow: var(--shadow-lift); transform: translateY(-1px); }
.auth-card, .note-page { animation: m-fade-up var(--m-slow) var(--e-out) both; }
body:has(.auth-card) { background: radial-gradient(900px 420px at 15% -10%, rgba(43, 89, 255, .09), transparent 60%), radial-gradient(700px 380px at 95% 10%, rgba(255, 197, 49, .12), transparent 60%), var(--paper); background-attachment: fixed; }

/* ---------- 16. Giảm chuyển động: xem mục 21 ở cuối file ---------- */

/* ---------- 17. Tổng quan: cập nhật thời gian thực ---------- */
.live-pill { display: inline-flex; align-items: center; gap: .45rem; padding: .2rem .65rem; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); font-weight: 500; font-variant-numeric: tabular-nums; transition: background-color var(--m-base) ease, color var(--m-base) ease; }
.live-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: #b5bcd3; }
.live-pill[data-state='live'] { background: var(--mint-tint); border-color: #bfe8d9; color: #0b7356; }
.live-pill[data-state='live'] .live-dot { background: var(--mint); }
.live-pill[data-state='live'] .live-dot::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: var(--mint); animation: m-live 1.8s ease-out infinite; }
.live-pill[data-state='poll'] .live-dot { background: var(--cobalt); }
.live-pill[data-state='reconnect'] { background: var(--coin-tint); border-color: #f5dc8e; color: #8a6400; }
.live-pill[data-state='reconnect'] .live-dot { background: var(--coin-dark); animation: m-dot 1.2s ease-in-out infinite; }
.live-pill[data-state='expired'] { background: #fde8e9; border-color: #f6c2c4; color: #a3262b; }
@keyframes m-live { 0% { transform: scale(1); opacity: .6; } 100% { transform: scale(3); opacity: 0; } }
.row-flash > td { animation: m-row-flash 1.6s var(--e-out); }
@keyframes m-row-flash { 0% { background-color: rgba(18, 163, 122, .16); } 100% { background-color: transparent; } }
.value-bump { animation: m-bump 600ms var(--e-spring); transform-origin: left center; }
.main-area tbody.no-enter > tr { animation: none; }
@keyframes m-bump { 0% { transform: scale(1); } 35% { transform: scale(1.08); } 100% { transform: none; } }

/* =====================================================================
   18. MÀN HÌNH CHỜ VƯỢT LINK — "tín hiệu" chạy quanh vòng
   Tiến trình (vòng, vệt sáng, vạch sáng dần, đầu sáng, --p) do JS vẽ theo đồng hồ thật.
   Các lớp trang trí chỉ quay bằng transform/opacity để giữ khung hình đều.
   Trình tự hoàn tất do JS điều phối (data-state="complete" + Web Animations).
   ===================================================================== */
@property --glow { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --bo-ang { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.vring { --vr-c1: #8fb0ff; --vr-c2: #2b59ff; --vr-c3: #7b5cff; position: relative; width: 208px; aspect-ratio: 1; margin: .35rem auto .9rem; isolation: isolate; animation: vr-enter 900ms var(--spring-smooth) 120ms both; contain: layout style; }
@keyframes vr-enter { from { opacity: 0; transform: scale(.86) rotate(-12deg); } to { opacity: 1; transform: none; } }
.vring-svg { position: relative; z-index: 2; display: block; width: 100%; height: 100%; overflow: visible; }
.vr-head, .vr-ripple { transform-box: view-box; transform-origin: 100px 100px; }
/* lớp trang trí: mỗi lớp là 1 svg xoay nguyên khối (GPU) */
.vr-layer { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; overflow: visible; pointer-events: none; will-change: transform; }

/* nền sáng: quầng sáng xung quanh + dải năng lượng xoay chậm, mạnh dần theo tiến trình */
.vring-aura { position: absolute; inset: -14%; z-index: 0; pointer-events: none; }
.vring-aura i { position: absolute; border-radius: 50%; }
.vr-wash { display: none; }
.vr-amb { inset: 14%; background: radial-gradient(closest-side, rgba(43, 89, 255, .12), rgba(43, 89, 255, .04) 62%, transparent); }


/* vòng năng lượng ngoài: 2 cung sáng quay ngược chiều, sáng dần theo tiến trình */
.vr-l-arc { opacity: calc(.45 + var(--p) * .55); }
.vr-energy-base { stroke: rgba(91, 123, 255, .16); }
.vr-l-arc-a { animation: m-spin 7s linear infinite; }
.vr-l-arc-b { animation: m-spin 11s linear infinite reverse; }

/* vạch chia: vạch sáng hiện dần đúng theo tiến trình, trùng khít vạch mờ */
.vr-ticks circle { stroke: #d3dbf3; }
.vr-ticks-lit { stroke: #6f8dff; }

/* vòng tiến trình */
.vr-track { stroke: #e9edfa; }
.vr-s1 { stop-color: var(--vr-c1); transition: stop-color .7s ease .24s; }
.vr-s2 { stop-color: var(--vr-c2); transition: stop-color .7s ease .32s; }
.vr-s3 { stop-color: var(--vr-c3); transition: stop-color .7s ease .4s; }
.vr-prog { stroke: url(#vr-prog); }
.vr-glow { stroke: url(#vr-prog); opacity: .1; transition: opacity .5s ease; }
.vr-trail { stroke: #5b7fff; opacity: .16; transition: opacity .3s ease; }
.vr-trail + .vr-trail { opacity: .3; }


/* hạt sáng có vệt đuôi */
.vr-pdot { fill: #8ea7ff; }
.vr-ptrail { stroke: #8ea7ff; opacity: .28; }
.vr-l-p { animation: m-spin 8s linear infinite; }
.vr-p-b { animation-duration: 12s; animation-delay: -3s; animation-direction: reverse; }
.vr-p-c { animation-duration: 10s; animation-delay: -6s; }
.vr-l-p.vr-p-b { opacity: .7; }

/* đầu vòng sáng */
.vr-dot { fill: #fff; }

/* số đếm: lật kiểu 3D (số cũ lật lên, số mới lật từ dưới vào), không đổi vị trí */
.vr-center { position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; }
.vr-num { position: relative; width: 2.2ch; height: 1.05em; font-size: 3.6rem; font-weight: 800; line-height: 1.05; letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--ink); perspective: 260px; transform-style: preserve-3d; }
.vr-num span { position: absolute; inset: 0; text-align: center; backface-visibility: hidden; transform-origin: 50% 50% -.35em; }
.vr-num span.in { animation: vr-num-in 620ms var(--spring-bouncy) 70ms both; }
.vr-num span.out { animation: vr-num-out 230ms cubic-bezier(.5, 0, .9, .4) both; }
@keyframes vr-num-in { from { opacity: 0; transform: translate3d(0, 34%, 0) rotateX(-75deg) scale(.82); } 45% { opacity: 1; } to { opacity: 1; transform: none; } }
@keyframes vr-num-out { from { opacity: 1; } to { opacity: 0; transform: translate3d(0, -30%, 0) rotateX(70deg) scale(.82); } }
.vr-unit { margin-top: .1rem; font-size: .72rem; font-weight: 600; letter-spacing: .12em; color: var(--ink-soft); transition: opacity .25s ease, transform .35s var(--spring-snappy); }
/* nhịp sáng mỗi giây ở tâm + sóng nhẹ lan ra */
.vr-flash, .vr-wave { position: absolute; left: 50%; top: 50%; border-radius: 50%; opacity: 0; pointer-events: none; }
.vr-flash { width: 104px; height: 104px; margin: -52px 0 0 -52px; background: radial-gradient(closest-side, rgba(127, 162, 255, .26), rgba(127, 162, 255, 0)); }
.vr-wave { width: 112px; height: 112px; margin: -56px 0 0 -56px; border: 1px solid rgba(91, 123, 255, .28); }

.vr-hint { margin: 0 0 1rem; text-align: center; font-weight: 500; color: var(--ink-soft); }

/* ---------- Hoàn tất (trình tự: vòng đầy → vòng năng lượng bừng sáng → số rút đi → lóe sáng
   + sóng → đổi màu xanh → dấu tích tự vẽ → hạt sáng tỏa ra → nền sáng lên → nút bật ra) ---------- */
.vr-ripple { stroke: #5ee0b4; opacity: 0; }
.vr-check { stroke: var(--mint); stroke-dasharray: 1 1.2; stroke-dashoffset: 1.1; opacity: 0; }
.vr-burst circle { fill: #5ee0b4; }
.vring[data-state='complete'] { --vr-c1: #7ce8c2; --vr-c2: #12a37a; --vr-c3: #36c2a0; }
.vring[data-state='complete'] .vr-l-arc { opacity: 1; }
.vring[data-state='complete'] .vr-energy-base { stroke: rgba(18, 163, 122, .28); transition: stroke .6s ease; }
.vring[data-state='complete'] .vr-l-arc circle { stroke: #5ee0b4; opacity: .7; transition: opacity .5s ease; }
.vring[data-state='complete'] .vr-ticks-lit { stroke: #5ee0b4; transition: stroke .6s ease .2s; }
.vring[data-state='complete'] .vr-glow { opacity: .2; }
.vring[data-state='complete'] .vr-trail, .vring[data-state='complete'] .vr-head, .vring[data-state='complete'] .vr-l-p { opacity: 0; transition: opacity .4s ease; }
/* vòng năng lượng bừng sáng một nhịp */
.vring[data-state='complete'] .vring-svg { animation: vr-energy-flare 900ms var(--spring-bouncy) both; }
@keyframes vr-energy-flare { 0% { transform: scale(1); } 35% { transform: scale(1.03); } 100% { transform: none; } }
.vring[data-state='complete'] .vr-ripple { animation: vr-ripple 1s cubic-bezier(.2, .7, .3, 1) 120ms both; }
@keyframes vr-ripple { 0% { opacity: .9; transform: scale(1); stroke-width: 6; } 100% { opacity: 0; transform: scale(1.36); stroke-width: .5; } }
.vring[data-state='complete'] .vr-num span { animation: vr-num-done 260ms cubic-bezier(.5, 0, .9, .4) both; }
@keyframes vr-num-done { to { opacity: 0; transform: scale(.6); } }
.vring[data-state='complete'] .vr-unit { opacity: 0; transform: scale(.7); }
.vring[data-state='complete'] .vr-flash { background: radial-gradient(closest-side, rgba(94, 224, 180, .65), rgba(94, 224, 180, 0)); animation: vr-burst-light 1s ease-out 120ms both; }
@keyframes vr-burst-light { 0% { opacity: 1; transform: scale(.35); } 100% { opacity: 0; transform: scale(2.2); } }
.vring[data-state='complete'] .vr-check { animation: vr-check-draw 540ms cubic-bezier(.65, 0, .2, 1) 300ms both; }
@keyframes vr-check-draw { 0% { opacity: 1; stroke-dashoffset: 1.1; } 100% { opacity: 1; stroke-dashoffset: 0; } }
.vring[data-state='complete'] .vr-amb { background: radial-gradient(closest-side, rgba(18, 163, 122, .1), rgba(18, 163, 122, .03) 62%, transparent); }
.vring[data-state='complete'] + .vr-hint { color: #0b7356; animation: vr-hint-done 520ms var(--spring-snappy) 380ms both; }
@keyframes vr-hint-done { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* nền thẻ sáng lên một nhịp khi mở khóa */
.opt-free { position: relative; isolation: isolate; }
.opt-free::after { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; background: radial-gradient(60% 50% at 50% 34%, rgba(94, 224, 180, .22), transparent 70%); opacity: 0; }
.opt-free.is-unlocked::after { animation: vr-card-glow 1.6s ease-out 260ms both; }
@keyframes vr-card-glow { 0% { opacity: 0; } 35% { opacity: 1; } 100% { opacity: .35; } }

/* ---------- Nút MỞ LINK NGAY ---------- */
.btn-open { --mx: 50%; position: relative; overflow: hidden; isolation: isolate; display: flex; align-items: center; justify-content: center; gap: .6rem; border: 0; color: #fff; font-weight: 800; letter-spacing: .05em;
  background: radial-gradient(160px circle at var(--mx) 50%, rgba(255, 255, 255, calc(.22 * var(--glow))), transparent 70%), linear-gradient(135deg, #4a76ff 0%, #2b59ff 48%, #6b4dff 100%);
  box-shadow: 0 12px 28px -12px rgba(43, 89, 255, .75), 0 0 0 1px rgba(255, 255, 255, .08) inset, 0 1px 0 rgba(255, 255, 255, .28) inset;
  transition: --glow .3s ease, box-shadow .25s ease, filter .25s ease; }
.btn-open:hover, .btn-open:focus-visible { --glow: 1; color: #fff; box-shadow: 0 16px 34px -12px rgba(43, 89, 255, .85), 0 0 0 1px rgba(255, 255, 255, .12) inset, 0 1px 0 rgba(255, 255, 255, .3) inset; }
.btn-open:active { filter: brightness(.96); }
.btn-open::after { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, .5) 50%, transparent 70%); transform: translateX(-120%); }
.btn-open:hover::after { transform: translateX(120%); transition: transform .85s cubic-bezier(.3, .6, .2, 1); }
/* viền sáng chạy một vòng quanh nút khi vừa sẵn sàng */
.btn-open::before { content: ''; position: absolute; inset: 0; z-index: 1; border-radius: inherit; padding: 1.5px; pointer-events: none; background: conic-gradient(from var(--bo-ang), transparent 0 70%, rgba(255, 255, 255, .95) 85%, transparent 100%); -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); opacity: 0; }
.btn-open i, .btn-open .bo-label { display: inline-block; }
.btn-open i { font-size: 1.05em; transition: transform .35s var(--spring-pop); }
.btn-open:hover i { transform: translate(2px, -2px); }
.btn-open:disabled { opacity: .55; filter: saturate(.6); }
.btn-open.is-loading { color: #fff; }
#getlink-box.is-revealing .btn-open { animation: vr-btn-in 760ms var(--spring-bouncy) both; }
#getlink-box.is-revealing .btn-open .bo-label { animation: vr-label-in 560ms var(--spring-smooth) 140ms both; }
#getlink-box.is-revealing .btn-open i { animation: vr-label-in 560ms var(--spring-smooth) 220ms both; }
@keyframes vr-btn-in { 0% { opacity: 0; transform: translateY(14px) scale(.9); clip-path: inset(0 30% round 14px); } 55% { opacity: 1; } 100% { opacity: 1; transform: none; clip-path: inset(0 0 round 0); } }
@keyframes vr-label-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
#getlink-box.is-revealing .steps-mini { animation: m-fade-up 520ms var(--e-out) 300ms both; }
#getlink-box.is-ready .btn-open::before { animation: vr-border-run 1.3s cubic-bezier(.45, .05, .25, 1) 80ms 1 both; }
@keyframes vr-border-run { 0% { opacity: 0; --bo-ang: 0deg; } 15% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; --bo-ang: 360deg; } }
#getlink-box.is-ready .btn-open { animation: vr-btn-glow 2.6s ease-in-out 300ms 1; }
@keyframes vr-btn-glow { 0%, 100% { box-shadow: 0 12px 28px -12px rgba(43, 89, 255, .75), 0 0 0 0 rgba(43, 89, 255, 0); } 40% { box-shadow: 0 12px 28px -12px rgba(43, 89, 255, .75), 0 0 0 10px rgba(43, 89, 255, .1); } }

@media (max-width: 575.98px) { .vring { width: 184px; } .vr-num { font-size: 3.2rem; } }
@media (prefers-reduced-motion: reduce) {
  .vr-layer { animation: none !important; }
  .vr-l-p, .vr-trail, .vr-glow { display: none; }
}

/* =====================================================================
   19. NÂNG CẤP CHUYỂN ĐỘNG TOÀN TRANG
   ===================================================================== */
.btn-primary, .btn-coin, .btn-ink { position: relative; overflow: hidden; }

/* danh sách link, API, kiểm duyệt: từng dòng hiện lần lượt, nổi nhẹ khi rê chuột */
.js .mod-list > li, .js .api-list > .api-card { animation: m-enter 280ms var(--e-out) both; }
.js .mod-list > li:nth-child(2), .js .api-list > .api-card:nth-child(2) { animation-delay: 40ms; }
.js .mod-list > li:nth-child(n+3), .js .api-list > .api-card:nth-child(n+3) { animation-delay: 60ms; }
.mod-list > li { transition: background-color var(--m-base) ease; }
.mod-list > li:hover { background-color: #f8faff; }
.api-card { transition: transform var(--m-base) var(--e-out), box-shadow var(--m-base) var(--e-out), border-color var(--m-base) ease; }
.api-card:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -16px rgba(20, 26, 51, .35); border-color: #d6dcec; }
.pay-tile:not(:disabled):active { transform: scale(.985); }
.pay-tile.active > i { animation: m-pop 420ms var(--e-spring); }
.auto-card { transition: transform var(--m-base) var(--e-out), box-shadow var(--m-base) var(--e-out), border-color var(--m-base) ease; }
.auto-card:hover { transform: translateY(-2px); }

/* ô tìm kiếm: viền sáng khi đang gõ */
.list-search .input-group, .filter-search, .filter-bar .form-select { transition: box-shadow var(--m-base) var(--e-out); border-radius: var(--bs-border-radius); }
.list-search .input-group:focus-within, .filter-search:focus-within { box-shadow: 0 0 0 4px rgba(43, 89, 255, .12); }

/* tạo link xong: khung kết quả bật ra, nút sao chép nhấp nháy mời bấm */
.result-card { position: relative; animation: vr-result 320ms var(--e-out) both; }
@keyframes vr-result { 0% { opacity: 0; transform: translateY(10px) scale(.97); } 100% { opacity: 1; transform: none; } }
.result-card .small.text-success i { display: inline-block; animation: m-pop 520ms var(--e-spring) 200ms both; }

/* mã QR hiện ra mờ → rõ */
.qr-box img { animation: vr-qr 520ms var(--e-out) 120ms both; }
@keyframes vr-qr { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }

/* hộp xác nhận xóa: biểu tượng rung nhẹ để báo thao tác nguy hiểm */
.alo-confirm.is-danger.show .confirm-ico { animation: m-shake 420ms ease 180ms; }

/* thẻ chọn trong form (cách mở link, loại tài khoản) */
.seg-tabs .nav-link { transition: background-color var(--m-base) var(--e-out), color var(--m-base) ease, box-shadow var(--m-base) var(--e-out); }

@media (prefers-reduced-motion: reduce) {
  .btn-primary::after, .btn-coin::after, .btn-ink::after, .btn-open::after, .btn-open::before, .qr-frame::after, .alo-toast::after { display: none !important; }
  .api-card:hover, .auto-card:hover { transform: none; }
}

/* =====================================================================
   20. CHIỀU SÂU & ÁNH SÁNG — tiết chế: vài lớp sáng nền rất nhẹ, bóng đổ nhiều lớp
   ===================================================================== */
.shell { position: relative; isolation: isolate; }
/* thẻ: bóng mảnh 2 lớp thay cho phẳng tuyệt đối */
.card { box-shadow: var(--sh-1); }
.card.stat-money { box-shadow: 0 1px 2px rgba(20, 26, 51, .2), 0 12px 28px -14px rgba(20, 26, 51, .55); }
/* menu trái: vệt phản chiếu ánh sáng ở mép trên */
.sidebar { background-image: linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, 0) 220px); }
/* trang vượt link: lưới mờ + quầng sáng phía sau vé */
.gate-page { position: relative; }
.gate-page::before { content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none; background-image: linear-gradient(rgba(20, 26, 51, .04) 1px, transparent 1px), linear-gradient(90deg, rgba(20, 26, 51, .04) 1px, transparent 1px); background-size: 40px 40px; -webkit-mask-image: radial-gradient(ellipse 60% 55% at 50% 30%, #000 20%, transparent 75%); mask-image: radial-gradient(ellipse 60% 55% at 50% 30%, #000 20%, transparent 75%); }
.ticket { box-shadow: 0 1px 2px rgba(20, 26, 51, .06), 0 18px 40px -18px rgba(20, 26, 51, .35), 0 40px 80px -48px rgba(43, 89, 255, .35); }
/* thanh trên khi cuộn: đường sáng mảnh ở mép dưới */
.topbar.is-scrolled { box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 8px 24px -18px rgba(20, 26, 51, .4); }

/* =====================================================================
   21. CHẾ ĐỘ GIẢM CHUYỂN ĐỘNG (Windows: Cài đặt > Trợ năng > Hiệu ứng hình ảnh > Hiệu ứng hoạt ảnh = Tắt;
   macOS/iOS: Giảm chuyển động). Không tắt sạch hiệu ứng, chỉ bỏ những gì làm vật thể di chuyển:
   trượt, xoay, phóng to, nảy, hạt bay, nam châm, thị sai. Giữ lại mờ dần, đổi màu, vòng tiến trình chạy liền,
   dấu tích tự vẽ, đếm số, để trang vẫn có cảm giác sống mà không gây chóng mặt.
   Đặt cuối file: các @keyframes cùng tên bên dưới thay thế bản gốc khi chế độ này bật.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root { --lift: 0px; --press: 1; --spring-bouncy: var(--spring-smooth); --spring-pop: var(--spring-smooth); }
  html { scroll-behavior: auto !important; }

  /* vào trang, hộp thoại, menu, thông báo, số đếm ngược: chỉ mờ dần, không di chuyển */
  @keyframes m-enter { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-enter-soft { from { opacity: .001; } to { opacity: 1; } }
  @keyframes m-fade-up { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-fade-down { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-scale-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-pop { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-slide-in-right { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-icon-morph { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-dd-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-toast-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes m-underline { from { transform: scaleX(1); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }
  @keyframes m-shimmer { 0%, 100% { opacity: .2; transform: none; } 50% { opacity: .6; transform: none; } }
  @keyframes m-qr-scan { from { opacity: 0; clip-path: none; } to { opacity: 1; clip-path: none; } }
  @keyframes vr-qr { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-result { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-hint-done { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-enter { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-num-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-num-out { from { opacity: 1; } to { opacity: 0; } }
  @keyframes vr-num-done { from { opacity: 1; } to { opacity: 0; } }
  @keyframes vr-btn-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vr-label-in { from { opacity: 1; } to { opacity: 1; } }
  @keyframes vr-burst-light { 0% { opacity: 0; transform: none; } 30% { opacity: .9; } 100% { opacity: 0; transform: none; } }
  @keyframes vr-ripple { 0% { opacity: 0; transform: none; } 30% { opacity: .7; } 100% { opacity: 0; transform: none; } }
  @keyframes vr-energy-flare { from { transform: none; } to { transform: none; } }
  /* chuyển trang: mờ chéo, không trượt, không nhòe */
  @keyframes vt-out { to { opacity: 0; } }
  @keyframes vt-in { from { opacity: 0; } to { opacity: 1; } }
  ::view-transition-group(nav-active) { animation-duration: 0s; }

  /* hiện khi cuộn: chỉ mờ dần tại chỗ */
  [data-reveal], [data-reveal='down'], [data-reveal='left'], [data-reveal='right'], [data-reveal='scale'], [data-reveal='blur'] { --rv-x: 0; --rv-y: 0; --rv-s: 1; --rv-blur: 0; }
  .js [data-reveal='clip']:not(.is-in) { opacity: 0; clip-path: none; }
  .js [data-reveal-stagger]:not(.is-in) > * { transform: none; }

  /* các vòng lặp trang trí dừng hẳn */
  .stat-money::after, .live-pill .live-dot::after, .value-bump, .form-control:user-invalid, .form-select:user-invalid, .alo-confirm.is-danger.show .confirm-ico { animation: none !important; }
  .qr-frame::after, .copy-ripple, .vr-wave, .vr-burst { display: none !important; }
  .tab-pane.fade { transform: none !important; }
  .modal.fade .modal-dialog, .modal.show .modal-dialog { transform: none !important; }
  .card-hover:hover, .plan-card:hover, .feature-card:hover, .type-card:hover, .buy-box:hover, .balance-chip:hover, .bank-strip-list li:hover, .page-link:hover { transform: none !important; }
  .feature:hover .ico, .who:hover .who-avatar, .author-card:hover .avatar, .brand:hover .brand-logo, .btn:hover i, .sidebar .nav-link:hover i { transform: none !important; }

}

/* =====================================================================
   22. KHU QUẢN LÝ NHẸ (html.app-lite: /member, /admin) và MÁY YẾU (html.low-power: tự nhận khi máy
   có ≤ 2 nhân CPU, ≤ 2 GB RAM hoặc bật tiết kiệm dữ liệu). Toàn trang đã bỏ kính mờ, nhòe, ánh sáng theo chuột,
   nút nam châm, thị sai; ở đây bỏ thêm hiệu ứng từng khối tự hiện và rút ngắn chuyển trang.
   ===================================================================== */
.app-lite .main-area > *, .app-lite .main-area > .row > *, .app-lite .main-area tbody > tr,
.app-lite .mod-list > li, .app-lite .api-list > .api-card, .app-lite .flow-steps li { animation: none !important; }
.app-lite .main-area { animation: m-fade 200ms ease-out both; }
.app-lite.vt-in .main-area { animation: none; }
html.app-lite::view-transition-old(page), html.low-power::view-transition-old(page) { animation: m-lite-out 120ms ease-in both !important; }
html.app-lite::view-transition-new(page), html.low-power::view-transition-new(page) { animation: m-fade 180ms ease-out both !important; }
@keyframes m-lite-out { to { opacity: 0; } }
.low-power .gate-page::before { display: none; }
/* máy yếu: trang vượt link bỏ hạt bay, chùm sáng quét, vệt trong và quầng nhòe; vòng tiến trình giữ nguyên */
.low-power .vr-l-p { display: none; }
.low-power .vr-burst { display: none; }

/* =====================================================================
   23. KHU QUẢN LÝ YÊN TĨNH (html.app-lite: /member, /admin) – bỏ hiệu ứng trang trí.
   Không còn: chuyển trang mờ dần, khối tự hiện / trượt vào, đếm số chạy lên, số phóng to khi đổi,
   dòng bảng nhấp nháy, biểu đồ chạy hình, chấm "trực tiếp" nhấp nháy, nút / thẻ nhích lên khi rê chuột,
   hộp thoại / menu phóng to, QR quét, ô nhập rung khi sai. Mọi thứ hiện ngay.
   Giữ lại (cho biết hệ thống đang làm việc): vòng xoay ở nút "đang xử lý", chấm chờ, vòng xoay Bootstrap.
   Trang công khai (trang chủ, trang vượt link, note) không đổi.
   ===================================================================== */
html.app-lite *, html.app-lite *::before, html.app-lite *::after { animation: none !important; transition: none !important; }
html.app-lite::view-transition-group(*), html.app-lite::view-transition-old(*), html.app-lite::view-transition-new(*) { animation: none !important; }
html.app-lite .btn.is-loading::before { animation: m-spin .65s linear infinite !important; }
html.app-lite .spinner-border { animation: .75s linear infinite spinner-border !important; }
html.app-lite .spinner-grow { animation: .75s linear infinite spinner-grow !important; }
html.app-lite .dots-wait span { animation: m-dot 1.2s ease-in-out infinite !important; }
html.app-lite [data-reveal], html.app-lite [data-reveal-stagger] > * { opacity: 1 !important; transform: none !important; clip-path: none !important; filter: none !important; }
html.app-lite .btn:hover, html.app-lite .btn:active, html.app-lite .btn i, html.app-lite .card:hover, html.app-lite .card-hover:hover,
html.app-lite .plan-card:hover, html.app-lite .type-card:hover, html.app-lite .api-card:hover, html.app-lite .auto-card:hover,
html.app-lite .balance-chip:hover, html.app-lite .page-link:hover, html.app-lite .pay-tile:active, html.app-lite .bank-strip-list li:hover,
html.app-lite .who:hover .who-avatar, html.app-lite .brand:hover .brand-logo, html.app-lite .sidebar .nav-link:hover i,
html.app-lite .form-switch .form-check-input:active, html.app-lite .modal .modal-dialog { transform: none !important; }
html.app-lite .alo-toast::after, html.app-lite .qr-frame::after, html.app-lite .skeleton::after { display: none !important; }
/* Điện thoại / máy tính bảng: .shell không tạo lớp xếp chồng riêng, để menu trượt (z-index 1045) nằm TRÊN thanh trên cùng
   (1030). Trước đây thanh trên cùng che nút Đóng (X) của menu, người dùng không bấm đóng menu được. */
@media (max-width: 991.98px) { .shell { isolation: auto; } }
