/* QuintEdge — UX polish layer (Phase 7).
   Loaded site-wide via /css/qe-ux-polish.css.
   • Respects prefers-reduced-motion
   • Restores focus-visible outline on all interactive elements
   • Provides .qe-skip-link for screen-reader skip-to-content
   • Skeleton loader animation (.qe-skel)
   • View Transitions API support (when meta is set)
*/

/* ── Skip link (visible on keyboard focus only) ─────────────── */
.qe-skip-link {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 99999;
  background: #00D4AA;
  color: #050A18;
  padding: 10px 18px;
  border-radius: 8px;
  font: 600 .85rem/1.2 'Poppins', system-ui, sans-serif;
  text-decoration: none;
  box-shadow: 0 4px 16px rgba(0, 212, 170, .35);
}
.qe-skip-link:focus,
.qe-skip-link:focus-visible {
  left: 8px;
  outline: 3px solid #00F0C5;
  outline-offset: 2px;
}

/* ── Restore focus-visible outline on buttons & links that strip it ── */
:focus-visible {
  outline: 2px solid #00D4AA;
  outline-offset: 3px;
  border-radius: 4px;
}
.btn:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid #00D4AA;
  outline-offset: 3px;
}

/* ── Skeleton loader (used by tools that load PDF.js etc.) ── */
.qe-skel {
  position: relative;
  background: linear-gradient(
    110deg,
    rgba(255, 255, 255, .04) 8%,
    rgba(255, 255, 255, .10) 18%,
    rgba(255, 255, 255, .04) 33%
  );
  background-size: 200% 100%;
  animation: qe-skel-shimmer 1.6s linear infinite;
  border-radius: 8px;
  min-height: 40px;
  color: transparent;
}
@keyframes qe-skel-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}

/* ── prefers-reduced-motion respect ──────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .qe-skel { animation: none; background: rgba(255, 255, 255, .06); }
  /* Disable autoplay on reveal animations */
  .rv { opacity: 1 !important; transform: none !important; }
}

/* ── View Transitions API smoothing ─────────────────────────── */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
  animation-timing-function: cubic-bezier(.22, 1, .36, 1);
}

/* ── Form error UX ──────────────────────────────────────────── */
.qe-form-msg {
  display: none;
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: 8px;
  font: 500 .85rem/1.4 'Poppins', system-ui, sans-serif;
}
.qe-form-msg.show { display: block; }
.qe-form-msg.err {
  background: rgba(255, 107, 107, .08);
  border: 1px solid rgba(255, 107, 107, .25);
  color: #ff8e8e;
}
.qe-form-msg.ok {
  background: rgba(0, 212, 170, .08);
  border: 1px solid rgba(0, 212, 170, .25);
  color: #00f0c5;
}

/* ── Field-level error highlight ────────────────────────────── */
[data-qe-invalid="1"] {
  outline: 2px solid #ff6b6b !important;
  outline-offset: 1px !important;
}

/* ── Inline per-field error message rendered by qe-form-core's
       live validator. Hidden by default; .show toggled in JS. ── */
.qe-field-msg {
  display: none;
  margin: 6px 0 0;
  font: 500 .76rem/1.4 'Poppins', system-ui, sans-serif;
  color: #ff8e8e;
  letter-spacing: .005em;
}
.qe-field-msg.show { display: block; }
/* Belt-and-suspenders: if a future form's phone-row keeps the <small>
   inside its flex/grid container (against the JS rule above), force the
   error to take the full row width so it wraps onto its own line below
   the country-code + phone inputs instead of squeezing in beside them.
   The country+phone rows ALL set flex-wrap: wrap, so 100% basis is
   sufficient to push the <small> to a new line. */
.qe-lead-phone-field > .qe-field-msg,
.qe-hire-phone-field > .qe-field-msg,
.qe-apply-phone-field > .qe-field-msg,
.access-phone-grid > .qe-field-msg,
.qe-re-phone-row > .qe-field-msg {
  flex-basis: 100%;
  width: 100%;
  order: 99;
}

/* ── Mobile tap targets — ensure ≥40×40 px hit area on every clickable ──
   WCAG 2.5.5 (AAA) recommends 44×44; Apple HIG = 44; Material = 48dp. We use
   40 as a pragmatic floor for the QuintEdge brand (matches our Pixel-7 audit
   minimum). Visual sizes mostly unchanged — these rules expand the click
   bounding box via min-* + padding, never the rendered icon. ── */

/* Skip link: was 36 px tall. Bump to 40. */
.qe-skip-link {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
}

/* Drawer brand + close: were 38×38 px. Bump to 44 for one-handed thumb tap. */
.qe-nav-v2-brand,
.qe-nav-v2-close {
  min-width: 44px;
  min-height: 44px;
}

/* Carousel pagination dots: visual is 10×10 (inactive) / 28×10 wide pill
   (active). Click target is 40×40 (WCAG tap-target minimum). Implemented
   via a transparent button + ::before pseudo for the visible dot — this is
   the only way `border-radius: 50%` (circle) can morph cleanly to a wide
   pill without clipping artifacts.

   Bug fixed 2026-04-30: previous version used padding + background-clip
   which rendered the active dot as a 20×12 sharp-edged square. */
