/* ==========================================================================
   Public site + student-facing styles (A6 + UI/UX refinement pass).
   Deliberately kept separate from admin.css — the two surfaces have
   different audiences and this keeps public-page CSS from ever leaking
   into (or being affected by future changes to) the untouched A1-A5
   admin interface. Reuses the :root brand variables from app.css.
   ========================================================================== */

/* ---- Z-index system --------------------------------------------------
   A single documented scale instead of ad-hoc/huge values scattered
   across rules. Anything stacking on the public site picks a value from
   here rather than inventing a new one. */
:root {
  --va-z-sticky-header: 1040;
  --va-z-bottom-nav: 1030;
  --va-z-floating-actions: 1035;
  --va-z-preloader: 2000;
}

/* ---- Preloader -----------------------------------------------------
   Shows the actual logo (which already contains the wordmark + slogan)
   plus a subtle animated tricolor line beneath it — never the
   horizontal logo squeezed into a tiny circle. */
.va-preloader {
  position: fixed;
  inset: 0;
  z-index: var(--va-z-preloader);
  background: var(--va-white);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity .35s ease, visibility .35s ease;
}
.va-preloader.va-preloader-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.va-preloader-mark { display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.va-preloader-logo {
  height: 150px;
  width: auto;
  max-width: 220px;
  object-fit: contain;
}
.va-preloader-line {
  width: 84px;
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--va-saffron), var(--va-white) 50%, var(--va-green));
  background-size: 200% 100%;
  animation: va-shimmer 1.4s ease-in-out infinite;
}
@keyframes va-shimmer { 0%, 100% { background-position: 0 0; } 50% { background-position: 100% 0; } }

/* ---- Scroll reveal --------------------------------------------------- */
.va-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .5s ease, transform .5s ease;
}
.va-reveal-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .va-preloader-line { animation: none; }
  .va-reveal { opacity: 1; transform: none; transition: none; }
}

/* ---- Utility bar --------------------------------------------------------
   Very compact, non-sticky (it scrolls away; .public-header below it is
   the sticky one). A 3px tricolor top border is the only "flag" element
   on the whole site — everywhere else tricolor shows as accents only. */
.va-utility-bar {
  background: var(--va-navy);
  border-top: 3px solid transparent;
  border-image: linear-gradient(90deg, var(--va-saffron), #fff 50%, var(--va-green)) 1;
  font-size: .74rem;
  padding: .35rem 0;
}
.va-utility-bar-left, .va-utility-bar-right { display: flex; align-items: center; gap: .9rem; }
.va-utility-bar a, .va-theme-toggle, .va-lang-dropdown .btn {
  color: rgba(255,255,255,.8);
  text-decoration: none;
  padding: 0;
  border: 0;
  background: transparent;
  font-size: .74rem;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
}
.va-utility-bar a:hover, .va-theme-toggle:hover, .va-lang-dropdown .btn:hover { color: var(--va-saffron); }
.va-lang-dropdown .dropdown-menu { font-size: .82rem; min-width: 9rem; }
.va-lang-dropdown .dropdown-item.disabled { pointer-events: none; }
.va-theme-toggle { font-size: .95rem; cursor: pointer; }

/* ---- Public header / nav ---------------------------------------------
   Compact by default (mobile-first); Bootstrap's navbar-expand-md
   handles the compact-hamburger -> full-navbar swap at the md
   breakpoint, so only spacing/typography is set here. */
.public-header {
  background: var(--va-white);
  box-shadow: var(--va-shadow);
  position: sticky;
  top: 0;
  z-index: var(--va-z-sticky-header);
}
.public-header .navbar-brand { padding: 0; }
.public-header .nav-link {
  font-weight: 500;
  color: var(--va-text);
  padding: .5rem .85rem !important;
  transition: color .15s ease;
}
.public-header .nav-link.active { color: var(--va-navy); font-weight: 700; }
.public-header .nav-link:hover { color: var(--va-saffron); }

/* ---- Public bottom navigation (authenticated students, mobile only) --
   App-style: consistent touch targets (min 44px tall), clear active
   state, safe-area-aware so it never sits under a phone's home
   indicator/gesture bar. */
.public-bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: #102a43;
  border-top: 1px solid var(--va-border);
  display: flex;
  justify-content: space-around;
  padding: .4rem 0 calc(.4rem + env(safe-area-inset-bottom, 0px));
  z-index: var(--va-z-bottom-nav);
  box-shadow: 0 -4px 16px rgba(16, 42, 67, .06);
}
.public-bottom-nav a,
.public-bottom-nav button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: .68rem;
  font-weight: 500;
  color: #fff;
  gap: .2rem;
  min-width: 56px;
  min-height: 44px;
  padding: .25rem;
  border-radius: var(--va-radius-sm);
  transition: color .15s ease;
  border: 0;
  background: transparent;
}
.public-bottom-nav a i,
.public-bottom-nav button i { font-size: 1.25rem; line-height: 1; }
.public-bottom-nav a.active { color: #FF5722; font-weight: 700; }
.public-bottom-nav a:hover,
.public-bottom-nav button:hover { color: #FF5722; }

/* Content never sits behind the fixed bottom nav — this padding must
   stay >= the bottom nav's real rendered height (~4.25rem) plus the
   safe-area inset it also reserves. */
body.has-public-bottom-nav { padding-bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px)); }
@media (min-width: 768px) { body.has-public-bottom-nav { padding-bottom: 0; } }

