/* ============================================================================
   SJP THEME — RESPONSIVE LAYER
   ----------------------------------------------------------------------------
   Loaded LAST (after main.css, woocommerce.css, tutor-sjp.css, react-final.css)
   so equal-specificity rules here win. This file does not duplicate the
   responsive work those files already do well (e.g. WooCommerce's stacked
   shop_table at 680px, the checkout column collapse at 900px, the
   course-detail-shell grid collapse at 900px, the courses/gallery/footer
   grid collapses already in main.css) — it closes the gaps found in the
   audit and normalizes the breakpoint system going forward.

   BREAKPOINT SYSTEM (consistent from here on):
     ≤479px   phone (small)      — content: 320/360/375/390/414/430/480
     480–767  phone (large)      — landscape phones, phablets
     768–1023 tablet             — 768/834 portrait tablets
     1024–1279 small desktop/laptop, tablet landscape (1024)
     ≥1280    desktop / large desktop (1280/1440+)
   Existing component breakpoints elsewhere in the theme (900/860/820/760/
   700/680/600/560/520px etc.) are intentionally left as-is — they were
   tuned per-component and rewriting them to the grid above would be a
   large, unnecessary regression risk. New rules below use the normalized
   breakpoints; a few components get one extra fine breakpoint only where
   the audit found a genuine gap (noted inline).
   ============================================================================ */


/* ==========================================================================
   1. GLOBAL FOUNDATION
   ========================================================================== */

/* Defensive layer only — the real overflow sources (marquee, absolute hero
   layers, sticky chat panel) are already sized safely elsewhere in this
   file and in main.css. This just catches anything still missed. */
html { max-width: 100%; overflow-x: hidden; }
body { max-width: 100%; overflow-x: hidden; }

/* Stop the browser's native "scroll anchoring" from jumping the page past
   the hero on load. The hero uses a GSAP ScrollTrigger pin that inserts a
   large spacer element; scroll anchoring tries to keep on-screen content
   in the same visual spot when that spacer appears and can misfire,
   landing the visitor scrolled into the Courses section instead of the
   top. This is paired with the scrollRestoration fix in main.js. */
html, body, .hero, .hero-pin-sticky {
  overflow-anchor: none;
}

img, svg, video, iframe, embed, object, canvas {
  max-width: 100%;
  height: auto;
}
/* full-bleed background/hero media is intentionally exempt from height:auto */
.hero-kb-canvas, .about-bg-video, .courses-bg-video, .account-bg,
video[class*="-bg"], [class*="-bg"] > video, .course-detail-featured-image {
  height: 100%;
}
.course-detail-featured-image { height: auto; max-height: 560px; }

/* Lightweight orb/particle background (same effect as the login/my-account
   page) that stands in for the heavy scroll-scrubbed canvas / mp4
   backgrounds on phones only. Hidden everywhere by default — the mobile
   media query below is the ONLY place that turns it on, so desktop/laptop
   (where the keyboard-frame parallax must stay exactly as-is) never sees
   it, regardless of window size tricks or JS timing. */
.mobile-orb-bg { display: none; }

/* Login/My-Account page star-field background — was showing on every
   screen size with no gating at all. Restricted to mobile only, same
   pattern as .mobile-orb-bg above: hidden by default here, re-enabled
   inside the mobile media query further down. Desktop/laptop keeps the
   two-column layout (.account-visual panel already carries the visual
   weight there via its own keyboard animation + branding), so nothing
   needs to visually replace it on larger screens. */
.account-bg { display: none; }

/* long words/links/emails never force horizontal scroll (contact info,
   footer email link, chat bubbles) */
.contact-info, .foot-col, .cb-bubble, .course-byline {
  overflow-wrap: anywhere;
}

/* body scroll lock while the mobile nav / search overlay / chat panel is
   open — toggled by a small main.js addition below */
body.sjp-scroll-lock { overflow: hidden; height: 100%; }


/* ==========================================================================
   2. TYPOGRAPHY — fluid scale, replaces desktop-fixed sizes at all widths
   ========================================================================== */
h1 { font-size: clamp(28px, 5vw + 4px, 56px); }
h2 { font-size: clamp(22px, 3.4vw + 4px, 38px); }
h3 { font-size: clamp(18px, 2.2vw + 4px, 26px); }

.hero-content h1, .hero-headline { font-size: clamp(30px, 6.5vw + 4px, 68px); }
.page-header h1 { font-size: clamp(26px, 5vw + 4px, 46px); }
.price--lg { font-size: clamp(20px, 3vw + 6px, 28px); }

/* page-header top padding is a fixed 150px desktop value on every legal/
   about/gallery/etc. page — fine on desktop, excessive dead space on
   phones where the header itself is shorter */
@media (max-width: 767px) {
  .page-header { padding: 100px 0 40px; }
}
@media (max-width: 479px) {
  .page-header { padding: 88px 0 32px; }
}
/* general heading floors (h1 28px / h2 22px / h3 18px / page-header h1
   26px) are fine down to ~360px but start to feel oversized relative to
   a 300–320px column, especially page-header h1 on long titles like
   "Terms & Conditions" or "Refund and Returns Policy" wrapping onto 3+
   lines. One extra step down, floor only — desktop/tablet clamp values
   above are untouched. */
@media (max-width: 360px) {
  h1 { font-size: clamp(24px, 7.5vw, 56px); }
  h2 { font-size: clamp(19px, 5.5vw, 38px); }
  h3 { font-size: clamp(16px, 4.5vw, 26px); }
  .page-header h1 { font-size: clamp(22px, 7vw, 46px); }
}
@media (max-width: 300px) {
  h1 { font-size: 22px; }
  h2 { font-size: 18px; }
  .page-header h1 { font-size: 20px; }
}


/* ==========================================================================
   3. HEADER / NAVIGATION
   ========================================================================== */
@media (max-width: 900px) {
  /* existing main.css rule collapses nav to a burger at 900px already;
     these are the gaps: tap target size + long-label handling.
     THE ACTUAL OVERFLOW FIX: .btn-search kept its full "Search" text
     label at every width with no flex-wrap safety on .nav, so on a
     narrow phone (logo + "Search" + cart icon + burger all fighting
     for space) it could overflow the header — on every page, not just
     Courses. Icon-only here removes the fixed-width text label. */
  .burger { width: 40px; height: 40px; } /* ≥40px comfortable tap target */
  .btn-search-label { display: none; }
  .btn-search {
    padding: 9px; width: 38px; height: 38px;
    justify-content: center; border-radius: 50%; gap: 0;
  }
  .btn-search-icon { width: 17px; height: 17px; }
  nav.links a, .mobile-account-link {
    overflow-wrap: anywhere; /* long custom menu labels never overflow */
  }
}
/* BUG FIX — react-final.css locks the header logo to a fixed
   width:170px !important (135px at one mid-breakpoint) with high
   selector specificity, which silently beat every earlier attempt to
   shrink it further for phones — including one already in this file that
   had no !important and lost. This matches that specificity + !important
   so it can actually win, shrinking the logo in real, tested steps down
   to very narrow screens instead of eating ~40% of a 300px-wide header. */
@media (max-width: 480px) {
  html body header#sjp-header .brand img { width: 110px !important; height: auto !important; max-height: 34px !important; }
}
@media (max-width: 360px) {
  html body header#sjp-header .brand img { width: 88px !important; max-height: 27px !important; }
  .nav.wrap { padding-left: 12px; padding-right: 12px; }
}
@media (max-width: 280px) {
  html body header#sjp-header .brand img { width: 68px !important; max-height: 21px !important; }
}

