/* ═══════════════════════════════════════════════════════════
   VEXTALEARN — GLOBAL EXPERIENCE LAYER (Phase UI-3)
   ───────────────────────────────────────────────────────────
   Site-wide premium visual layer inspired by Linear / Stripe /
   Framer / Vercel / Notion. Purely additive: every rule here is
   a new selector or a new utility class, so nothing already
   shipped (main.css, mobile-ui.css, per-page redesigns) is
   overridden or renamed. Reuses the tokens already defined in
   main.css's :root (--primary, --accent, --gradient-brand,
   --radius*, --shadow*, --font-*) — no new palette introduced.

   Loaded once, globally, from base.html — no page template
   needs to know this file exists.
   ═══════════════════════════════════════════════════════════ */

/* ─── 1. Aurora background + ambient radial gradients ──────
   A single fixed, decorative layer behind all page content.
   Very low opacity, GPU-friendly (background-position/opacity
   only — no layout-affecting properties), and skipped entirely
   under reduced-motion. */
body {
  position: relative;
}
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(ellipse 80% 50% at 20% -10%, rgba(109,56,232,0.10), transparent 60%),
    radial-gradient(ellipse 60% 50% at 100% 10%, rgba(23,163,232,0.08), transparent 60%),
    radial-gradient(ellipse 70% 60% at 50% 120%, rgba(109,56,232,0.06), transparent 60%);
  background-repeat: no-repeat;
  animation: vxtAurora 22s ease-in-out infinite alternate;
}
@keyframes vxtAurora {
  0%   { background-position: 0% 0%, 100% 0%, 50% 100%; }
  100% { background-position: 4% 6%, 96% 8%, 54% 94%; }
}

/* ─── 2. Floating blurred blobs ─────────────────────────────
   Opt-in via .vxt-blobs wrapper so pages can host it inside a
   hero without affecting global layout/paint cost everywhere. */
.vxt-blobs {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
}
.vxt-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.35;
  animation: vxtBlobFloat 16s ease-in-out infinite;
  will-change: transform;
}
.vxt-blob--primary { background: var(--primary); width: 340px; height: 340px; top: -80px; left: -60px; }
.vxt-blob--accent  { background: var(--accent); width: 280px; height: 280px; bottom: -60px; right: -40px; animation-delay: -5s; }
.vxt-blob--warm    { background: var(--accent-warm); width: 200px; height: 200px; top: 40%; left: 60%; animation-delay: -10s; }
@keyframes vxtBlobFloat {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(20px, -24px) scale(1.06); }
  66%      { transform: translate(-16px, 14px) scale(0.96); }
}

/* ─── 3. Glass utility classes ──────────────────────────────
   Reusable frosted-glass primitives so any page/component can
   opt in without redefining backdrop-filter/border combos. */
.vxt-glass {
  background: rgba(255,255,255,0.65);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.5);
}
.vxt-glass-dark {
  background: rgba(14,24,48,0.55);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.12);
}
.vxt-glass-card {
  background: rgba(255,255,255,0.7);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(255,255,255,0.55);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 32px rgba(20,22,43,0.08);
}

/* ─── 4. Scroll reveal animations ───────────────────────────
   Fills in main.js's existing `.fade-in-up` class (added via
   IntersectionObserver in initAnimations()) which previously had
   no matching CSS, plus a generic opt-in `.vxt-reveal` for any
   element. Both share the same easing/duration for consistency. */
.fade-in-up,
.vxt-reveal.vxt-reveal--visible {
  animation: vxtRevealUp 0.6s cubic-bezier(0.16,1,0.3,1) both;
}
.vxt-reveal {
  opacity: 0;
  transform: translateY(16px);
}
.vxt-reveal.vxt-reveal--visible {
  opacity: 1;
  transform: translateY(0);
}
@keyframes vxtRevealUp {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Stagger helper: add data-vxt-stagger="1|2|3…" to children for a
   cascading reveal without per-element inline styles. */
[data-vxt-stagger="1"] { animation-delay: 0.05s; }
[data-vxt-stagger="2"] { animation-delay: 0.10s; }
[data-vxt-stagger="3"] { animation-delay: 0.15s; }
[data-vxt-stagger="4"] { animation-delay: 0.20s; }
[data-vxt-stagger="5"] { animation-delay: 0.25s; }
[data-vxt-stagger="6"] { animation-delay: 0.30s; }

/* ─── 5. Skeleton loading (extends mobile-ui.css) ───────────
   mobile-ui.css already defines .vxt-skeleton / --text / --title
   / --thumb / --card with the shimmer keyframe. These add the
   remaining shapes referenced by the loading-state guidance
   without redefining anything already shipped. */
.vxt-skeleton--avatar { width: 40px; height: 40px; border-radius: 50%; }
.vxt-skeleton--button  { height: 40px; width: 120px; border-radius: var(--radius); }
.vxt-skeleton--badge   { height: 22px; width: 70px; border-radius: var(--radius-sm); }

/* ─── 6. Smooth page transitions ────────────────────────────
   mobile-ui.css already opts every navigation into the native
   View Transition API and fades `<main>` in via .vxt-page-fade-
   enter. This adds the matching *outbound* transition so cross-
   document navigations feel continuous, and is a no-op in
   browsers without View Transition support. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vxtPageOut 0.18s ease both; }
  ::view-transition-new(root) { animation: vxtPageIn 0.22s cubic-bezier(0.16,1,0.3,1) both; }
}
@keyframes vxtPageOut { to   { opacity: 0; } }
@keyframes vxtPageIn  { from { opacity: 0; transform: translateY(6px); } }

/* ─── 7. Premium hover interactions ─────────────────────────
   Generic opt-in lift/glow utilities for any card/button that
   doesn't already define its own hover treatment. */
.vxt-lift {
  transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s ease;
}
.vxt-lift:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 36px -10px rgba(109,56,232,0.25);
}
.vxt-glow-hover { transition: box-shadow 0.3s ease; }
.vxt-glow-hover:hover { box-shadow: 0 0 0 4px rgba(109,56,232,0.12); }