/* ---- Promo slider (compact, Flipkart/Amazon-strip style, not a hero) -
   Kept intentionally short (100-150px mobile / 150-220px desktop). A
   subtle radial shape stands in for a photograph — no heavy imagery. */
.va-promo-slider {
  position: relative;
  overflow: hidden;
  border-radius: var(--va-radius);
  height: 170px;
  background: linear-gradient(120deg, var(--va-navy) 0%, var(--va-navy-light) 100%);
  box-shadow: var(--va-shadow);
}
@media (min-width: 768px) { .va-promo-slider { height: 200px; } }

.va-promo-slider::before,
.va-promo-slider::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.va-promo-slider::before {
  width: 180px; height: 180px;
  right: -60px; top: -80px;
  background: radial-gradient(circle, rgba(255,122,0,.22), transparent 70%);
}
.va-promo-slider::after {
  width: 220px; height: 220px;
  left: -80px; bottom: -110px;
  background: radial-gradient(circle, rgba(19,138,75,.2), transparent 70%);
}

.va-promo-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .6s ease;
  display: flex;
  align-items: center;
  padding: 1rem 1.5rem;
  color: #fff;
}
/* height:100% is required here — switching to position:relative (so the
   active slide takes up normal document space above the still-absolute,
   opacity:0 inactive slides) drops the top/right/bottom/left:0 stretch
   the base rule relies on for sizing (inset offsets don't size a
   position:relative box, only position:absolute/fixed ones do), so
   without it the active slide collapses to its content's natural
   height. That was invisible for plain text over the slider's own navy
   background, but crops a banner's image/overlay to that same shrunk
   box the moment a slide carries a real photo — the slider's navy
   background then shows through below the cropped image. */
.va-promo-slide.active { opacity: 1; position: relative; height: 100%; z-index: 1; }
.va-promo-slide h3 { font-size: 1rem; font-weight: 700; margin-bottom: .15rem; letter-spacing: .2px; }
@media (min-width: 768px) { .va-promo-slide h3 { font-size: 1.4rem; } }
.va-promo-slide p { font-size: .78rem; margin-bottom: 0; opacity: .85; }
@media (min-width: 768px) { .va-promo-slide p { font-size: .95rem; } }

/* Admin-managed banner image slides (Content > Banners) — the image and
   a readability overlay sit behind the text, both absolutely filling the
   slide; the text itself is lifted onto its own stacking layer on top. */
.va-promo-slide picture {
  position: absolute;
  inset: 0;
  display: block;
  z-index: 0;
}
.va-promo-slide-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.va-promo-slide-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
 
}
.va-promo-slide-content { position: relative; z-index: 2; }
.va-promo-slide.has-image .va-promo-slide-content { max-width: 78%; }
@media (min-width: 768px) { .va-promo-slide.has-image .va-promo-slide-content { max-width: 60%; } }
.va-promo-slide-content .btn { pointer-events: auto; }
/* Inactive slides stay in the DOM (opacity 0) between transitions — this
   keeps their button/link inert so it can never be clicked while hidden. */
.va-promo-slide:not(.active) .va-promo-slide-content { pointer-events: none; }

.va-promo-dots {
  position: absolute;
  bottom: .6rem;
  right: .9rem;
  display: flex;
  gap: .35rem;
  z-index: 2;
}
.va-promo-dots button {
  width: 7px; height: 7px; border-radius: 50%;
  border: 0; background: rgba(255,255,255,.4); padding: 0; cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
.va-promo-dots button.active { background: var(--va-saffron); transform: scale(1.2); }

/* ---- Section spacing / headings --------------------------------------- */
.va-section { padding: 2rem 0; }
@media (min-width: 768px) { .va-section { padding: 3rem 0; } }
.va-section-title { font-size: 1.25rem; font-weight: 700; color: var(--va-navy); margin-bottom: .25rem; }
.va-section-subtitle { color: var(--va-text-muted); margin-bottom: 1.5rem; font-size: .92rem; }

/* ---- Cards -------------------------------------------------------------- */
.va-series-card, .va-info-card, .va-category-card, .va-test-card {
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius);
  background: #fff;
  box-shadow: var(--va-shadow);
  transition: box-shadow .18s ease, transform .18s ease;
  height: 100%;
}
@media (hover: hover) {
  .va-series-card:hover, .va-info-card:hover, .va-category-card:hover, .va-test-card:hover {
    box-shadow: var(--va-shadow-lg);
    transform: translateY(-3px);
  }
}
/* Opt-out of the height:100% above for cards stacked vertically in a
   sidebar rather than sitting side-by-side in the same grid row. Inside
   a Bootstrap .row (a flex container, default align-items: stretch), a
   short sidebar column still gets stretched to match a taller adjacent
   column — height:100% then blows the card up to fill that whole
   stretched column instead of just its own content, leaving a large
   blank area below the content (student dashboard's Quick Actions/
   Profile cards, first hit by this). */
/* !important here is deliberate and narrowly scoped to this one
   two-class combination: the override should always win regardless of
   any other rule targeting .va-info-card, and there's no legitimate
   case where a .va-card-auto card should ever be stretched. */