/* search overlay: fits small phones without its own overflow */
@media (max-width: 480px) {
  .search-panel { padding: 20px 16px; }
  .search-panel-head h2 { font-size: 22px; }
}


/* ==========================================================================
   4. HERO SECTIONS
   ========================================================================== */
@media (max-width: 767px) {
  .hero-pin-sticky { min-height: 100svh; }
  .hero-pin-sticky .hero-content { padding: 0 20px; }
  /* PARALLAX RESTORED ON MOBILE — the scroll-scrubbed keyboard-frame
     canvas was previously hidden here (solid --ink background swapped
     in, canvas display:none) as a mobile performance/bandwidth
     tradeoff. Per explicit request, it's back on both mobile and
     desktop now: no override here means .hero-pin-sticky's own default
     background (var(--ink) + frame-001.webp fallback) and .hero-kb-canvas
     both apply exactly as they do on desktop. Note for future reference:
     this does mean phones now load/draw the same ~121-frame webp
     sequence as desktop, which is heavier on mobile data and CPU than
     the previous orb-background fallback was — that tradeoff was the
     reason this was turned off originally. */
  /* same reasoning applies to the Courses (home + course-list) and About
     section backdrops: scroll-scrubbed canvas frames / the course-list
     mp4 are desktop-scroll effects that read as a static, cropped image
     on phones — hide them and show the lightweight orb/particle layer
     (identical markup/animation to the login page) in their place.
     (Hero is excluded from this — see restoration note above.) */
  .courses-bg-video, .about-bg-video { display: none !important; }
  .mobile-orb-bg {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
  }
  /* the hero's own orb instance is switched back off now that the real
     canvas/photo background is restored above — Courses/About sections'
     orb backgrounds (targeted by the generic rule above) are untouched */
  #hero .mobile-orb-bg { display: none !important; }

  /* Login/My-Account page star field — mobile only (base display:none
     is set earlier in this file). A dark radial vignette sits behind
     the orbs/particles so the star field reads as an intentional
     background scene instead of scattered dots on flat black — the
     .account-shell card itself already has its own blur/tint for the
     form text, this is purely for the empty space around that card. */
  .account-bg {
    display: block;
    background: radial-gradient(120% 90% at 50% 30%, rgba(74,32,110,0.35), rgba(4,3,10,0.92) 72%);
  }
}
@media (max-width: 400px) {
  .hero-pin-sticky .hero-content { padding: 0 16px; }
}

/* NOTE — the hero headline ("KEYBOARD ESSENTIALS" / "LEARN | CREATE |
   GROW"), the badge pill, and .hero-sub are already handled by a single
   continuous vw-based clamp() further down this file (see "18. HERO" /
   "18b. HERO CONTAINER CASCADE"), which scales them smoothly across the
   whole ≤767px range with no fixed floor. That system already covers a
   320px-and-below screen correctly (verified: title ≈19px, accent ≈14px,
   badge 11px, sub ≈12.5px at 320px — none of them overflow), so nothing
   extra is added here for those. Kept here: the progress readout and
   Explore-Courses link, which that later section doesn't touch. */
@media (max-width: 480px) {
  .hero-progress { right: 14px; top: 500px; }
  .hero-progress-track { width: 44px; }
}
@media (max-width: 360px) {
  .hero-link { font-size: 13px; }
}
@media (max-width: 320px) {
  /* 320px is the supported minimum width — verified no overflow above.
     Nothing further needed here today; this tier is kept as the explicit
     floor marker so any future heading-size tweak has a clear home. */
}

/* the ticker bar below the headline ("*KEYBOARD *HARMONY *RHYTHM...") is
   letter-spacing:0.7em by design on desktop — left untouched that alone
   is wider than a 320px screen, forcing the bar's own horizontal
   scroll wider than intended and making each word barely readable in
   the visible sliver. It's already a self-contained horizontally
   scrolling marquee (overflow:hidden + translateX loop), so shrinking
   font-size/letter-spacing/gap here only makes more of each word visible
   per pass — it doesn't change the desktop version at all. (No-op today
   since this ticker markup isn't currently output on the front page —
   kept so it's correct automatically if the ticker is reintroduced.) */
@media (max-width: 480px) {
  .hero-keyword { font-size: 0.85rem; letter-spacing: 0.35em; }
  .hero-keywords-track { gap: 2rem; padding: 0 24px; }
  .hero-keywords-bar { padding: 18px 0; }
}
@media (max-width: 360px) {
  .hero-keyword { font-size: 0.72rem; letter-spacing: 0.22em; }
  .hero-keywords-track { gap: 1.4rem; padding: 0 18px; }
}
@media (max-width: 320px) {
  .hero-keyword { font-size: 0.64rem; letter-spacing: 0.14em; }
  .hero-keywords-track { gap: 1rem; padding: 0 14px; }
  .hero-keywords-bar { padding: 14px 0; }
}

/* short-viewport landscape phones: a 100svh pinned hero can swallow the
   whole screen with nothing below the fold visible */
@media (max-height: 480px) and (orientation: landscape) {
  .hero-pin-sticky { height: auto; min-height: 100svh; }
}


/* ==========================================================================
   5. CARDS / GRIDS — blanket collapse to complement each component's
   existing bespoke breakpoint (already present in main.css/react-final.css
   at 900/860/820/760/700/600px). This only adds the ≤480px single-column
   guarantee, since a couple of grids only ever collapse to 2 columns.
   ========================================================================== */
@media (max-width: 480px) {
  .foot-grid, .foot-grid--4,
  .how-it-works-grid,
  .gallery-grid, .gallery-grid--full,
  .bts-grid, .bts-grid--gallery,
  .production-gallery-grid,
  .account-stat-grid,
  .sjp-download-grid, .sjp-address-grid,
  .combo-offer-grid {
    grid-template-columns: 1fr;
  }
}


/* ==========================================================================
   6. FRONT PAGE
   ========================================================================== */
/* the red "combo offer" marquee band is white-space:nowrap by design
   (it's a scrolling ticker) — on phones its inner item font/padding
   already scales down at an existing breakpoint; this only tightens the
   band's own vertical padding so it doesn't dominate a short screen */
@media (max-width: 480px) {
  .combo-offer-marquee { padding: 14px 0; }
}

/* the two bundle cards ("All 3 Levels" / "Already own 1?") only had the
   1-column grid stack (existing rule above, untouched) — nothing tuned
   their own internal spacing/type for a real phone width. Desktop's
   .combo-offer / .combo-offer-card / .combo-offer-foot rules in main.css
   are untouched; these only apply ≤480px. */
@media (max-width: 480px) {
  .combo-offer { padding: 18px; margin-top: 28px; }
  .combo-offer-grid { gap: 14px; }
  .combo-offer-card { padding: 16px 18px; gap: 12px; }
  .combo-offer-top h4 { font-size: 15px; }
  .combo-offer-top p { font-size: 13px; line-height: 1.5; }
  .combo-offer-now { font-size: 17px; }
  .combo-offer-was { font-size: 12px; }
  /* price + button stay side-by-side down to 361px; below that the pill
     button no longer has room next to two price figures, so it drops
     to its own full-width row instead of squeezing/wrapping mid-word */
}
@media (max-width: 360px) {
  .combo-offer-foot { flex-wrap: wrap; }
  .combo-offer-foot .btn-mini { width: 100%; justify-content: center; }
}


/* ==========================================================================
   7. COURSE LIST / COURSE DETAIL
   ========================================================================== */
/* course-tabs (Overview/Curriculum/Reviews) is a plain flex row with no
   wrap handling — on a 320–360px phone with 3+ tabs this can overflow.
   Make it a contained horizontal scroller instead of letting the page
   itself scroll sideways. */