/* ─── 8. Better buttons (global additive states) ────────────
   Existing .vxt-btn-primary / .vxt-btn-outline in main.css are
   untouched. This adds an active/press state and a focus-visible
   ring so keyboard users get a visible indicator, plus a new
   optional pill/ghost variant for pages that want it. */
.vxt-btn-primary:active,
.vxt-btn-outline:active {
  transform: translateY(0) scale(0.98);
}
.vxt-btn-primary:focus-visible,
.vxt-btn-outline:focus-visible,
.btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(23,163,232,0.35);
}
.vxt-btn-ghost {
  background: transparent;
  border: none;
  color: var(--text-secondary);
  border-radius: var(--radius);
  font-weight: 600;
  padding: 10px 20px;
  transition: var(--transition);
}
.vxt-btn-ghost:hover { background: var(--surface); color: var(--text-primary); }

/* ─── 9. Better cards (generic, opt-in) ─────────────────────
   A neutral premium card primitive for any component that isn't
   already a `.course-card`, `.why-card`, etc. */
.vxt-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(20,22,43,0.04);
  transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s ease, border-color 0.3s ease;
}
.vxt-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 36px -10px rgba(109,56,232,0.2);
  border-color: rgba(109,56,232,0.16);
}

/* ─── 10. Better form controls (global, additive) ───────────
   Bootstrap's .form-control/.form-select ship with a generic
   look site-wide; this refines them consistently everywhere
   without redefining Bootstrap's own classes' base rules. */
.form-control,
.form-select {
  border-radius: var(--radius);
  border-color: var(--border);
  font-family: var(--font-body);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.form-control:focus,
.form-select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(109,56,232,0.15);
}

/* ─── 11. Better focus states (accessibility, global) ───────
   A consistent focus-visible ring for links/buttons/inputs that
   don't already define one, using the same accent as the rest
   of the interactive-state language above. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ─── 12. Better loading spinners ───────────────────────────
   A brand-colored spinner primitive, sized via modifier classes,
   for anywhere a page needs an inline loading indicator. */
.vxt-spinner {
  display: inline-block;
  width: 22px;
  height: 22px;
  border: 2.5px solid rgba(109,56,232,0.18);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: vxtSpin 0.7s linear infinite;
}
.vxt-spinner--sm { width: 14px; height: 14px; border-width: 2px; }
.vxt-spinner--lg { width: 34px; height: 34px; border-width: 3px; }
.vxt-spinner--light { border-color: rgba(255,255,255,0.3); border-top-color: #fff; }
@keyframes vxtSpin { to { transform: rotate(360deg); } }

/* ─── 13. Better section spacing (consistency utility) ──────
   main.css's `.section-pad` (80px) already exists per-page; this
   adds a shared, slightly larger rhythm other pages can opt into
   to match the homepage/catalog redesigns without redefining
   `.section-pad` itself. */
.vxt-section {
  padding: 96px 0;
}
@media (max-width: 767.98px) {
  .vxt-section { padding: 56px 0; }
}

/* ─── 14. Mobile animation tuning ───────────────────────────
   Slightly shorter/lighter motion on small screens to keep things
   snappy on lower-powered devices, without disabling motion. */
@media (max-width: 575.98px) {
  .fade-in-up,
  .vxt-reveal.vxt-reveal--visible { animation-duration: 0.4s; }
  .vxt-lift:hover, .vxt-card:hover { transform: translateY(-2px); }
}

/* ─── 15. prefers-reduced-motion: reduce ────────────────────
   Single, comprehensive kill-switch for every animation this
   file introduces. Existing motion elsewhere (splash.css,
   social.css, student.css, mobile-ui.css) already has its own
   reduced-motion handling and is unaffected by this block. */
@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; }
  .vxt-blob { animation: none; }
  .fade-in-up,
  .vxt-reveal,
  .vxt-reveal.vxt-reveal--visible {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none !important; }
  .vxt-lift, .vxt-card, .vxt-glow-hover { transition: none; }
  .vxt-lift:hover, .vxt-card:hover { transform: none; }
  .vxt-spinner { animation-duration: 1.4s; }
}