.va-info-card.va-card-auto { height: auto !important; }
.va-series-card-thumb {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: var(--va-radius) var(--va-radius) 0 0;
  background: var(--va-bg);
}
.va-series-card-body { padding: 1rem; }
.va-series-card-title {
  font-weight: 700;
  color: var(--va-navy);
  font-size: .98rem;
  margin-bottom: .35rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.va-series-meta { font-size: .78rem; color: var(--va-text-muted); }
.va-series-price { font-weight: 700; color: var(--va-navy); font-size: 1.05rem; }
.va-series-price-strike { text-decoration: line-through; color: var(--va-text-muted); font-size: .82rem; font-weight: 400; }

.va-category-card { text-align: center; padding: 1.1rem .75rem; color: var(--va-text); }
.va-category-card i { font-size: 1.6rem; color: var(--va-navy-light); margin-bottom: .5rem; display: block; }
.va-category-card .va-category-name { font-weight: 600; font-size: .85rem; }

/* ---- Quick category chips (compact, homepage, above the fold) ------------ */
.va-chip-row {
  display: flex;
  gap: .5rem;
  overflow-x: auto;
  padding-bottom: .25rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.va-chip-row::-webkit-scrollbar { display: none; }
.va-chip {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  flex-shrink: 0;
  padding: .45rem .9rem;
  border-radius: 20px;
  background: #fff;
  border: 1px solid var(--va-border);
  color: var(--va-navy);
  font-weight: 600;
  font-size: .8rem;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.va-chip i { color: var(--va-saffron); font-size: .9em; }
.va-chip:hover { background: var(--va-navy); border-color: var(--va-navy); color: #fff; }
.va-chip:hover i { color: var(--va-gold, var(--va-saffron)); }

/* ---- Important Notices ---------------------------------------------------- */
.va-notice-card {
  background: #fff;
  border: 1px solid var(--va-border);
  border-left: 4px solid var(--va-saffron);
  border-radius: var(--va-radius-sm);
  padding: .9rem 1.1rem;
}
.va-notice-icon {
  width: 34px; height: 34px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(255, 122, 0, .12);
  color: var(--va-saffron);
  font-size: 1.05rem;
}
.va-notice-title { font-weight: 700; color: var(--va-navy); font-size: .92rem; }
.va-notice-message { font-size: .85rem; color: var(--va-text-muted); }

/* ---- Promotional tricolor banner (visual separator, not a photo) --------- */
.va-tricolor-banner {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 2rem 1.5rem;
  border-radius: var(--va-radius-lg, var(--va-radius));
  background: linear-gradient(120deg, var(--va-navy) 0%, var(--va-navy-light) 100%);
  color: #fff;
}
.va-tricolor-banner-shape { position: absolute; border-radius: 50%; pointer-events: none; }
.va-tricolor-banner-shape-1 {
  width: 200px; height: 200px; left: -70px; top: -90px;
  background: radial-gradient(circle, rgba(255,122,0,.25), transparent 70%);
}
.va-tricolor-banner-shape-2 {
  width: 220px; height: 220px; right: -80px; bottom: -100px;
  background: radial-gradient(circle, rgba(19,138,75,.22), transparent 70%);
}
.va-tricolor-banner-title {
  position: relative;
  font-size: 1.4rem;
  font-weight: 700;
  margin-bottom: .35rem;
}
.va-tricolor-banner-text { position: relative; color: rgba(255,255,255,.8); font-size: .92rem; }
@media (min-width: 768px) { .va-tricolor-banner-title { font-size: 1.75rem; } }

/* ---- Badges ---------------------------------------------------------------
   Standardized palette per brand spec: LIVE = green (with a subtle pulse,
   reduced-motion guarded), FREE = green accent, PAID = saffron, UPCOMING =
   navy-tinted neutral, COMPLETED = neutral gray. Consistent padding/radius/
   font-size/icon gap across every status. */
.va-badge {
  font-weight: 600;
  font-size: .68rem;
  letter-spacing: .3px;
  padding: .3em .65em;
  border-radius: 20px;
  display: inline-flex;
  align-items: center;
  gap: .3em;
  line-height: 1.4;
}
.va-badge i { font-size: .95em; line-height: 1; }
.va-badge-free { background: var(--va-green); color: #fff; }
.va-badge-paid { background: var(--va-saffron); color: #fff; }
.va-badge-featured { background: var(--va-gold); color: var(--va-navy); }
.va-badge-live { background: var(--va-green); color: #fff; position: relative; }
.va-badge-upcoming { background: var(--va-navy-light, #1e4066); color: #fff; }
.va-badge-completed { background: #eef1f5; color: var(--va-text-muted); }
/* A8: Test Conduct Engine's conduct_status() values, distinct from the
   plain UPCOMING/LIVE/COMPLETED ones above — see
   templates/student/test_instructions.html. Pre-A9 UI pass: recolored
   to a muted red so "the live window is over" reads as distinct from
   both navy UPCOMING and green LIVE/COMPLETED at a glance. */
.va-badge-live_ended { background: var(--va-red); color: #fff; }
.va-badge-no_schedule { background: #eef1f5; color: var(--va-text-muted); }
/* Schedule-review pass: TestAttemptService.display_status()'s TODAY
   state — a same-day-but-not-yet-live test. Saffron rather than
   upcoming's navy so a student scanning the timeline can tell "today"
   apart from "some other day" at a glance. */
.va-badge-today { background: var(--va-saffron); color: #fff; }
/* Pre-A9 UI pass: LIVE ENDED + this student's own LIVE attempt was
   terminal (CASE 5 — "you completed this") — green like LIVE/FREE
   (a positive, "you did it" state) rather than red LIVE_ENDED or grey
   COMPLETED (which is reserved for an admin's manual archival override,
   unrelated to whether this student participated). */
.va-badge-live_completed { background: var(--va-green); color: #fff; }

@media (prefers-reduced-motion: no-preference) {
  .va-badge-live i { animation: va-badge-pulse 1.6s ease-in-out infinite; }
}
@keyframes va-badge-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .45; }
}

/* ---- Status-aware test card (Home "Today's Tests" / dashboard) --------
   Pre-A9 UI pass. Shares .va-test-card's base surface/shadow/radius; the
   only addition here is a left accent border that turns green while
   LIVE, so a LIVE card is visually unmistakable even before reading the
   badge — subtle, not an animated/attention-grabbing border. */
.va-test-status-card { border-left: 3px solid transparent; }
.va-test-status-card.is-live { border-left-color: var(--va-green); }

/* ---- Timeline (Test Schedule on the detail page) ------------------------ */
.va-timeline { position: relative; padding-left: 1.5rem; }
.va-timeline::before {
  content: '';
  position: absolute; left: 5px; top: 4px; bottom: 4px; width: 2px;
  background: var(--va-border);
}
.va-timeline-item { position: relative; padding-bottom: 1.25rem; }
.va-timeline-item::before {
  content: '';
  position: absolute; left: -1.5rem; top: 3px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--va-navy-light); border: 2px solid #fff; box-shadow: 0 0 0 2px var(--va-border);
}
.va-timeline-item.is-live::before { background: var(--va-green); }
.va-timeline-item.is-completed::before { background: #adb5bd; }

/* ---- Public schedule countdown (Live Test Countdown pass) ---------------
   Compact, non-alarming — a visual convenience over the server-rendered
   starts_in_seconds/ends_in_seconds; see static/js/countdown.js. Two
   flavors share one base class: starts_in (flexible d/h/m/s text) and
   ends_in (a monospace HH:MM:SS "clock face" used for the LIVE window,
   where every digit shifting is expected and shouldn't visually jitter). */
.va-countdown {
  display: inline-flex;
  flex-direction: column;
  gap: .1rem;
  line-height: 1.2;
}
.va-countdown-label {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--va-text-muted);
}
.va-countdown-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-size: .95rem;
  color: var(--va-navy);
}
.va-countdown[data-mode="ends_in"] .va-countdown-value {
  color: var(--va-green);
  letter-spacing: .5px;
}
/* Last minute of a LIVE window — a small, non-flashing color shift only
   (never an animation), so it stays readable without becoming alarming. */
.va-countdown.va-countdown-critical .va-countdown-value { color: var(--va-red); }

/* ---- Search / filter ----------------------------------------------------- */
.va-search-box .form-control { border-radius: var(--va-radius-sm) 0 0 var(--va-radius-sm); }
.va-search-box .btn { border-radius: 0 var(--va-radius-sm) var(--va-radius-sm) 0; }

/* ---- Auth pages (student register/login) — mirrors, not reuses, admin's
   .auth-page pattern so admin/public CSS stay independently editable --- */
.student-auth-page {
  background: radial-gradient(circle at top left, var(--va-navy-light), var(--va-navy) 65%);
}
.student-auth-card-container {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}
.student-auth-card {
  width: 100%;
  max-width: 460px;
  background: var(--va-white);
  border-radius: var(--va-radius);
  box-shadow: var(--va-shadow-lg);
  padding: 2.25rem 2rem 2rem;
}
.student-auth-card .brand-logo { justify-content: center; }
.student-auth-card .brand-wordmark { text-align: center; }
.student-auth-title { font-size: 1.3rem; font-weight: 700; color: var(--va-navy); margin-bottom: .25rem; }
.student-auth-subtitle { color: var(--va-text-muted); font-size: .88rem; margin-bottom: 1.5rem; }
.student-auth-card .form-label { font-weight: 500; font-size: .85rem; }
.student-auth-footer { font-size: .78rem; color: var(--va-text-muted); margin-top: 1.5rem; margin-bottom: 0; text-align: center; }

/* ---- Footer --------------------------------------------------------------- */
.public-footer { background: var(--va-navy); color: rgba(255,255,255,.85); }
.public-footer a { color: rgba(255,255,255,.75); }
.public-footer a:hover { color: var(--va-saffron); }
.public-footer h6 { color: #fff; font-weight: 700; font-size: .85rem; text-transform: uppercase; letter-spacing: .5px; margin-bottom: .9rem; }
.public-footer .public-footer-bottom { border-top: 1px solid rgba(255,255,255,.12); font-size: .78rem; color: rgba(255,255,255,.55); }

@media (max-width: 767.98px) {
  .public-footer { padding: 1.75rem 0 1rem; }
  .public-footer h6 { margin-top: 1rem; }
}

/* The logo artwork's wordmark text is navy — nearly invisible directly on
   this navy footer. Rather than recoloring/distorting the logo itself, a
   light chip sits behind it so the full-color logo stays legible. */
.footer-logo-chip {
  display: inline-flex;
  background: var(--va-white);
  border-radius: var(--va-radius-sm);
  padding: .6rem .9rem;
}

/* ---- Daily Motivation card -------------------------------------------------
   Premium card: eyebrow label, fading quote slides (server renders today's
   quote active so it works with JS disabled), attribution, dot indicators.
   Subtle tricolor accents + an abstract book/knowledge shape — no large
   flag, no glassmorphism, no photograph. */
.va-motivation-section { padding-top: .5rem; }
.va-motivation-card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(165deg, #fff 0%, var(--va-bg) 100%);
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-lg, var(--va-radius));
  box-shadow: var(--va-shadow-lg);
  padding: 2rem 1.5rem 1.75rem;
  text-align: center;
  max-width: 720px;
  margin: 0 auto;
}
.va-motivation-accent-line {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--va-saffron), var(--va-gold) 50%, var(--va-green));
}
.va-motivation-shape {
  position: absolute;
  top: -18px;
  right: -14px;
  font-size: 7rem;
  color: var(--va-navy);
  opacity: .05;
  transform: rotate(12deg);
  pointer-events: none;
}
.va-motivation-eyebrow {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: 1.4px;
  color: var(--va-saffron);
  margin-bottom: 1rem;
}
.va-motivation-slides { position: relative; min-height: 7rem; }
@media (min-width: 768px) { .va-motivation-slides { min-height: 5rem; } }
.va-motivation-quote {
  /* Anchored to the top edge only (not inset:0) so an active slide's
     real content height — quote text plus its own attribution line —
     is never force-clipped to a fixed box; min-height above is just a
     layout floor to avoid a jump while slides cross-fade. */
  position: absolute;
  top: 0; left: 0; right: 0;
  margin: 0;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .5s ease, transform .5s ease;
  pointer-events: none;
}
.va-motivation-quote.active { opacity: 1; transform: none; position: relative; pointer-events: auto; }
.va-motivation-quote p {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--va-navy);
  line-height: 1.5;
  max-width: 46rem;
  margin: 0 auto;
}
@media (min-width: 768px) { .va-motivation-quote p { font-size: 1.2rem; } }
.va-motivation-attribution {
  display: block;
  font-size: .8rem;
  font-weight: 700;
  color: var(--va-gold);
  margin: .85rem 0 0;
  font-style: normal;
  letter-spacing: .2px;
}
.va-motivation-dots { display: flex; justify-content: center; gap: .4rem; margin-top: 1.1rem; }
.va-motivation-dots button {
  width: 8px; height: 8px; border-radius: 50%;
  border: 0; background: var(--va-border); padding: 0; cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
.va-motivation-dots button:hover { background: var(--va-navy-light); }
.va-motivation-dots button.active { background: var(--va-saffron); transform: scale(1.25); }

@media (prefers-reduced-motion: reduce) {
  .va-motivation-quote { transition: none; }
}

/* ---- Floating actions ------------------------------------------------------
   LEFT stack = WhatsApp + Enquiry. RIGHT = Back to Top. Positioned above the
   fixed bottom nav on mobile (via body.has-public-bottom-nav) and above the
   safe-area inset, using the single shared z-index scale declared at the
   top of this file — never an ad-hoc large value. */
.va-floating-actions {
  position: fixed;
  left: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  z-index: var(--va-z-floating-actions);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .6rem;
}
.va-back-to-top {
  position: fixed;
  right: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  z-index: var(--va-z-floating-actions);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s ease;
}
.va-back-to-top.is-visible { opacity: 1; visibility: visible; transform: none; }

/* Lift both stacks clear of the fixed bottom nav on mobile so nothing
   overlaps it. */
body.has-public-bottom-nav .va-floating-actions,
body.has-public-bottom-nav .va-back-to-top {
  bottom: calc(4.75rem + 1rem + env(safe-area-inset-bottom, 0px));
}
@media (min-width: 768px) {
  body.has-public-bottom-nav .va-floating-actions,
  body.has-public-bottom-nav .va-back-to-top {
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  }
}

.va-floating-btn {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--va-white);
  color: var(--va-navy);
  border: 1px solid var(--va-border);
  box-shadow: var(--va-shadow-lg);
  justify-content: center;
  font-size: 1.15rem;
  text-decoration: none;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease;
}
.va-floating-btn:hover { transform: translateY(-2px); box-shadow: var(--va-shadow-lg); }
.va-floating-btn:focus-visible { outline: 3px solid var(--va-saffron); outline-offset: 2px; }

.va-floating-whatsapp { background: #25d366; color: #fff; border-color: #25d366; }
.va-floating-whatsapp:hover { color: #fff; background: #1ebe5a; }

.va-floating-enquiry {
  background: var(--va-navy);
  color: #fff;
  border-color: var(--va-navy);
}
.va-floating-enquiry:hover { color: #fff; background: var(--va-navy-light); }
.va-floating-btn-label { font-size: .8rem; font-weight: 600; padding-right: .3rem; }
@media (min-width: 768px) {
  .va-floating-enquiry { width: auto; padding: 0 1.1rem 0 .9rem; border-radius: 24px; }
}

.va-back-to-top { color: var(--va-navy); }

/* ---- Account page (row-based, app-like) ------------------------------------ */
.va-account-row {
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: .95rem 1.1rem;
  color: var(--va-text);
  text-decoration: none;
  border-bottom: 1px solid var(--va-border);
  transition: background .15s ease;
}
.va-account-row:last-child { border-bottom: 0; }
.va-account-row:hover { background: var(--va-bg); color: var(--va-navy); }
.va-account-row > i:first-child {
  width: 34px; height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--va-bg);
  color: var(--va-navy);
  font-size: 1.05rem;
  flex-shrink: 0;
}
.va-account-row span { flex: 1; font-weight: 600; font-size: .92rem; }
.va-account-row-chevron { color: var(--va-text-muted); font-size: .85rem; }
.va-account-row-danger { color: #b02a37; }
.va-account-row-danger > i:first-child { background: #fdecea; color: #b02a37; }
.va-account-row-danger:hover { background: #fdecea; color: #b02a37; }

/* ---- Typography hierarchy --------------------------------------------------
   A small, deliberate scale reused across public/student pages instead of
   ad-hoc font sizes — keeps mobile readability consistent. */
.va-eyebrow { font-size: .72rem; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; color: var(--va-saffron); }
.va-caption { font-size: .78rem; color: var(--va-text-muted); }

/* ---- Focus-visible (accessibility) -----------------------------------------
   Consistent, visible keyboard focus ring across public + student pages;
   color alone never carries meaning (badges/links also change weight or
   icon, not color only). */
.public-header a:focus-visible,
.public-header button:focus-visible,
.public-bottom-nav a:focus-visible,
.va-series-card:focus-visible,
.va-test-card:focus-visible,
.va-category-card a:focus-visible,
.va-account-row:focus-visible,
.va-motivation-dots button:focus-visible,
.va-promo-dots button:focus-visible,
.student-auth-card a:focus-visible,
.public-footer a:focus-visible,
.btn:focus-visible,
.form-control:focus-visible {
  outline: 3px solid var(--va-saffron);
  outline-offset: 2px;
}

/* ---- Empty states ----------------------------------------------------------- */
.va-empty-state { text-align: center; padding: 3rem 1rem; color: var(--va-text-muted); }
.va-empty-state i { font-size: 2.25rem; color: var(--va-border); display: block; margin-bottom: .75rem; }

/* ---- Offcanvas filter panel (mobile) ----------------------------------------- */
.va-filter-toggle-btn { border-radius: var(--va-radius-sm); }

/* ---- Dark theme foundation --------------------------------------------------
   Scoped to `body.public-body[data-theme="dark"]` — deliberately never just
   `[data-theme="dark"]` or `html[data-theme="dark"]` — so it can only ever
   match the public/student layout's own <body>, never the admin shell
   (admin pages use body class "admin-body", set in templates/admin/
   layout.html and untouched by this pass). Redefining the --va-* custom
   properties here means every public.css rule that already reads
   var(--va-bg)/var(--va-text)/etc picks up the dark values automatically —
   this is a foundation (documented "surfaces" below), not a guarantee every
   single literal color everywhere has a dark equivalent yet.
   Toggle + persistence: static/js/public.js (localStorage, no DB). */
body.public-body[data-theme="dark"] {
  --va-bg: #121820;
  --va-white: #1B2530;
  --va-text: #F5F7FA;
  --va-text-muted: #AAB7C4;
  --va-border: #2A3644;
  --va-saffron: #FF8A1F;
  --va-green: #39A96B;
  --va-gold: #D4AF37;
  --va-shadow: 0 4px 16px rgba(0, 0, 0, .35);
  --va-shadow-lg: 0 20px 60px rgba(0, 0, 0, .5);
}
/* Surfaces that use a literal #fff instead of var(--va-white) — listed
   explicitly rather than hunting every occurrence, per "foundation, not
   full pixel-parity" scope. */
body.public-body[data-theme="dark"] .public-header,
body.public-body[data-theme="dark"] .public-bottom-nav,
body.public-body[data-theme="dark"] .va-series-card,
body.public-body[data-theme="dark"] .va-info-card,
body.public-body[data-theme="dark"] .va-category-card,
body.public-body[data-theme="dark"] .va-test-card,
body.public-body[data-theme="dark"] .student-auth-card,
body.public-body[data-theme="dark"] .va-notice-card,
body.public-body[data-theme="dark"] .va-chip,
body.public-body[data-theme="dark"] .va-floating-btn {
  background: #202C38;
  border-color: #2A3644;
}
body.public-body[data-theme="dark"] .va-motivation-card {
  background: linear-gradient(165deg, #202C38 0%, #1B2530 100%);
  border-color: #2A3644;
}
body.public-body[data-theme="dark"] .va-utility-bar { background: #0B2239; }
body.public-body[data-theme="dark"] .student-auth-page {
  background: radial-gradient(circle at top left, #1B2530, #0B2239 65%);
}
/* .public-footer already reads var(--va-navy), which is intentionally left
   the same in dark mode — a dark navy footer reads correctly in both
   themes without a separate override. */
body.public-body[data-theme="dark"] .va-theme-toggle .bi-moon-stars { display: none; }
body.public-body[data-theme="dark"] .va-theme-toggle .bi-sun { display: inline-block; }
.va-theme-toggle .bi-sun { display: none; }

/* ==========================================================================
   A9 — Result, Answer Key, History & Basic Analysis.
   No new surface colors are introduced — every rule below reads the
   existing --va-* tokens (already redefined for dark mode above), and
   every card reuses .va-info-card/.va-test-card as its base class in the
   templates rather than declaring a parallel background here, so this
   section needs no separate dark-theme override block of its own.
   ========================================================================== */

/* ---- Result hero (score circle + headline stats) ---------------------- */
.va-result-hero { text-align: center; padding: 1.75rem 1.25rem; }
.va-result-ring {
  --va-ring-pct: 0;
  --va-ring-color: var(--va-green);
  width: 128px;
  height: 128px;
  border-radius: 50%;
  margin: 0 auto .75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: conic-gradient(var(--va-ring-color) calc(var(--va-ring-pct) * 1%), var(--va-border) 0);
}
.va-result-ring-inner {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: var(--va-white);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: var(--va-shadow);
}
.va-result-ring-value { font-size: 1.4rem; font-weight: 800; color: var(--va-navy); line-height: 1.1; }
.va-result-ring-label { font-size: .68rem; color: var(--va-text-muted); text-transform: uppercase; letter-spacing: .4px; }
.va-result-marks { font-size: 1rem; color: var(--va-text-muted); margin-bottom: .5rem; }
.va-result-marks strong { color: var(--va-navy); font-size: 1.15rem; }

/* ---- Stat tiles (Correct / Wrong / Unanswered / Time / Accuracy) ------ */
.va-stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .6rem; }
@media (min-width: 576px) { .va-stat-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 992px) { .va-stat-grid { grid-template-columns: repeat(5, 1fr); } }
.va-stat-tile {
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: .8rem .5rem;
  text-align: center;
}
.va-stat-tile i { font-size: 1.15rem; display: block; margin-bottom: .3rem; }
.va-stat-tile .va-stat-value { font-size: 1.05rem; font-weight: 700; color: var(--va-navy); line-height: 1.2; }
.va-stat-tile .va-stat-label { font-size: .7rem; color: var(--va-text-muted); text-transform: uppercase; letter-spacing: .3px; }
.va-stat-tile.is-correct i { color: var(--va-green); }
.va-stat-tile.is-wrong i { color: var(--va-red); }
.va-stat-tile.is-unanswered i { color: var(--va-text-muted); }
.va-stat-tile.is-time i, .va-stat-tile.is-accuracy i { color: var(--va-navy-light, var(--va-navy)); }

/* ---- Outcome badges (Answer Key + Result page) ------------------------ */
.va-badge-correct { background: var(--va-green); color: #fff; }
.va-badge-wrong { background: var(--va-red); color: #fff; }
.va-badge-unanswered { background: #eef1f5; color: var(--va-text-muted); }
body.public-body[data-theme="dark"] .va-badge-unanswered { background: #2A3644; color: var(--va-text-muted); }

/* ---- Answer Key question cards ---------------------------------------- */
.va-answer-key-card {
  border: 1px solid var(--va-border);
  border-left: 4px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: 1rem;
  margin-bottom: .9rem;
  background: var(--va-white);
}
.va-answer-key-card.is-correct { border-left-color: var(--va-green); }
.va-answer-key-card.is-wrong { border-left-color: var(--va-red); }
.va-answer-key-card.is-unanswered { border-left-color: var(--va-border); }
.va-answer-key-qno { font-size: .72rem; color: var(--va-text-muted); text-transform: uppercase; letter-spacing: .4px; margin-bottom: .25rem; }
.va-answer-key-option {
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: .5rem .75rem;
  margin-bottom: .4rem;
  font-size: .9rem;
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  word-break: break-word;
}
.va-answer-key-option .va-ako-tag { font-size: .68rem; font-weight: 700; padding: .1em .5em; border-radius: 10px; white-space: nowrap; }
.va-answer-key-option.is-correct-option { border-color: var(--va-green); background: rgba(19, 138, 75, .08); }
.va-answer-key-option.is-correct-option .va-ako-tag { background: var(--va-green); color: #fff; }
.va-answer-key-option.is-wrong-selected { border-color: var(--va-red); background: rgba(179, 65, 62, .08); }
.va-answer-key-option.is-wrong-selected .va-ako-tag { background: var(--va-red); color: #fff; }
.va-answer-key-meta { font-size: .78rem; color: var(--va-text-muted); display: flex; flex-wrap: wrap; gap: 1rem; margin-top: .5rem; }
.va-answer-key-explanation {
  font-size: .85rem;
  color: var(--va-text);
  background: var(--va-bg);
  border-radius: var(--va-radius-sm);
  padding: .6rem .75rem;
  margin-top: .6rem;
}
body.public-body[data-theme="dark"] .va-answer-key-card { background: #202C38; border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-answer-key-option { border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-answer-key-explanation { background: #0B2239; }

/* ---- Result History filters + table/cards ------------------------------ */
.va-history-filter-btn {
  border: 1px solid var(--va-border);
  border-radius: 20px;
  padding: .3em 1em;
  font-size: .82rem;
  font-weight: 600;
  color: var(--va-text-muted);
  background: var(--va-white);
}
.va-history-filter-btn.active { background: var(--va-navy); color: #fff; border-color: var(--va-navy); }
.va-history-row { border: 1px solid var(--va-border); border-radius: var(--va-radius-sm); padding: .85rem 1rem; margin-bottom: .6rem; background: var(--va-white); }
body.public-body[data-theme="dark"] .va-history-row { background: #202C38; border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-history-filter-btn { background: #202C38; border-color: #2A3644; }

/* ====================================================================
   A11 — Student Dashboard, Performance Analytics, Public Result & LIVE
   Ranking. Built entirely from the existing --va-* design tokens and the
   existing .va-info-card/.va-stat-grid/.va-badge/.va-empty-state/
   .va-history-row primitives above — no new colors, no second theme
   system. Every dark-theme rule below is scoped the same way the
   existing ones are: body.public-body[data-theme="dark"] only.
   ==================================================================== */

/* ---- Dashboard section headings ----------------------------------- */
.va-dash-section-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--va-navy);
  margin-bottom: .75rem;
  display: flex;
  align-items: center;
  gap: .4rem;
}
body.public-body[data-theme="dark"] .va-dash-section-title { color: #E8EEF5; }

/* ---- LIVE NOW banner strip ----------------------------------------- */
.va-live-now-strip {
  border: 1px solid var(--va-green);
  background: rgba(30, 138, 76, .06);
  border-radius: var(--va-radius);
  padding: .5rem .9rem;
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: .85rem;
  font-weight: 700;
  color: var(--va-green);
  font-size: .85rem;
}
body.public-body[data-theme="dark"] .va-live-now-strip { background: rgba(30, 138, 76, .12); }

/* ---- Recent Results / Practice mini-rows (compact va-history-row) --- */
.va-mini-history-row {
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: .65rem .85rem;
  margin-bottom: .5rem;
  background: var(--va-white);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  flex-wrap: wrap;
}
body.public-body[data-theme="dark"] .va-mini-history-row { background: #202C38; border-color: #2A3644; }

/* ---- Performance trend chart container ------------------------------ */
.va-trend-chart-wrap { position: relative; height: 220px; }

/* ---- Subject-wise performance table ---------------------------------- */
.va-subject-table th { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: var(--va-text-muted); border-bottom-width: 1px; }
.va-subject-table td { vertical-align: middle; font-size: .88rem; }

/* ---- LIVE vs Practice comparison bars -------------------------------- */
.va-compare-row { margin-bottom: .9rem; }
.va-compare-row:last-child { margin-bottom: 0; }
.va-compare-label { display: flex; justify-content: space-between; font-size: .78rem; margin-bottom: .3rem; }
.va-compare-track { height: 8px; border-radius: 4px; background: var(--va-bg); overflow: hidden; }
.va-compare-fill { height: 100%; border-radius: 4px; }
.va-compare-fill.is-live { background: var(--va-green); }
.va-compare-fill.is-practice { background: var(--va-saffron); }
body.public-body[data-theme="dark"] .va-compare-track { background: #202C38; }

/* ====================================================================
   Public LIVE Ranking page
   ==================================================================== */
.va-ranking-hero {
  background: linear-gradient(135deg, var(--va-navy), var(--va-navy-light, #1e4066));
  color: #fff;
  border-radius: var(--va-radius);
  padding: 1.5rem;
  margin-bottom: 1.25rem;
}
.va-ranking-hero .va-ranking-series { color: rgba(255,255,255,.75); font-size: .85rem; }
.va-ranking-hero .va-ranking-badges { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; }

.va-ranking-summary-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: .6rem;
  margin-bottom: 1.25rem;
}
@media (min-width: 576px) { .va-ranking-summary-grid { grid-template-columns: repeat(4, 1fr); } }
.va-ranking-summary-tile {
  background: var(--va-white);
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: .75rem;
  text-align: center;
}
.va-ranking-summary-tile .val { font-size: 1.15rem; font-weight: 700; color: var(--va-navy); }
.va-ranking-summary-tile .lbl { font-size: .68rem; text-transform: uppercase; color: var(--va-text-muted); letter-spacing: .02em; }
body.public-body[data-theme="dark"] .va-ranking-summary-tile { background: #202C38; border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-ranking-summary-tile .val { color: #E8EEF5; }

.va-my-rank-card {
  border: 2px solid var(--va-saffron);
  border-radius: var(--va-radius);
  background: rgba(255, 122, 0, .06);
  padding: 1rem 1.1rem;
  margin-bottom: 1.25rem;
}
body.public-body[data-theme="dark"] .va-my-rank-card { background: rgba(255, 122, 0, .1); }

.va-podium { display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; margin-bottom: 1.25rem; }
.va-podium-card {
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius);
  background: var(--va-white);
  text-align: center;
  padding: 1rem .5rem .85rem;
}
.va-podium-card.is-rank-1 { border-color: var(--va-gold, #D4AF37); background: linear-gradient(180deg, rgba(212,175,55,.12), var(--va-white)); }
.va-podium-card.is-rank-2 { border-color: #A9B4C0; }
.va-podium-card.is-rank-3 { border-color: #C08552; }
.va-podium-rank { font-size: 1.4rem; font-weight: 800; color: var(--va-navy); }
.va-podium-name { font-weight: 600; font-size: .85rem; margin: .25rem 0; word-break: break-word; }
.va-podium-score { font-size: .8rem; color: var(--va-text-muted); }
body.public-body[data-theme="dark"] .va-podium-card { background: #202C38; border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-podium-rank,
body.public-body[data-theme="dark"] .va-podium-name { color: #E8EEF5; }

.va-rank-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  border: 1px solid var(--va-border);
  border-radius: var(--va-radius-sm);
  padding: .6rem .85rem;
  margin-bottom: .5rem;
  background: var(--va-white);
}
.va-rank-row.is-me { border-color: var(--va-saffron); background: rgba(255, 122, 0, .06); }
.va-rank-row .va-rank-num { font-weight: 800; color: var(--va-navy); min-width: 2.2rem; }
.va-rank-row .va-rank-name { flex: 1 1 auto; font-weight: 600; font-size: .9rem; }
.va-rank-row .va-rank-score { font-weight: 700; color: var(--va-navy); font-size: .88rem; text-align: right; }
.va-rank-row .va-rank-time { font-size: .74rem; color: var(--va-text-muted); text-align: right; min-width: 4.5rem; }
body.public-body[data-theme="dark"] .va-rank-row { background: #202C38; border-color: #2A3644; }
body.public-body[data-theme="dark"] .va-rank-row .va-rank-num,
body.public-body[data-theme="dark"] .va-rank-row .va-rank-score { color: #E8EEF5; }
body.public-body[data-theme="dark"] .va-rank-row.is-me { background: rgba(255, 122, 0, .12); }

.va-ranking-pager { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin-top: 1rem; font-size: .82rem; color: var(--va-text-muted); }

@media (max-width: 575.98px) {
  .va-podium { grid-template-columns: 1fr; }
  .va-rank-row .va-rank-time { min-width: auto; }
}