@media (max-width: 480px) {
  .course-tabs {
    overflow-x: auto;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .course-tabs button { flex-shrink: 0; }
}

/* course catalog filter panel: ensure checklist columns collapse and
   the toolbar (results count + sort) stacks instead of squeezing */
@media (max-width: 600px) {
  .course-list-toolbar { flex-wrap: wrap; row-gap: 10px; }
}


/* ==========================================================================
   8. DASHBOARD / MY ACCOUNT
   ========================================================================== */
/* account-dashboard-nav already goes 2-col at one breakpoint and 1-col at
   a smaller one in react-final.css; this guarantees the shell itself
   never exceeds the viewport padding on very small phones */
@media (max-width: 400px) {
  html body .account-dashboard-nav > a { padding: 10px; font-size: 12.5px; }
}


/* ==========================================================================
   9. WOOCOMMERCE — cart / checkout
   ========================================================================== */
/* cart-react-table-head is a 3-col grid header that doesn't get the same
   ≤900px 2-col treatment as .cart-react-item, so the header labels stop
   lining up with the stacked-thumbnail row layout below 900px. Hiding the
   header row here (the item cards already restate qty/price inline) is
   safer than fighting three layers of !important to re-align it. */
@media (max-width: 900px) {
  html body.sjp-react-cart .cart-react-table-head { display: none !important; }
}


/* ==========================================================================
   10. FORMS
   ========================================================================== */
@media (max-width: 480px) {
  .contact-form button { width: 100%; }
  form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
  form select, form textarea {
    max-width: 100%;
  }
}


/* ==========================================================================
   11. GALLERY
   ========================================================================== */
/* gallery-item images already sit in a grid that collapses via main.css;
   nothing additional needed beyond the ≤480px 1-col rule in section 5 */


/* ==========================================================================
   12. FOOTER
   ========================================================================== */
@media (max-width: 480px) {
  .foot-col { text-align: left; }
  .newsletter-row { flex-direction: column; gap: 10px; }
  .newsletter-row input, .newsletter-row button { width: 100%; }
}


/* ==========================================================================
   13. FLOATING WIDGETS (WhatsApp FAB + chat assistant) — keep both inside
   the viewport and never overlapping the edge on small phones
   ========================================================================== */
@media (max-width: 480px) {
  .cb-root, .cb-fab, .whatsapp-fab { right: 14px; }
  .cb-panel { width: min(360px, calc(100vw - 28px)); }
}


/* ==========================================================================
   14. MID-RANGE GAP (901–1024px) — theme's own breakpoints jump from
   900px straight to desktop; this smooths iPad-landscape / small-laptop
   widths that fall in that gap.
   ========================================================================== */
@media (min-width: 901px) and (max-width: 1024px) {
  .wrap { max-width: 940px; }
}


/* ==========================================================================
   16. HOMEPAGE FOLLOW-UP FIXES — stats bar / hero features on small phones
   ========================================================================== */
@media (max-width: 767px) {
  .hero-features { margin-top: 3rem; justify-content: center; }
}


/* ==========================================================================
   17. QUANTITY STEPPER — Amazon-app-style "-  qty  +" control, reused on
   course cards (homepage + course list "Add to Cart") and the cart page.
   Structure: <div class="qty-stepper"><button class="qty-minus">−</button>
   <input class="qty-input" type="number" min="1" value="1">
   <button class="qty-plus">+</button></div>
   JS in main.js keeps the value in [1, 99], and — on course cards — keeps
   the paired "Add to Cart" button's data-quantity attribute in sync so
   WooCommerce's own ajax_add_to_cart handler adds the chosen quantity.
   ========================================================================== */
.qty-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line-strong, rgba(255,255,255,.18));
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255,255,255,0.04);
  height: 36px;
  flex-shrink: 0;
}
.qty-stepper .qty-btn {
  width: 34px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--ivory, #fff);
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
  user-select: none;
}
.qty-stepper .qty-btn:hover { background: rgba(255,255,255,0.08); }
.qty-stepper .qty-btn:active { background: rgba(255,255,255,0.14); }
.qty-stepper .qty-input {
  width: 36px;
  height: 100%;
  border: none;
  border-left: 1px solid var(--line-strong, rgba(255,255,255,.18));
  border-right: 1px solid var(--line-strong, rgba(255,255,255,.18));
  background: transparent;
  color: var(--ivory, #fff);
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  -moz-appearance: textfield;
}
.qty-stepper .qty-input::-webkit-outer-spin-button,
.qty-stepper .qty-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* course card "Add to Cart" row (replaces the old icon-only cart button) */
.card-actions {
  flex-wrap: wrap;
  row-gap: 8px;
}
.card-actions .btn-add-to-cart {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--gradient-brand);
  color: #0c0c12;
  font-weight: 700;
  font-size: 12.5px;
  white-space: nowrap;
  border: none;
  cursor: pointer;
}
.card-actions .btn-add-to-cart svg { width: 15px; height: 15px; flex-shrink: 0; }
.card-actions .btn-add-to-cart[disabled] { opacity: .6; cursor: default; }

@media (max-width: 480px) {
  .card-actions { justify-content: flex-start; }
  .card-actions .qty-stepper { height: 34px; }
  .card-actions .qty-stepper .qty-btn { width: 30px; }
  .card-actions .qty-stepper .qty-input { width: 30px; }
}

/* cart page: swap the plain number input for the same stepper look */
.cart-qty { display: flex; align-items: center; gap: 8px; }
.cart-qty .qty-stepper { height: 38px; }

/* checkout order-review quantity: WooCommerce prints this as plain text
   ("Course Title × 2"), not an editable field — Woo intentionally keeps
   checkout quantities read-only and only lets you change them on the cart
   page, so we only restyle it into a matching pill rather than faking an
   interactive control that wouldn't actually update anything. */
.sjp-wc-checkout-real .product-quantity {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  font-size: 12px;
  font-weight: 700;
  margin-left: 6px;
}


/* ==========================================================================
   15. GENERIC TABLE SAFETY NET — for any table in page content (e.g. legal
   pages) that isn't shop_table (already handled in woocommerce.css) or
   compare-table (already has its own scroll wrapper in main.css)
   ========================================================================== */