button.vtc-dot,
.vtc-dot {
  position: relative;
  min-width: 40px;
  min-height: 40px;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent !important;
  background-clip: border-box; /* reset the previous content-box trick */
  border: none !important;
  cursor: pointer;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
button.vtc-dot::before,
.vtc-dot::before {
  content: '';
  display: block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid rgba(0, 212, 170, .3);
  background: transparent;
  transition: all .3s ease;
}
button.vtc-dot.active::before,
.vtc-dot.active::before {
  width: 28px;
  border-radius: 5px;
  background: var(--teal, #00d4aa);
  border-color: var(--teal, #00d4aa);
}
button.vtc-dot:hover::before,
.vtc-dot:hover::before {
  border-color: var(--teal, #00d4aa);
}

/* Blog category filter pills: were 33 px tall. Bump to 40. */
button.cat-pill,
.cat-pill {
  min-height: 40px;
  padding-top: 6px;
  padding-bottom: 6px;
}

/* Contact-page office chips (Directions / Book a visit / WhatsApp):
   were 39 px tall. Bump to 40. */
.c-office-chip {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
}

/* Top-bar logo link is the brand mark — ensure mobile users can tap home.
   Visual logo image stays 32 px tall; we expand the anchor's hit area. */
@media (max-width: 900px) {
  a.logo {
    min-height: 40px;
    padding: 4px 0;
    display: inline-flex;
    align-items: center;
  }
}

/* "View All Stories" link (and similar small inline anchors flagged by the
   tap-target audit) — bump padding when used as a standalone CTA. */
a.btn-sm,
a.btn.btn-ghost {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
}

/* ── MCTA expandable batch panel (site-wide) ─────────────────────────
   The mobile sticky bottom bar (.mcta) includes a hidden batch-schedule
   panel that slides up when the user taps the "Next batch" pill. The
   canonical CSS is shipped in /css/qe-theme-cfa.min.css and was lifted
   into qe-theme-ib.min.css in commit f586737e. But ~25 pages with
   inlined-only CSS (index.html, contact.html, careers.html, the
   `/access-*-doubt-solver/` pages, payment pages, evaluator tools, etc.)
   plus blog/ and success-stories/ pages have no copy of these rules.
   Without them, .mcta-panel renders as a `position:static; max-height:none`
   block that stretches the position:fixed bar UPWARD to ~1500px, covering
   the entire viewport with the bar's 99%-opaque dark background — which
   is exactly the "front page is dark" symptom user reported on test.
   quintedge.com on 2026-05-01. Putting the rules here means every page
   that loads qe-ux-polish.css (363 of 365 pages) is fixed in one shot,
   without needing to re-edit every HTML file. */
/* Base bar — lifted from qe-theme-cfa.min.css so pages that don't load a
   course-theme CSS (index.html, contact.html, careers.html, payment pages,
   evaluators, doubt-solver pages, recruit, etc.) get a properly-styled
   bar instead of a transparent inheriting-defaults pill. */
.mcta {
  /* The footer is always rendered on a dark surface, but blog +
     success-story themes redefine --w / --t1 / --t3 / --teal / --bdr
     to LIGHT-theme values for their article body. Scope the dark-theme
     values back here so every child rule using var(--*) resolves to
     readable colors regardless of the outer theme. */
  --w: #fff;
  --t1: #e4e9f2;
  --t3: #8896b3;
  --teal: #00d4aa;
  --teal-dim: #00d4aa1a;
  --bdr: #ffffff0f;
  --bdr2: #ffffff1a;
  z-index: 999;
  background: #080e1efc;
  border-top: 1px solid #00d4aa26;
  padding: 0;
  display: block;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  box-shadow: 0 -4px 24px #00000080, 0 -1px #64c8ff0f;
}
.mcta-inner {
  max-width: var(--mw, 1200px);
  align-items: stretch;
  margin: 0 auto;
  display: flex;
}
.mcta-inner > * {
  cursor: pointer;
  border-right: 1px solid #ffffff0f;
  flex: 1;
  justify-content: center;
  align-items: center;
  gap: 8px;
  padding: 13px 0;
  text-decoration: none;
  transition: all .3s;
  display: flex;
  position: relative;
}
.mcta-inner > :last-child { border-right: none; }
.mcta-inner > a:hover  { background: #ffffff08; }
.mcta-inner > a:active { background: #00d4aa14; }
.mcta-inner > a svg    { flex-shrink: 0; width: 18px; height: 18px; }
.mcta-inner > a span   { font-size: .74rem; font-weight: 600; }

/* Pill (the clickable "Next batch: <date> — <urgency>" element).
   Typography + colors lifted from course-page .batch-trigger so the
   front-page (mcta-allbatches) pill is pixel-identical to the
   course-page widget. Course CSS:
     .bt-dot   #FFCC66 + glow box-shadow + 8×8
     .bt-text  rgba(255,255,255,.95) + .82rem + letter-spacing .01em
     .bt-arrow #00D4AA teal + .78rem + font-weight 700 */
.mcta-batch { text-decoration: none !important; }
.mcta-batch:hover { background: #ffcc660a; }
.mcta-batch .mb-dot {
  background: #FFCC66;
  border-radius: 50%;
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  box-shadow: 0 0 8px rgba(255, 204, 102, .6);
  animation: 1.5s ease-in-out infinite btPulse;
}
.mcta-batch .mb-text {
  color: rgba(255, 255, 255, .95);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .01em;
}
.mcta-batch .mb-text strong { color: #FFCC66; font-weight: 800; }
.mcta-batch .mb-arrow {
  color: #00D4AA;
  font-size: .78rem;
  font-weight: 700;
  opacity: 1;
  transition: transform .35s;
}
@keyframes btPulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }

/* Per-button accent colors. */
.mcta-phone svg  { stroke: #00d4aa; }
.mcta-phone span { color: #00d4aa; }
.mcta-wa svg     { fill: #25d366; }
.mcta-wa span    { color: #25d366; }
.mcta-visit svg  { stroke: #64c8ff; }
.mcta-visit span { color: #64c8ff; }
.mcta-visit { background: linear-gradient(#64c8ff0f, #0000); }
.mcta-visit:before {
  content: "";
  background: #64c8ff14;
  border: 1px solid #64c8ff26;
  border-radius: 50%;
  width: 38px;
  height: 38px;
  animation: 2s ease-in-out infinite visitPulse;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
@keyframes visitPulse {
  0%, 100% { box-shadow: 0 0 #64c8ff33; }
  50%      { box-shadow: 0 0 0 8px #64c8ff00; }
}

/* Mobile: hide the "Call Us / Visit Campus / WhatsApp" text labels so the
   bar reads as 3 clean icons (matches the homepage + course-page treatment).
   Course-themed CSS files have this rule already; polish.css ships it for
   the brochure / success-story / blog pages that don't load a course theme. */
@media (max-width: 768px) {
  .mcta-inner > a span { display: none; }
  .mcta-inner > a      { padding: 14px 0; }
}

.mcta.panel-open .mcta-batch .mb-arrow { transform: rotate(180deg); }
.mcta.panel-open .mcta-batch { background: #ffcc660f; }
.mcta-panel {
  background: #080e1efc;
  border-top: 1px solid #ffcc661f;
  max-height: 0;
  transition: max-height .4s cubic-bezier(.22, 1, .36, 1);
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  overflow: hidden;
  box-shadow: 0 -8px 32px #0006;
}
/* Vertical scroll inside the panel kicks in once the panel is expanded —
   so even a tall sectioned panel (5 courses on the all-batches variant)
   stays bounded by max-height and the user can scroll any extra content
   into view rather than it getting clipped. overflow:hidden during the
   slide-up keeps the animation clean. */
.mcta.panel-open .mcta-panel {
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}
/* Cap expanded panel at 60vh on every page + every viewport so it
   can never feel overwhelming. Was 260px (course) / 600px (all-batches)
   which on a tall desktop monitor wasted space, and on a phone the
   600px sometimes covered most of the screen. 60vh = ~500px on a
   typical phone, ~600px on most desktops — enough room for several
   batches with vertical scroll for the rest. */
.mcta.panel-open .mcta-panel { max-height: 60vh; }
.mcta[data-mcta-allbatches].panel-open .mcta-panel { max-height: 60vh; }
/* Close button — top-right of the expanded panel, visible on mobile
   AND desktop. Lets users dismiss without scrolling all the way down
   to find the toggle pill. */
.mcta-panel-close {
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 2;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .04);
  color: rgba(255, 255, 255, .65);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 50%;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  transition: background .2s, color .2s, border-color .2s;
}
.mcta-panel-close:hover,
.mcta-panel-close:focus-visible {
  background: rgba(255, 107, 107, .12);
  color: #ff8e8e;
  border-color: rgba(255, 107, 107, .35);
  outline: none;
}
.mcta-panel-inner { position: relative; }
@media (max-width: 768px) {
  .mcta-panel-close { top: 6px; right: 8px; width: 30px; height: 30px; }
}

/* ── Sticky panel header (.mcta-panel-header / .batch-panel-header) ──
   Wraps the panel-title + close button so they stay pinned to the top
   of the panel while the user scrolls a long list of batches. Founder
   report: "this top bar is still not sticking while scrolling down in
   both mobile and desktop". Without this the close button + course
   label scrolled out of view, forcing the user to scroll all the way
   back up to dismiss.
   The wrapper exists in:
     - partials/mcta.html              (course-page .mcta widget)
     - partials/mcta-allbatches.html   (front-page all-batches variant)
     - inline batch-panel-inner in every course HTML (added via sed)
   Same selector pattern targets both .mcta-panel and .batch-panel
   variants so behaviour is identical across all three. */
.mcta-panel-header,
.batch-panel-header {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Opaque-ish bg so scrolled content beneath doesn't bleed through —
     matches the .mcta-panel base bg (#080e1efc) with a soft fade-out
     at the bottom edge so the boundary feels like a header band, not
     a hard line. */
  background: linear-gradient(180deg, #080e1efc 0%, #080e1ee8 80%, rgba(8, 14, 30, .85) 100%);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  /* Break out of .mcta-panel-inner padding so the header band runs
     edge-to-edge — looks intentional, not pinched. */
  margin: -20px -24px 14px;
  padding: 14px 24px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, .05);
}
@media (max-width: 768px) {
  .mcta-panel-header,
  .batch-panel-header {
    margin: -16px -16px 14px;
    padding: 12px 16px 10px;
  }
}
/* Title sits inside the sticky header now — drop its own bottom margin
   (header-bottom border + margin replaces it) and let it grow into the
   available width before the close button. */
.mcta-panel-header .mcta-panel-title,
.batch-panel-header .batch-panel-title {
  margin-bottom: 0;
  flex: 1 1 auto;
  min-width: 0;
}
/* Close button moves into the flex header (no longer absolute). Visual
   styling preserved via existing .mcta-panel-close / .batch-panel-close
   rules above; just neutralize the absolute-positioning here. */
.mcta-panel-header .mcta-panel-close,
.batch-panel-header .batch-panel-close {
  position: static;
  top: auto;
  right: auto;
  flex-shrink: 0;
}

/* ── Course-page batch panel CTA (.batch-panel-cta) ──
   Mirror of .mcta-panel-cta for the course-page .batch-bar widget.
   Founder report: "in desktop there is still no CTA in the end like in
   mobile". Same teal pill, same target, same hover treatment — just
   scoped to the course-page widget so all three batch surfaces (course
   .batch-bar, course .mcta, front-page .mcta-allbatches) end with the
   same Talk-to-a-Counsellor escape hatch on every viewport. */
.batch-panel-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
  padding: 12px 20px;
  background: linear-gradient(135deg, var(--teal, #00d4aa), #00b894);
  color: #052821 !important;
  text-decoration: none;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .01em;
  border-radius: 10px;
  border: 1px solid rgba(0, 212, 170, .35);
  box-shadow: 0 4px 16px rgba(0, 212, 170, .25);
  transition: transform .2s, box-shadow .2s, background .2s;
}
.batch-panel-cta:hover,
.batch-panel-cta:focus-visible {
  transform: translateY(-1px);
  background: linear-gradient(135deg, #00f0c5, var(--teal, #00d4aa));
  box-shadow: 0 6px 22px rgba(0, 212, 170, .35);
  outline: none;
}
.batch-panel-cta svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  stroke-width: 2.5;
  fill: none;
  flex-shrink: 0;
}

/* ── Course-page .batch-bar widget (separate from .mcta) — scroll fix ──
   Course pages use a SEPARATE batch widget (.batch-bar) sitting just
   above the bottom .mcta bar on mobile. Its base CSS in the minified
   themes uses `max-height: 500px; overflow: hidden` when open, which
   on a phone caps content visibility AND cannot be scrolled — taller
   content just gets cut off with no affordance.
   Override: same 60vh cap as .mcta-panel + overflow-y: auto so the
   user can scroll the rest of the batch list into view. Apply on
   every viewport so behaviour is consistent. */
.batch-bar.open .batch-panel {
  max-height: 60vh !important;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}
.batch-panel-inner { position: relative; }
/* Close button on the course-page .batch-bar widget — same shape and
   placement as .mcta-panel-close so behaviour reads consistently
   regardless of which widget the user is on. */
.batch-panel-close {
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 2;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .04);
  color: rgba(255, 255, 255, .65);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 50%;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  transition: background .2s, color .2s, border-color .2s;
}
.batch-panel-close:hover,
.batch-panel-close:focus-visible {
  background: rgba(255, 107, 107, .12);
  color: #ff8e8e;
  border-color: rgba(255, 107, 107, .35);
  outline: none;
}
@media (max-width: 768px) {
  .batch-panel-close { top: 6px; right: 8px; width: 30px; height: 30px; }
}

/* ── Panel CTA button (front-page all-batches variant) ──
   Sits at the bottom of the panel as a primary action — when a user
   has skimmed the upcoming batches and wants to actually act, it gives
   them a single clear path to the contact form. Course pages don't
   need this (they already have course-specific lead forms on-page);
   only renders on the all-batches partial which sets data-mcta-allbatches. */
.mcta-panel-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
  padding: 12px 20px;
  background: linear-gradient(135deg, var(--teal, #00d4aa), #00b894);
  color: #052821 !important;
  text-decoration: none;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .01em;
  border-radius: 10px;
  border: 1px solid rgba(0, 212, 170, .35);
  box-shadow: 0 4px 16px rgba(0, 212, 170, .25);
  transition: transform .2s, box-shadow .2s, background .2s;
}
.mcta-panel-cta:hover,
.mcta-panel-cta:focus-visible {
  transform: translateY(-1px);
  background: linear-gradient(135deg, #00f0c5, var(--teal, #00d4aa));
  box-shadow: 0 6px 22px rgba(0, 212, 170, .35);
  outline: none;
}
.mcta-panel-cta svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  stroke-width: 2.5;
  fill: none;
  flex-shrink: 0;
}
.mcta-panel-inner { max-width: var(--mw, 1200px); margin: 0 auto; padding: 20px 24px; }
.mcta-panel-title {
  /* Hard-coded #fff (not var(--w)) because the footer panel is always on
     a dark bg, but blog / success-story themes redefine --w to #1a1d26
     for their light-theme article body — which would make this title
     dark-on-dark and illegible. Same logic for .mpc-day / .mpc-name. */
  color: #fff;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
  font-size: .82rem;
  font-weight: 600;
  display: flex;
}
.mcta-panel-title svg { width: 16px; height: 16px; stroke: var(--teal, #00d4aa); flex-shrink: 0; }
/* Grid is just a block container now — actual layout happens inside
   .mcta-panel-hscroll (one per course on the all-batches variant, one
   total on course pages). */
.mcta-panel-grid { display: block; }
/* Per-course section on the all-batches variant. Course pages don't use
   sections (the panel-title at top of the panel is enough context — only
   one course shown), so this only shows up when the JS injects sections. */
.mcta-panel-section { margin-bottom: 14px; }
.mcta-panel-section:last-child { margin-bottom: 0; }
.mcta-panel-section-title {
  color: var(--teal, #00d4aa);
  text-transform: uppercase;
  letter-spacing: .12em;
  margin-bottom: 8px;
  font-size: .68rem;
  font-weight: 700;
}
/* Horizontal-scroll row of cards. Cards are fixed-width so scroll feels
   right (and so a partial card peeks at the right edge to hint scrollability).
   scroll-snap keeps the swipe feeling clean. Custom thin scrollbar so the
   scroll affordance is visible without being heavy. */
.mcta-panel-hscroll {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 10px;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 212, 170, .45) rgba(255, 255, 255, .06);
}
.mcta-panel-hscroll::-webkit-scrollbar { height: 8px; }
.mcta-panel-hscroll::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, .06);
  border-radius: 4px;
}
.mcta-panel-hscroll::-webkit-scrollbar-thumb {
  background: rgba(0, 212, 170, .45);
  border-radius: 4px;
  border: 1px solid rgba(0, 212, 170, .25);
}
.mcta-panel-hscroll::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 212, 170, .7);
}
.mcta-panel-hscroll .mcta-panel-card {
  flex: 0 0 260px;
  scroll-snap-align: start;
}
@media (max-width: 480px) {
  .mcta-panel-hscroll .mcta-panel-card { flex-basis: 240px; }
}
.mcta-panel-card {
  border: 1px solid var(--bdr, #ffffff0f);
  background: #ffffff08;
  border-radius: 10px;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  transition: all .3s;
  display: flex;
}
.mcta-panel-card:hover { background: #00d4aa08; border-color: #00d4aa26; }
.mpc-date { text-align: center; min-width: 40px; }
.mpc-date .mpc-day { color: #fff; font-size: 1rem; font-weight: 700; line-height: 1; }
.mpc-date .mpc-mon {
  color: var(--teal, #00d4aa);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-top: 2px;
  font-size: .5rem;
  font-weight: 600;
}
.mpc-info { flex: 1; min-width: 0; }
.mpc-info .mpc-name {
  color: #fff;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: .76rem;
  font-weight: 600;
  overflow: hidden;
}
.mpc-info .mpc-meta { color: #8896b3; margin-top: 1px; font-size: .62rem; }
.mpc-badge {
  white-space: nowrap;
  border-radius: 12px;
  flex-shrink: 0;
  padding: 3px 8px;
  font-size: .56rem;
  font-weight: 700;
}
.mpc-badge.almost { color: #ff6b6b; background: #ff6b6b1a; border: 1px solid #ff6b6b1f; }
.mpc-badge.filling { color: #fc6; background: #ffcc661a; border: 1px solid #ffcc661f; }
.mpc-badge.open {
  background: var(--teal-dim, #00d4aa1a);
  color: var(--teal, #00d4aa);
  border: 1px solid #00d4aa1a;
}
/* "Coming Soon" placeholder card — rendered by qe-mcta-allbatches.js AND
   by per-course-page inline batch-loaders when /api/batches returns an
   empty array for that course. Uses the lavender accent so it reads as
   informational rather than alerting (which the red .almost / gold .filling
   variants do for real urgency). */
.mpc-badge.soon,
.batch-seats.soon {
  color: var(--lav, #9b8aff);
  background: var(--lav-dim, #9b8aff14);
  border: 1px solid #9b8aff26;
}
.mcta-panel-card.mcta-panel-card-soon,
.batch-card.batch-card-soon { opacity: .92; }
.mcta-panel-card.mcta-panel-card-soon .mpc-day,
.batch-card.batch-card-soon .bd-day {
  color: var(--lav, #9b8aff);
  font-size: 1.4rem;
  line-height: .9;
}
.mcta-panel-card.mcta-panel-card-soon .mpc-mon,
.batch-card.batch-card-soon .bd-mon {
  color: var(--lav, #9b8aff);
  letter-spacing: .08em;
}
/* Panel stays visible on mobile too — collapsed by default, opens on
   tap of the batch pill. Tighter padding + smaller heading on phones so
   the panel doesn't dominate the screen when expanded. */
@media (max-width: 768px) {
  .mcta-panel-inner { padding: 16px 16px 14px; }
  /* Headline matches course-page .batch-panel-title (.82rem / 14px gap). */
  .mcta-panel-title { font-size: .82rem; margin-bottom: 14px; }
  .mcta-panel-section-title { font-size: .64rem; margin-bottom: 6px; }
  /* mobile uses the same 60vh cap as desktop now (set globally above) */

  /* All-batches variant (non-course pages) parity with course pages:
     course pages have a SEPARATE .batch-bar widget that sits as its own
     horizontal strip above the bottom .mcta bar — so the .mcta-batch
     pill is hidden inline (display:none) and the standalone strip shows
     "Next batch: <date> — <urgency>". Non-course pages don't have that
     separate widget, so they were rendering .mcta-batch as a 4th button
     alongside Call / Visit / WhatsApp. Fix: on mobile, force .mcta-batch
     onto its OWN full-width row above the 3 action buttons, AND match
     the course-page .batch-trigger exactly (gradient bg, teal border-top,
     heavy upper shadow, larger typography) so the visual experience is
     identical across course AND non-course pages. */
  .mcta[data-mcta-allbatches] .mcta-inner { flex-wrap: wrap; }
  /* Critical for REAL glass on the strip: the strip's parent (.mcta) is
     normally opaque navy, which means backdrop-filter on the strip has
     no actual page content to blur — it just blurs the navy. Replace
     .mcta's solid bg with a hard-stopped gradient: TRANSPARENT in the
     top ~44px (strip's area) + the original opaque navy below (icons
     area). The strip now sits on a transparent region and its
     backdrop-filter blurs ACTUAL page content scrolling underneath. */
  .mcta[data-mcta-allbatches] {
    background: linear-gradient(
      180deg,
      transparent 0,
      transparent 44px,
      #080e1efc 44px,
      #080e1efc 100%
    ) !important;
  }
  .mcta[data-mcta-allbatches] .mcta-batch {
    flex: 1 1 100%;
    border-right: none;
    /* Glass that survives BOTH dark and light backdrops:
       - Lower layer (linear-gradient): same dark-navy tint as glass4 —
         this is the part that reads as glass over light sections (the
         success-stories card etc.) and keeps white text contrast.
       - Upper layer (radial-gradient): subtle white "lit-from-above"
         glow at the top center of the strip — visible even when the
         page section behind is solid dark navy (where backdrop-filter
         has no color variation to frost on its own). The glow gives
         the strip its own internal lighting that doesn't depend on
         the backdrop, so the plate reads as glass on any background.
       - backdrop-filter: still does its real-frost work whenever
         there IS color variation behind. */
    background:
      radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255, 255, 255, .14), transparent 65%),
      linear-gradient(180deg, rgba(8, 14, 30, .55), rgba(8, 14, 30, .72)) !important;
    -webkit-backdrop-filter: blur(28px) saturate(200%);
    backdrop-filter: blur(28px) saturate(200%);
    border-top: 1px solid rgba(255, 255, 255, .25) !important;
    border-bottom: 1px solid rgba(255, 255, 255, .14) !important;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .38),
      inset 0 -1px 0 rgba(0, 0, 0, .25) !important;
    justify-content: center;
    padding: 12px 16px;
  }
  /* Soft amber wash on tap/open so the pill still reads as the bar's
     primary CTA without breaking the glass surface. */
  .mcta[data-mcta-allbatches].panel-open .mcta-batch {
    background:
      radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255, 220, 150, .18), transparent 65%),
      linear-gradient(180deg, rgba(60, 40, 10, .65), rgba(40, 25, 5, .78)) !important;
  }
  /* Note: .mb-text/.mb-dot/.mb-arrow already inherit the new course-matched
     typography from the base .mcta-batch rules (above) — no overrides
     needed here. */
  .mcta[data-mcta-allbatches] .mcta-inner > a {
    flex: 1 1 0;
    /* keep their existing border-right separators for the 3-button row */
  }
}

/* ── Sticky batch pill — glassy parity on course pages ──────────────
   The homepage / all-batches pages already get a glassy treatment via
   the `.mcta[data-mcta-allbatches] .mcta-batch` block above. The
   course-themed CSS (qe-theme-cfa / acca / ib / crm) used to swap the
   `.batch-trigger` to a flat dark-navy gradient and kill its
   `backdrop-filter`, so the same "Next batch" pill rendered glassy on
   the homepage but solid on course pages. Re-apply the elevated glass
   look here so visitors see the same UI everywhere.

   qe-ux-polish.css loads AFTER the theme CSS in the cascade, so
   matching `!important` weight + later source order wins. Dot / text /
   arrow color rules from the theme override (gold dot, white text with
   gold emphasis, teal arrow) stay intact — only the plate background,
   backdrop blur, border, and inset shadow are restyled. */
.batch-trigger {
  background:
    radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255, 255, 255, .14), transparent 65%),
    linear-gradient(180deg, rgba(8, 14, 30, .55), rgba(8, 14, 30, .72)) !important;
  -webkit-backdrop-filter: blur(28px) saturate(200%) !important;
  backdrop-filter: blur(28px) saturate(200%) !important;
  border-top: 1px solid rgba(255, 255, 255, .25) !important;
  border-bottom: 1px solid rgba(255, 255, 255, .14) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .38),
    inset 0 -1px 0 rgba(0, 0, 0, .25) !important;
  padding: 12px 16px !important;
}
/* Tap-state amber wash matching the .mcta-batch open state above so
   the pill still reads as the bar's primary CTA when expanded. */
.batch-bar.open .batch-trigger {
  background:
    radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255, 220, 150, .18), transparent 65%),
    linear-gradient(180deg, rgba(60, 40, 10, .65), rgba(40, 25, 5, .78)) !important;
}
/* Course-themed `.mcta-batch` (visible as the 4th flex item on desktop
   course pages where `.batch-bar` is hidden) also gets glass parity.
   On homepage / all-batches pages, the higher-specificity
   `.mcta[data-mcta-allbatches] .mcta-batch` rule above still wins. */
.mcta-batch {
  background:
    radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255, 255, 255, .14), transparent 65%),
    linear-gradient(180deg, rgba(8, 14, 30, .55), rgba(8, 14, 30, .72)) !important;
  -webkit-backdrop-filter: blur(28px) saturate(200%) !important;
  backdrop-filter: blur(28px) saturate(200%) !important;
}
/* NOTE: We don't punch a transparent strip into the parent `.mcta` on
   course pages the way the all-batches variant does. On course pages
   mobile, `.mcta-batch` is `display:none` (theme CSS hides it because
   `.batch-bar` already shows the pill above .mcta). On desktop course
   pages `.mcta-batch` is visible as a flex item inside opaque .mcta,
   but cutting a 44px transparent gap there would leave a weird empty
   strip above the 3 icons row — the radial-gradient highlight on
   `.mcta-batch` itself gives the glassy LOOK without needing a true
   frost. `.batch-trigger` (the mobile pill above .mcta) IS over the
   transparent area of the page, so its `backdrop-filter` does real
   frost work — no parent-bg adjustment needed there. */

/* ── Pricing table — mobile horizontal scroll affordance ──
   Earlier rev had a soft fade gradient + thin scrollbar but the package
   column was so wide (CFA Level 1 + Financial Modeling & Valuation) it
   filled the entire mobile viewport with NO visible peek of the price
   columns — users had no idea more content existed to the right.

   The new affordance stack — strong, intuitive, not tacky:
   1) Constrained .pkg-col width (200px) so the table genuinely overflows
      AND the second column peeks visibly past the viewport edge
   2) Stronger right-edge mask fade (44px instead of 28px) — the peek
      column visibly fades, telegraphing "more to the right"
   3) Always-visible 8px teal scrollbar (was 6px) — now obvious
   4) Animated chevron hint pinned to the right of the wrapper that
      pulses gently for the first 6s after the page loads, then settles
      to a static guide. Hides itself once user scrolls past 8px. */
@media (max-width: 768px) {
  .ptbl {
    position: relative;
    overflow-x: auto !important;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 212, 170, .65) rgba(0, 0, 0, .06);
    /* Stronger right-edge fade — 44px instead of 28px, fading further
       toward transparent so the peek column visibly "trails off" instead
       of looking like a clipped table. */
    -webkit-mask-image: linear-gradient(to right, black 0, black calc(100% - 44px), rgba(0,0,0,.05) 100%);
            mask-image: linear-gradient(to right, black 0, black calc(100% - 44px), rgba(0,0,0,.05) 100%);
  }
  /* iOS Safari uses overlay scrollbars that auto-hide unless we explicitly
     opt out via `-webkit-appearance:none`. Without this the teal bar only
     flashes during a swipe and the user has no idea the table scrolls.
     With it, the scrollbar takes up real space at the bottom of the
     scroll container and is visible 100% of the time. (2026-05-02) */
  .ptbl::-webkit-scrollbar {
    -webkit-appearance: none !important;
    height: 8px !important;
    display: block !important;
  }
  .ptbl::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, .08);
    border-radius: 4px;
  }
  .ptbl::-webkit-scrollbar-thumb {
    background: rgba(0, 212, 170, .85);   /* bumped from .65 for stronger visibility */
    border-radius: 4px;
    min-width: 40px;                       /* keeps thumb chunky even when content barely overflows */
    border: 1px solid rgba(0, 212, 170, .35);
  }
  .ptbl::-webkit-scrollbar-thumb:hover { background: rgba(0, 212, 170, 1); }
  /* Force the inner table wider than the viewport so horizontal scroll
     actually engages on phones and the affordance is visible. */
  .ptbl table { min-width: 520px; }
  /* 2026-05-12: was 720px which left only ONE mode column visible on a
     375px phone (package eats 180px, first mode ~190px, the rest spills
     off-screen). Tightened to ~390px so package + 2 mode columns fit in
     the viewport with just a small scroll for the 3rd mode. Combined
     with the cell-padding / font tightening below. */
  .ptbl-unified table { min-width: 390px; }

  /* Constrain the package column on mobile — was auto-sizing to its
     widest content (e.g. "CFA Level 1 + Financial Modeling & Valuation")
     and eating the whole viewport so no price column peeked. 2026-05-12:
     tightened from 180px → 122px so 3 mode columns fit beside it on a
     375px phone. Long package names wrap to 3-4 lines now, which is
     fine since the row's vertical rhythm stays consistent.
     2026-05-12 (rev): bumped 122 → 158px. 122 was sized for CFA/FRM
     where bundle names are short ("CFA Level 1", "FRM Part 1") — for
     ACCA bundles ("Full ACCA — All 13 Papers" + a 12-word description)
     it collapsed the cell to 8+ lines and looked crushed. With 158px:
       - 2-mode (ACCA bundles, no hybrid): 158 + 90×2 = 338px → fits
         in 390px viewport, no scroll.
       - 4-col (CFA/FRM/RM/CRM with hybrid): 158 + 90×3 = 428px →
         small ~40px scroll on 390px viewport (already expected;
         min-width: 390px on the table forces a tiny scroll there
         anyway, the affordance is already wired up).
     Also tightened .pkg-desc font on phones so long descriptions
     don't tower into 8-line walls. */
  .ptbl-unified .pkg-col,
  .ptbl-unified th:first-child,
  .ptbl-unified td:first-child {
    width: 158px;
    min-width: 158px;
    max-width: 158px;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: anywhere;
  }
  .ptbl-unified .pkg-desc {
    font-size: .68rem;
    line-height: 1.4;
  }
  .ptbl-unified .pkg-name {
    font-size: .82rem;
    line-height: 1.25;
  }
  .ptbl-unified .mode-col {
    min-width: 90px;
  }

  /* Tighter thead / price-cell / enrol button on phones so 4 columns
     can comfortably coexist in ~390px of viewport. */
  .ptbl-unified thead th.mode-col {
    padding: 14px 4px;
    font-size: .58rem;
    letter-spacing: .06em;
  }
  .ptbl-unified thead th.mode-col svg {
    width: 11px;
    height: 11px;
    margin-right: 2px;
    vertical-align: -2px;
  }
  .ptbl-unified tbody td.price-cell {
    padding: 11px 4px;
  }
  .ptbl-unified tbody td.price-cell .price-amt {
    font-size: .85rem;
    margin-bottom: 4px;
  }
  .ptbl-unified .enrol-btn-sm {
    padding: 4px 7px;
    font-size: .55rem;
    letter-spacing: .03em;
    gap: 3px;
  }
  .ptbl-unified .enrol-btn-sm svg {
    width: 9px;
    height: 9px;
  }

  /* Earlier rev had an animated "›" chevron pinned to the right edge as
     a scroll affordance. User feedback (2026-05-02): visually awkward
     against the price-cell rows. Removed entirely — the column-peek
     (180px first column lets the next column show ~195px of viewport)
     plus the soft fade gradient + visible scrollbar are enough signal
     on their own. */
}

/* ── Unified pricing table (4 columns: package + Live + Recorded + Hybrid) ──
   Replaces the 3-tab Live/Recorded/Hybrid layout with a single side-by-side
   comparison. Mode columns are tinted (red/blue/green) so users can scan
   prices across modes at a glance without tab-switching. */
.ptbl-unified .pkg-col {
  text-align: left;
}
.ptbl-unified thead th.mode-col {
  text-align: center;
  vertical-align: middle;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .72rem;
  font-weight: 700;
}
.ptbl-unified thead th.mode-col svg {
  vertical-align: -3px;
  margin-right: 4px;
}
.ptbl-unified thead th.mode-live {
  background: rgba(239, 68, 68, .07);
  color: #B91C1C;
}
.ptbl-unified thead th.mode-recorded {
  background: rgba(10, 102, 194, .07);
  color: #0A66C2;
}
.ptbl-unified thead th.mode-hybrid {
  background: rgba(16, 185, 129, .07);
  color: #047857;
}

/* Each mode cell is a small price "card" — amount stacked over Enrol link. */
.ptbl-unified tbody td.price-cell {
  text-align: center;
  vertical-align: middle;
  padding: 16px 14px;
  white-space: nowrap;
}
.ptbl-unified tbody td.price-cell .price-amt {
  display: block;
  color: #111827;
  font-size: 1rem;
  font-weight: 500;
  margin-bottom: 6px;
}
.ptbl-unified tbody td.price-cell.empty {
  color: #9CA3AF;
  font-size: 1.1rem;
  font-weight: 300;
}

/* ── Elite compact Enrol button for the unified pricing table ──────
   2026-05-12 redesign: the old hollow outline read as a weak CTA — every
   pricing row got 2-3 of them which made the action feel optional. This
   version pre-fills with a subtle teal gradient (so each button is
   visually anchored even at rest), uses a stronger 600-weight letter-
   spaced label, and intensifies on hover with a full gradient fill, a
   1-pixel lift, a soft glow and an arrow nudge. The :before layer is
   the hover-fill — kept behind a z-index-1 inner wrapper so the label
   stays on top during the opacity crossfade. */
.ptbl-unified .enrol-btn-sm {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 13px;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #007a66;
  background: linear-gradient(135deg, rgba(0, 155, 128, .09), rgba(0, 155, 128, .18));
  border: 1px solid rgba(0, 155, 128, .42);
  border-radius: 6px;
  box-shadow: 0 1px 2px rgba(0, 155, 128, .08), inset 0 1px 0 rgba(255, 255, 255, .55);
  white-space: nowrap;
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
  transition: color .22s ease, border-color .22s ease, transform .22s cubic-bezier(.4,0,.2,1), box-shadow .22s ease;
}
.ptbl-unified .enrol-btn-sm::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #00b890 0%, #009b80 55%, #007e68 100%);
  opacity: 0;
  transition: opacity .25s ease;
  z-index: -1;
}
.ptbl-unified .enrol-btn-sm:hover,
.ptbl-unified .enrol-btn-sm:focus-visible {
  color: #fff;
  border-color: #009b80;
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(0, 155, 128, .35), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.ptbl-unified .enrol-btn-sm:hover::before,
.ptbl-unified .enrol-btn-sm:focus-visible::before {
  opacity: 1;
}
.ptbl-unified .enrol-btn-sm:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(0, 155, 128, .3), inset 0 1px 0 rgba(255, 255, 255, .12);
}
.ptbl-unified .enrol-btn-sm svg {
  width: 11px;
  height: 11px;
  transition: transform .25s cubic-bezier(.4,0,.2,1);
}
.ptbl-unified .enrol-btn-sm:hover svg,
.ptbl-unified .enrol-btn-sm:focus-visible svg {
  transform: translateX(2px);
}

/* "Most Popular" row gets a slightly stronger Enrol button so the row
   pulls more weight visually (matches the row's left-accent treatment). */
.ptbl-unified tr.row-pop .enrol-btn-sm {
  background: linear-gradient(135deg, rgba(0, 155, 128, .18), rgba(0, 155, 128, .30));
  border-color: rgba(0, 155, 128, .58);
  box-shadow: 0 2px 6px rgba(0, 155, 128, .16), inset 0 1px 0 rgba(255, 255, 255, .55);
}

/* Tighten header cell tints on the body too so the column band reads as
   one continuous tinted column, not just a tinted header. Subtle. */
.ptbl-unified tbody tr td:nth-child(2) { background: rgba(239, 68, 68, .025); }
.ptbl-unified tbody tr td:nth-child(3) { background: rgba(10, 102, 194, .025); }
.ptbl-unified tbody tr td:nth-child(4) { background: rgba(16, 185, 129, .025); }

/* Popular row keeps its left teal accent + faint gradient — but our column
   tints would otherwise wash it out. Strengthen the row-pop background
   so it stays visible across all 4 cells. */
.ptbl-unified tbody tr.row-pop td:nth-child(2) { background: rgba(239, 68, 68, .04); }
.ptbl-unified tbody tr.row-pop td:nth-child(3) { background: rgba(10, 102, 194, .04); }
.ptbl-unified tbody tr.row-pop td:nth-child(4) { background: rgba(16, 185, 129, .04); }


/* ── reCAPTCHA v3 badge — hide site-wide ───────────────────────
   Google permits hiding the badge as long as the disclosure text
   is shown elsewhere. qe-form-core.js injects the disclosure
   ".qe-recaptcha-credit" line in the bottom-right of every page
   that loads the reCAPTCHA SDK. We also hide the badge here at
   the global CSS layer so it stays hidden regardless of which
   load path triggered the SDK (lazy-load via qe-form-core, or
   direct <script> tag like /pay does). */
.grecaptcha-badge {
  visibility: hidden !important;
  opacity: 0 !important;
  pointer-events: none !important;
}


/* ──────────────────────────────────────────────────────────────
   DEDICATED REVIEWS PAGES (/cfa-reviews, /frm-reviews,
   /acca-reviews, /fm-reviews)
   ──────────────────────────────────────────────────────────────
   The course landing pages render LinkedIn reviews as a
   horizontal-scroll slider (.li-grid). The dedicated reviews
   pages need a multi-column responsive grid so visitors can scan
   ALL reviews at once. Adding `.li-page` to the parent .li-section
   switches the layout to a CSS grid and hides the slider arrows /
   dots — without touching the theme's base .li-grid rules used by
   the course landing pages. */

.li-section.li-page {
  padding-top: 32px !important;
}

.li-section.li-page .li-grid {
  /* override theme's flex/scroll-snap with a responsive grid */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  gap: 24px;
  overflow: visible;
  scroll-snap-type: none;
  margin-top: 32px;
  padding-bottom: 0;
}

.li-section.li-page .li-embed {
  /* reset slider-card width — let grid track decide */
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  scroll-snap-align: none;
}

.li-section.li-page .li-arrow,
.li-section.li-page .li-dots {
  display: none !important;
}

.li-section.li-page .li-slider-wrap {
  padding: 0;
}

/* Page-style hero strip above the reviews grid. Uses the theme's existing
   .S-title / .S-sub typography (Poppins headline + Times-italic em with
   gradient) so the page inherits the site-wide design language. The strip
   itself just provides the light-grey LinkedIn-section background, the
   breadcrumb row, and slightly tighter top padding than the landing-page
   --spy clamp (which is sized for full hero rhythm).

   .li-section's normal `.S-title em` rule applies the LinkedIn-blue
   gradient and pulls Times New Roman italic from `.S-title em` in the
   theme. We re-apply that same blue gradient inside the hero (which sits
   ABOVE .li-section) so the headline matches. */
.reviews-hero {
  padding: clamp(56px, 8vw, 96px) 0 clamp(16px, 3vw, 32px);
  background: #f8f9fb;
  position: relative;
  overflow: hidden;
  border-top: 1px solid rgba(0, 0, 0, .04);
}
.reviews-hero .W { text-align: center; }
.reviews-hero .S-title {
  color: #111827;
  margin: 14px 0 14px;
}
.reviews-hero .S-title em {
  background: linear-gradient(90deg, #0a66c2, #009b80, #6366f1);
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  background-clip: text;
}
.reviews-hero .S-sub {
  color: #6b7280;
  margin: 0 auto 24px;
  max-width: 720px;
}
.reviews-hero-stats {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}
.reviews-hero-stat {
  font-size: .76rem;
  font-weight: 600;
  color: #0A66C2;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 18px;
  background: rgba(10, 102, 194, .06);
  border: 1px solid rgba(10, 102, 194, .12);
  border-radius: 30px;
}
.reviews-hero-crumbs {
  font-size: .74rem;
  color: #6b7280;
  letter-spacing: .02em;
  margin-bottom: 4px;
}
.reviews-hero-crumbs a {
  color: #0a66c2;
  font-weight: 500;
  text-decoration: none;
}
.reviews-hero-crumbs a:hover { text-decoration: underline; }
.reviews-hero-crumbs span { color: #9ca3af; }

@media (max-width: 768px) {
  .li-section.li-page .li-grid {
    grid-template-columns: 1fr;
    gap: 18px;
  }
}


/* ──────────────────────────────────────────────────────────────
   STICKY COUNTDOWN BANNER (flip-clock layout)
   ──────────────────────────────────────────────────────────────
   Sits ABOVE the <header class="topbar"> in DOM order and visually,
   pinned to the very top of the viewport with `position: sticky;
   top: 0`. Higher z-index (1001) than the topbar (1000) and the
   mob-overlay (998) so it stays on top when scrolled.

   Visual language — deliberately off-brand: a bright mint-teal
   ground (lighter and more saturated than the dark navy + muted
   teal that the rest of the site speaks in), with each digit
   rendered inside its own dark, near-black square. Sufficient
   vertical padding so the rows breathe. A bold violet CTA on the
   right gives a third high-contrast colour the eye snaps to.

   The banner is HIDDEN by default (the partial sets the `hidden`
   attribute) and revealed once /js/qe-countdown-banner.js has
   confirmed an upcoming batch from /api/batches?page={course}.

   While visible, body.has-qe-countdown pushes the topbar's sticky
   `top` down by the banner height so the two stack cleanly. */

.qe-countdown-banner {
  position: sticky;
  top: 0;
  z-index: 1001;                /* above topbar (1000) and mob-overlay (998) */
  display: block;
  /* 2026-05-12 rev 2: bumped 48 → 64px so the banner has actual visual
     presence instead of reading as a thin label strip. The pulsing
     dot now sits in a roomier row, and the clock pill gets enough
     air for the gold-amber digits to feel like a premium watch face
     rather than cramped text. Aesthetic stays minimal — single soft
     gradient, no decorative texture. */
  background:
    radial-gradient(ellipse 70% 100% at 50% 0%, rgba(255, 255, 255, .12), transparent 65%),
    linear-gradient(90deg, #005a47 0%, #008c70 50%, #005a47 100%);
  border-bottom: 1px solid rgba(0, 0, 0, .15);
  box-shadow: 0 4px 14px -6px rgba(0, 0, 0, .35);
  color: #fff;
  font-family: Poppins, sans-serif;
  height: 64px;
  overflow: hidden;
}

/* Drop the stardust pseudo — minimal redesign moved away from
   decorative texture. Kept the rule with `content: none` so older
   cache copies of this CSS don't accidentally render the dots. */
.qe-countdown-banner::before {
  content: none;
}
.qe-countdown-banner[hidden] { display: none; }

body.has-qe-countdown .topbar { top: 64px; }

/* Center the whole composition on desktop — headline + clock-pill
   sit as a single horizontally-centred row, vertically aligned
   centre (banner is single-line now, no need for top-align tricks).
   The close × is absolutely positioned so it doesn't disrupt the
   centring. */
.qe-countdown-inner {
  max-width: var(--mw, 1200px);
  margin: 0 auto;
  padding: 0 60px 0 28px;      /* right-pad clears the × */
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  font-size: .95rem;
}

/* Dot + label group, kept together as one row item so they stay
   side-by-side even when the banner stacks vertically on mobile. */
.qe-cd-headline {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* Live status dot — white on the brand-teal ground, with a soft
   pulsing white ripple. The pulse is THE attention anchor in the
   minimal layout, so it's kept clean and visible. */
.qe-cd-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  position: relative;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .22);
}
.qe-cd-dot::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  animation: qeCdPulse 2.4s cubic-bezier(.25, 1, .3, 1) infinite;
}
@keyframes qeCdPulse {
  0%   { transform: scale(.55); opacity: .85; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* Label — soft-white regular weight; the batch name (<strong>) pops
   in pure white bold. Reads as "Next [BATCH] Batch Starts in" with
   the batch as the visual anchor before the numbers. */
.qe-cd-label {
  font-weight: 500;
  color: rgba(255, 255, 255, .92);
  font-size: 1.02rem;
  letter-spacing: .005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.qe-cd-label strong { color: #fff; font-weight: 700; }

/* ── The clock — single glass pill containing four "02d : 08h : 34m : 26s"
   segments. 2026-05-12 minimal rev: dropped the 8 individual dark-navy
   digit boxes (heavy, busy) for one soft translucent pill that floats
   the numbers in bold white. The unit labels switch from a separate
   row of "Days/Hours/Minutes/Seconds" beneath the digits to inline
   one-letter suffixes (d/h/m/s) injected via ::after on each block,
   sitting tight against each number pair. ── */
/* 2026-05-12 rev 4: dropped the warm-gold treatment — it clashed
   with the brand teal and read "festive" rather than "premium".
   New look: a deep glass pill (darker dive into the teal ground)
   with a clean white inner highlight + a faint cool-white shimmer
   sweep. The attention now comes from per-digit tick animations
   (see .qe-cd-digit.is-ticking) rather than colour, which is what
   a real countdown should feel like — a thing that responds when
   numbers actually change. */
.qe-cd-numbers {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-variant-numeric: tabular-nums;
  background:
    linear-gradient(180deg, rgba(0, 30, 22, .42), rgba(0, 22, 16, .28));
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: 999px;
  padding: 7px 18px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .12),
    inset 0 -1px 0 rgba(0, 0, 0, .22),
    0 1px 3px rgba(0, 0, 0, .18);
  overflow: hidden;
}
/* Cool-white shimmer — same cadence as before (frequent, slow,
   apparent) but the highlight is white, matching the digit colour
   so the pill reads as one polished glass surface catching light. */
.qe-cd-numbers::after {
  content: '';
  position: absolute;
  top: 0;
  left: -85%;
  width: 75%;
  height: 100%;
  background: linear-gradient(
    105deg,
    transparent 15%,
    rgba(255, 255, 255, .14) 38%,
    rgba(255, 255, 255, .32) 50%,
    rgba(255, 255, 255, .14) 62%,
    transparent 85%
  );
  animation: qeCdShimmer 4.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes qeCdShimmer {
  0%   { transform: translateX(0);     opacity: 0; }
  8%   { opacity: 1; }
  62%  { transform: translateX(220%);  opacity: 1; }
  72%  { transform: translateX(245%);  opacity: 0; }
  100% { transform: translateX(245%);  opacity: 0; }
}

/* One unit (Days, Hours, …) — inline pair of digits + one-letter
   suffix injected via ::after. */
.qe-cd-block {
  display: inline-flex;
  align-items: baseline;
  gap: 0;
  background: transparent;
  border: 0;
  padding: 0 2px;
}
.qe-cd-block::after {
  font-size: .76rem;
  font-weight: 600;
  color: rgba(255, 255, 255, .65);
  margin-left: 3px;
  line-height: 1;
  letter-spacing: .02em;
}
.qe-cd-numbers > .qe-cd-block:nth-child(1)::after { content: 'd'; }
.qe-cd-numbers > .qe-cd-block:nth-child(3)::after { content: 'h'; }
.qe-cd-numbers > .qe-cd-block:nth-child(5)::after { content: 'm'; }
.qe-cd-numbers > .qe-cd-block:nth-child(7)::after { content: 's'; }

.qe-cd-digits {
  display: inline-flex;
  gap: 0;
  align-items: baseline;
}

/* 2026-05-12 rev 4: crisp white digits replace the gold gradient.
   White matches the brand voice (the rest of the banner — label,
   dot, separators — is already white-on-teal) so the timer reads
   as one cohesive piece of UI rather than two competing colour
   families.

   Each digit is a fixed-size inline-block container so the tick
   animation translates one digit cleanly without nudging the
   whole pill layout. The min-width keeps tabular alignment when
   the JS swaps "1" for "0" (different glyph widths in some
   fonts). overflow:hidden on the container scissors the digit
   while it slides in, so the animation reads as "card flip"
   rather than "letter drifting from above the pill". */
.qe-cd-digit {
  display: inline-block;
  min-width: .7em;
  text-align: center;
  padding: 0;
  background: transparent;
  color: #fff;
  border-radius: 0;
  font-weight: 800;
  font-size: 1.2rem;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: 0;
  box-shadow: none;
  overflow: hidden;
  position: relative;
  text-shadow:
    0 0 12px rgba(255, 255, 255, .18),
    0 1px 1px rgba(0, 0, 0, .35);
}

/* Tick animation — fires each time a digit's textContent actually
   changes (qe-countdown-banner.js detects and toggles .is-ticking).
   The new digit slides in from above with a quick ease-out so it
   "snaps" into position. 280ms is long enough to register as
   animation, short enough to never be in the way of the next tick
   (1s gap on seconds; longer for higher units). */
@keyframes qeCdTick {
  0%   { transform: translateY(-72%); opacity: 0; filter: blur(.6px); }
  55%  { opacity: 1; }
  100% { transform: translateY(0);    opacity: 1; filter: blur(0); }
}
.qe-cd-digit.is-ticking {
  animation: qeCdTick .28s cubic-bezier(.22, 1, .36, 1);
}
/* Respect users who'd rather not see motion — keep the digit
   change instantaneous for them. */
@media (prefers-reduced-motion: reduce) {
  .qe-cd-digit.is-ticking { animation: none; }
  .qe-cd-numbers::after   { animation: none; opacity: 0; }
}

/* Hide the old "Days / Hours / Minutes / Seconds" labels — replaced
   by the inline ::after suffixes above. Keeping the HTML so the JS
   contract stays unchanged. */
.qe-cd-block .qe-cd-unit {
  display: none;
}

/* Thin colon separator between unit groups, just enough rhythm. */
.qe-cd-sep {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
  font-size: 1.05rem;
  font-weight: 400;
  color: rgba(255, 255, 255, .35);
  line-height: 1;
}

/* CTA — hidden site-wide. The bottom MCTA bar (mobile) and the
   topbar's nav (desktop) already give users a Call Us / Enroll
   surface, so a third CTA inside the countdown banner cluttered
   the row without adding new value. Markup is kept (.qe-cd-cta is
   still in the partial) so we can re-enable with a single rule
   change if the call pattern shifts. */
.qe-cd-cta {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  gap: 6px;
  height: 23px;
  color: #006b55;
  background: #fff;
  font-weight: 700;
  text-decoration: none;
  padding: 0 12px;
  border-radius: 5px;
  font-size: .74rem;
  letter-spacing: .015em;
  white-space: nowrap;
  transition: transform .2s ease, box-shadow .2s ease, filter .2s ease;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .25);
}
.qe-cd-cta-icon {
  flex: 0 0 auto;
  display: inline-block;
  vertical-align: middle;
}
.qe-cd-cta:hover {
  transform: translateY(-1px);
  filter: brightness(.98);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
  color: #00513f;
}

/* Close × — vertically centred in the slim banner (48px high). The
   previous top:14px was tuned for the old 69px banner with top-aligned
   content; now the whole row is center-aligned so the × matches. */
.qe-cd-close {
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, .12);
  border: 0;
  color: rgba(255, 255, 255, .8);
  cursor: pointer;
  padding: 0;
  width: 24px;
  height: 24px;
  font-size: 1rem;
  line-height: 1;
  border-radius: 50%;
  z-index: 2;
  transition: color .2s, background .2s, transform .2s;
}
.qe-cd-close:hover {
  color: #fff;
  background: rgba(255, 255, 255, .24);
  transform: translateY(-50%) rotate(90deg);
}

/* Mobile — minimal redesign:
     row 1: dot + (possibly wrapped) batch label
     row 2: clock pill (DD : HH : MM : SS with letter suffixes)
   Banner drops from 128px to ~86px since:
     - unit-label row is gone (suffixes are inline)
     - digit boxes are gone (just bold text inside one pill)
     - tighter padding everywhere
   Call Us CTA stays hidden (bottom MCTA bar handles it). × close
   stays anchored top-right. */
@media (max-width: 640px) {
  /* 2026-05-12 rev 2: mobile 86 → 104px (+18px) so the larger gold
     digits and slightly bigger label have room to breathe without
     crowding either row. 104px = ~40px row1 label + 10px gap +
     ~40px row2 clock pill + 14px top/bottom padding. Fits the
     longest "Next BT — Business and Technology Batch Starts in"
     label on 360px screens without clipping. */
  .qe-countdown-banner { height: 104px; }
  body.has-qe-countdown .topbar { top: 104px; }
  .qe-countdown-inner {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 10px;
    padding: 12px 44px;            /* right-pad clears × */
    font-size: .9rem;
  }
  .qe-cd-headline {
    flex-wrap: nowrap;
    justify-content: center;
    text-align: center;
    gap: 8px;
    max-width: 100%;
    min-width: 0;
  }
  .qe-cd-dot { width: 8px; height: 8px; box-shadow: 0 0 0 2px rgba(255, 255, 255, .22); }
  /* Drop the animated halo on mobile — it dominates the small text. */
  .qe-cd-dot::before { display: none; }
  .qe-cd-label {
    white-space: normal;
    font-size: .92rem;
    line-height: 1.3;
    text-align: center;
    min-width: 0;
    flex: 0 1 auto;
  }
  /* Mobile clock pill — same gold/dark glass treatment, just packed
     tighter. Shimmer sweep is kept on mobile since the pill is the
     main element on row 2 and the sweep reinforces it. */
  .qe-cd-numbers {
    gap: 0;
    padding: 6px 14px;
    border-radius: 999px;
  }
  .qe-cd-block { padding: 0 1px; }
  .qe-cd-block::after { font-size: .7rem; margin-left: 2px; }
  .qe-cd-digit { font-size: 1.05rem; }
  .qe-cd-sep { padding: 0 4px; font-size: .95rem; }
  .qe-cd-close {
    top: 8px;
    right: 6px;
    transform: none;
    width: 22px;
    height: 22px;
    font-size: .9rem;
  }
  .qe-cd-close:hover {
    /* Override the desktop translateY hover transform — on mobile
       the × is anchored to a corner, not vertically centred. */
    transform: rotate(90deg);
  }
}

/* In-page anchor jumps (#enroll, #counselling, …) need scroll-padding
   that accounts for both the banner AND the topbar so the target lands
   below them, not behind them. The theme's html { scroll-padding-top: 80px }
   covers the topbar alone; bump on landing pages with an active banner. */
html { scroll-behavior: smooth; }
/* 64px banner + 80px topbar = 144 + 20 breathing buffer = 164px. */
body.has-qe-countdown { scroll-padding-top: 164px; }
@media (max-width: 640px) {
  /* 2026-05-12 rev 2: mobile banner 86 → 104px. Topbar ~54px on
     mobile. 104 + 54 + 20 buffer = 178px. #counselling / #pricing
     anchor jumps land cleanly below both surfaces. */
  body.has-qe-countdown { scroll-padding-top: 178px; }
}


/* =====================================================================
   ACCA Gold Approved Learning Partner — sash divider
   ---------------------------------------------------------------------
   Replaces the plain <hr class="g-divider"> that used to sit between
   the hero and the trust-metrics strip. Now: a gold gradient line
   that runs full-width and fades to transparent at the page edges,
   with the official ACCA Gold Approved Learning Partner badge pinned
   at center — like an award sash with a medal.

   The badge image is /accreditation-logos/acca.webp (the same asset
   used in the home page's "Officially Accredited" row).
   ===================================================================== */
.qe-acca-ribbon {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 32px;
  /* Negative margins pull the ribbon UP into the hero's bottom padding
     and the trust strip UP into the ribbon's bottom — so the line
     literally sits ON the section boundary instead of in its own band
     of dark space. The badge straddles both sections. z-index keeps the
     ribbon visually on top while the surrounding sections stay flush. */
  margin: -50px 0;
  position: relative;
  z-index: 5;
  /* Per-credential colour token. ACCA Gold by default; CFA / FRM
     modifier classes override below. Channels are a comma-separated
     RGB triplet so the rule gradients can vary alpha. */
  --ribbon-color: 197, 165, 90;
}
/* CFA Institute electric blue — sampled from the swirl in
   /accreditation-logos/cfa-prep-logo.png so the gradient sash
   reads cohesively with the mark instead of going dim against
   the dark hero backdrop. The colour is bright at full alpha,
   so CFA-specific gradient overrides below dial the peak
   opacity down to keep the line refined rather than neon. */
.qe-acca-ribbon--cfa { --ribbon-color: 68, 118, 255; }
.qe-acca-ribbon--cfa .qe-acca-ribbon-rule-left {
  background: linear-gradient(
    to right,
    rgba(var(--ribbon-color), 0) 0%,
    rgba(var(--ribbon-color), .15) 40%,
    rgba(var(--ribbon-color), .50) 100%
  );
}
.qe-acca-ribbon--cfa .qe-acca-ribbon-rule-right {
  background: linear-gradient(
    to left,
    rgba(var(--ribbon-color), 0) 0%,
    rgba(var(--ribbon-color), .15) 40%,
    rgba(var(--ribbon-color), .50) 100%
  );
}
/* GARP cyan-blue (distinct from CFA's deeper navy). */
.qe-acca-ribbon--frm { --ribbon-color: 8, 145, 178; }
.qe-acca-ribbon-rule {
  flex: 1 1 0;
  height: 1px;
  /* Three-stop gradient: transparent at the page edge, building to
     full gold strength near the centre where it meets the badge. */
}
.qe-acca-ribbon-rule-left {
  background: linear-gradient(
    to right,
    rgba(var(--ribbon-color), 0) 0%,
    rgba(var(--ribbon-color), .25) 40%,
    rgba(var(--ribbon-color), .85) 100%
  );
}
.qe-acca-ribbon-rule-right {
  background: linear-gradient(
    to left,
    rgba(var(--ribbon-color), 0) 0%,
    rgba(var(--ribbon-color), .25) 40%,
    rgba(var(--ribbon-color), .85) 100%
  );
}
.qe-acca-ribbon-badge {
  flex: 0 0 auto;
  height: 101px;
  width: auto;
  display: block;
  /* Soft gold glow plus a faint dark drop so the badge separates
     from the surrounding gradient line without needing a frame. */
  filter:
    drop-shadow(0 0 14px rgba(197, 165, 90, .25))
    drop-shadow(0 6px 14px rgba(0, 0, 0, .25));
}

@media (max-width: 640px) {
  .qe-acca-ribbon { gap: 14px; padding: 0 16px; margin: -36px 0; }
  .qe-acca-ribbon-badge { height: 72px; }
}

/* Push the trust strip's metric grid down so it doesn't kiss the
   bottom of the sash badge. The ribbon's symmetric negative margins
   leave the badge bisecting the section boundary; this rule just
   gives the metric tiles ~40px of breathing space below the badge. */
.qe-acca-ribbon + section.trust { padding-top: 80px; }
@media (max-width: 640px) {
  .qe-acca-ribbon + section.trust { padding-top: 56px; }
}

/* Horizontal-wordmark variant — used by CFA Institute and GARP/FRM marks
   (partials/cfa-institute-ribbon.html, partials/frm-garp-ribbon.html).
   The base .qe-acca-ribbon assumes a roughly square circular badge (101px
   tall on desktop, sized for the ACCA Gold medal). Horizontal logos at
   that height become 250–400px wide and overwhelm the sash, so this
   modifier shrinks the badge so the wordmark reads naturally on the gold
   gradient line. The negative margin scales with the badge so the gold
   line still bisects the badge at the section boundary.
   Note: the .qe-acca-ribbon class is shared across all credential
   ribbons (ACCA, CFA, FRM) — the "acca" prefix is historical. */
/* Total badge element is 76px tall on desktop (56px mobile) — the
   pill chrome wraps the wordmark. With the inherited `box-sizing:
   border-box`, the height value IS the total: padding shrinks the
   content (image) area to 60px (44px mobile), which is the right
   visual size for the wordmark. The negative margin is half the
   total so the gradient line still bisects the boundary at the
   badge's centre. The 2px box-shadow stroke uses --ribbon-color so
   the pill border matches the gradient sash colour. */
.qe-acca-ribbon--horizontal { margin: -20px 0; }
.qe-acca-ribbon--horizontal .qe-acca-ribbon-badge {
  /* The CFA + FRM marks ship as white-fill PNGs, so they sit
     directly on the dark hero/trust backdrop — no pill chrome.
     A subtle drop shadow gives them lift against the gradient
     sash without competing with the wordmark. */
  height: 40px;
  background: transparent;
  padding: 0;
  border-radius: 0;
  box-shadow: none;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .35));
}
@media (max-width: 640px) {
  .qe-acca-ribbon--horizontal { margin: -15px 0; }
  .qe-acca-ribbon--horizontal .qe-acca-ribbon-badge {
    height: 30px;
  }
}

/* CFA-only override: the CFA Institute mark reads slightly larger
   than the GARP wordmark to match its visual weight. */
.qe-acca-ribbon--cfa.qe-acca-ribbon--horizontal { margin: -25px 0; }
.qe-acca-ribbon--cfa.qe-acca-ribbon--horizontal .qe-acca-ribbon-badge {
  height: 50px;
}
@media (max-width: 640px) {
  .qe-acca-ribbon--cfa.qe-acca-ribbon--horizontal { margin: -19px 0; }
  .qe-acca-ribbon--cfa.qe-acca-ribbon--horizontal .qe-acca-ribbon-badge {
    height: 38px;
  }
}

/* Optional eyebrow label that floats above the pill (e.g. "Affiliated to"
   above the CFA Institute mark). Absolutely positioned so it doesn't
   change the stack's flow height — the gradient line still bisects the
   badge at the section boundary, and the eyebrow text sits in the hero's
   bottom padding above the line. Treatment is serif italic, lowercase,
   soft cream — heritage / museum-label vocabulary, not tracked-out
   newsletter caps. */
.qe-acca-ribbon-stack { position: relative; display: block; line-height: 0; }
.qe-acca-ribbon-eyebrow {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-family: Georgia, "Cormorant Garamond", "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  font-size: .72rem;
  letter-spacing: .01em;
  color: rgba(255, 255, 255, .62);
  white-space: nowrap;
  pointer-events: none;
  line-height: 1;
}
@media (max-width: 640px) {
  .qe-acca-ribbon-eyebrow {
    bottom: 100%;
    font-size: .64rem;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   CFA "Why QuintEdge" — three bespoke feature visuals
   ─────────────────────────────────────────────────────────────────────────
   These three .fvis variants live alongside the existing .fvis-chat /
   .fvis-dash / .fvis-vid stages defined in the per-theme minified CSS.
   Each visual is a standalone "stage" that fills its .fvis container
   (height: 460px on desktop, scaled to 380px on mobile) and tells one
   value-prop story:

     .fvis-copilot  → AI study-companion chat
     .fvis-notes    → in-house note set preview
     .fvis-mockexp  → mock answer-explanation card

   Patterns mirrored from existing fvis stages:
     - aspect-ratio: auto + fixed height (so the visual doesn't shrink
       when the .fcon copy beside it grows tall)
     - z-index: 1 on the inner stage (caption sits at z-index: 3)
     - inset 0 / 6px (depending on whether we have a hard frame)
*/

/* === Block 1 · CFA Co-Pilot — AI chat panel ============================ */
.fvis.fvis-copilot { aspect-ratio: auto; height: 460px; }
.cop-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 16px 48px;
  font-family: Poppins, sans-serif;
  background: linear-gradient(165deg, #0e1f3e 0%, #050a18 55%, #0a1128 100%);
  overflow: hidden;
}
.cop-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 12% 8%, rgba(0,212,170,.18), transparent 38%),
    radial-gradient(circle at 88% 92%, rgba(155,138,255,.14), transparent 42%);
  pointer-events: none;
}
.cop-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding: 4px 6px 12px; margin-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.cop-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem; letter-spacing: .01em;
}
.cop-spark { width: 16px; height: 16px; color: #00f0c5; flex-shrink: 0; }
.cop-status {
  display: inline-flex; align-items: center; gap: 6px;
  color: #8896b3; font-size: .62rem; font-weight: 500;
}
.cop-status i {
  width: 6px; height: 6px; border-radius: 50%;
  background: #00f0c5; box-shadow: 0 0 8px #00f0c5;
  animation: cop-pulse 1.6s ease-in-out infinite;
}
@keyframes cop-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.cop-stream {
  position: relative; z-index: 1;
  flex: 1; overflow: hidden;
  display: flex; flex-direction: column; gap: 12px;
  padding: 4px 2px;
}
.cop-row { display: flex; gap: 8px; opacity: 0; animation: cop-in .5s ease-out forwards; }
.cop-row.cop-u { justify-content: flex-end; }
.cop-row.cop-a { align-items: flex-start; }
.cop-msg-1 { animation-delay: .2s; }
.cop-msg-2 { animation-delay: .8s; }
.cop-msg-3 { animation-delay: 1.6s; }
@keyframes cop-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.cop-av {
  width: 28px; height: 28px; border-radius: 50%;
  background: linear-gradient(135deg, #00d4aa, #9b8aff);
  color: #fff; font-size: .58rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; letter-spacing: .04em;
}
.cop-bub {
  max-width: 78%;
  padding: 10px 14px; border-radius: 12px;
  font-size: .76rem; line-height: 1.55;
  background: rgba(255,255,255,.05);
  color: #e4e9f2;
  border: 1px solid rgba(255,255,255,.06);
}
.cop-row.cop-u .cop-bub {
  background: rgba(0,212,170,.14);
  border-color: rgba(0,212,170,.22);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.cop-bub-ai {
  border-bottom-left-radius: 4px;
  background: rgba(155,138,255,.07);
  border-color: rgba(155,138,255,.18);
}
.cop-bub-ai em {
  font-style: italic; color: #00f0c5; font-weight: 500;
}
.cop-eq {
  margin: 10px 0 8px; padding: 9px 12px;
  background: rgba(0,0,0,.32);
  border: 1px solid rgba(0,240,197,.18);
  border-radius: 6px;
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: .92rem; color: #00f0c5;
  font-style: italic; text-align: center; letter-spacing: .03em;
}
.cop-list {
  display: flex; flex-direction: column; gap: 6px;
  font-size: .7rem; line-height: 1.5;
}
.cop-list span { color: #8896b3; }
.cop-list span b { color: #fff; font-weight: 600; }
.cop-list span em { font-style: italic; color: #00f0c5; }
.cop-typing { padding: 12px 14px; display: inline-flex; align-items: center; }
.cop-dots { display: flex; gap: 4px; }
.cop-dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: #9b8aff;
  animation: cop-dot 1.2s ease-in-out infinite;
}
.cop-dots i:nth-child(2) { animation-delay: .15s; }
.cop-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes cop-dot {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

/* === Block 2 · Unique Notes — premium notebook page ==================== */
.fvis.fvis-notes { aspect-ratio: auto; height: 460px; }
.nts-stage {
  position: absolute; inset: 6px;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 22px 26px 48px;
  background: #fdfbf3;
  border-radius: 6px;
  font-family: Poppins, sans-serif;
  color: #1f2937;
  box-shadow:
    0 0 0 1px rgba(0,0,0,.06),
    inset 0 0 80px rgba(197,165,90,.04);
  background-image:
    repeating-linear-gradient(
      transparent 0,
      transparent 25px,
      rgba(11,26,58,.04) 25px,
      rgba(11,26,58,.04) 26px
    );
  overflow: hidden;
}
.nts-stage::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(135deg, rgba(197,165,90,.08), transparent 40%);
  pointer-events: none;
}
.nts-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: baseline;
  padding-bottom: 8px; margin-bottom: 16px;
  border-bottom: 2px solid rgba(197,165,90,.45);
}
.nts-ttl {
  font-size: .66rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #b08e3e;
}
.nts-page {
  font-size: .68rem; font-style: italic; color: #6b7280;
  font-family: "Cormorant Garamond", Georgia, serif;
}
.nts-body { flex: 1; position: relative; z-index: 1; }
.nts-h {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.45rem; font-weight: 600;
  color: #0b1a3a;
  margin-bottom: 12px;
  display: inline-block;
  border-bottom: 1.5px solid rgba(197,165,90,.45);
  padding-bottom: 2px;
}
.nts-p {
  font-size: .82rem; color: #374151;
  margin-bottom: 16px; line-height: 1.65;
}
.nts-p em {
  background: linear-gradient(transparent 60%, rgba(255,204,102,.55) 60%);
  font-style: normal; font-weight: 600;
  padding: 0 2px; color: #1f2937;
}
.nts-eq {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin: 14px auto 16px;
  padding: 14px 24px;
  background: rgba(11,26,58,.04);
  border-left: 3px solid #b08e3e;
  border-radius: 0 4px 4px 0;
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.5rem; color: #0b1a3a;
}
.nts-eq-v { font-style: italic; }
.nts-eq-eq { font-style: italic; color: #6b7280; }
.nts-frac {
  display: inline-flex; flex-direction: column; align-items: center;
  font-style: italic; line-height: 1.05;
}
.nts-num { border-bottom: 1.5px solid #0b1a3a; padding: 0 10px 2px; }
.nts-den { padding: 4px 10px 0; }
.nts-callout {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 14px;
  background: rgba(197,165,90,.12);
  border-radius: 4px;
  font-size: .76rem; color: #374151; line-height: 1.5;
  margin-bottom: 14px;
}
.nts-callout-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase;
  color: #b08e3e;
  white-space: nowrap; padding-top: 2px;
}
.nts-callout b { color: #0b1a3a; font-weight: 700; }
.nts-tags {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding-top: 4px;
}
.nts-tag {
  font-size: .64rem; font-weight: 600;
  padding: 4px 12px; border-radius: 30px;
  background: #fff;
  border: 1px solid rgba(11,26,58,.14);
  color: #0b1a3a;
}

/* === Block 3 · Mocks With Explanations — answer breakdown card ========= */
.fvis.fvis-mockexp { aspect-ratio: auto; height: 460px; }
.mxp-stage {
  position: absolute; inset: 6px;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  background: #fdfdfe;
  border-radius: 12px;
  color: #0b1020;
  box-shadow: 0 0 0 1px rgba(15,23,42,.07);
  overflow: hidden;
}
.mxp-hdr {
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid rgba(15,23,42,.08);
}
.mxp-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #475569;
}
.mxp-meter {
  font-size: .65rem; color: #475569; font-weight: 500;
}
.mxp-meter b { color: #00a886; font-weight: 700; }
.mxp-q {
  font-size: .8rem; line-height: 1.55;
  color: #0b1020; font-weight: 500;
  margin-bottom: 12px;
  padding: 4px 0 4px 12px;
  border-left: 2px solid #475569;
}
.mxp-opts {
  display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 12px;
}
.mxp-opt {
  display: grid;
  grid-template-columns: 22px 90px 22px 1fr;
  align-items: center; gap: 10px;
  padding: 8px 12px;
  border: 1px solid rgba(15,23,42,.08);
  border-radius: 6px;
  font-size: .72rem;
  background: #fff;
  transition: all .3s ease;
}
.mxp-opt-correct {
  background: linear-gradient(90deg, rgba(0,168,134,.08), rgba(0,168,134,.03));
  border-color: rgba(0,168,134,.32);
  box-shadow: 0 0 0 1px rgba(0,168,134,.12);
}
.mxp-opt-l {
  width: 22px; height: 22px; border-radius: 50%;
  background: rgba(15,23,42,.08);
  color: #475569; font-size: .65rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.mxp-opt-correct .mxp-opt-l {
  background: #00a886; color: #fff;
}
.mxp-opt-t { color: #1e293b; font-weight: 600; font-size: .76rem; }
.mxp-opt-correct .mxp-opt-t { color: #00754e; }
.mxp-opt-mark {
  width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: .68rem; font-weight: 700;
}
.mxp-opt-mark.mxp-c {
  background: #00a886; color: #fff;
}
.mxp-opt-mark.mxp-x {
  background: rgba(220,38,38,.1); color: #dc2626;
}
.mxp-opt-why {
  color: #475569; font-size: .68rem; line-height: 1.45;
  font-style: italic;
}
.mxp-opt-correct .mxp-opt-why { color: #0b6e4f; font-style: normal; font-weight: 500; }
.mxp-opt-why em {
  font-style: normal; font-weight: 700; color: inherit;
  background: rgba(255,204,102,.45); padding: 0 4px; border-radius: 2px;
}
.mxp-opt-why i { font-style: italic; color: #475569; }
.mxp-foot {
  margin-top: auto;
  display: flex; justify-content: space-between; align-items: center;
  padding-top: 10px;
  border-top: 1px dashed rgba(15,23,42,.16);
  font-size: .65rem;
}
.mxp-foot-l {
  color: #475569; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
}
.mxp-foot-r {
  color: #1e293b; font-weight: 700;
}

/* === Block 4 · Score Forecast — exam-score prediction terminal ========= */
.fvis.fvis-forecast { aspect-ratio: auto; height: 460px; }
.fcst-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  background: linear-gradient(180deg, #0d1a36 0%, #050a18 65%);
  color: #e4e9f2;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
.fcst-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 88% 6%, rgba(0,212,170,.16), transparent 38%),
    radial-gradient(circle at 4% 92%, rgba(155,138,255,.12), transparent 50%);
  pointer-events: none;
}
.fcst-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.fcst-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem; letter-spacing: .01em;
}
.fcst-spark { width: 16px; height: 16px; color: #00f0c5; flex-shrink: 0; }
.fcst-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #8896b3;
  padding: 3px 8px; border-radius: 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
}
.fcst-hero {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding: 6px 4px 14px;
  border-bottom: 1px dashed rgba(255,255,255,.08);
  margin-bottom: 12px;
}
.fcst-hero-l { display: flex; flex-direction: column; gap: 4px; }
.fcst-hero-lbl {
  font-size: .62rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: #8896b3;
}
.fcst-hero-num {
  display: flex; align-items: baseline; gap: 4px;
  line-height: 1;
}
.fcst-num {
  font-size: 2.4rem; font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, #00f0c5, #9b8aff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -.02em;
}
.fcst-pct { font-size: 1rem; color: #8896b3; font-weight: 600; }
.fcst-pm {
  font-size: .72rem; color: #00f0c5; font-weight: 600;
  margin-left: 6px;
  padding: 2px 8px; border-radius: 30px;
  background: rgba(0,240,197,.1);
  border: 1px solid rgba(0,240,197,.22);
  letter-spacing: .02em;
}
.fcst-hero-meta {
  font-size: .64rem; color: #56627a; font-weight: 500;
}
.fcst-hero-r { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.fcst-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 30px;
  background: linear-gradient(135deg, rgba(0,212,170,.18), rgba(0,240,197,.1));
  border: 1px solid rgba(0,240,197,.4);
  color: #00f0c5; font-weight: 700;
  font-size: .76rem; letter-spacing: .14em;
}
.fcst-badge svg { width: 12px; height: 12px; }
.fcst-badge-sub {
  font-size: .58rem; color: #56627a; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
}

.fcst-curve {
  position: relative; z-index: 1;
  flex: 1;
  display: flex; flex-direction: column;
  margin-bottom: 10px;
}
.fcst-curve-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 6px;
}
.fcst-curve-hd > span:first-child {
  font-size: .68rem; font-weight: 600; color: #e4e9f2; letter-spacing: .04em;
}
.fcst-curve-sub {
  font-size: .58rem; color: #56627a; font-weight: 500; font-style: italic;
}
.fcst-curve-svg {
  width: 100%; flex: 1; min-height: 90px;
  overflow: visible;
}
.fcst-base { stroke: rgba(255,255,255,.12); stroke-width: 1; }
.fcst-curve-line { stroke: #00f0c5; stroke-width: 1.6; opacity: .85; }
.fcst-mps { stroke: #ff6b6b; stroke-width: 1.4; opacity: .75; }
.fcst-mps-lbl { font-size: 6px; fill: #ff6b6b; font-weight: 700; letter-spacing: .04em; }
.fcst-pred { stroke: #00f0c5; stroke-width: 1.4; opacity: .9; }
.fcst-pred-halo { fill: #00f0c5; opacity: .3; animation: fcst-halo 1.6s ease-in-out infinite; }
.fcst-pred-dot { fill: #00f0c5; }
.fcst-pred-lbl { font-size: 7px; fill: #00f0c5; font-weight: 700; }
.fcst-axis-lbl { font-size: 6px; fill: #56627a; font-weight: 600; }
@keyframes fcst-halo {
  0%, 100% { opacity: .3; r: 6; }
  50% { opacity: .15; r: 9; }
}

.fcst-trend {
  position: relative; z-index: 1;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.07);
}
.fcst-trend-lbl {
  display: block;
  font-size: .58rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #56627a;
  margin-bottom: 8px;
}
.fcst-trend-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr) auto;
  align-items: end; gap: 6px;
}
.fcst-mock {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 4px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 4px;
}
.fcst-mock-cur {
  background: linear-gradient(180deg, rgba(0,240,197,.14), rgba(0,240,197,.04));
  border-color: rgba(0,240,197,.32);
  box-shadow: 0 0 12px rgba(0,240,197,.15);
}
.fm-l {
  font-size: .56rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: #56627a;
}
.fcst-mock-cur .fm-l { color: #00f0c5; }
.fm-v {
  font-size: .88rem; font-weight: 700; color: #e4e9f2;
}
.fcst-mock-cur .fm-v { color: #fff; }
.fcst-trend-arrow {
  align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  padding-left: 4px;
  font-size: .82rem; color: #00f0c5;
  font-weight: 700;
}

/* Mobile sizing — match the existing chat-stage / dash-stage breakpoint
   so all 5 visuals shrink together. */
@media (max-width: 640px) {
  .fvis.fvis-copilot,
  .fvis.fvis-notes,
  .fvis.fvis-mockexp,
  .fvis.fvis-forecast { height: 420px; }
  .cop-stage { padding: 12px 12px 44px; }
  .cop-bub { font-size: .72rem; padding: 8px 12px; }
  .cop-eq { font-size: .82rem; padding: 7px 10px; }
  .cop-list { font-size: .66rem; }
  .nts-stage { padding: 18px 18px 44px; }
  .nts-h { font-size: 1.25rem; }
  .nts-p { font-size: .76rem; margin-bottom: 12px; }
  .nts-eq { font-size: 1.25rem; padding: 12px 16px; margin: 10px auto 12px; }
  .nts-callout { font-size: .7rem; padding: 8px 12px; }
  .mxp-stage { padding: 14px 14px 44px; }
  .mxp-q { font-size: .76rem; }
  .mxp-opt {
    grid-template-columns: 20px 88px 20px 1fr;
    gap: 8px; padding: 7px 8px;
  }
  .mxp-opt-t { font-size: .68rem; line-height: 1.2; }
  .mxp-opt-why { font-size: .64rem; line-height: 1.4; }
  .fcst-stage { padding: 12px 14px 44px; }
  .fcst-num { font-size: 2rem; }
  .fcst-badge { font-size: .68rem; padding: 5px 11px; letter-spacing: .12em; }
  .fcst-curve-svg { min-height: 78px; }
  .fcst-mock { padding: 5px 2px; }
  .fm-v { font-size: .78rem; }
  .fm-l { font-size: .54rem; }
  .fcst-trend-arrow { font-size: .72rem; }
}

/* ─────────────────────────────────────────────────────────────────────────
   FRM "Why QuintEdge" — bespoke Pass Forecast (quartile stack)
   ─────────────────────────────────────────────────────────────────────────
   Visually distinct from the CFA bell-curve forecast: FRM is graded by
   quartile (Q1-Q4), so the surface here is a stacked-probability view
   across the four quartile outcomes plus a per-mock quartile trajectory.
   Cyan/teal-blue accents keep it differentiated from CFA's mint-teal.
*/
.fvis.fvis-frm-forecast { aspect-ratio: auto; height: 460px; }
.frmf-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  background: linear-gradient(180deg, #08182d 0%, #050a18 65%);
  color: #e4e9f2;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
.frmf-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 92% 4%, rgba(34,211,238,.16), transparent 38%),
    radial-gradient(circle at 6% 94%, rgba(8,145,178,.16), transparent 50%);
  pointer-events: none;
}
.frmf-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.frmf-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem;
}
.frmf-spark { width: 16px; height: 16px; color: #22d3ee; flex-shrink: 0; }
.frmf-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #94a3b8;
  padding: 3px 8px; border-radius: 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
}
.frmf-hero {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding: 4px 4px 14px;
  border-bottom: 1px dashed rgba(255,255,255,.08);
  margin-bottom: 14px;
}
.frmf-hero-l { display: flex; flex-direction: column; gap: 6px; }
.frmf-hero-lbl {
  font-size: .62rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: #94a3b8;
}
.frmf-hero-row { display: flex; align-items: center; gap: 14px; }
.frmf-q-badge {
  display: inline-flex; align-items: baseline;
  padding: 6px 14px;
  background: linear-gradient(135deg, rgba(34,211,238,.18), rgba(8,145,178,.12));
  border: 1.5px solid rgba(34,211,238,.5);
  border-radius: 10px;
  box-shadow: 0 0 16px rgba(34,211,238,.18);
}
.frmf-q-letter {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.5rem; font-weight: 600; color: #e0f2fe;
  font-style: italic;
}
.frmf-q-num {
  font-size: 2rem; font-weight: 700; color: #22d3ee;
  margin-left: 2px; line-height: 1;
}
.frmf-q-meta { display: flex; flex-direction: column; gap: 2px; }
.frmf-q-rank {
  font-size: .76rem; font-weight: 700; color: #67e8f9;
  letter-spacing: .08em;
}
.frmf-q-delta {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .64rem; color: #94a3b8; font-weight: 500;
}
.frmf-q-delta svg { width: 7px; height: 7px; color: #22d3ee; }
.frmf-hero-r {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
}
.frmf-pass {
  font-size: 1.7rem; font-weight: 700;
  background: linear-gradient(135deg, #22d3ee, #67e8f9);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  line-height: 1; letter-spacing: -.02em;
}
.frmf-pass-pct { font-size: .9rem; color: #94a3b8; margin-left: 2px; }
.frmf-pass-lbl {
  font-size: .6rem; font-weight: 600; letter-spacing: .04em;
  color: #94a3b8;
}

.frmf-stack {
  position: relative; z-index: 1;
  flex: 1;
  display: flex; flex-direction: column;
  margin-bottom: 10px;
}
.frmf-stack-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 8px;
}
.frmf-stack-hd > span:first-child {
  font-size: .68rem; font-weight: 600; color: #e4e9f2; letter-spacing: .04em;
}
.frmf-stack-sub {
  font-size: .58rem; color: #56627a; font-style: italic; font-weight: 500;
}
.frmf-stack-rows { display: flex; flex-direction: column; gap: 5px; }
.frmf-row {
  display: grid;
  grid-template-columns: 24px 1fr 38px 110px;
  align-items: center; gap: 10px;
  padding: 4px 6px;
  border-radius: 4px;
}
.frmf-row-l {
  font-size: .68rem; font-weight: 700; color: #94a3b8;
  letter-spacing: .04em;
}
.frmf-bar-wrap {
  height: 7px; border-radius: 4px;
  background: rgba(255,255,255,.04);
  overflow: hidden;
}
.frmf-bar {
  height: 100%; border-radius: 4px;
  transition: width .8s cubic-bezier(.4,0,.2,1);
}
.frmf-row--q4 .frmf-bar { background: linear-gradient(90deg, rgba(255,107,107,.5), rgba(255,107,107,.7)); }
.frmf-row--q3 .frmf-bar { background: linear-gradient(90deg, rgba(255,107,107,.35), rgba(255,107,107,.55)); }
.frmf-row--q2 .frmf-bar { background: linear-gradient(90deg, rgba(34,211,238,.45), rgba(34,211,238,.7)); }
.frmf-row--q1 .frmf-bar { background: linear-gradient(90deg, rgba(34,211,238,.7), rgba(103,232,249,.95)); }
.frmf-row-v {
  font-size: .76rem; font-weight: 700; color: #fff;
  text-align: right;
}
.frmf-row-tag {
  font-size: .58rem; font-weight: 600; letter-spacing: .04em;
  color: #56627a; text-align: right;
}
.frmf-row--q4 .frmf-row-tag,
.frmf-row--q3 .frmf-row-tag { color: #fda4af; }
.frmf-row--q2 .frmf-row-tag { color: #67e8f9; }
.frmf-row--q1 .frmf-row-tag { color: #22d3ee; font-weight: 700; }
.frmf-row--cur {
  background: linear-gradient(90deg, rgba(34,211,238,.08), transparent 70%);
  box-shadow: inset 2px 0 0 #22d3ee;
}
.frmf-row--cur .frmf-row-l { color: #22d3ee; }

.frmf-trend {
  position: relative; z-index: 1;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.07);
}
.frmf-trend-lbl {
  display: block;
  font-size: .58rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #56627a;
  margin-bottom: 8px;
}
.frmf-trend-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr) auto;
  align-items: end; gap: 6px;
}
.frmf-mock {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 4px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 4px;
}
.frmf-mock-cur {
  background: linear-gradient(180deg, rgba(34,211,238,.16), rgba(34,211,238,.04));
  border-color: rgba(34,211,238,.36);
  box-shadow: 0 0 12px rgba(34,211,238,.18);
}
.fmm-l {
  font-size: .56rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: #56627a;
}
.frmf-mock-cur .fmm-l { color: #22d3ee; }
.fmm-v { font-size: .88rem; font-weight: 700; color: #e4e9f2; }
.frmf-mock-cur .fmm-v { color: #fff; }
.fmm-q {
  font-size: .55rem; font-weight: 700; letter-spacing: .04em;
  color: #94a3b8;
}
.frmf-mock-cur .fmm-q { color: #67e8f9; }
.frmf-trend-arrow {
  align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  padding-left: 4px;
  font-size: .82rem; color: #22d3ee; font-weight: 700;
}

/* ─────────────────────────────────────────────────────────────────────────
   ACCA "Why QuintEdge" — bespoke Pass Forecast (MPS proximity meter)
   ─────────────────────────────────────────────────────────────────────────
   ACCA exams are graded 0-100 with a binary 50% pass mark. The visual is
   a horizontal pass-mark proximity meter showing the predicted mark, the
   MPS line, and the safety margin above it — distinct from the CFA bell
   curve and the FRM quartile stack. Gold accents tie it back to the
   ACCA Gold Approved Learning Partner brand.
*/
.fvis.fvis-acca-forecast { aspect-ratio: auto; height: 460px; }
.accaf-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  /* Navy background matches CFA/FRM forecast family — gold lives in the
     accents, not the canvas, so it reads as "premium heritage gold"
     instead of a separate brown-tinted world. */
  background: linear-gradient(180deg, #0e1a2e 0%, #050a18 65%);
  color: #e4e9f2;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
.accaf-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 92% 4%, rgba(255,204,102,.12), transparent 38%),
    radial-gradient(circle at 6% 94%, rgba(197,165,90,.1), transparent 50%);
  pointer-events: none;
}
.accaf-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.accaf-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem;
}
.accaf-spark { width: 16px; height: 16px; color: #ffcc66; flex-shrink: 0; }
.accaf-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #94a3b8;
  padding: 3px 8px; border-radius: 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
}
.accaf-hero {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding: 4px 4px 14px;
  border-bottom: 1px dashed rgba(255,255,255,.08);
  margin-bottom: 14px;
}
.accaf-hero-l { display: flex; flex-direction: column; gap: 4px; }
.accaf-hero-lbl {
  font-size: .62rem; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: #94a3b8;
}
.accaf-hero-row { display: flex; align-items: baseline; gap: 14px; }
.accaf-mark {
  display: inline-flex; align-items: baseline; gap: 4px;
  line-height: 1;
}
.accaf-num {
  font-size: 2.4rem; font-weight: 700;
  background: linear-gradient(135deg, #ffcc66, #c5a55a);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -.02em;
}
.accaf-of { font-size: .9rem; color: #94a3b8; font-weight: 500; }
.accaf-margin {
  display: inline-flex; flex-direction: column; align-items: center;
  padding: 4px 10px; border-radius: 4px;
  background: rgba(255,204,102,.1);
  border: 1px solid rgba(255,204,102,.28);
}
.accaf-margin-v {
  font-size: .9rem; font-weight: 700; color: #ffcc66; line-height: 1;
}
.accaf-margin-l {
  font-size: .54rem; color: #94a3b8; font-weight: 600;
  letter-spacing: .04em; margin-top: 2px;
}
.accaf-hero-meta {
  font-size: .62rem; color: #56627a; font-weight: 500;
}
.accaf-hero-r { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.accaf-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 30px;
  background: linear-gradient(135deg, rgba(255,204,102,.18), rgba(197,165,90,.1));
  border: 1px solid rgba(255,204,102,.45);
  color: #ffcc66; font-weight: 700;
  font-size: .76rem; letter-spacing: .14em;
}
.accaf-badge svg { width: 12px; height: 12px; }
.accaf-badge-sub {
  font-size: .58rem; color: #56627a; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
}

.accaf-meter {
  position: relative; z-index: 1;
  flex: 1;
  display: flex; flex-direction: column;
  margin-bottom: 12px;
}
.accaf-meter-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 12px;
}
.accaf-meter-hd > span:first-child {
  font-size: .68rem; font-weight: 600; color: #e4e9f2; letter-spacing: .04em;
}
.accaf-meter-sub {
  font-size: .58rem; color: #56627a; font-style: italic; font-weight: 500;
}
.accaf-meter-bar {
  position: relative;
  height: 36px; border-radius: 6px;
  display: flex;
  overflow: visible;
  margin-bottom: 8px;
}
.accaf-fail {
  width: 50%;
  background: linear-gradient(90deg, rgba(255,107,107,.32), rgba(255,107,107,.16));
  border-radius: 6px 0 0 6px;
}
.accaf-pass {
  width: 50%;
  background: linear-gradient(90deg, rgba(255,204,102,.14), rgba(255,204,102,.4));
  border-radius: 0 6px 6px 0;
}
.accaf-mps {
  position: absolute; left: 50%; top: -8px; bottom: -8px;
  display: flex; flex-direction: column; align-items: center;
  pointer-events: none;
}
.accaf-mps-line {
  width: 2px; flex: 1;
  background: linear-gradient(180deg, #94a3b8, transparent);
  opacity: .65;
}
.accaf-mps-lbl {
  position: absolute; top: -4px;
  font-size: .56rem; font-weight: 700; letter-spacing: .06em;
  color: #94a3b8; white-space: nowrap;
  transform: translateX(-50%);
  background: #050a18;
  padding: 0 4px;
}
.accaf-margin-band {
  position: absolute; top: 4px; bottom: 4px;
  background: linear-gradient(90deg, rgba(255,204,102,.32), rgba(255,204,102,.18));
  border-left: 1px dashed rgba(255,204,102,.55);
  border-radius: 0;
  pointer-events: none;
}
.accaf-cur {
  position: absolute; top: -16px; bottom: -16px;
  display: flex; flex-direction: column; align-items: center;
  transform: translateX(-50%);
  pointer-events: none;
}
.accaf-cur-dot {
  width: 12px; height: 12px; border-radius: 50%;
  background: #ffcc66;
  box-shadow: 0 0 12px rgba(255,204,102,.7), 0 0 0 3px rgba(255,204,102,.18);
  margin-top: 18px; margin-bottom: 4px;
  animation: accaf-pulse 1.8s ease-in-out infinite;
}
@keyframes accaf-pulse {
  0%, 100% { box-shadow: 0 0 12px rgba(255,204,102,.7), 0 0 0 3px rgba(255,204,102,.18); }
  50% { box-shadow: 0 0 18px rgba(255,204,102,.85), 0 0 0 6px rgba(255,204,102,.1); }
}
.accaf-cur-lbl {
  font-size: .6rem; font-weight: 700; letter-spacing: .04em;
  color: #ffcc66;
  background: rgba(255,204,102,.08);
  padding: 2px 8px; border-radius: 30px;
  border: 1px solid rgba(255,204,102,.32);
  white-space: nowrap;
  margin-top: 4px;
}
.accaf-axis {
  display: flex; justify-content: space-between;
  font-size: .58rem; font-weight: 600;
  color: #56627a; letter-spacing: .04em;
  padding: 0 2px;
}
.accaf-axis-mps { color: #94a3b8; font-weight: 700; }

.accaf-trend {
  position: relative; z-index: 1;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.07);
}
.accaf-trend-lbl {
  display: block;
  font-size: .58rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #56627a;
  margin-bottom: 8px;
}
.accaf-trend-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr) auto;
  align-items: end; gap: 6px;
}
.accaf-mock {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 4px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 4px;
}
.accaf-mock--fail {
  background: rgba(255,107,107,.05);
  border-color: rgba(255,107,107,.18);
}
.accaf-mock--pass {
  background: rgba(255,204,102,.05);
  border-color: rgba(255,204,102,.18);
}
.accaf-mock-cur {
  background: linear-gradient(180deg, rgba(255,204,102,.18), rgba(255,204,102,.04)) !important;
  border-color: rgba(255,204,102,.4) !important;
  box-shadow: 0 0 12px rgba(255,204,102,.18);
}
.amm-l {
  font-size: .56rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: #56627a;
}
.accaf-mock-cur .amm-l { color: #ffcc66; }
.amm-v { font-size: .88rem; font-weight: 700; color: #e4e9f2; }
.accaf-mock-cur .amm-v { color: #fff; }
.amm-tag {
  font-size: .54rem; font-weight: 700; letter-spacing: .04em;
  color: #94a3b8;
}
.accaf-mock--fail .amm-tag { color: #fda4af; }
.accaf-mock--pass .amm-tag { color: #ffcc66; }
.accaf-trend-arrow {
  align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  padding-left: 4px;
  font-size: .82rem; color: #ffcc66; font-weight: 700;
}

/* Mobile sizing for FRM + ACCA forecasts */
@media (max-width: 640px) {
  .fvis.fvis-frm-forecast,
  .fvis.fvis-acca-forecast { height: 460px; }
  .frmf-stage,
  .accaf-stage { padding: 12px 14px 44px; }
  .frmf-q-num { font-size: 1.7rem; }
  .frmf-q-letter { font-size: 1.25rem; }
  .frmf-pass { font-size: 1.4rem; }
  .frmf-row { grid-template-columns: 22px 1fr 32px 86px; gap: 8px; }
  .frmf-row-tag { font-size: .54rem; }
  .accaf-num { font-size: 2rem; }
  .accaf-margin-v { font-size: .82rem; }
  .accaf-meter-bar { height: 30px; }
  .accaf-cur-dot { width: 10px; height: 10px; margin-top: 14px; }
  .accaf-cur-lbl { font-size: .56rem; padding: 1px 6px; }
  .accaf-mps-lbl { font-size: .52rem; }
}

/* ─────────────────────────────────────────────────────────────────────────
   FM "Why QuintEdge" — bespoke Build Forecast (multi-dimensional scorecard)
   ─────────────────────────────────────────────────────────────────────────
   FM mock tests are timed model-build exercises — not multiple-choice. So
   the surface here is a scorecard across four dimensions (build time,
   model ties, structure, audit trail) plus a per-mock letter-grade
   trajectory. Lavender accents make it visually distinct from CFA mint,
   FRM cyan, and ACCA gold.
*/
.fvis.fvis-fm-forecast { aspect-ratio: auto; height: 460px; }
.fmf-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  background: linear-gradient(180deg, #181333 0%, #050a18 65%);
  color: #e4e9f2;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
.fmf-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 92% 4%, rgba(155,138,255,.18), transparent 40%),
    radial-gradient(circle at 6% 94%, rgba(167,139,250,.12), transparent 50%);
  pointer-events: none;
}
.fmf-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.fmf-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem;
}
.fmf-spark { width: 16px; height: 16px; color: #a78bfa; flex-shrink: 0; }
.fmf-tag {
  font-size: .6rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #94a3b8;
  padding: 3px 8px; border-radius: 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
}
/* Hero is a 3-column grid (badge | meta | rate) so widths are predictable
   and elements never collide. The right-side rate is separated by a soft
   left rule so it reads as a distinct stat, not a competing title. */
.fmf-hero {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center; gap: 16px;
  padding: 8px 4px 18px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  margin-bottom: 18px;
}
.fmf-hero-lbl {
  font-size: .6rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #94a3b8;
  grid-column: 1 / -1;
  margin-bottom: -8px;
}
.fmf-grade-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 64px; height: 64px;
  background: linear-gradient(135deg, rgba(167,139,250,.2), rgba(155,138,255,.08));
  border: 1.5px solid rgba(167,139,250,.5);
  border-radius: 14px;
  box-shadow: 0 0 20px rgba(155,138,255,.18);
}
.fmf-grade {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 2.4rem; font-weight: 600;
  color: #c4b5fd;
  font-style: italic; line-height: 1;
  letter-spacing: -.02em;
}
.fmf-grade-meta {
  display: flex; flex-direction: column; gap: 5px;
  min-width: 0;
}
.fmf-grade-rank {
  font-size: .8rem; font-weight: 700; color: #c4b5fd;
  letter-spacing: .06em;
  white-space: nowrap;
}
.fmf-grade-delta {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .66rem; color: #94a3b8; font-weight: 500;
}
.fmf-grade-delta svg { width: 8px; height: 8px; color: #a78bfa; flex-shrink: 0; }
.fmf-hero-r {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 4px; text-align: right;
  padding-left: 14px;
  border-left: 1px solid rgba(255,255,255,.08);
}
.fmf-rate {
  font-size: 1.75rem; font-weight: 700;
  background: linear-gradient(135deg, #a78bfa, #c4b5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  line-height: 1; letter-spacing: -.02em;
}
.fmf-rate-pct { font-size: .95rem; color: #94a3b8; margin-left: 2px; }
.fmf-rate-lbl {
  font-size: .58rem; font-weight: 600; letter-spacing: .04em;
  color: #94a3b8;
  max-width: 110px; line-height: 1.35;
}

.fmf-card {
  position: relative; z-index: 1;
  flex: 1;
  display: flex; flex-direction: column;
  margin-bottom: 12px;
}
.fmf-card-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 10px;
}
.fmf-card-hd > span:first-child {
  font-size: .68rem; font-weight: 600; color: #e4e9f2; letter-spacing: .04em;
}
.fmf-card-sub {
  font-size: .58rem; color: #56627a; font-style: italic; font-weight: 500;
}
.fmf-card-rows {
  display: flex; flex-direction: column; gap: 2px;
  background: rgba(255,255,255,.02);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 8px;
  padding: 6px 4px;
}
.fmf-row {
  display: grid;
  grid-template-columns: 96px 1fr 42px 36px;
  align-items: center; gap: 12px;
  padding: 8px 10px;
  border-radius: 5px;
}
.fmf-row + .fmf-row {
  border-top: 1px solid rgba(255,255,255,.04);
}
.fmf-row-l {
  font-size: .7rem; font-weight: 600; color: #c4b5fd;
  letter-spacing: .01em;
}
.fmf-bar-wrap {
  height: 8px; border-radius: 4px;
  background: rgba(255,255,255,.05);
  overflow: hidden;
}
.fmf-bar {
  height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, rgba(167,139,250,.6), rgba(196,181,253,.95));
  transition: width .8s cubic-bezier(.4,0,.2,1);
}
.fmf-bar--mid {
  background: linear-gradient(90deg, rgba(155,138,255,.4), rgba(155,138,255,.72));
}
.fmf-row-v {
  font-size: .76rem; font-weight: 700; color: #fff;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.fmf-row-grade {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.15rem; font-weight: 600; font-style: italic;
  color: #c4b5fd; text-align: center; line-height: 1;
  letter-spacing: -.02em;
}
.fmf-row-grade--top { color: #a78bfa; }
.fmf-row-grade--mid { color: #94a3b8; }

.fmf-trend {
  position: relative; z-index: 1;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.07);
}
.fmf-trend-lbl {
  display: block;
  font-size: .58rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: #56627a;
  margin-bottom: 8px;
}
.fmf-trend-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr) auto;
  align-items: end; gap: 6px;
}
.fmf-mock {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 4px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 4px;
}
.fmf-mock-cur {
  background: linear-gradient(180deg, rgba(167,139,250,.18), rgba(167,139,250,.04));
  border-color: rgba(167,139,250,.4);
  box-shadow: 0 0 12px rgba(167,139,250,.18);
}
.fmf-mock .fmm-l {
  font-size: .56rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: #56627a;
}
.fmf-mock-cur .fmm-l { color: #a78bfa; }
.fmf-mock .fmm-v { font-size: .82rem; font-weight: 700; color: #e4e9f2; }
.fmf-mock-cur .fmm-v { color: #fff; }
.fmm-g {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: .9rem; font-weight: 600; font-style: italic;
  line-height: 1;
}
.fmm-g--c { color: #94a3b8; }
.fmm-g--b { color: #c4b5fd; }
.fmm-g--a { color: #a78bfa; }
.fmf-trend-arrow {
  align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  padding-left: 4px;
  font-size: .82rem; color: #a78bfa; font-weight: 700;
}

@media (max-width: 640px) {
  .fvis.fvis-fm-forecast { height: 480px; }
  .fmf-stage { padding: 14px 16px 44px; }
  /* Mobile hero: 2-row stack — badge+meta on row 1, rate on row 2,
     so the place-rate stat doesn't crash into the rank text. */
  .fmf-hero {
    grid-template-columns: auto 1fr;
    gap: 12px 14px;
    padding: 6px 2px 16px;
  }
  .fmf-hero-r {
    grid-column: 1 / -1;
    flex-direction: row; align-items: baseline;
    justify-content: flex-start;
    padding-left: 0; padding-top: 10px;
    border-left: none;
    border-top: 1px solid rgba(255,255,255,.06);
    gap: 10px; text-align: left;
  }
  .fmf-rate-lbl { max-width: none; flex: 1; }
  .fmf-grade-badge { width: 56px; height: 56px; border-radius: 12px; }
  .fmf-grade { font-size: 2rem; }
  .fmf-grade-rank { font-size: .72rem; }
  .fmf-grade-delta { font-size: .62rem; }
  .fmf-rate { font-size: 1.45rem; }
  .fmf-row { grid-template-columns: 80px 1fr 36px 30px; gap: 10px; padding: 7px 8px; }
  .fmf-row-l { font-size: .64rem; }
  .fmf-row-grade { font-size: 1rem; }
  .fmm-g { font-size: .82rem; }
}

/* ─────────────────────────────────────────────────────────────────────────
   FM "Why QuintEdge" — bespoke Placement Portal (live job feed + outcome stats)
   ─────────────────────────────────────────────────────────────────────────
   FM is sold on placement, not on test scores — the dashboard surfaces the
   placement promise directly: live openings at name-brand IB/PE/ER firms,
   exclusivity tag, freshness, and bottom-line outcome stats. Lavender
   accents tie it back to the FM page palette set by the Co-Pilot block.
*/
.fvis.fvis-fm-portal { aspect-ratio: auto; height: 540px; }
.fmp-stage {
  position: absolute; inset: 0;
  z-index: 1;
  display: flex; flex-direction: column;
  padding: 16px 18px 48px;
  font-family: Poppins, sans-serif;
  background: linear-gradient(180deg, #181333 0%, #050a18 65%);
  color: #e4e9f2;
  overflow: hidden;
}
.fmp-stage::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 92% 4%, rgba(155,138,255,.16), transparent 40%),
    radial-gradient(circle at 6% 94%, rgba(167,139,250,.1), transparent 50%);
  pointer-events: none;
}
.fmp-hdr {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center;
  padding-bottom: 10px; margin-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.fmp-ttl {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; font-weight: 600; font-size: .82rem;
}
.fmp-spark { width: 16px; height: 16px; color: #a78bfa; flex-shrink: 0; }
/* QuintEdge brand mark inside the portal header — small white pill so the
   dark Q logo has contrast against the navy stage, mirroring the same
   white-pill treatment used for the firm favicons in the job feed. */
.fmp-brand {
  width: 22px; height: 22px; border-radius: 5px;
  background: #fff;
  padding: 3px;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(255,255,255,.1);
}
.fmp-brand img {
  width: 100%; height: 100%; object-fit: contain; display: block;
}
.fmp-live {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .62rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #c4b5fd;
  padding: 3px 10px; border-radius: 30px;
  background: rgba(167,139,250,.1);
  border: 1px solid rgba(167,139,250,.28);
}
.fmp-live i {
  width: 6px; height: 6px; border-radius: 50%;
  background: #a78bfa;
  box-shadow: 0 0 8px #a78bfa;
  animation: fmp-live-pulse 1.6s ease-in-out infinite;
}
@keyframes fmp-live-pulse { 0%,100%{opacity:1;} 50%{opacity:.4;} }
.fmp-feed-hd {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 8px;
}
.fmp-feed-hd > span:first-child {
  font-size: .68rem; font-weight: 600; color: #e4e9f2; letter-spacing: .04em;
}
.fmp-feed-sub {
  font-size: .58rem; color: #56627a; font-style: italic; font-weight: 500;
}

.fmp-feed {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 5px;
  margin-bottom: 12px;
}
.fmp-job {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 11px; align-items: center;
  padding: 7px 11px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 7px;
  transition: all .25s ease;
}
.fmp-job:hover {
  background: rgba(167,139,250,.06);
  border-color: rgba(167,139,250,.22);
  transform: translateX(2px);
}
/* Logos render as real brand favicons inside a white pill so the brand
   art has enough contrast against the dark navy stage. The image fills
   the pill with a small inset; tiny favicons up-scale via the rendering
   pipeline but stay sharp at the 30px display size. */
.fmp-logo {
  width: 30px; height: 30px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  background: #fff;
  padding: 3px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.08);
  overflow: hidden;
}
.fmp-logo img {
  width: 100%; height: 100%;
  object-fit: contain;
  image-rendering: -webkit-optimize-contrast;
  display: block;
}
.fmp-job-body { min-width: 0; }
.fmp-job-row {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 1px;
}
.fmp-firm {
  font-size: .72rem; font-weight: 700; color: #fff;
  letter-spacing: .01em;
}
.fmp-tag {
  font-size: .5rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase;
  padding: 1px 7px; border-radius: 30px;
  background: rgba(255,255,255,.06);
  color: #94a3b8;
  border: 1px solid rgba(255,255,255,.06);
}
.fmp-tag--excl {
  background: rgba(167,139,250,.12);
  color: #c4b5fd;
  border-color: rgba(167,139,250,.32);
}
.fmp-role {
  font-size: .62rem; color: #c4b5fd; font-weight: 500;
  margin-bottom: 2px;
}
.fmp-meta {
  display: flex; align-items: center; gap: 6px;
  font-size: .56rem; color: #94a3b8; font-weight: 500;
}
.fmp-dot { color: #56627a; }
.fmp-cta {
  color: #a78bfa; font-weight: 700; letter-spacing: .04em;
  margin-left: auto;
}

/* Application pipeline tracker — replaces the passive stats card with a
   live 3-stage funnel (Applied → Interview → Offer). Conveys the portal
   as a working tracker, not just a job list. Stage tints get warmer as
   the candidate progresses; the Offer column glows. */
.fmp-pipeline {
  position: relative; z-index: 1;
  margin-top: auto;
  padding: 12px 12px 14px;
  background: linear-gradient(135deg, rgba(167,139,250,.06), rgba(155,138,255,.015));
  border: 1px solid rgba(167,139,250,.18);
  border-radius: 10px;
}
.fmp-pipeline-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 2px 8px;
  border-bottom: 1px dashed rgba(255,255,255,.06);
  margin-bottom: 8px;
}
.fmp-pipeline-hd > span:first-child {
  font-size: .66rem; font-weight: 700; color: #e4e9f2;
  letter-spacing: .04em;
}
.fmp-pipeline-sub {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .54rem; color: #94a3b8;
  font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase;
}
.fmp-pipeline-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.fmp-col {
  display: flex; flex-direction: column;
  padding: 7px 8px;
  background: rgba(255,255,255,.025);
  border: 1px solid rgba(255,255,255,.05);
  border-radius: 6px;
  border-top: 2px solid rgba(148,163,184,.4);
}
.fmp-col--int {
  border-top-color: rgba(167,139,250,.55);
  background: rgba(167,139,250,.05);
}
.fmp-col--offer {
  border-top-color: #c4b5fd;
  background: linear-gradient(180deg, rgba(196,181,253,.12), rgba(167,139,250,.04));
  box-shadow: 0 0 18px rgba(196,181,253,.15);
}
.fmp-col-hd {
  display: flex; justify-content: space-between; align-items: baseline;
  padding-bottom: 6px; margin-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,.05);
}
.fmp-col-l {
  font-size: .54rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: #94a3b8;
}
.fmp-col--int .fmp-col-l { color: #c4b5fd; }
.fmp-col--offer .fmp-col-l { color: #ddd6fe; }
.fmp-col-c {
  font-size: 1.15rem; font-weight: 700; color: #fff;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.fmp-col--offer .fmp-col-c {
  background: linear-gradient(135deg, #a78bfa, #c4b5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.fmp-col-list {
  display: flex; flex-direction: column; gap: 4px;
}
.fmp-col-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: 4px;
  padding: 4px 6px;
  background: rgba(255,255,255,.02);
  border-radius: 3px;
  font-size: .58rem;
  font-weight: 600;
}
.fmp-col-item--offer {
  background: rgba(196,181,253,.1);
  box-shadow: inset 0 0 0 1px rgba(196,181,253,.18);
}
.fmp-col-firm {
  color: #e4e9f2; letter-spacing: .01em;
}
.fmp-col-when {
  font-size: .52rem; color: #56627a; font-weight: 500;
}
.fmp-col-tag {
  font-size: .5rem; font-weight: 700; letter-spacing: .04em;
  padding: 1px 5px; border-radius: 3px;
  background: rgba(167,139,250,.12);
  color: #c4b5fd;
}
.fmp-col-tag--win {
  background: rgba(196,181,253,.18);
  color: #ddd6fe;
  white-space: nowrap;
}
.fmp-col-more {
  font-size: .52rem; color: #56627a; font-weight: 600;
  font-style: italic;
  padding: 2px 6px;
}

@media (max-width: 640px) {
  .fvis.fvis-fm-portal { height: 560px; }
  .fmp-stage { padding: 14px 16px 44px; }
  .fmp-job { padding: 7px 10px; gap: 10px; grid-template-columns: 30px 1fr; }
  .fmp-logo { width: 30px; height: 30px; }
  .fmp-firm { font-size: .7rem; }
  .fmp-role { font-size: .6rem; }
  .fmp-meta { font-size: .54rem; gap: 4px; flex-wrap: wrap; }
  .fmp-cta { margin-left: 0; }
  .fmp-tag { font-size: .48rem; padding: 1px 6px; }
  .fmp-pipeline { padding: 10px 8px; }
  .fmp-pipeline-grid { gap: 4px; }
  .fmp-col { padding: 6px 6px; }
  .fmp-col-c { font-size: 1.05rem; }
  .fmp-col-l { font-size: .5rem; }
  .fmp-col-firm { font-size: .56rem; }
  .fmp-col-tag, .fmp-col-tag--win { font-size: .46rem; padding: 1px 4px; }
}

/* ===========================================================
   Blog · Zest Capital — inline editorial graphics
   Three lightweight HTML visuals embedded in the article body.
   Design system:
     palette  navy (#0a1628 → #142845) + gold (#ffcc66 / #c5a55a)
     surface  subtle gradient + 1px hairline + soft shadow + top accent
     type     small caps for eyebrows, mono numerals, gradient text on
              hero stats, controlled letter-spacing throughout
     ornament hairlines, inner highlights, accent dots — no heavy chrome
   =========================================================== */

.zest-fig {
  position: relative;
  margin: 44px 0;
  padding: 44px 40px 36px;
  background:
    radial-gradient(ellipse 120% 80% at 50% 0%, rgba(255,204,102,.06) 0%, transparent 55%),
    linear-gradient(135deg, #0a1628 0%, #142845 100%);
  border-radius: 18px;
  color: #fff;
  border: 1px solid rgba(255,255,255,.06);
  box-shadow:
    0 4px 32px rgba(0,0,0,.28),
    inset 0 1px 0 rgba(255,255,255,.05);
  overflow: hidden;
}
.zest-fig::before {
  content: '';
  position: absolute;
  top: 0; left: 24px; right: 24px;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,204,102,.45) 50%,
    transparent 100%);
}

.zest-fig-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-size: 10px;
  color: #ffcc66;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 2.6px;
  margin: 0 0 32px;
}
.zest-fig-title::before,
.zest-fig-title::after {
  content: '';
  flex: 0 0 36px;
  height: 1px;
  background: linear-gradient(90deg, rgba(255,204,102,0), rgba(255,204,102,.35));
}
.zest-fig-title::after {
  background: linear-gradient(90deg, rgba(255,204,102,.35), rgba(255,204,102,0));
}

.zest-fig-cap {
  font-size: 13px;
  color: #9ca3b8;
  font-style: italic;
  margin: 32px auto 0;
  padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,.06);
  line-height: 1.65;
  text-align: center;
  max-width: 560px;
  letter-spacing: .15px;
}
.zest-fig-body { min-width: 0; }
.zest-arrow-svg { display: block; }
.zest-arrow-svg path,
.zest-arrow-svg line,
.zest-arrow-svg polyline {
  fill: none; stroke: #ffcc66;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}

/* ----- Visual 1 — the CV pile vs. useful hires ----- */
.zest-fig-1 .zest-fig-body {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 40px;
}
.zest-pile {
  position: relative;
  background:
    radial-gradient(ellipse at top, rgba(255,255,255,.03) 0%, transparent 60%),
    rgba(255,255,255,.02);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 14px;
  padding: 24px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04);
}
.zest-pile-grid {
  display: grid;
  grid-template-columns: repeat(20, 1fr);
  gap: 5px;
}
.zest-cv {
  aspect-ratio: 5 / 7;
  background: linear-gradient(180deg, #2a3854 0%, #1f2c45 100%);
  border-radius: 1.5px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04);
}
.zest-cv.useful {
  background: linear-gradient(180deg, #ffd87a 0%, #c5a55a 100%);
  box-shadow:
    0 0 0 1px rgba(255,204,102,.5),
    0 0 14px rgba(255,204,102,.55),
    inset 0 1px 0 rgba(255,255,255,.4);
  z-index: 1;
}
.zest-pile-label {
  text-align: center;
  font-size: 10px;
  color: #9ca3b8;
  margin-top: 20px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  font-weight: 600;
}
.zest-pile-label b {
  color: #ffcc66;
  font-weight: 700;
  font-feature-settings: "tnum";
  letter-spacing: 1.5px;
}

.zest-fig-1 .zest-arrow {
  width: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.zest-fig-1 .zest-arrow::before {
  content: '';
  position: absolute;
  inset: 50% 4px auto 4px;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(255,204,102,0) 0%,
    rgba(255,204,102,.4) 30%,
    rgba(255,204,102,.6) 100%);
}
.zest-fig-1 .zest-arrow-svg { width: 14px; height: 14px; position: relative; z-index: 1; margin-left: auto; }

.zest-result { text-align: center; padding: 0 4px; }
.zest-result-num {
  font-size: 76px;
  font-weight: 800;
  background: linear-gradient(180deg, #ffe296 0%, #c5a55a 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  line-height: 1;
  letter-spacing: -3px;
  font-feature-settings: "tnum";
  filter: drop-shadow(0 0 18px rgba(255,204,102,.18));
}
.zest-result-label {
  font-size: 13px;
  color: #fff;
  font-weight: 600;
  margin-top: 18px;
  line-height: 1.45;
  letter-spacing: .15px;
}
.zest-result-sub {
  font-size: 12px;
  color: #9ca3b8;
  margin-top: 8px;
  line-height: 1.55;
  letter-spacing: .15px;
}

/* ----- Visual 2 — segmented timeline before/after ----- */
.ztime {
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.ztime-row { display: flex; flex-direction: column; gap: 12px; }
.ztime-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 0 2px;
}
.ztime-name {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  color: rgba(255,255,255,.82);
  letter-spacing: .15px;
}
.ztime-name::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255,255,255,.3);
  flex-shrink: 0;
}
.ztime-row--new .ztime-name { color: #fff; }
.ztime-row--new .ztime-name::before {
  background: #ffcc66;
  box-shadow: 0 0 10px rgba(255,204,102,.55);
}
.ztime-meta {
  font-size: 11px;
  color: #9ca3b8;
  font-weight: 500;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.ztime-bar {
  display: flex;
  height: 76px;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.04),
    0 4px 18px rgba(0,0,0,.18);
}
.ztime-seg {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 10px 14px;
  text-align: center;
  line-height: 1.35;
  color: rgba(255,255,255,.96);
  border-right: 1px solid rgba(0,0,0,.22);
  min-width: 0;
  position: relative;
}
.ztime-seg::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: rgba(255,255,255,.08);
}
.ztime-seg:last-child { border-right: 0; }
.ztime-seg .step-name {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.ztime-seg .step-meta {
  font-size: 10px;
  font-weight: 600;
  margin-top: 5px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  opacity: .7;
}

.ztime-row--old .ztime-seg--joins    { flex: 0 0 100px; background: linear-gradient(180deg, #324968 0%, #2a3d57 100%); }
.ztime-row--old .ztime-seg--wait     { flex: 1 1 auto; min-width: 200px; background: linear-gradient(90deg, #4a4267 0%, #b56c52 100%); }
.ztime-row--old .ztime-seg--billable { flex: 0 0 124px; background: linear-gradient(180deg, #2a7860 0%, #1f6651 100%); }

.ztime-row--new .ztime-bar { width: 26%; min-width: 240px; }
.ztime-row--new .ztime-seg--joins    { flex: 0 0 100px; background: linear-gradient(180deg, #324968 0%, #2a3d57 100%); }
.ztime-row--new .ztime-seg--billable { flex: 1 1 auto; min-width: 100px; background: linear-gradient(90deg, #c5a55a 0%, #ffd87a 100%); color: #0e1a2e; box-shadow: inset 0 0 24px rgba(255,255,255,.15); }
.ztime-row--new .ztime-seg--billable .step-name,
.ztime-row--new .ztime-seg--billable .step-meta { color: #0e1a2e; opacity: 1; }
.ztime-row--new .ztime-seg--billable .step-meta { opacity: .65; }

/* ----- Visual 3 — journey track (icons on the line) ----- */
.ztrack {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 32px;
  position: relative;
  padding: 12px 0 6px;
}
.ztrack-line {
  position: absolute;
  top: 44px;
  left: calc(16.67% + 36px);
  right: calc(16.67% + 36px);
  height: 1px;
  background: linear-gradient(90deg,
    rgba(255, 204, 102, 0) 0%,
    rgba(255, 204, 102, .25) 12%,
    rgba(255, 204, 102, .5) 50%,
    rgba(255, 204, 102, .25) 88%,
    rgba(255, 204, 102, 0) 100%);
  pointer-events: none;
}
.ztrack-step {
  text-align: center;
  position: relative;
  padding: 0 8px;
}
.ztrack-icon {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto 22px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%, rgba(255,204,102,.14) 0%, rgba(255,204,102,.03) 70%),
    linear-gradient(135deg, #0e1a2e 0%, #1a2a4a 100%);
  border: 1px solid rgba(255, 204, 102, .42);
  position: relative;
  z-index: 1;
  box-shadow:
    0 0 0 4px rgba(10, 22, 40, 1),
    0 4px 16px rgba(0,0,0,.32),
    0 0 28px rgba(255,204,102,.1),
    inset 0 1px 0 rgba(255,255,255,.06);
}
.ztrack-icon svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: #ffcc66;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ztrack-icon svg .filled {
  fill: #ffcc66;
  stroke: none;
}
.ztrack-name {
  font-size: 22px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -.4px;
  margin-bottom: 12px;
  line-height: 1.15;
}
.ztrack-tag {
  font-size: 13px;
  color: #9ca3b8;
  font-weight: 500;
  letter-spacing: .15px;
  line-height: 1.65;
  max-width: 250px;
  margin: 0 auto;
}

/* ----- Mobile / narrow viewports ----- */
@media (max-width: 720px) {
  .zest-fig { padding: 30px 22px 26px; margin: 32px 0; border-radius: 14px; }
  .zest-fig::before { left: 16px; right: 16px; }
  .zest-fig-title { margin-bottom: 26px; letter-spacing: 2.2px; }
  .zest-fig-title::before, .zest-fig-title::after { flex-basis: 22px; }
  .zest-fig-cap { margin-top: 26px; padding-top: 18px; font-size: 12.5px; }

  .zest-fig-1 .zest-fig-body { grid-template-columns: 1fr; gap: 24px; }
  .zest-fig-1 .zest-arrow { width: 100%; height: 28px; }
  .zest-fig-1 .zest-arrow::before { inset: 50% 30% auto 30%; }
  .zest-fig-1 .zest-arrow-svg { transform: rotate(90deg); margin: 0 auto; }
  .zest-pile { padding: 18px 18px 16px; }
  .zest-pile-grid { gap: 4px; }
  .zest-result-num { font-size: 64px; letter-spacing: -2.2px; }

  .ztime { gap: 24px; }
  .ztime-bar { height: 64px; }
  .ztime-row--old .ztime-seg--joins    { flex: 0 0 78px; }
  .ztime-row--old .ztime-seg--billable { flex: 0 0 96px; }
  .ztime-row--old .ztime-seg--wait     { min-width: 100px; }
  .ztime-row--new .ztime-bar           { width: 100%; min-width: 0; }
  .ztime-row--new .ztime-seg--joins    { flex: 0 0 78px; }
  .ztime-seg { padding: 8px 10px; }
  .ztime-seg .step-name { font-size: 11.5px; }
  .ztime-seg .step-meta { font-size: 9.5px; }
  .ztime-meta { font-size: 10px; letter-spacing: 1px; }

  .ztrack { grid-template-columns: 1fr; gap: 32px; padding: 10px 0 0; }
  .ztrack-line { display: none; }
  .ztrack-icon { width: 56px; height: 56px; margin-bottom: 16px; }
  .ztrack-icon svg { width: 26px; height: 26px; }
  .ztrack-name { font-size: 22px; }
  .ztrack-tag { max-width: 100%; }
}

/* ───────────── enrollment-page price tag ─────────────────────
   Added 2026-05-11 alongside js/qe-enrollment-cards.js. The dynamic
   renderer drops a .course-price chip between .course-description and
   .course-features so visitors see the price BEFORE the CTA. .course-*
   classes are scoped to enrollment pages only (audited 2026-05-11). */
.course-card .course-price {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text-primary, #0f172a);
  letter-spacing: -0.02em;
  margin-bottom: 1.25rem;
  line-height: 1.1;
}
.course-card .course-price .rs {
  font-size: 1rem;
  font-weight: 500;
  color: var(--text-secondary, #64748b);
  margin-right: 0.25rem;
  vertical-align: 0.05em;
}
@media (max-width: 768px) {
  .course-card .course-price { font-size: 1.4rem; margin-bottom: 1rem; }
}
@media (max-width: 480px) {
  .course-card .course-price { font-size: 1.2rem; margin-bottom: 0.75rem; }
}



/* ════════════════ ACCA ENROLLMENT PAGE LAYOUT ════════════════════════
   Added 2026-05-11 alongside js/qe-acca-enrollment.js. Replaces the
   3-card grid (which only worked for products with ONE flagship SKU)
   with a plan-list — every bundle and every individual subject gets
   its own row, and each row has three clickable mode tiles (Live /
   Hybrid / Self-Paced) so the visitor can enrol in the exact mode of
   the exact plan they want without an intermediate step. Scoped to the
   .acca-en-* prefix so it can't collide with other pages.            */

.acca-en-section + .acca-en-section { margin-top: 3rem; }

.acca-en-section-title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary, #0f172a);
  letter-spacing: -0.02em;
  margin-bottom: 0.25rem;
}
.acca-en-section-subtitle {
  font-size: 0.95rem;
  color: var(--text-secondary, #64748b);
  margin-bottom: 1.5rem;
}

.acca-en-group { margin-top: 2rem; }
.acca-en-group:first-child { margin-top: 0; }

.acca-en-group-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-secondary, #64748b);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border, #e2e8f0);
}

.acca-en-plans { display: flex; flex-direction: column; gap: 1rem; }

.acca-en-plan {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 2fr);
  gap: 1.5rem;
  align-items: center;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 14px;
  padding: 1.25rem 1.5rem;
  transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
}
.acca-en-plan:hover {
  box-shadow: 0 8px 20px -10px rgba(15, 23, 42, 0.18);
  transform: translateY(-1px);
  border-color: transparent;
}
.acca-en-plan.is-popular {
  border-color: rgba(59, 130, 246, 0.35);
  box-shadow: 0 4px 16px -6px rgba(59, 130, 246, 0.18);
}

.acca-en-plan-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.35rem;
}

.acca-en-plan-code {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--primary, #3b82f6);
  background: rgba(59, 130, 246, 0.1);
  padding: 0.2rem 0.55rem;
  border-radius: 6px;
  min-width: 2.4rem;
  text-transform: uppercase;
}

.acca-en-plan-name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-primary, #0f172a);
  line-height: 1.35;
}

.acca-en-plan-badge {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #fff;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  text-transform: uppercase;
}

.acca-en-plan-desc {
  font-size: 0.825rem;
  color: var(--text-secondary, #64748b);
  line-height: 1.45;
}

/* 2026-05-12: was grid-template-columns: repeat(3, 1fr) which forced 3
   columns even when a plan only had 2 modes (e.g. ACCA bundles after we
   stripped Hybrid pricing — Live + Self-Paced ended up in cols 1+2 with
   an empty col 3 hanging off the right). Switched to flex so any number
   of tiles (1, 2, or 3) expand to fill the row width evenly. */
.acca-en-plan-modes {
  display: flex;
  gap: 0.6rem;
}

.acca-en-mode {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.85rem 0.85rem 0.7rem;
  background: var(--background, #fafafa);
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 10px;
  text-decoration: none;
  color: var(--text-primary, #0f172a);
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.acca-en-mode:hover {
  background: #fff;
  transform: translateY(-1px);
}
.acca-en-mode--live:hover     { border-color: #3b82f6; }
.acca-en-mode--hybrid:hover   { border-color: #10b981; }
.acca-en-mode--recorded:hover { border-color: #8b5cf6; }

.acca-en-mode-label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary, #64748b);
}
.acca-en-mode--live     .acca-en-mode-label { color: #3b82f6; }
.acca-en-mode--hybrid   .acca-en-mode-label { color: #10b981; }
.acca-en-mode--recorded .acca-en-mode-label { color: #8b5cf6; }

.acca-en-mode-price {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--text-primary, #0f172a);
}
.acca-en-mode-price .rs {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-secondary, #64748b);
  margin-right: 0.15rem;
}

.acca-en-mode-cta {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-secondary, #64748b);
  margin-top: 0.1rem;
}

/* ─ Tablet + small-laptop: drop the side-by-side info|modes layout ─ */
@media (max-width: 880px) {
  .acca-en-plan {
    grid-template-columns: 1fr;
    gap: 1rem;
    padding: 1rem 1.1rem;
  }
}

/* ─ Phone ─
   2026-05-12 redesign: previous mobile look stacked solid-color pill
   buttons inside gray tiles inside outlined cards — too many visual
   layers competing per row. User feedback ("too heavy, make it minimal").
   New layout reads like an Apple/Stripe list:
     - Plan card has only a hairline border, no popular-outline emphasis
     - Mode rows are inline (no per-row backgrounds), separated by
       hairline dividers
     - CTA becomes subtle mode-tinted text (not a solid pill)
     - Most-Popular badge is a tiny light-bg chip, not a gradient pill
   Result: roughly half the visual weight per card with the same info. */
@media (max-width: 520px) {
  /* Section + page chrome — tighter so more plans fit per screen */
  .acca-en-section + .acca-en-section { margin-top: 2rem; }
  .acca-en-section-title    { font-size: 1.1rem; margin-bottom: 0.1rem; font-weight: 600; }
  .acca-en-section-subtitle { font-size: 0.8rem; margin-bottom: 1rem; }
  .acca-en-group            { margin-top: 1.5rem; }
  .acca-en-group-title {
    font-size: 0.68rem;
    margin-bottom: 0.5rem;
    padding-bottom: 0.4rem;
    letter-spacing: 0.08em;
  }
  .acca-en-plans { gap: 0.65rem; }

  /* Plan card — lighter border, no popular emphasis on mobile */
  .acca-en-plan {
    padding: 0.95rem 1rem;
    border-radius: 12px;
    gap: 0.5rem;
    box-shadow: none;
    border: 1px solid rgba(15, 23, 42, 0.08);
    background: #fff;
  }
  .acca-en-plan:hover,
  .acca-en-plan.is-popular {
    box-shadow: none;
    transform: none;
    border-color: rgba(15, 23, 42, 0.08);
  }

  /* Title row */
  .acca-en-plan-head {
    margin-bottom: 0.05rem;
    gap: 0.4rem;
    align-items: center;
  }
  .acca-en-plan-code {
    font-size: 0.6rem;
    padding: 0.15rem 0.42rem;
    min-width: 0;
    background: rgba(15, 23, 42, 0.06);
    color: rgba(15, 23, 42, 0.72);
    border-radius: 4px;
    letter-spacing: 0.04em;
  }
  .acca-en-plan-name {
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.3;
    flex: 1 1 auto;
    min-width: 0;
  }
  /* Most Popular: small light chip, no gradient */
  .acca-en-plan-badge {
    font-size: 0.55rem;
    padding: 0.13rem 0.45rem;
    line-height: 1.3;
    flex-shrink: 0;
    background: rgba(139, 92, 246, 0.12);
    color: #6d28d9;
    border-radius: 4px;
    letter-spacing: 0.05em;
  }
  .acca-en-plan-desc {
    font-size: 0.78rem;
    line-height: 1.45;
    color: rgba(15, 23, 42, 0.55);
  }

  /* Mode rows: inline list with hairline dividers, no individual tiles. */
  .acca-en-plan-modes {
    flex-direction: column;
    gap: 0;
    margin-top: 0.4rem;
    border-top: 1px solid rgba(15, 23, 42, 0.07);
  }

  .acca-en-mode {
    flex: 1 1 auto;
    flex-direction: row;
    align-items: center;
    padding: 0.7rem 0;
    gap: 0.6rem;
    background: transparent;
    border: 0;
    border-bottom: 1px solid rgba(15, 23, 42, 0.07);
    border-radius: 0;
  }
  .acca-en-mode:last-child { border-bottom: 0; padding-bottom: 0.2rem; }
  .acca-en-mode:hover {
    transform: none;
    background: transparent;
  }
  .acca-en-mode--live:hover,
  .acca-en-mode--hybrid:hover,
  .acca-en-mode--recorded:hover {
    border-bottom-color: rgba(15, 23, 42, 0.07);
  }

  /* Label: small neutral caps, no mode color. The mode is still
     differentiated by the colored CTA on the right. */
  .acca-en-mode-label,
  .acca-en-mode--live     .acca-en-mode-label,
  .acca-en-mode--hybrid   .acca-en-mode-label,
  .acca-en-mode--recorded .acca-en-mode-label {
    flex: 0 0 5.5rem;
    font-size: 0.6rem;
    line-height: 1.15;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: rgba(15, 23, 42, 0.55);
    text-transform: uppercase;
  }

  /* Price: clean number, right-aligned */
  .acca-en-mode-price {
    flex: 1 1 auto;
    text-align: right;
    font-size: 0.95rem;
    font-weight: 600;
    color: #0f172a;
  }
  .acca-en-mode-price .rs {
    font-size: 0.7rem;
    margin-right: 0.05rem;
    color: rgba(15, 23, 42, 0.55);
    font-weight: 500;
  }

  /* CTA: subtle mode-tinted text with arrow — no pill, no background.
     The whole row is a tap target via the wrapping <a>, so a heavy
     button isn't needed. */
  .acca-en-mode-cta {
    flex: 0 0 auto;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 0;
    border-radius: 0;
    background: transparent !important;
    margin-top: 0;
    text-transform: uppercase;
  }
  .acca-en-mode--live     .acca-en-mode-cta { color: #3b82f6 !important; }
  .acca-en-mode--hybrid   .acca-en-mode-cta { color: #10b981 !important; }
  .acca-en-mode--recorded .acca-en-mode-cta { color: #8b5cf6 !important; }
}

/* Very narrow phones (e.g. older devices, split-screen): tighten further
   and abbreviate the longest mode label to keep everything on one row. */
@media (max-width: 380px) {
  .acca-en-mode { padding: 0.55rem 0.65rem; gap: 0.5rem; }
  .acca-en-mode-label { flex-basis: 5.2rem; font-size: 0.58rem; }
  .acca-en-mode-price { font-size: 0.88rem; }
  .acca-en-mode-cta   { padding: 0.3rem 0.5rem; font-size: 0.58rem; }
}


/* ════════════════ HIDE VERCEL PREVIEW TOOLBAR ════════════════════════
   Belt-and-suspenders against the Vercel-injected toolbar / feedback
   widget / build watcher that pollutes Preview deployments. Production
   builds don't inject it, but in case any of these ever leak through
   on an aliased domain (test.quintedge.com etc.), nuke them in CSS too.
   Added 2026-05-11. */
vercel-live-feedback,
vercel-toolbar,
[data-vercel-toolbar],
[data-vercel-feedback-mode],
#__next-build-watcher,
iframe[src*="vercel.live"],
iframe[src*="vercel.com/comments"],
[id^="vercel-"],
[class^="vercel-toolbar"] {
  display: none !important;
  visibility: hidden !important;
  pointer-events: none !important;
}


/* ════════════════ GLOBAL [hidden] ENFORCEMENT ═══════════════════════
   The HTML `hidden` attribute is documented as equivalent to display:none,
   but any author CSS rule like `.thing { display: flex }` overrides it
   silently — this exact bug let the success state on access-*-doubt-solver
   pages render alongside the form for users with stale cached CSS.
   Adding an `!important` here so any element marked `hidden` is hidden no
   matter what other rules say. Added 2026-05-11. */
[hidden] { display: none !important; }


/* ════════════════ LEAD-FORM SUCCESS — MOBILE OVERFLOW FIX ═══════════
   2026-05-12: students on phones reported the post-submit confirmation
   ("Thank you — we'll call you shortly. / We will connect with you
   within the next 30 minutes. Keep your phone handy!") being cut off
   mid-sentence at the bottom — the "Keep your phone handy!" line was
   invisible.

   Root cause: the per-page success rule is
     .qe-lead-success{position:absolute;inset:0;…}
   so when the form is submitted the success state overlays the form
   box (avoids layout shift on desktop, where the form's grid row is
   stretched by the taller banner column next to it).

   On mobile the .qe-lead grid collapses to a single column. When the
   form's input fields go display:none on submit, the form row
   collapses to just its padding — so the absolute success overlay's
   inset:0 maps to a tiny box, and the icon + heading + paragraph
   content overflows it. The parent .qe-lead has `overflow:hidden`,
   which clips the bottom of the paragraph.

   Fix: on mobile, let the success state participate in normal flow
   so the form auto-sizes to its content. The slight layout shift on
   submit is acceptable — the page has already committed to a "thanks"
   state by then. Desktop behaviour is preserved. */
@media (max-width: 900px) {
  .qe-lead-form.qe-lead-submitted .qe-lead-success {
    position: static;
    inset: auto;
  }
}