@media (max-width: 600px) {
  .entry-content table:not(.shop_table):not(.compare-table):not(.compare-table--lg) {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* ==========================================================================
   18. HERO — "LEARN | CREATE | GROW" shrinks clearly smaller than
   "ESSENTIALS" on phones, and the main title itself scales smoothly all
   the way down to very narrow screens instead of hitting a fixed minimum
   that's still too wide for the smallest phones (tested 200–767px).
   ========================================================================== */

/* BUG FIX — the main hero title ("KEYBOARD" / "ESSENTIALS") was getting
   cut off / overflowing on phones. Its clamp() has a 70px MINIMUM that
   never shrinks below that no matter how narrow the screen — a 400px-wide
   review earlier showed this cutting text off directly. An earlier mobile
   fix targeted .hero-content h1, but the actual visible text size comes
   from the more specific .hero-title .line selector, which that fix never
   touched. This targets the real element, and uses a pure vw-based scale
   with a low floor (not a fixed minimum) so it keeps shrinking smoothly
   all the way down to very narrow widths (tested 200–767px) instead of
   hitting a floor that's still too wide for the smallest screens. */
@media (max-width: 767px) {
  .hero-title .line { font-size: clamp(16px, 2.47vw + 11px, 30px); }
  .hero-title .line.accent { font-size: clamp(12px, 1.59vw + 8.8px, 21px); margin-top: 8px; }
}

/* ==========================================================================
   18b. HERO CONTAINER CASCADE — the heading now sits much smaller on
   phones (fix above), so the surrounding padding, paragraph text, and
   buttons are rebalanced to match instead of leaving oversized gaps
   around now-smaller text. The title/accent font-size above is ONE
   continuous formula across the whole ≤767px range rather than several
   separate breakpoint values — an earlier version of this used different
   formulas at 767/480/360px that didn't connect smoothly, causing text to
   visibly shrink as the screen got WIDER at the 480→500px boundary
   (caught by testing, not assumed). Padding/spacing below don't have that
   problem since they're plain fixed values, not formulas, so they're
   still safely graduated across the same breakpoint ladder.
   ========================================================================== */
@media (max-width: 767px) {
  .hero-pin-sticky .hero-content { padding: 0 20px 32px; }
  .hero-content { padding: 70px 20px 44px; }
  .hero-sub { font-size: 14.5px; margin: 14px auto 16px; line-height: 1.7; }
  .hero-actions { gap: 12px; margin-top: 8px; margin-bottom: 0.5rem; }
  .hero-badge { font-size: 11px; padding: 6px 12px; }
}
@media (max-width: 600px) {
  .hero-content { padding: 56px 18px 36px; }
  .hero-sub { font-size: 13.5px; margin: 12px auto 14px; }
}
@media (max-width: 480px) {
  .hero-content { padding: 48px 16px 30px; }
  .hero-sub { font-size: 13px; }
}
@media (max-width: 360px) {
  .hero-content { padding: 40px 14px 26px; }
  .hero-sub { font-size: 12.5px; }
}


/* ==========================================================================
   19. HOW IT WORKS — single column on every phone. main.css only drops to
   1 column under 560px and shows a cramped 2x2 grid between 561–900px;
   this keeps it one clean stack through the whole phone range instead.
   ========================================================================== */
@media (max-width: 767px) {
  .how-it-works-grid { grid-template-columns: 1fr; }
}


/* ==========================================================================
   20. COURSE CARD BUTTONS — minimal dark style (distinct from the bright
   brand gradient used elsewhere) for "Add to Cart" / "Buy Now" / "Continue"
   specifically inside course cards, and nudged right on mobile so the
   action sits at the edge of the card instead of butting against the
   quantity stepper.
   ========================================================================== */
.card-actions .btn-add-to-cart,
.card-actions .btn-buy-now {
  background: linear-gradient(160deg, rgba(28,26,46,.95), rgba(10,9,16,.98));
  border: 1px solid var(--line-strong, rgba(255,255,255,.16));
  color: var(--ivory, #f5f3fa);
  transition: background .35s ease, border-color .35s ease, color .35s ease;
}
.card-actions .btn-add-to-cart:hover,
.card-actions .btn-buy-now:hover {
  border-color: var(--gold, #a855f7);
  color: var(--gold-soft, #e9d5ff);
  filter: none;
}
@media (max-width: 767px) {
  .card-actions .btn-buy-now { margin-left: auto; }
}

/* "Add to Cart" → "View Cart": once the item is added, the same button
   fills with the brand gradient and its text changes (handled in
   main.js) — a single element transforming in place instead of a
   separate WooCommerce-inserted link appearing next to it. */
.card-actions .btn-add-to-cart.is-in-cart {
  background: var(--gradient-brand);
  border-color: transparent;
  color: #0c0c12;
}
.card-actions .btn-add-to-cart.is-in-cart:hover {
  filter: brightness(1.08);
  color: #0c0c12;
}


/* ==========================================================================
   21. CELEBRATION CONFETTI — spawned once by main.js when the combo-offer
   section first scrolls into view. Pure CSS animation on JS-inserted
   pieces; respects prefers-reduced-motion (JS skips spawning entirely).
   ========================================================================== */
.sjp-confetti-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 5;
}
.sjp-confetti-piece {
  position: absolute;
  top: -24px;
  width: 8px;
  height: 14px;
  opacity: 0.95;
  animation-name: sjpConfettiFall;
  animation-timing-function: cubic-bezier(.35,0,.65,1);
  animation-fill-mode: forwards;
}
@keyframes sjpConfettiFall {
  0%   { transform: translateY(0) translateX(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(var(--sjp-fall, 420px)) translateX(var(--sjp-drift, 40px)) rotate(var(--sjp-spin, 380deg)); opacity: 0; }
}

/* ==========================================================================
   22. BUG FIX — course card actions row was overflowing/overlapping on
   phones. .card-actions has flex-shrink:0 in main.css so it never yielded
   space to .price on the same row, and its own wrapped content (qty
   stepper + Add to Cart + Buy Now) could spill past the card edge. Now
   price gets its own row and actions get the full card width to wrap
   safely within.
   ========================================================================== */
@media (max-width: 600px) {
  .card-foot { flex-direction: column; align-items: stretch; gap: 12px; }
  .card-actions {
    flex-shrink: 1;
    flex-basis: auto;
    width: 100%;
    max-width: 100%;
    justify-content: flex-start;
  }
  /* .card-actions is full-width here, so margin-left:auto on Buy Now
     (meant for the 600–767px row layout above) would shove it away from
     Add to Cart to the far right of that full row instead of sitting
     next to it — reset it back to sitting together. */
  .card-actions .btn-buy-now { margin-left: 0; }
}

/* ==========================================================================
   23. BUG FIX — testimonial cards stayed a fixed 280px even on the
   smallest phones (main.css only steps down from 340px to 280px at
   900px, nothing smaller). Shrinks proportionally further down.
   ========================================================================== */
@media (max-width: 480px) {
  .testi-track .testi-card { width: 230px; padding: 20px; }
}
@media (max-width: 360px) {
  .testi-track .testi-card { width: 200px; padding: 16px; }
}

/* ==========================================================================
   24. BUG FIX — footer newsletter button had no vertical padding
   (main.css sets "padding:0 18px"), so next to the input it rendered as a
   thin, squashed bar instead of a proper button — worst on mobile where
   the row stacks to full width and the flatness becomes obvious.
   ========================================================================== */
.newsletter-row button {
  padding: 13px 18px;
  min-height: 44px;
}

/* ==========================================================================
   25. CHECKOUT POLISH
   ========================================================================== */

/* "Have a coupon? Click here to enter your code" — WooCommerce prints this
   as a plain default notice with no intentional styling from us before
   now. Contained width (it was bleeding edge-to-edge), a real pill shape,
   and icon/text spacing so nothing overlaps if a gateway or browser adds
   its own leading icon. */
.sjp-wc-checkout-real .woocommerce-notices-wrapper {
  width: 100%;
  max-width: 100%;
  margin: 0 0 20px;
}
.sjp-wc-checkout-real .woocommerce-info,
.sjp-wc-checkout-real .woocommerce-message {
  display: flex !important;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  box-sizing: border-box;
  padding: 14px 20px !important;
  margin: 0 0 14px !important;
  border-radius: 12px;
  list-style: none;
  font-size: 13.5px;
  line-height: 1.5;
}
.sjp-wc-checkout-real .woocommerce-info::before,
.sjp-wc-checkout-real .woocommerce-message::before {
  position: static !important;
  margin-right: 4px;
}
.sjp-wc-checkout-real .showcoupon {
  color: var(--gold-soft, #e9d5ff);
  font-weight: 700;
  text-decoration: underline;
  white-space: nowrap;
}

/* ==========================================================================
   47. BUG FIX — the icon/text overlap fix above was scoped only to
   checkout, so the exact same overlap ("✓rt updated." — the checkmark
   icon sitting on top of the text) still showed up on the cart page's
   "Cart updated." notice and anywhere else WooCommerce prints a notice.
   This is the same fix, applied sitewide instead of just on checkout.
   ========================================================================== */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
  display: flex !important;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  box-sizing: border-box;
  padding: 14px 20px !important;
  margin: 0 0 14px !important;
  border-radius: 12px;
  list-style: none;
  font-size: 13.5px;
  line-height: 1.5;
}
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before {
  position: static !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px !important;
  height: 20px !important;
  font-size: 16px !important;
  line-height: 1 !important;
  margin: 0 4px 0 0 !important;
  top: auto !important;
  left: auto !important;
  float: none !important;
}

/* Payment method gateway logos (PhonePe / Razorpay etc.) print at their
   native banner size by default — far too large next to a small radio
   label. Capped down to a small, consistent icon like a modern payment
   app's UPI section, not a full logo banner. */
.sjp-wc-checkout-real ul.payment_methods img,
.sjp-wc-checkout-real .payment_box img,
.sjp-wc-checkout-real .wc_payment_method img {
  max-height: 20px !important;
  width: auto !important;
  max-width: 60px !important;
  vertical-align: middle !important;
  margin: 0 0 0 8px !important;
  object-fit: contain;
}
.sjp-wc-checkout-real ul.payment_methods li label {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Order-notes section is removed via functions.php
   (woocommerce_enable_order_notes_field filter) — nothing to hide here. */


/* ==========================================================================
   26. Course-card action row — unify heights so the qty stepper, "Add to
   Cart" and "Buy Now"/"Continue" line up pixel-for-pixel on both web and
   mobile instead of each sitting at a slightly different height.
   ========================================================================== */
.card-actions .qty-stepper,
.card-actions .btn-add-to-cart,
.card-actions .btn-buy-now {
  height: 36px;
  box-sizing: border-box;
}
@media (max-width: 480px) {
  .card-actions .qty-stepper,
  .card-actions .btn-add-to-cart,
  .card-actions .btn-buy-now {
    height: 34px;
  }
}

/* ==========================================================================
   27. FOOTER SOCIAL ICONS — bigger circle + a hover treatment that
   actually reads as intentional (color fill + lift) instead of the bare
   34px outline they were before.
   ========================================================================== */
.socials { gap: 12px; }
.socials a {
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-strong, rgba(255,255,255,.18));
  background: rgba(255,255,255,0.04);
  transition: transform .2s ease, border-color .2s ease, background .2s ease, color .2s ease;
}
.socials a:hover {
  transform: translateY(-3px);
  background: var(--gradient-brand);
  color: #fff;
  border-color: transparent;
}
.social-link--insta:hover { background: linear-gradient(135deg, #F58529, #DD2A7B, #8134AF, #515BD4); }
.social-link--youtube:hover { background: #FF0000; }


/* ==========================================================================
   28. HOW IT WORKS — the 4 cards run large on phones (26px/22px padding,
   38px icon) because they were only ever sized for desktop's 4-across
   grid. Compact them specifically for phones now that section 19 already
   stacks them to one column there.
   ========================================================================== */
@media (max-width: 767px) {
  .how-step { padding: 18px 16px; }
  .how-step-ico { width: 30px; height: 30px; margin-bottom: 10px; }
  .how-step-num { margin-bottom: 8px; font-size: 12px; }
  .how-step h4 { font-size: 15px; margin: 0 0 4px; }
  .how-step p { font-size: 13px; line-height: 1.5; }
}


/* ==========================================================================
   29. BUG FIX — course cards overflowing their own grid column (visible
   on the Course List page, where the filter sidebar leaves less room per
   card). CSS Grid items default to min-width:auto, so a card whose
   content has a large min-content width (the nowrap "Buy Now"/"Add to
   Cart" buttons) can force its whole grid column wider than the track,
   pushing the layout past the viewport instead of wrapping internally.
   This lets the card actually shrink to the track's width so the
   existing flex-wrap on .card-actions can do its job.
   ========================================================================== */
.courses-grid { min-width: 0; }
.courses-grid > * { min-width: 0; }
.course-card { min-width: 0; }


/* ==========================================================================
   30. Hide any third-party floating accessibility widget button. This
   widget isn't part of the theme — it's injected by a separate plugin —
   so this covers the common plugin patterns defensively. If it's still
   visible after this, the cleanest fix is deactivating that plugin from
   Plugins in wp-admin (search for "accessibility").
   ========================================================================== */
#wah-btn-load, .wah-btn, #userwayAccessibilityIcon, .acsb-trigger, #acsb-trigger,
[class*="accessibility-widget"], [id*="accessibility-widget"],
[class*="a11y-toolbar"], [id*="a11y-toolbar"] {
  display: none !important;
}

/* ==========================================================================
   31. BUG FIX — Production page's 3 feature cards (Track Production /
   Mixing & Mastering / Session Keyboards) used an INLINE
   grid-template-columns:repeat(3,1fr) with no responsive fallback (inline
   styles can't have media queries), so on any narrower screen the text
   was forced into 3 fixed columns and got cut off. Replaced with a real
   class, styled as square bordered cards like the homepage's how-it-works
   steps, that properly collapses on smaller screens.
   ========================================================================== */
.production-features-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.production-features-grid .feature {
  flex-direction: column;
  align-items: flex-start;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 22px 20px;
}
.production-features-grid .feature .ico { margin-bottom: 12px; }
@media (max-width: 900px) {
  .production-features-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 600px) {
  .production-features-grid { grid-template-columns: 1fr; }
}


/* ==========================================================================
   32. BUG FIX — footer nav links (Policies / Quick Links / Get In Touch)
   were rendering as bordered pill buttons instead of plain text links.
   The theme's own footer CSS never styled them that way — something else
   in the stack (a page-builder's global link/button style) was bleeding
   onto them — so this resets every footer link back to plain text,
   consistent across every page the footer appears on.
   ========================================================================== */
.foot-col a,
.foot-col ul li a,
.foot-col ul li {
  display: block !important;
  background: none !important;
  border: none !important;
  outline: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 0 !important;
  font-size: 13.5px !important;
  font-weight: 400 !important;
  color: var(--slate) !important;
  text-decoration: none !important;
}
.foot-col a:hover,
.foot-col ul li a:hover {
  color: var(--gold) !important;
}

/* ==========================================================================
   33. ROOT-CAUSE FIX — course card action row alignment + "disappearing"
   Buy Now button.

   What was actually happening: .course-card has overflow:hidden (needed
   for its gradient border effect) and, on the Course List page specifically,
   .course-list-section .course-card{height:100%} stretches every card to
   match the tallest one in its grid row. Combined with the Add to Cart /
   Buy Now row wrapping to 2 lines on narrow cards (when both buttons don't
   fit on one line), a card whose own natural content was shorter than the
   row's stretched height could have its wrapped second line pushed past
   the visible/clipped box — not hidden by any display:none, genuinely
   clipped by the overflow. On the homepage this specific height:100% rule
   doesn't apply, so the effect was more like inconsistent alignment than
   full disappearance there — the same underlying gap (buttons not reliably
   pinned to a bottom row) is the cause of the alignment issue too.

   Fix: make every .course-card a flex column where the body grows to fill
   available space and the price/action row is pinned to the bottom with
   margin-top:auto. This means card height is always driven by whichever
   card actually needs the most room (auto, never a hardcoded pixel value),
   so a wrapped 2-line action row simply makes that card taller instead of
   being clipped — and every card's action row lines up at the same
   position regardless of description length, on both the homepage and
   Course List page, mobile and desktop.
   ========================================================================== */
.course-card {
  display: flex;
  flex-direction: column;
}
.course-card .body {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.course-card .card-foot {
  margin-top: auto;
}

/* ==========================================================================
   34. STRONGER FIX — the previous flex-column pass (section 33) fixed
   internal distribution but left the actual suspect rule untouched:
   .course-list-section .course-card{height:100%} in main.css forces every
   card to exactly match its grid row's stretched height. Combined with
   overflow:hidden on .course-card (kept intentionally for the gradient
   border), a card whose Add to Cart + Buy Now row wraps to 2 lines can
   still need more height than that stretched value allows, and the
   overflow clips the second line — a genuine, reproducible bug, not a
   display:none anywhere. Overriding height:100% to auto lets each card
   size to its own content; CSS Grid's default align-items:stretch still
   equalizes the row using every card's natural (uncropped) height, so
   cards still line up — the difference is nothing gets clipped anymore.
   ========================================================================== */
.course-list-section .course-card {
  height: auto;
}

/* Graduated shrink for the two action buttons before they're ever allowed
   to wrap to a second line — smaller padding/font/gap first, matching the
   brief's "shrink before stacking" requirement. */
@media (max-width: 400px) {
  .card-actions { gap: 6px; }
  .card-actions .btn-add-to-cart,
  .card-actions .btn-buy-now {
    padding: 0 10px;
    font-size: 11.5px;
  }
  .card-actions .btn-add-to-cart svg { width: 13px; height: 13px; }
}


/* ==========================================================================
   35. Mobile course thumbnail — 16/10 crops too much of the person's
   upper body/face on a narrow card. Taller ratio + a slightly top-biased
   object-position keeps the face fully in frame without stretching or
   distorting the image. Desktop (≥768px) keeps the original 16/10 crop
   from main.css untouched.
   ========================================================================== */
@media (max-width: 767px) {
  .course-card .thumb {
    aspect-ratio: 4 / 3;
  }
  .course-card .thumb img {
    object-position: center 22%;
  }
}

/* ==========================================================================
   36. Desktop Buy Now alignment — made explicit rather than relying on
   .card-foot's space-between as an implicit side-effect. .price gets
   flex:1 so it never competes for space, and .card-actions is pinned to
   the end of the row — guarantees the button group always sits at the
   right edge even if a price string is unusually long or short, on every
   card consistently.
   ========================================================================== */
.card-foot .price { flex: 1; }
.card-foot .card-actions { justify-content: flex-end; }

/* ==========================================================================
   37. CONTACT PAGE REDESIGN — all new classes, scoped only to the contact
   page (verified nothing else in the theme uses .contact-form/.contact-grid
   etc., and these are new class names entirely so there's no collision).
   The <form> itself keeps the exact same action/fields/nonce as before —
   only the presentation changed, so inc/forms.php's handler needs no
   changes at all.
   ========================================================================== */

.sjp-contact-quick {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin: 0 0 40px;
}
.sjp-contact-chip {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 220px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px 18px;
  color: var(--ivory);
  transition: border-color .2s ease, transform .2s ease, background .2s ease;
}
.sjp-contact-chip:hover {
  border-color: var(--gold);
  transform: translateY(-3px);
  background: var(--card-2);
}
.sjp-contact-chip-ico {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gradient-brand);
  color: #fff;
}
.sjp-contact-chip-ico svg { width: 19px; height: 19px; }
.sjp-contact-chip strong { display: block; font-size: 13.5px; font-weight: 700; }
.sjp-contact-chip small { display: block; font-size: 11.5px; color: var(--slate); margin-top: 2px; overflow-wrap: anywhere; }

.sjp-contact-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 32px;
  align-items: start;
  padding-bottom: 80px;
}

.sjp-contact-form-card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(165deg, rgba(30,28,54,.7), rgba(13,12,22,.85));
  border: 1px solid var(--line-strong);
  border-radius: 22px;
  padding: 40px;
  backdrop-filter: blur(16px);
}
.sjp-contact-form-glow {
  position: absolute;
  top: -80px;
  right: -80px;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  background: var(--gradient-brand);
  opacity: .18;
  filter: blur(50px);
  pointer-events: none;
}
.sjp-contact-form-card h2 { margin: 0 0 6px; font-size: 24px; position: relative; z-index: 1; }
.sjp-contact-form-card > p { color: var(--slate); font-size: 13.5px; margin: 0 0 28px; position: relative; z-index: 1; }

.sjp-contact-form { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 22px; }
.sjp-field { position: relative; }
.sjp-field input,
.sjp-field textarea {
  width: 100%;
  box-sizing: border-box;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  padding: 20px 16px 8px;
  color: var(--ivory);
  font-size: 14px;
  font-family: inherit;
  transition: border-color .2s ease;
}
.sjp-field textarea { resize: vertical; min-height: 110px; }
.sjp-field input:focus, .sjp-field textarea:focus { outline: none; border-color: var(--gold); }
.sjp-field label {
  position: absolute;
  left: 16px;
  top: 19px;
  color: var(--slate);
  font-size: 14px;
  pointer-events: none;
  transition: transform .18s ease, color .18s ease;
  transform-origin: left top;
}
.sjp-field input:focus + label,
.sjp-field input:not(:placeholder-shown) + label,
.sjp-field textarea:focus + label,
.sjp-field textarea:not(:placeholder-shown) + label {
  transform: translateY(-11px) scale(.78);
  color: var(--gold);
}

.sjp-contact-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--gradient-brand);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 14px 26px;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  transition: filter .2s ease, transform .2s ease;
  align-self: flex-start;
}
.sjp-contact-submit:hover { filter: brightness(1.1); transform: translateY(-1px); }
.sjp-contact-submit svg { width: 16px; height: 16px; transition: transform .2s ease; }
.sjp-contact-submit:hover svg { transform: translateX(3px); }

.sjp-contact-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.5;
}
.sjp-contact-banner svg { flex-shrink: 0; }
.sjp-contact-banner--ok { background: rgba(34,197,94,.12); color: #8ef7c0; border: 1px solid rgba(34,197,94,.3); }
.sjp-contact-banner--err { background: rgba(239,68,68,.12); color: #ff8e8e; border: 1px solid rgba(239,68,68,.3); }

.sjp-contact-side { display: flex; flex-direction: column; gap: 20px; }
.sjp-contact-side-card { background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 26px; }
.sjp-contact-side-card h3 { margin: 0 0 8px; font-size: 16px; }
.sjp-contact-side-card p { color: var(--slate); font-size: 13px; margin: 0 0 16px; line-height: 1.6; }
.sjp-contact-side-card:last-child p { margin-bottom: 0; }

@media (max-width: 860px) {
  .sjp-contact-grid { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  .sjp-contact-quick { flex-direction: column; }
}
@media (max-width: 480px) {
  .sjp-contact-form-card { padding: 26px 20px; }
}

/* ==========================================================================
   38. CHECKOUT — payment method section redesign (minimal, icon-led) and
   removal of the now-empty "Additional information" wrapper left behind
   after order notes were disabled in functions.php.
   ========================================================================== */

/* Now-empty wrapper — order notes were removed via
   woocommerce_enable_order_notes_field, so this card has nothing left in
   it and was just showing as a blank box. */
.sjp-wc-checkout-real .woocommerce-additional-fields { display: none !important; }

/* "UPI Payments" heading above the method list */
.sjp-wc-checkout-real .woocommerce-checkout-payment { padding: 16px 14px; }
.sjp-wc-checkout-real .woocommerce-checkout-payment::before {
  content: "UPI Payments";
  display: block;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gold-soft, #e9d5ff);
  margin: 2px 4px 12px;
}

.sjp-wc-checkout-real ul.payment_methods {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0;
  margin: 0;
}
.sjp-wc-checkout-real ul.payment_methods li {
  display: flex;
  align-items: center;
  border: 1px solid var(--line-strong, rgba(255,255,255,.16));
  border-radius: 12px;
  padding: 12px 14px;
  transition: border-color .2s ease, background .2s ease;
}
.sjp-wc-checkout-real ul.payment_methods li:hover {
  border-color: var(--gold);
}
.sjp-wc-checkout-real ul.payment_methods li:has(input:checked) {
  border-color: var(--gold);
  background: rgba(168,85,247,.08);
}
.sjp-wc-checkout-real ul.payment_methods input.input-radio { margin: 0 10px 0 0; flex-shrink: 0; }
.sjp-wc-checkout-real ul.payment_methods label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  cursor: pointer;
  flex: 1;
}

/* The gateway plugin's own <img> logo is hidden and replaced with a
   fixed, known-good icon — a small circular badge using the exact PhonePe
   / Razorpay artwork provided, rather than whatever the plugin renders at
   whatever size/shape it chooses. Each li gets the icon via ::before so
   it's not dependent on the plugin's own markup structure at all. */
.sjp-wc-checkout-real ul.payment_methods img { display: none !important; }
.sjp-wc-checkout-real ul.payment_methods li { position: relative; }
.sjp-wc-checkout-real ul.payment_methods li::before {
  content: "";
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  flex-shrink: 0;
  margin-right: 10px;
  order: -1;
}
.sjp-wc-checkout-real ul.payment_methods li:has(label[for*="phonepe" i])::before {
  background-image: url('../img/payment-icons/phonepe-icon.png');
}
.sjp-wc-checkout-real ul.payment_methods li:has(label[for*="razorpay" i])::before {
  background-image: url('../img/payment-icons/razorpay-icon.png');
  background-color: #fff;
  background-size: 70%;
}

/* PhonePe — icon badge tints green on hover/selected, matching its brand */
.sjp-wc-checkout-real ul.payment_methods li:has(label[for*="phonepe" i]):hover,
.sjp-wc-checkout-real ul.payment_methods li:has(input:checked + label[for*="phonepe" i]) {
  border-color: #3fe07f;
  background: rgba(63,224,127,.08);
}
.sjp-wc-checkout-real ul.payment_methods li:has(label[for*="phonepe" i]) img {
  transition: background .2s ease;
}
.sjp-wc-checkout-real ul.payment_methods li:has(label[for*="phonepe" i]):hover img,
.sjp-wc-checkout-real ul.payment_methods li:has(input:checked + label[for*="phonepe" i]) img {
  background: #3fe07f;
}

/* The description "speech bubble" WooCommerce prints under the selected
   method (the arrow + explanatory paragraph) — dropped for a cleaner,
   minimal look; the icon + label already say what's needed. */
.sjp-wc-checkout-real .payment_box { display: none !important; }

/* ==========================================================================
   39. BUG FIX — Sign In / Register page too large on mobile. Two real
   causes: (1) react-final.css sets .account-visual h2{font-size:26px
   !important} with no media query at all, so it silently overrides
   main.css's own attempt to shrink it at ≤820px (26px !important always
   wins over a plain, non-!important rule regardless of source order); and
   (2) more importantly, the decorative "Learn. Create. Perform." panel
   (with the animated keyboard graphic) keeps its full desktop padding and
   size when it stacks on top of the actual sign-in form on mobile,
   pushing the real form down and making the whole page feel oversized
   before you even reach a username field.
   ========================================================================== */
@media (max-width: 767px) {
  html body .sjp-account-react { padding: 110px 16px 60px; }
  .account-visual { padding: 26px 20px 20px; gap: 12px; }
  .auto-keyboard { transform: scale(0.72); margin-bottom: -8px; }
  html body .account-visual h2 { font-size: 20px !important; margin-bottom: 4px; }
  .account-visual p { font-size: 12.5px; max-width: 240px; }
  .account-form-side { padding: 26px 20px; }
  html body .account-react-tabs { margin-bottom: 18px; }
  html body .sjp-account-submit { padding: 12px 20px !important; font-size: 13.5px; }
  html body .sjp-auth-form .input-text { padding: 11px 13px !important; }
}

/* ==========================================================================
   40. BUG FIX — auth card (Sign In / Register) was never actually
   horizontally centered. .account-shell has width:100%;max-width:920px
   but no margin:auto anywhere in the theme, so on a wide viewport it just
   sits at the left edge of its container instead of the middle.
   ========================================================================== */
.account-shell { margin: 0 auto; }

/* BUG FIX — label sat right on top of its input with no breathing room;
   .sjp-auth-form label was never given display:block or margin-bottom, so
   it only had the browser's inline default spacing. */
html body .sjp-auth-form label {
  display: block;
  margin-bottom: 8px;
}
.sjp-auth-form .form-row {
  margin-bottom: 18px;
}

/* Registration form: hide any field beyond the three the theme actually
   defines (Full name / Email / Password). Whatever adds "Prove your
   humanity" and "Academy Track" isn't part of this theme's own code — it
   hooks in via WooCommerce's woocommerce_register_form action, most
   likely from a separate plugin. This hides them by whitelisting the
   fields we know, rather than needing to guess that plugin's exact class
   names.
   IMPORTANT: if "Prove your humanity" is a spam/anti-bot check, hiding it
   with CSS only hides it visually — the plugin may still expect it to be
   filled server-side and could reject every registration. Test an actual
   sign-up after uploading this. If it fails, the correct fix is disabling
   that field in the plugin's own settings, not hiding it here. */
.woocommerce-form-register .form-row:not(:has(#reg_full_name)):not(:has(#reg_email)):not(:has(#reg_password)) {
  display: none !important;
}

/* ==========================================================================
   41. BUG FIX — Sign In and Register both showing at the same time,
   stacked on the page. Real cause, confirmed by searching the entire
   theme: no CSS anywhere ever hides the inactive .account-react-form
   section, and no JS anywhere handles clicking the Sign In / Register
   tabs. The "tabs" were purely decorative — clicking them did nothing.
   Both forms have simply always been fully visible regardless of which
   tab is highlighted. This is a theme code gap, not a plugin conflict.
   ========================================================================== */
.account-react-form { display: none; }
.account-react-form.is-active { display: block; }

/* ==========================================================================
   42. CART CROSS-SELLS — "You might also like", wired to WooCommerce's
   native Cross-sells field (Products → edit a course → Linked Products
   tab). Previously nothing rendered this anywhere on the site, so
   configuring it in wp-admin had no visible effect. Set a bundle as the
   cross-sell on each individual course product to surface it here when
   someone has that course in their cart.
   ========================================================================== */
.cart-cross-sells { margin-top: 40px; }
.cart-cross-sells-title { font-size: 18px; margin: 0 0 16px; }
.cart-cross-sells-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 18px;
}
.cart-cross-sell-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.cart-cross-sell-thumb { display: block; aspect-ratio: 16/9; overflow: hidden; background: #000; }
.cart-cross-sell-thumb img { width: 100%; height: 100%; object-fit: cover; }
.cart-cross-sell-body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 8px; }
.cart-cross-sell-body h4 { margin: 0; font-size: 14px; }
.cart-cross-sell-body h4 a { color: var(--ivory); }
.cart-cross-sell-price { font-size: 13px; font-weight: 700; color: var(--gold-soft, #e9d5ff); }
.cart-cross-sell-body .btn-buy-now { align-self: flex-start; }

/* ==========================================================================
   43. BUG FIX — combo-offer cards were showing THREE price numbers
   instead of two: our own hardcoded "was" price alongside the real
   product's full price_html (which already contains its own del/ins
   pair). The hardcoded span is now removed from the template for the
   real-product case (see front-page.php) — this just styles
   WooCommerce's own <del>/<ins> markup to match the look the old
   hardcoded spans had, so the visual style doesn't change, only the
   duplicate number goes away.
   ========================================================================== */
.combo-offer-price del { font-size: 13px; color: var(--slate); text-decoration: line-through; opacity: 1; }
.combo-offer-price ins { font-size: 19px; font-weight: 800; color: var(--ivory); text-decoration: none; margin-left: 6px; }

/* ==========================================================================
   44. BUG FIX — comparison table (Level 2 vs Level 3 etc.) already
   scrolls horizontally on narrow screens (.compare-table-wrap has
   overflow-x:auto), but the row-label column ("Best For", "Lessons",
   "Access", "Price") scrolls away with everything else — so once you
   scroll to actually read the Level 2/3 values, you lose track of which
   row you're looking at. Pinning that first column fixes exactly the
   "cut off, confusing" mobile screenshot.
   ========================================================================== */
.compare-table th:first-child,
.compare-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: rgba(14,13,20,0.97);
}
.compare-table th:first-child { background: rgba(20,19,28,0.97); }

/* ==========================================================================
   45. BUG FIX — search overlay "jumping up". It's position:fixed with
   align-items:center, so it re-centers inside whatever the CURRENT
   viewport height is. On mobile, tapping the search input opens the
   keyboard, which shrinks the visible viewport — the overlay then
   re-centers into that shorter space, visually jumping upward. Anchoring
   it near the top instead of centering avoids the recenter entirely.
   ========================================================================== */
.search-overlay {
  align-items: flex-start;
  padding-top: max(90px, 10vh);
}

/* ==========================================================================
   46. Show/hide password toggle — small eye icon inside any password
   field (login, register, account details), added by main.js.
   ========================================================================== */
.sjp-pw-wrap { position: relative; display: block; }
.sjp-pw-wrap input[type="password"],
.sjp-pw-wrap input[type="text"] { padding-right: 44px !important; }
.sjp-pw-toggle {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 4px;
  color: var(--slate, #9a95b0);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sjp-pw-toggle svg { width: 18px; height: 18px; }
.sjp-pw-toggle.is-visible { color: var(--gold, #a855f7); }

/* ==========================================================================
   47. HERO POLISH — badge clarity, "Explore Courses" border to match the
   Login button's animated gradient-border style, and stats bar reverted
   to the 2-column grid at every phone width (a previous fix forced it to
   a single stacked column below 380px, which looked worse, not better).
   ========================================================================== */
.hero-badge {
  background: rgba(168,85,247,0.10);
  border-color: rgba(168,85,247,0.35);
  color: var(--ivory, #f5f3fa);
  box-shadow: 0 0 0 1px rgba(168,85,247,0.08), 0 4px 18px rgba(168,85,247,0.15);
}

.hero-link {
  position: relative;
  border: 3.5px solid transparent;
  border-radius: 999px;
  padding: 10px 20px;
  background:
    linear-gradient(120deg, #09090d 0%, #09090d 100%) padding-box,
    linear-gradient(120deg, #EC4899 0%, #4A7CFF 52%, #EC4899 100%) border-box;
  background-clip: padding-box, border-box;
  background-origin: padding-box, border-box;
  background-size: 100% 100%, 200% 100%;
  animation: snakeMove 4s linear infinite;
}
.hero-link .underline { display: none; }

/* "View Course" (comparison table) — a distinct dark-outline style
   instead of the same bright pink/purple gradient used for Buy Now
   everywhere else, so it reads as its own, more understated action. */
.compare-table--lg .btn-mini.btn-buy-now {
  background: linear-gradient(160deg, rgba(28,26,46,.95), rgba(10,9,16,.98)) !important;
  border: 1.5px solid var(--gold, #a855f7) !important;
  color: var(--ivory, #f5f3fa) !important;
}
.compare-table--lg .btn-mini.btn-buy-now:hover {
  background: var(--gold, #a855f7) !important;
  color: #0c0c12 !important;
}

/* ==========================================================================
   48. BUG FIX — after clicking "Add to Cart" on a course card, WooCommerce
   automatically inserts its own "View cart" link (class .added_to_cart)
   right next to the button. This class was never styled anywhere in the
   theme, so it was rendering with WooCommerce's own default styling
   (typically float-based), which breaks out of the card-actions flexbox
   entirely instead of wrapping — exactly the overflow-past-the-card
   screenshot showed, appearing once "Buy Now" made the row 3 items wide.
   Styling it to match the other pill buttons and explicitly killing any
   float lets it participate in the existing flex-wrap layout correctly.
   ========================================================================== */
.card-actions .added_to_cart {
  float: none !important;
  display: inline-flex !important;
  width: auto !important;
  max-width: none !important;
  align-items: center;
  gap: 6px;
  height: 36px !important;
  min-height: 0 !important;
  box-sizing: border-box;
  padding: 0 14px !important;
  margin: 0 !important;
  border-radius: 999px !important;
  background: var(--gradient-brand) !important;
  color: #fff !important;
  font-weight: 700;
  font-size: 12.5px !important;
  line-height: 36px !important;
  white-space: nowrap;
  flex-shrink: 0;
}
.card-actions .added_to_cart:hover { filter: brightness(1.1); }
/* ==========================================================================
   FREE SAMPLE VIDEO MODAL — button sits on the right via the existing
   .lead-magnet flex layout. This is the popup itself: full-screen
   overlay, centered 16:9 video box, tested down to a 320x756 phone.
   ========================================================================== */
.sjp-video-modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.sjp-video-modal[hidden] { display: none; }
.sjp-video-modal.is-open { opacity: 1; }
body.sjp-video-modal-open { overflow: hidden; }

.sjp-video-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 5, 10, 0.88);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.sjp-video-modal-box {
  position: relative;
  width: 100%;
  max-width: 900px;
  transform: scale(0.96);
  transition: transform 0.22s ease;
}
.sjp-video-modal.is-open .sjp-video-modal-box { transform: scale(1); }

.sjp-video-modal-frame {
  position: relative;
  z-index: 1;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: #000;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.08);
}
.sjp-video-modal-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.sjp-video-modal-close {
  position: absolute;
  top: -46px;
  right: 0;
  z-index: 2;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.sjp-video-modal-close:hover { background: var(--gold, #a855f7); border-color: transparent; }
.sjp-video-modal-close svg { width: 18px; height: 18px; }

@media (max-width: 480px) {
  .sjp-video-modal { padding: 10px; }
  .sjp-video-modal-close {
    top: 8px;
    right: 8px;
    width: 34px;
    height: 34px;
    background: rgba(10,9,16,0.75);
  }
  .sjp-video-modal-close svg { width: 15px; height: 15px; }
}

@media (max-width: 700px) {
  .lead-magnet .js-open-video-modal { width: 100%; justify-content: center; }
}

/* ==========================================================================
   49. Lead-magnet ("Start learning Keyboard") card sitting flush against
   the course card grid right below it — at narrow phone widths (roughly
   340–400px) the gap between them reads small enough that the course
   card's own animated rainbow border can look like it's part of the
   lead-magnet card. Extra bottom margin here just spaces them apart;
   nothing else about either card changes.
   ========================================================================== */
@media (min-width: 340px) and (max-width: 400px) {
  #lead-magnet {
    margin-bottom: 24px;
  }
}