/* ============================================================================
   Pallavi Spoken English Classes — style.css
   Ported from the client-approved UI_System/styles.css (same tokens, same class
   names) and extended for a real site: nav interactions, mobile bottom nav,
   sticky purchase sidebar, comparison table, video reviews, popup, chatbot,
   accordion, alerts, pagination.

   Screenshot-only rules from the original (fixed .page heights, .phone-preview,
   body[data-variant] hero variations) are intentionally dropped.
   ========================================================================== */

:root{
  --navy:#0B3A82; --navy-2:#06285d; --orange:#F58220; --ink:#15233b;
  --muted:#64748b; --line:#dfe7f1; --pale:#EEF5FF; --gray:#F5F7FA;
  --white:#fff; --green:#16a273; --red:#e85959;
  --shadow:0 18px 50px rgba(11,58,130,.10);
  --r:20px;
  --serif:"Lora",Georgia,serif;
  --sans:"DM Sans","Segoe UI",system-ui,sans-serif;
  --chat-font:"Poppins","Segoe UI",system-ui,sans-serif;
  --nav-h:88px;
}

*{box-sizing:border-box}

/* The mobile horizontal-scroll guard.
   MUST be `clip`, never `hidden`. `overflow-x:hidden` on html/body computes
   overflow-y to `auto`, which turns the root into a scroll container and
   SILENTLY BREAKS every position:sticky on the site — the header, the sticky
   purchase panel and the admin sidebar all scrolled away because of it.
   `clip` stops horizontal scrolling without creating a scroll container.
   Wide tracks (.vid-row, .reel-row, .rev-viewport, .table-wrap) each carry their
   own overflow, so this is only a backstop. */
body{overflow-x:clip}

/* An author `display` rule beats the browser's [hidden] rule, so any element we
   hide from JS stays visible unless we say this once, globally. Cost us a live
   bug: the shelf arrows had display:grid and ignored `hidden` completely. */
[hidden]{display:none !important}

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;background:#fff;color:var(--ink);
  font:16px/1.55 var(--sans);letter-spacing:0;
  -webkit-font-smoothing:antialiased;
}
button,input,select,textarea{font:inherit}
img,video{max-width:100%;height:auto}
a{color:inherit}
:focus-visible{outline:3px solid rgba(11,58,130,.35);outline-offset:2px;border-radius:6px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

.wrap{width:min(1320px,calc(100% - 48px));margin-inline:auto}

/* ── Typography ─────────────────────────────────────────────────────────── */
h1,h2,h3,p{margin-top:0}
h1{font:italic 700 clamp(38px,4.4vw,64px)/1.08 var(--serif);letter-spacing:-.03em}
h2{font:italic 700 clamp(30px,3vw,42px)/1.15 var(--serif);letter-spacing:-.02em}
h3{font-size:19px;line-height:1.3;font-weight:700}
p{color:var(--muted)}
.orange{color:var(--orange)}
.navy{color:var(--navy)}
.muted{color:var(--muted)}
.tiny{font-size:12px}
.center{text-align:center}
.right{text-align:right}
.mr-line{color:var(--navy);font-weight:600}          /* the Marathi/Devanagari line */

.eyebrow{
  display:inline-flex;align-items:center;gap:8px;color:var(--navy);
  font-weight:700;font-size:13px;text-transform:uppercase;letter-spacing:.12em;
}
.eyebrow:before{content:"";width:24px;height:3px;border-radius:3px;background:var(--orange)}

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn{
  border:0;border-radius:12px;padding:14px 22px;font-weight:700;
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  text-decoration:none;cursor:pointer;line-height:1.1;
  transition:transform .18s ease,box-shadow .18s ease,background .18s ease,color .18s ease;
}
.btn.primary{background:var(--orange);color:#fff;box-shadow:0 10px 24px rgba(245,130,32,.25)}
.btn.secondary{background:var(--navy);color:#fff}
.btn.ghost{background:#fff;border:1px solid var(--line);color:var(--navy)}
.btn.white{background:#fff;color:var(--navy)}
.btn.danger{background:var(--red);color:#fff}
.btn.block{width:100%}
.btn.small{padding:10px 15px;font-size:13px}
.btn.large{padding:17px 30px;font-size:17px}
.btn:hover{transform:translateY(-2px)}
.btn.primary:hover{box-shadow:0 16px 32px rgba(245,130,32,.34)}
.btn.secondary:hover{background:var(--navy-2)}
.btn.ghost:hover{background:var(--pale);border-color:#c9dcf4}
.btn:active{transform:translateY(0)}
.btn[disabled],.btn.is-disabled{opacity:.55;pointer-events:none}
.btn .ic{width:18px;height:18px;flex:0 0 18px}

.tag,.badge{
  display:inline-flex;align-items:center;border-radius:999px;padding:7px 11px;
  font-size:12px;font-weight:700;background:var(--pale);color:var(--navy);
}
.badge.orange{background:#fff0e3;color:#c85a00}
.badge.green{background:#e4f8f0;color:#087a51}
.badge.red{background:#fdecec;color:#b02525}
.badge.off{background:#eef1f5;color:#7b8794}

.ic{width:20px;height:20px;display:inline-block;vertical-align:middle}
.stars{color:#ff9d21;letter-spacing:2px}

/* ── Header / nav ───────────────────────────────────────────────────────── */
.header{
  height:var(--nav-h);display:flex;align-items:center;
  background:rgba(255,255,255,.88);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(223,231,241,.8);
  position:sticky;top:0;z-index:60;
}
.header .wrap{display:flex;align-items:center;gap:34px}
/* The logo artwork has its own navy background, so it reads as a rounded pill on
   white and a lighter block on the dark sidebar/footer. No invert filter — that
   would erase the orange.
   Height drives the size and width is auto: the source (logo-wide.png, trimmed to
   the artwork by gen-icons.php) is never cropped, so the letters can never touch
   the rounded corners. Do not put a fixed width back on this. */
/* Demo video */
.demo-grid{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center}
.demo-poster{
  position:relative;padding:0;border:0;background:#000;cursor:pointer;display:block;
  border-radius:22px;overflow:hidden;aspect-ratio:16/9;box-shadow:0 26px 70px rgba(8,32,73,.20);
}
.demo-poster img{width:100%;height:100%;object-fit:cover;opacity:.86;transition:opacity .3s ease,transform .5s ease}
.demo-poster:hover img{opacity:1;transform:scale(1.03)}
.demo-poster .vid-play{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:78px;height:78px;border-radius:50%;background:var(--orange);
  box-shadow:0 12px 34px rgba(245,130,32,.5);
}
.demo-poster .vid-play:after{
  content:"";position:absolute;left:52%;top:50%;transform:translate(-50%,-50%);
  border-left:22px solid #fff;border-top:14px solid transparent;border-bottom:14px solid transparent;
}
.demo-modal{max-width:860px;width:min(860px,94vw)}
.demo-frame{position:relative;aspect-ratio:16/9;border-radius:16px;overflow:hidden;background:#000}
.demo-frame iframe,.demo-frame video{position:absolute;inset:0;width:100%;height:100%;border:0;background:#000}
@media(max-width:900px){
  .demo-grid{grid-template-columns:1fr;gap:28px}
  .demo-poster .vid-play{width:62px;height:62px}
  .demo-poster .vid-play:after{border-left-width:18px;border-top-width:11px;border-bottom-width:11px}
}

/* Kinetic headline word. The caret only shows while JS is driving it. */
.rotate-word{display:inline-block;min-width:1ch}
.rotate-word.typing:after{
  content:"";display:inline-block;width:2px;height:.95em;margin-left:3px;
  background:currentColor;vertical-align:-.08em;animation:caret .75s step-end infinite;
}
@keyframes caret{0%,100%{opacity:1}50%{opacity:0}}

/* Hero picture stack — every slide is layered, one is visible. */
/* Hero picture stack. `cover` now, not `contain`: the slides are proper 4:3
   landscape photographs and CODEX-IMAGE-PROMPT.md tells whoever makes the next
   ones to keep the subject in the middle two thirds, so filling the panel crops
   nothing that matters. The gradient behind still covers a slow-loading image.
   If a portrait cut-out is ever put back here, switch this line to `contain`. */
.hero-art.slides{position:relative;border-radius:34px;overflow:hidden;box-shadow:var(--shadow);
  background:linear-gradient(160deg,var(--pale) 0%,#fff 55%,#ffe9d4 100%)}
.hero-art.slides img{
  width:100%;height:100%;object-fit:cover;object-position:center;
  border-radius:0;box-shadow:none;transition:opacity .8s ease;
}
.hero-art.slides img + img{position:absolute;inset:0}
.hero-art.slides img:not(.on){opacity:0}
.hero-art.slides img.on{opacity:1}

.logo{height:62px;width:auto;max-width:100%;object-fit:contain;border-radius:8px;display:block}
.brand{flex:0 0 auto}
.nav{display:flex;gap:6px;align-items:center;flex:0 0 auto}
.nav-top{
  display:inline-flex;align-items:center;gap:5px;background:none;border:0;font:inherit;cursor:pointer;
  color:#34445c;text-decoration:none;font-weight:600;font-size:14px;
  padding:9px 12px;border-radius:11px;position:relative;white-space:nowrap;
  transition:background .2s ease,color .2s ease;
}
.nav-top:hover,.nav-top.active{background:var(--pale);color:var(--navy)}
.nav-top .chev{width:15px;height:15px;transition:transform .25s ease}
.nav-drop:hover .chev,.nav-drop:focus-within .chev{transform:rotate(180deg)}

/* Dropdowns are pure CSS. :focus-within covers the keyboard, so there is no JS
   to break and no aria state to keep in sync by hand. */
.nav-drop{position:relative}
.nav-menu{
  position:absolute;top:calc(100% + 10px);left:50%;transform:translateX(-50%) translateY(-8px);
  min-width:230px;background:#fff;border:1px solid var(--line);border-radius:16px;
  box-shadow:0 24px 60px rgba(8,32,73,.16);padding:8px;
  opacity:0;visibility:hidden;transition:opacity .2s ease,transform .2s ease,visibility .2s;
  z-index:70;
}
.nav-menu.wide{min-width:290px}
/* A hover bridge, so the pointer can cross the 10px gap without the menu closing. */
.nav-drop:after{content:"";position:absolute;left:0;right:0;top:100%;height:12px}
.nav-drop:hover .nav-menu,.nav-drop:focus-within .nav-menu{
  opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);
}
/* A menu item that opens a modal instead of navigating — same list, same look,
   just a <button> under the hood. Reset first, then it rides every ".nav-menu
   a" / ".mnav-drop a" / ".mnav-panel a" rule below via the shared selector. */
.as-link{background:none;border:0;font:inherit;text-align:left;cursor:pointer;width:100%}
.nav-menu a,.nav-menu .as-link{
  display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:11px;
  text-decoration:none;color:var(--ink);font-size:14px;
}
.nav-menu a:hover,.nav-menu .as-link:hover{background:var(--pale);color:var(--navy)}
.nav-menu .ic{color:var(--navy);flex:0 0 auto;width:19px;height:19px}
.nav-menu b{display:block;font-weight:600;line-height:1.3}
.nav-menu em{display:block;font-style:normal;font-size:12px;color:var(--muted);margin-top:1px}

.nav-actions{display:flex;gap:9px;align-items:center;flex:0 0 auto}

/* Inline header search — the box itself, not an icon. */
.hdr-inline{
  flex:1 1 auto;min-width:0;max-width:420px;margin:0 6px;position:relative;
  display:flex;align-items:center;
}
.hdr-inline > .ic{position:absolute;left:14px;color:var(--muted);pointer-events:none;width:19px;height:19px}
.hdr-inline input{
  width:100%;height:44px;border:1px solid var(--line);border-radius:12px;
  padding:0 14px 0 42px;background:var(--gray);color:var(--ink);font:inherit;font-size:14px;min-width:0;
}
.hdr-inline input:focus{
  outline:none;border-color:var(--navy);background:#fff;box-shadow:0 0 0 4px rgba(11,58,130,.10);
}
.hdr-inline .hdr-suggest{
  position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:70;
  box-shadow:0 24px 60px rgba(8,32,73,.16);
}
.mobile-menu{
  display:none;background:none;border:0;color:var(--navy);padding:8px;
  margin-left:auto;cursor:pointer;line-height:0;
}
.mobile-menu .ic{width:26px;height:26px}

/* Header search */
.hdr-search{
  position:sticky;top:var(--nav-h);z-index:59;background:#fff;
  border-bottom:1px solid var(--line);box-shadow:0 14px 34px rgba(8,32,73,.09);
  padding:16px 0;
}
.hdr-search form{display:flex;align-items:center;gap:10px;position:relative}
.hdr-search > .wrap > form > .ic{position:absolute;left:15px;color:var(--muted);pointer-events:none}
.hdr-search input{
  flex:1;height:50px;border:1px solid var(--line);border-radius:13px;
  padding:0 15px 0 44px;background:var(--gray);color:var(--ink);min-width:0;
}
.hdr-search input:focus{outline:none;border-color:var(--navy);background:#fff;box-shadow:0 0 0 4px rgba(11,58,130,.10)}
.hdr-suggest{margin-top:10px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:#fff}
.hdr-suggest a{
  display:flex;align-items:center;gap:12px;padding:12px 15px;text-decoration:none;
  border-bottom:1px solid var(--line);color:var(--ink);
}
.hdr-suggest a:last-child{border-bottom:0}
.hdr-suggest a:hover,.hdr-suggest a.on{background:var(--pale)}
.hdr-suggest .lbl{flex:1;min-width:0;font-weight:600;font-size:14.5px}
.hdr-suggest .kind{font-size:11px;font-weight:800;color:var(--navy);background:var(--pale);border-radius:999px;padding:4px 9px;flex:0 0 auto}
.hdr-suggest .note{font-size:12.5px;color:var(--muted);flex:0 0 auto}
.hdr-suggest .none{padding:14px 15px;color:var(--muted);font-size:14px}
@media(max-width:768px){
  .hdr-search{padding:12px 0}
  .hdr-search input{height:46px}
  .hdr-search form .btn.primary{padding:10px 14px}
  .hdr-suggest .note{display:none}
}

/* Off-canvas mobile menu */
.mnav-panel{
  position:fixed;inset:0 0 0 auto;width:min(340px,86vw);background:#fff;z-index:120;
  transform:translateX(102%);transition:transform .3s ease;
  padding:22px 22px 40px;overflow-y:auto;box-shadow:-20px 0 60px rgba(8,32,73,.18);
}
.mnav-panel.open{transform:translateX(0)}
.mnav-panel .mnav-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:22px}
.mnav-panel a,.mnav-panel .as-link{
  display:flex;align-items:center;gap:12px;padding:14px 6px;text-decoration:none;
  font-weight:600;color:var(--ink);border-bottom:1px solid var(--line);
}
.mnav-panel .ic{color:var(--navy)}
.mnav-panel .mnav-cta{display:grid;gap:10px;margin-top:22px}
.mnav-search{position:relative;display:flex;align-items:center;margin-bottom:6px}
.mnav-search > .ic{position:absolute;left:13px;color:var(--muted);pointer-events:none;width:18px;height:18px}
.mnav-search input{
  width:100%;height:46px;border:1px solid var(--line);border-radius:12px;
  padding:0 14px 0 40px;background:var(--gray);color:var(--ink);font:inherit;font-size:15px;
}
.mnav-search input:focus{outline:none;border-color:var(--navy);background:#fff;box-shadow:0 0 0 4px rgba(11,58,130,.10)}
.mnav-group{
  font-size:11px;font-weight:800;letter-spacing:.10em;text-transform:uppercase;
  color:var(--muted);margin:20px 0 2px;
}
.mnav-group:first-of-type{margin-top:14px}
.mnav-ov{position:fixed;inset:0;background:rgba(6,22,47,.5);z-index:110;opacity:0;pointer-events:none;transition:opacity .3s ease}
.mnav-ov.open{opacity:1;pointer-events:auto}

/* Mobile bottom nav */
.bottom-nav{
  display:none;position:fixed;bottom:0;left:0;right:0;z-index:90;
  background:rgba(255,255,255,.96);backdrop-filter:blur(12px);
  border-top:1px solid var(--line);padding:9px 6px 7px;
  justify-content:space-around;
}
.bottom-nav a{
  display:grid;justify-items:center;gap:3px;text-decoration:none;
  color:var(--muted);font-size:11px;font-weight:600;padding:2px 8px;
}
.bottom-nav a.active{color:var(--navy)}
.bottom-nav .ic{width:22px;height:22px}

/* ── Hero ───────────────────────────────────────────────────────────────── */
.hero{
  padding:74px 0 60px;position:relative;
  background:linear-gradient(140deg,#fff 15%,#f5f9ff 65%,#fff4eb 100%);
  overflow:hidden;
}
.hero-grid{display:grid;grid-template-columns:.95fr 1.05fr;align-items:center;gap:38px}
.hero-copy{position:relative;z-index:2}
.hero h1{max-width:760px;margin:18px 0 22px}
.hero p{font-size:19px;max-width:650px}
.hero-actions{display:flex;gap:12px;margin:30px 0;flex-wrap:wrap}
/* "New here? How to use this website" — a text link under the hero buttons, so
   it is visible without being a fourth big CTA competing with Explore Courses. */
.hero-howto{margin:-12px 0 0}
.howto-link{
  display:inline-flex;align-items:center;gap:8px;background:none;border:0;cursor:pointer;
  font:inherit;font-size:14px;color:var(--muted);padding:6px 0;
}
.howto-link b{color:var(--navy);text-decoration:underline;text-underline-offset:3px}
.howto-link .ic{width:18px;height:18px;color:var(--orange)}
.howto-link:hover b{color:var(--orange)}
.trust-row{display:flex;align-items:center;gap:18px;margin-top:26px;flex-wrap:wrap}
.avatars{display:flex}
.avatar{
  width:38px;height:38px;border-radius:50%;background:linear-gradient(135deg,#f9c5a0,#9dbef0);
  border:3px solid #fff;margin-left:-8px;object-fit:cover;flex:0 0 auto;
}
.avatar:first-child{margin-left:0}
.hero-art{height:580px;display:flex;align-items:center;justify-content:center}
.hero-art img{width:100%;height:100%;object-fit:cover;border-radius:34px;box-shadow:var(--shadow);object-position:center}

/* ── Stats band ─────────────────────────────────────────────────────────── */
.stats{background:var(--navy);color:#fff}
.stats .wrap{display:grid;grid-template-columns:repeat(4,1fr);padding:25px 0}
.stat{padding:5px 32px;border-right:1px solid rgba(255,255,255,.18)}
.stat:last-child{border-right:0}
.stat strong{font:italic 700 32px var(--serif);display:block}
.stat span{color:#ccdaf0;font-size:13px}

/* ── Sections ───────────────────────────────────────────────────────────── */
.section{padding:90px 0}
.section.tight{padding:56px 0}
.section.alt{background:var(--gray)}
.section.blue{background:var(--navy);color:#fff}
.section.blue h2,.section.blue h3{color:#fff}
.section.blue p{color:#ccdaf0}
.section.blue .eyebrow{color:#fff}
.section-head{display:flex;align-items:end;justify-content:space-between;gap:40px;margin-bottom:34px}
.section-head h2{margin-bottom:0;max-width:720px}
.section-head p{max-width:560px;margin:0}

.grid{display:grid;gap:20px}
.grid.two{grid-template-columns:repeat(2,1fr)}
.grid.three{grid-template-columns:repeat(3,1fr)}
.grid.four{grid-template-columns:repeat(4,1fr)}

/* ── Cards ──────────────────────────────────────────────────────────────── */
.card{
  background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:26px;
  box-shadow:0 10px 35px rgba(12,42,85,.06);
}
.card.soft{background:var(--pale);border-color:transparent}
.card.dark{background:var(--navy-2);border-color:transparent;color:#fff}
.card.dark p{color:#c5d6ef}
.card.orange{background:linear-gradient(145deg,#fff4e8,#fff);border-color:#ffd4b2}
.card.hover:hover{transform:translateY(-4px);box-shadow:0 24px 55px rgba(12,42,85,.13)}
.card.hover{transition:transform .25s ease,box-shadow .25s ease}

.icon{
  width:46px;height:46px;border-radius:14px;background:var(--pale);
  display:grid;place-items:center;color:var(--navy);font-size:22px;margin-bottom:18px;
}
.icon.orange{background:#fff0e3;color:var(--orange)}
.icon .ic{width:24px;height:24px}

/* Course card */
.course-card{padding:0;overflow:hidden;display:flex;flex-direction:column;text-decoration:none;color:inherit}
/* aspect-ratio, NOT a fixed height. With height:210px the box was 3.09:1 while the
   artwork is 1.78:1, so about 42% of every cover was cropped away — which is
   exactly the "top got cut off" the client reported. A ratio crops nothing.
   The art is a background rather than an <img>: predictable at any width, and
   Chrome does not offer its Google Lens button over a background. */
.course-cover{
  aspect-ratio:16/9;background:linear-gradient(135deg,var(--navy),#2f6fc5);
  background-size:cover;background-position:center;
  color:#fff;position:relative;overflow:hidden;
  border-radius:20px 20px 0 0;      /* its own radius — do not rely on the parent clip */
}
/* Eight pages put an <img width="420" height="210"> inside this box and nothing
   ever sized it. That went unnoticed while .course-cover was itself height:210px
   — the numbers happened to agree. The moment it became aspect-ratio:16/9 the
   picture started sitting at 420x210 in the top-left of a 648x365 box with the
   gradient showing around it. Only index.php uses a CSS background; every other
   page still uses an <img>, so this is the rule that was missing all along. */
.course-cover img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;display:block;
}
.course-cover.orange{background-image:linear-gradient(135deg,#db6507,#ffab60)}
.course-cover.pale{background-image:linear-gradient(135deg,#dbeafe,#fff0e4);color:var(--navy)}
/* Once there is a photograph, drop the gradient so it does not tint the picture. */
.course-cover.has-art{background-color:#0b3a82;background-image:none}
.course-cover.has-art.orange,.course-cover.has-art.pale{background-image:none}

/* The badge used to sit in 24px of padding with nothing behind it, floating over a
   busy photo. Now it is pinned with its own backdrop. */
.course-cover .cover-badge{
  position:absolute;top:12px;left:12px;z-index:2;
  background:rgba(255,255,255,.95);color:var(--navy);
  backdrop-filter:blur(6px);box-shadow:0 4px 14px rgba(6,22,47,.18);
}
.cover-off{
  position:absolute;top:12px;right:12px;z-index:2;
  background:var(--orange);color:#fff;border-radius:999px;
  padding:4px 10px;font-size:11px;font-weight:800;letter-spacing:.02em;
  box-shadow:0 4px 14px rgba(245,130,32,.4);
}

/* Rating + review count. Visible at EVERY width — an nth-child rule used to hide
   it on phones, which is the one place it matters most. */
.card-rate{display:flex;align-items:center;gap:7px;margin-top:9px}
.card-rate .stars{font-size:13px;letter-spacing:.5px;color:var(--orange)}
.card-rate b{font-size:13.5px;color:var(--ink)}
.card-rate i{font-style:normal;font-size:12px;color:var(--muted)}

/* "Best for …" — the client's own claim about who a course suits. */
.card-for{
  display:inline-flex;align-items:flex-start;gap:6px;margin-top:9px;
  background:var(--pale);color:var(--navy);border-radius:9px;
  padding:6px 10px;font-size:12.5px;font-weight:600;line-height:1.35;
}
.card-for .ic{width:14px;height:14px;flex:0 0 auto;margin-top:1px;color:var(--green,#16a34a)}
.course-cover .mini-art{position:absolute;right:20px;bottom:15px;font-size:70px;filter:drop-shadow(0 12px 12px rgba(0,0,0,.16))}
.course-body{padding:22px;display:flex;flex-direction:column;flex:1}
.course-body h3{margin-bottom:0}
.meta{display:flex;gap:16px;color:var(--muted);font-size:13px;margin:12px 0;flex-wrap:wrap}
.meta span{display:inline-flex;align-items:center;gap:5px}
.meta .ic{width:15px;height:15px}
.price{font-size:22px;color:var(--navy);font-weight:800;display:inline-flex;align-items:baseline;gap:8px}
.price s{font-size:13px;color:#9aa7b7;font-weight:400}
.price-row{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:auto;padding-top:16px}

/* Quote / testimonial */
.quote{font:italic 600 21px/1.55 var(--serif);color:var(--ink)}
.person{display:flex;align-items:center;gap:12px;margin-top:20px}
.person .avatar{margin:0;width:44px;height:44px}
.person strong{display:block}
.person span{font-size:13px;color:var(--muted)}

/* ── Steps ──────────────────────────────────────────────────────────────── */
.steps{display:grid;grid-template-columns:repeat(4,1fr);position:relative}
.steps:before{content:"";position:absolute;top:30px;left:8%;right:8%;height:2px;background:#cddcf0}
.step{position:relative;text-align:center;padding:0 24px}
.step-no{
  width:62px;height:62px;background:#fff;border:2px solid #bbd0eb;border-radius:50%;
  display:grid;place-items:center;margin:0 auto 18px;color:var(--navy);font-weight:800;
  box-shadow:0 5px 20px rgba(11,58,130,.08);position:relative;z-index:2;
}

/* ── Comparison table (Others vs Pallavi) ───────────────────────────────── */
.compare{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:start}
.compare-col{border-radius:var(--r);padding:30px;border:1px solid var(--line);background:#fff}
.compare-col.them{background:var(--gray)}
.compare-col.us{border-color:#bcd4f5;box-shadow:0 18px 50px rgba(11,58,130,.12)}
.compare-col h3{display:flex;align-items:center;gap:10px;margin-bottom:18px;font-size:22px}
.compare-col ul{list-style:none;margin:0;padding:0;display:grid;gap:13px}
.compare-col li{display:flex;gap:11px;font-size:14.5px;line-height:1.5;color:var(--ink)}
.compare-col li .ic{flex:0 0 20px;margin-top:1px}
.compare-col.them li{color:var(--muted)}
.compare-col.them li .ic{color:#b6c0cc}
.compare-col.us li .ic{color:var(--green)}

/* ── Video reviews (9:16, lazy iframes, poster behind — no flicker) ─────── */
.vid-row{
  display:flex;gap:18px;overflow-x:auto;overflow-y:hidden;
  padding:6px 2px 22px;scroll-snap-type:x proximity;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
}
.vid-row::-webkit-scrollbar{display:none}
.vid-card{
  flex:0 0 262px;width:262px;border-radius:18px;overflow:hidden;background:var(--navy-2);
  scroll-snap-align:start;box-shadow:0 16px 40px rgba(8,32,73,.18);position:relative;
}
.vid-box{
  position:relative;width:100%;aspect-ratio:9/16;background:#06162f;
  transform:translateZ(0);backface-visibility:hidden;
}
.vid-poster{
  position:absolute;inset:0;z-index:0;width:100%;height:100%;display:block;
  background-color:#06162f;background-size:cover;background-position:center;
}
.vid-box iframe{
  position:absolute;inset:0;z-index:1;width:100%;height:100%;border:0;display:block;
  opacity:0;transition:opacity .45s ease;transform:translateZ(0);backface-visibility:hidden;
}
.vid-box iframe.is-loaded{opacity:1}
.vid-play{
  position:absolute;inset:0;z-index:2;display:grid;place-items:center;
  background:linear-gradient(180deg,rgba(6,22,47,.05),rgba(6,22,47,.55));
  border:0;cursor:pointer;color:#fff;
}
.vid-play span{
  width:58px;height:58px;border-radius:50%;background:var(--orange);
  display:grid;place-items:center;box-shadow:0 10px 26px rgba(0,0,0,.35);
}
.vid-play .ic{width:24px;height:24px;fill:#fff;stroke:none}
.vid-cap{padding:13px 15px;color:#fff;font-size:13px;font-weight:600}
.vid-cap span{display:block;color:#a9c2e5;font-weight:400;font-size:12px;margin-top:2px}

/* ── Reels row (the client's YouTube Shorts) ────────────────────────────────
   Same no-flicker build as the video reviews: a solid poster sits behind the
   iframe, the iframe is created only on scroll-into-view and fades in, so
   swiping between cards never reloads or flashes. */
.reel-row{
  display:flex;gap:16px;overflow-x:auto;overflow-y:hidden;
  padding:8px 2px 24px;scroll-snap-type:x proximity;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
}
.reel-row::-webkit-scrollbar{display:none}
.reel-card{
  flex:0 0 236px;width:236px;border-radius:20px;overflow:hidden;background:var(--navy-2);
  scroll-snap-align:start;box-shadow:0 16px 42px rgba(8,32,73,.16);position:relative;
  display:flex;flex-direction:column;
}
.reel-card .vid-box{border-radius:0}
/* Instagram gives no thumbnail without an API token, so the card is branded
   instead of showing a dead grey box — the reel itself loads on tap. */
.ig-box{background:linear-gradient(150deg,#3f2b96,#a4508b 55%,#f0762b)}
/* With a real poster there is no gradient to show through, and the frame is
   letterboxed by Instagram — cover crops the black bars away. */
.ig-box.has-poster{background:#0b1220}
.ig-box .vid-poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
/* Title at the top, not the middle — the play button sits dead centre and was
   printed straight over it. */
.ig-poster{
  position:absolute;inset:0;z-index:0;display:flex;flex-direction:column;
  align-items:center;justify-content:flex-start;gap:10px;padding:16px 14px;text-align:center;color:#fff;
}
.ig-poster svg{width:26px;height:26px;opacity:.95;flex:0 0 auto}
.ig-poster em{
  font-style:normal;font-size:12.5px;font-weight:700;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.ig-box iframe{position:absolute;inset:0;z-index:1;width:100%;height:100%;border:0;background:#000}
.reel-cap{padding:13px 15px 15px;color:#fff}
.reel-cap strong{display:block;font-size:13.5px;line-height:1.35}
.reel-cap span{display:block;color:#a9c2e5;font-size:11.5px;margin-top:3px}
.reel-cap .btn{margin-top:11px;width:100%}
.reel-scrollers{display:flex;gap:8px}
.reel-scroll{
  width:40px;height:40px;border-radius:50%;border:1px solid var(--line);background:#fff;
  color:var(--navy);cursor:pointer;display:grid;place-items:center;font-size:18px;line-height:1;
}
.reel-scroll:hover{background:var(--pale)}
@media(max-width:768px){
  .reel-card{flex:0 0 190px;width:190px}
  .reel-scrollers{display:none}
}

/* ── Reviews: stat card + rating bars + auto-scrolling marquee ─────────────── */
.rev-top{display:grid;grid-template-columns:300px 1fr;gap:28px;align-items:center;margin-bottom:34px}
.rev-score{
  background:linear-gradient(150deg,var(--navy),#155fbd);color:#fff;
  border-radius:24px;padding:28px;text-align:center;box-shadow:var(--shadow);
}
.rev-score b{display:block;font:italic 700 54px/1 var(--serif)}
.rev-score .stars{font-size:20px;letter-spacing:3px;display:block;margin:8px 0 6px}
.rev-score span{font-size:13px;color:#cbdcf3}
.rev-bars{display:grid;gap:9px}
.rev-bar{display:grid;grid-template-columns:52px 1fr 42px;gap:12px;align-items:center;font-size:13px}
.rev-bar .t{color:var(--muted);white-space:nowrap}
.rev-bar .track{height:8px;border-radius:999px;background:#e8eef6;overflow:hidden}
.rev-bar .fill{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--orange),#ffb15c);width:0;transition:width 1s cubic-bezier(.22,.61,.36,1)}
.rev-bar .n{color:var(--muted);text-align:right}

.rev-viewport{overflow:hidden;position:relative;padding:4px 0}
.rev-viewport:before,.rev-viewport:after{
  content:"";position:absolute;top:0;bottom:0;width:60px;z-index:2;pointer-events:none;
}
.rev-viewport:before{left:0;background:linear-gradient(90deg,var(--gray),transparent)}
.rev-viewport:after{right:0;background:linear-gradient(270deg,var(--gray),transparent)}
.rev-marquee{display:flex;gap:18px;width:max-content;animation:revLoop 60s linear infinite}
.rev-viewport:hover .rev-marquee,.rev-viewport:focus-within .rev-marquee{animation-play-state:paused}
@keyframes revLoop{from{transform:translateX(0)}to{transform:translateX(calc(-50% - 9px))}}
.rev-card{
  flex:0 0 330px;width:330px;background:#fff;border:1px solid var(--line);
  border-radius:20px;padding:22px;box-shadow:0 10px 30px rgba(12,42,85,.06);
}
.rev-card .head{display:flex;align-items:center;gap:11px;margin-bottom:12px}
.rev-av{
  width:42px;height:42px;border-radius:50%;flex:0 0 42px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--navy),#4d8de1);color:#fff;font-weight:800;font-size:15px;
  object-fit:cover;
}
.rev-card .who{min-width:0}
.rev-card .who strong{display:block;font-size:14.5px}
.rev-card .who span{display:block;font-size:12px;color:var(--muted)}
.rev-tick{
  margin-left:auto;flex:0 0 auto;width:22px;height:22px;border-radius:50%;
  background:#e4f8f0;color:#087a51;display:grid;place-items:center;
}
.rev-tick .ic{width:13px;height:13px}
.rev-card p{margin:0;font-size:14.5px;line-height:1.6;color:var(--ink)}
.rev-card .verified{display:block;margin-top:12px;font-size:11.5px;color:var(--muted)}

@media(max-width:768px){
  .rev-top{grid-template-columns:1fr;gap:18px}
  .rev-score{padding:22px}
  .rev-score b{font-size:42px}
  /* Swipe instead of auto-scroll on a phone: an animation that moves under the
     thumb makes it impossible to read a card. */
  .rev-viewport{overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .rev-viewport::-webkit-scrollbar{display:none}
  .rev-viewport:before,.rev-viewport:after{display:none}
  .rev-marquee{animation:none;width:auto}
  .rev-card{flex:0 0 270px;width:270px;scroll-snap-align:start;padding:18px}
}

/* ── FAQ accordion ──────────────────────────────────────────────────────── */
.faq{border-bottom:1px solid var(--line)}
.faq-q{
  width:100%;background:none;border:0;padding:20px 0;display:flex;
  justify-content:space-between;align-items:center;gap:20px;
  font-weight:700;font-size:16px;text-align:left;color:var(--ink);cursor:pointer;
}
.faq-q .sign{color:var(--orange);font-size:24px;line-height:1;flex:0 0 auto;transition:transform .25s ease}
.faq.open .faq-q .sign{transform:rotate(45deg)}
.faq-a{max-height:0;overflow:hidden;transition:max-height .3s ease}
.faq-a p{padding:0 0 20px;margin:0;max-width:80ch}

/* ── Newsletter ─────────────────────────────────────────────────────────── */
.newsletter{
  padding:56px;border-radius:30px;background:linear-gradient(135deg,var(--navy),#155fbd);
  color:#fff;display:flex;align-items:center;justify-content:space-between;gap:30px;flex-wrap:wrap;
}
.newsletter h2{margin-bottom:6px}
.newsletter p{color:#cbdcf3;margin:0}
.newsletter form{display:flex;gap:10px;flex-wrap:wrap}
.newsletter input{width:390px;max-width:100%;border:0;border-radius:12px;padding:16px 18px;color:var(--ink)}

/* ── Footer ─────────────────────────────────────────────────────────────── */
.footer{background:#071e43;color:#fff;padding:64px 0 30px}
.footer-grid{display:grid;grid-template-columns:1.5fr repeat(3,1fr);gap:50px}
.footer h4{font-size:14px;text-transform:uppercase;letter-spacing:.1em;margin:0 0 16px;color:#fff}
.footer p,.footer a{color:#b9c7da}
.footer a{display:block;text-decoration:none;margin:10px 0;font-size:14px}
.footer a:hover{color:#fff}
.footer .logo{height:46px;margin-bottom:16px}
.footer-bot{
  border-top:1px solid rgba(255,255,255,.12);margin-top:44px;padding-top:22px;
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-size:13px;color:#8fa3bd;
}
.footer-bot a{display:inline;margin:0 8px}

/* ── Sub-hero (inner page header) ───────────────────────────────────────── */
.subhero{padding:62px 0;background:linear-gradient(135deg,var(--pale),#fff8f1)}
.subhero .wrap{display:flex;align-items:center;justify-content:space-between;gap:30px}
.subhero h1{font-size:clamp(34px,4vw,52px);margin:12px 0}
.subhero p{max-width:620px;margin:0}
.crumb{font-size:13px;color:var(--muted)}
.crumb a{color:var(--muted);text-decoration:none}
.crumb a:hover{color:var(--navy)}
.blobicon{
  width:190px;height:150px;border-radius:40% 60% 58% 42%;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--navy),#3983df);color:#fff;font-size:70px;
  box-shadow:var(--shadow);flex:0 0 auto;
}
.blobicon .ic{width:64px;height:64px}

/* Opt-in, not a change to the shared .subhero used on ten other pages —
   tests.php's specific complaint was excess scroll before its practice cards,
   so this variant is much shorter and drops the max-width paragraph cap
   since there is no icon competing for the row's width any more. */
.subhero.compact{padding:30px 0}
.subhero.compact h1{font-size:clamp(26px,3vw,36px);margin:8px 0}
.subhero.compact p{max-width:none}
/* Undoes the subhero's own bottom padding stacking with this section's own
   top padding, which together read as a second scroll before real content. */
.practice-cards-sec{padding-top:26px}

/* ── Toolbar / filters ─────────────────────────────────────────────────── */
.toolbar{display:flex;gap:12px;margin:28px 0;flex-wrap:wrap}
.field{
  height:48px;border:1px solid var(--line);border-radius:12px;background:#fff;
  padding:0 15px;color:var(--ink);
}
.field:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(11,58,130,.10)}
.search{flex:1;min-width:200px}
.filter{min-width:190px}

/* ── Feature split ──────────────────────────────────────────────────────── */
.feature-split{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:center}
.visual-panel{
  min-height:380px;border-radius:28px;
  background:linear-gradient(135deg,#e7f1ff,#fff2e6);
  display:grid;place-items:center;font-size:120px;overflow:hidden;
}
.visual-panel img{width:100%;height:100%;object-fit:cover}

.timeline{border-left:2px solid #c7d9ef;margin-left:14px}
.timeline-item{position:relative;padding:0 0 30px 38px}
.timeline-item:before{
  content:"";position:absolute;left:-9px;top:4px;width:15px;height:15px;border-radius:50%;
  background:var(--orange);border:4px solid #fff;box-shadow:0 0 0 1px #c7d9ef;
}

/* ── Auth ───────────────────────────────────────────────────────────────── */
.auth-shell{min-height:100vh;display:grid;grid-template-columns:1fr 1fr}
.auth-art{
  background:linear-gradient(150deg,var(--navy-2),var(--navy));padding:70px;color:#fff;
  display:flex;flex-direction:column;justify-content:space-between;
}
.auth-art h1{font-size:clamp(36px,3.6vw,58px)}
.auth-art p{color:#cbd9ea}
.auth-art .logo{height:64px}
.auth-art .eyebrow{color:#fff}
.auth-art .eyebrow:before{background:var(--orange)}
.auth-panel{display:grid;place-items:center;padding:70px}
.auth-card{width:min(520px,100%)}
.auth-card h2{font-size:clamp(28px,3vw,38px)}
.form-group{margin:16px 0}
.form-group label{display:block;font-weight:700;font-size:13px;margin-bottom:7px}
.form-group input,.form-group select,.form-group textarea{
  width:100%;height:52px;border:1px solid var(--line);border-radius:12px;padding:0 14px;background:#fff;color:var(--ink);
}
.form-group textarea{height:120px;padding-top:14px;resize:vertical}
.form-group input:focus,.form-group select:focus,.form-group textarea:focus{
  outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(11,58,130,.10);
}
.form-group .hint{font-size:12px;color:var(--muted);margin-top:6px}
.form-group.err input{border-color:var(--red)}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.auth-card .btn{width:100%;margin-top:12px}
.or{display:flex;align-items:center;gap:14px;color:var(--muted);font-size:12px;margin:23px 0}
.or:before,.or:after{content:"";height:1px;background:var(--line);flex:1}
.btn-google{
  background:#fff;border:1px solid var(--line);color:var(--ink);width:100%;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  border-radius:12px;padding:14px;font-weight:700;text-decoration:none;
}
.btn-google:hover{background:var(--gray)}
.btn-google img,.btn-google svg{width:20px;height:20px}

/* ── App shell (student + admin) ────────────────────────────────────────── */
.app-shell{min-height:100vh;background:#f4f7fb;display:grid;grid-template-columns:260px 1fr}
/* The sidebar stays put while the content scrolls. Without this it scrolls off
   the top on long screens (Settings, Products) and the client loses the menu. */
.sidebar{
  background:var(--navy-2);padding:28px 22px;color:#fff;
  position:sticky;top:0;align-self:start;
  height:100vh;overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.25) transparent;
}
.sidebar::-webkit-scrollbar{width:6px}
.sidebar::-webkit-scrollbar-thumb{background:rgba(255,255,255,.22);border-radius:3px}
.sidebar::-webkit-scrollbar-track{background:transparent}
.sidebar .logo{height:52px;margin:0 auto 30px}
.menu-title{color:#8297b7;font-size:11px;text-transform:uppercase;letter-spacing:.12em;margin:28px 12px 10px}
.menu-item{
  display:flex;align-items:center;gap:12px;padding:13px 14px;border-radius:11px;margin:4px 0;
  color:#c5d1e2;font-weight:600;font-size:14px;text-decoration:none;transition:background .18s ease,color .18s ease;
}
.menu-item:hover{background:rgba(255,255,255,.07);color:#fff}
.menu-item.active{background:rgba(255,255,255,.12);color:#fff}
.menu-item .ic{width:19px;height:19px;flex:0 0 19px}
.main{padding:28px 34px 50px;min-width:0}
/* Menu button for the phone sidebar drawer — hidden on desktop */
.app-menu-btn{
  display:none;width:42px;height:42px;border-radius:11px;border:1px solid var(--line);
  background:#fff;color:var(--navy);place-items:center;cursor:pointer;padding:0;flex:0 0 auto;
}
.app-menu-btn .ic{width:22px;height:22px}
.sidebar-ov{display:none}
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:28px;gap:20px;flex-wrap:wrap}
.topbar h2{font-size:clamp(24px,2.4vw,30px);margin:0}
.topbar .eyebrow{margin-bottom:6px}
.top-actions{display:flex;gap:10px;align-items:center}
.circle{
  width:42px;height:42px;border-radius:50%;display:grid;place-items:center;
  background:#fff;border:1px solid var(--line);color:var(--navy);cursor:pointer;
}

.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.metric{background:#fff;border:1px solid var(--line);padding:22px;border-radius:16px}
.metric label{font-size:13px;color:var(--muted);display:block;margin-bottom:6px}
.metric .k{font-size:28px;font-weight:800;color:var(--navy)}
.metric .delta{font-size:12px;color:var(--green);margin-top:6px;display:block}
.metric .delta.down{color:var(--red)}
.dashboard-grid{display:grid;grid-template-columns:1.55fr 1fr;gap:20px;margin-top:20px}
.panel{background:#fff;border:1px solid var(--line);border-radius:18px;padding:24px}
.panel-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;gap:16px}
.panel-head h3{margin:0}

.chart{height:260px;display:flex;align-items:end;gap:16px;padding:30px 10px 0;border-bottom:1px solid var(--line)}
.bar{flex:1;background:linear-gradient(180deg,#4d8de1,var(--navy));border-radius:9px 9px 0 0;min-height:30px}
.bar.orange{background:linear-gradient(180deg,#ffb272,var(--orange))}

.progress{height:9px;border-radius:999px;background:#e8eef6;overflow:hidden}
.progress span{display:block;height:100%;background:linear-gradient(90deg,var(--orange),#ffb15c);border-radius:inherit}
.course-row{display:grid;grid-template-columns:64px 1fr 130px 90px;gap:16px;align-items:center;padding:14px 0;border-bottom:1px solid var(--line)}
.course-row:last-child{border-bottom:0}
.thumb{width:62px;height:52px;border-radius:11px;object-fit:cover;background:linear-gradient(135deg,var(--navy),#73a6e4);display:grid;place-items:center;color:#fff}

.table-wrap{overflow-x:auto}
.table{width:100%;border-collapse:collapse}
.table th{
  text-align:left;color:var(--muted);font-size:11px;text-transform:uppercase;
  letter-spacing:.08em;padding:12px;border-bottom:1px solid var(--line);white-space:nowrap;
}
.table td{padding:15px 12px;border-bottom:1px solid var(--line);font-size:14px}
.table tr:last-child td{border-bottom:0}
.status{padding:6px 9px;border-radius:999px;font-size:11px;font-weight:800;background:#e4f8f0;color:#087a51;white-space:nowrap}
.status.pending{background:#fff1df;color:#b85b05}
.status.failed{background:#fdecec;color:#b02525}

/* ── Course player ──────────────────────────────────────────────────────── */
.player{display:grid;grid-template-columns:1fr 390px;gap:20px}
.video{
  aspect-ratio:16/9;border-radius:20px;overflow:hidden;
  background:linear-gradient(135deg,#06162f,#0d326c);
  display:grid;place-items:center;color:#fff;position:relative;
}
.video iframe,.video video{position:absolute;inset:0;width:100%;height:100%;border:0}
.play{width:84px;height:84px;border-radius:50%;background:var(--orange);display:grid;place-items:center;font-size:32px;border:0;cursor:pointer;color:#fff}
.play .ic{width:32px;height:32px;fill:#fff;stroke:none}
.video .video-title{position:absolute;left:28px;bottom:24px;z-index:2}
.lesson{display:flex;gap:12px;padding:13px 4px;border-bottom:1px solid var(--line);text-decoration:none;color:inherit;align-items:center}
.lesson:last-child{border-bottom:0}
.lesson:hover{background:var(--pale)}
.lesson.active{background:var(--pale)}
.lesson .num{width:32px;height:32px;border-radius:9px;background:var(--pale);display:grid;place-items:center;color:var(--navy);font-weight:800;flex:0 0 32px;font-size:13px}
.lesson.done .num{background:#e4f8f0;color:#087a51}
.lesson.locked{opacity:.55}
.lesson-meta{font-size:12px;color:var(--muted)}

/* ── Tabs ───────────────────────────────────────────────────────────────── */
.tabs{display:flex;gap:6px;border-bottom:1px solid var(--line);margin:18px 0;overflow-x:auto}
.tab{
  padding:12px 16px;font-weight:700;color:var(--muted);background:none;border:0;
  cursor:pointer;white-space:nowrap;border-bottom:3px solid transparent;text-decoration:none;
}
.tab.active{color:var(--navy);border-bottom-color:var(--orange)}

/* ── Test / quiz ────────────────────────────────────────────────────────── */
.test-card{max-width:900px;margin:30px auto}
.option{
  border:1px solid var(--line);border-radius:13px;padding:16px;margin:10px 0;
  display:flex;gap:12px;cursor:pointer;align-items:flex-start;
  transition:border-color .18s ease,background .18s ease;
}
.option:hover{border-color:#bcd4f5}
.option.selected{border-color:var(--navy);background:var(--pale)}
.option.correct{border-color:var(--green);background:#e9f9f2}
.option.wrong{border-color:var(--red);background:#fdecec}
.option input{margin-top:3px}
.timer{font-weight:800;color:var(--orange)}

/* ── Single-product purchase sidebar ────────────────────────────────────── */
.product-grid{display:grid;grid-template-columns:1fr 400px;gap:44px;align-items:start}
/* A grid item cannot reliably be position:sticky — its containing block is its
   own box, so it has nowhere to travel. .buy-col is the grid item and stretches;
   the sticky panel lives inside it. */
.buy-col{align-self:stretch;min-width:0}
/* NOT sticky: this panel is the tallest item in its grid row, so a sticky
   position has no travel room and silently does nothing. The persistent CTA is
   .buy-bar below, which appears once this panel scrolls out of view. */
.buy-box{
  background:#fff;border:1px solid var(--line);border-radius:24px;overflow:hidden;
  box-shadow:0 22px 60px rgba(11,58,130,.13);
}
.buy-media{aspect-ratio:16/10;background:var(--navy-2);position:relative;overflow:hidden}
.buy-media img{width:100%;height:100%;object-fit:cover}
.buy-media .play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:64px;height:64px}
.buy-body{padding:24px}
.buy-price{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:4px}
.buy-price b{font-size:34px;color:var(--navy);font-weight:800;letter-spacing:-.02em}
.buy-price s{color:#9aa7b7}
.buy-list{list-style:none;padding:0;margin:20px 0}
.buy-list li{display:flex;gap:10px;padding:8px 0;font-size:14px;align-items:flex-start}
.buy-list .ic{flex:0 0 18px;width:18px;height:18px;color:var(--green);margin-top:2px}
.buy-note{font-size:12px;color:var(--muted);text-align:center;margin-top:14px}
.setup-pending{
  background:#fff1df;border:1px solid #ffd4a3;color:#8a4b06;border-radius:12px;
  padding:12px 14px;font-size:13px;font-weight:600;text-align:center;
}

/* Persistent purchase bar — every width. Slides in once the main Enrol CTA has
   scrolled out of view (JS adds .in), so there is always one tap to buy. */
.buy-bar{
  display:flex;position:fixed;left:0;right:0;bottom:0;z-index:92;
  align-items:center;justify-content:space-between;gap:16px;
  background:rgba(255,255,255,.97);backdrop-filter:blur(12px);
  border-top:1px solid var(--line);padding:12px 24px;
  box-shadow:0 -10px 30px rgba(8,32,73,.10);
  transform:translateY(105%);transition:transform .3s cubic-bezier(.22,.61,.36,1);
}
.buy-bar.in{transform:translateY(0)}
.buy-bar .bb-what{min-width:0;flex:1}
.buy-bar .bb-what b{display:block;font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.buy-bar .bb-what span{display:block;font-size:11.5px;color:var(--muted)}
.buy-bar .bb-price{flex:0 0 auto;text-align:right}
.buy-bar strong{font-size:21px;color:var(--navy);font-weight:800;display:block;line-height:1.1}
.buy-bar s{color:#9aa7b7;font-size:13px}
.buy-bar .btn{flex:0 0 auto}
@media(min-width:769px){
  .buy-bar{padding:12px max(24px, calc((100vw - 1320px) / 2))}
}
@media(max-width:768px){
  /* Sit above the bottom nav rather than covering it. */
  .buy-bar{bottom:62px;padding:10px 14px;gap:10px}
  .buy-bar .bb-what{display:none}
  body.has-buy-bar{padding-bottom:138px}
}

/* ── Purchase drawer ────────────────────────────────────────────────────────
   Slides in from the right when someone presses Enrol, so they choose without
   losing the page they were reading. Falls back to the enrol page without JS. */
.buy-drawer-ov{position:fixed;inset:0;background:rgba(6,22,47,.55);z-index:170;opacity:0;pointer-events:none;transition:opacity .3s ease}
.buy-drawer-ov.open{opacity:1;pointer-events:auto}
.buy-drawer{
  position:fixed;top:0;right:0;bottom:0;width:min(430px,100vw);background:#fff;z-index:180;
  transform:translateX(102%);transition:transform .32s cubic-bezier(.22,.61,.36,1);
  display:flex;flex-direction:column;box-shadow:-24px 0 70px rgba(8,32,73,.28);
}
.buy-drawer.open{transform:translateX(0)}
.buy-drawer-h{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:18px 22px;border-bottom:1px solid var(--line)}
.buy-drawer-h strong{font-size:17px}
.buy-drawer-b{padding:22px;overflow-y:auto;flex:1}
.buy-drawer-f{padding:16px 22px 22px;border-top:1px solid var(--line);background:var(--gray)}

/* The two ways to buy, as pickable cards */
.buy-opt{
  display:block;border:2px solid var(--line);border-radius:16px;padding:16px;margin-bottom:12px;
  cursor:pointer;transition:border-color .2s ease,background .2s ease;background:#fff;
}
.buy-opt:hover{border-color:#bcd4f5}
.buy-opt.on{border-color:var(--navy);background:var(--pale)}
.buy-opt .top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.buy-opt .name{font-weight:800;font-size:15px}
.buy-opt .amt{font-weight:800;font-size:19px;color:var(--navy);white-space:nowrap}
.buy-opt .amt s{font-size:13px;color:#9aa7b7;font-weight:400;margin-right:5px}
.buy-opt .why{display:block;font-size:12.5px;color:var(--muted);margin-top:6px;line-height:1.5}
.buy-opt .save{display:inline-block;margin-top:8px;background:#e4f8f0;color:#087a51;border-radius:999px;padding:3px 9px;font-size:11px;font-weight:800}
.buy-opt input{position:absolute;opacity:0;pointer-events:none}

.buy-lines{list-style:none;padding:0;margin:18px 0 0}
.buy-lines li{display:flex;gap:9px;font-size:13.5px;padding:6px 0;color:var(--ink)}
.buy-lines .ic{flex:0 0 17px;width:17px;height:17px;color:var(--green);margin-top:2px}

@media(max-width:768px){
  .buy-drawer{width:100vw;top:auto;height:88vh;border-radius:22px 22px 0 0;transform:translateY(102%)}
  .buy-drawer.open{transform:translateY(0)}
}

/* ── Popup modal ────────────────────────────────────────────────────────── */
.modal-ov{
  position:fixed;inset:0;background:rgba(6,22,47,.62);z-index:200;
  display:grid;place-items:center;padding:20px;opacity:0;pointer-events:none;
  transition:opacity .3s ease;
}
.modal-ov.open{opacity:1;pointer-events:auto}
.modal{
  background:#fff;border-radius:26px;width:min(520px,100%);max-height:92vh;overflow-y:auto;
  padding:34px;position:relative;transform:translateY(14px);transition:transform .3s ease;
}
.modal-ov.open .modal{transform:translateY(0)}
.modal-x{
  position:absolute;top:14px;right:14px;width:38px;height:38px;border-radius:50%;
  border:1px solid var(--line);background:#fff;color:var(--muted);cursor:pointer;
  display:grid;place-items:center;font-size:20px;line-height:1;z-index:2;
}
.modal h3{font:italic 700 28px/1.2 var(--serif);margin-bottom:8px}

/* ── "Install the app" bar (phone) ──────────────────────────────────────── */
.install-bar{
  position:fixed;left:10px;right:10px;bottom:72px;z-index:97;
  display:flex;align-items:center;gap:12px;
  background:#fff;border:1px solid var(--line);border-radius:18px;
  padding:12px 14px;box-shadow:0 18px 46px rgba(8,32,73,.22);
  transform:translateY(140%);opacity:0;
  transition:transform .35s cubic-bezier(.22,.61,.36,1),opacity .35s ease;
}
.install-bar.in{transform:translateY(0);opacity:1}
.install-bar img{border-radius:11px;flex:0 0 44px}
.install-txt{flex:1;min-width:0;line-height:1.35}
.install-txt strong{display:block;font-size:14.5px}
.install-txt span{display:block;font-size:12px;color:var(--muted)}
.install-x{
  background:none;border:0;color:var(--muted);font-size:22px;line-height:1;
  padding:4px 2px;cursor:pointer;flex:0 0 auto;
}
/* Desktop installs are a browser-menu affair; the bar is phone-only. */
@media(min-width:769px){ .install-bar{display:none} }

/* ── Chatbot ────────────────────────────────────────────────────────────── */
/* A friendlier, more rounded voice than the rest of the site's DM Sans, so the
   assistant reads as a distinct, warmer space rather than another form. */
.chat-page,.chat-fab,.chat-teaser{font-family:var(--chat-font)}

.chat-fab{
  position:fixed;right:20px;bottom:20px;z-index:95;
  display:inline-flex;align-items:center;gap:9px;
  height:52px;padding:0 20px 0 17px;border-radius:999px;
  background:var(--navy);color:#fff;border:0;cursor:pointer;text-decoration:none;
  font:700 14.5px/1 var(--chat-font);
  box-shadow:0 14px 34px rgba(11,58,130,.36);
  transition:transform .18s ease,background .18s ease;
}
.chat-fab:hover{background:var(--navy-2);transform:translateY(-2px)}
.chat-fab svg{width:20px;height:20px;flex:0 0 auto}
/* Phone: the bottom nav already carries a Chat item with the word on it, so a
   second floating invitation is clutter. */
@media(max-width:768px){ .chat-fab{display:none} }
/* ── Ask Pallavi, the page ────────────────────────────────────────────────
   Two shapes from one markup. Desktop: an intro column beside a fixed-height
   assistant panel. Phone: the panel is the whole screen and the intro is
   dropped, so it opens like a messaging app.
   100dvh, not 100vh: on iOS Safari the address bar makes vh taller than the
   visible area, which would push the input under the browser chrome. */
.chat-page{padding-top:34px}
.chat-page-grid{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start}
@media(max-width:1080px){ .chat-page-grid{grid-template-columns:1fr;gap:30px} }

.chat-intro h1{font-size:clamp(30px,3.4vw,44px);line-height:1.14}
.chat-can{list-style:none;padding:0;margin:26px 0 0;display:grid;gap:12px}
.chat-can li{display:flex;gap:11px;align-items:flex-start;font-size:15.5px}
.chat-can svg{width:19px;height:19px;flex:0 0 auto;color:var(--orange);margin-top:2px}
.chat-intro-alt{display:flex;gap:12px;flex-wrap:wrap;margin-top:28px}

.chat-stage{
  background:#fff;border:1px solid var(--line);border-radius:26px;overflow:hidden;
  box-shadow:var(--shadow);display:flex;flex-direction:column;
  height:min(660px,calc(100vh - 190px));min-height:520px;
}

@media(max-width:768px){
  /* The panel becomes the page. The site header, footer and bottom nav all step
     out of the way so nothing floats over a conversation. */
  .chat-page{padding:0}
  .chat-page-grid{gap:0}
  .chat-intro{display:none}
  .chat-stage{
    position:fixed;inset:0;z-index:200;
    height:100dvh;min-height:0;border:0;border-radius:0;box-shadow:none;
  }
  body:has(.chat-stage) .footer,
  body:has(.chat-stage) .bottom-nav,
  body:has(.chat-stage) .header,
  body:has(.chat-stage) .push-ask,
  body:has(.chat-stage) .install-bar,
  body:has(.chat-stage) .ann-bar{display:none !important}
  body:has(.chat-stage){overflow:hidden}
}

/* A way out of the conversation, on every width — on desktop it is the only way
   back to the site, since the panel is the focus of the page. */
.chat-back{
  display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  background:rgba(255,255,255,.14);color:#fff;font-size:19px;line-height:1;
  text-decoration:none;flex:0 0 auto;
}
.chat-back:hover{background:rgba(255,255,255,.24)}
.chat-who{flex:1;min-width:0}
.chat-who strong em{
  font-style:normal;font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  background:rgba(255,255,255,.18);border-radius:999px;padding:2px 7px;margin-left:7px;vertical-align:2px;
}
.chat-call{
  width:36px;height:36px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  background:rgba(255,255,255,.14);color:#fff;
}
.chat-call:hover{background:rgba(255,255,255,.26)}
.chat-call .ic{width:18px;height:18px}
.chat-note{
  background:#fff7ed;color:#8a5a20;font-size:11.5px;text-align:center;
  padding:7px 14px;border-bottom:1px solid #fde8cf;
}
.chat-legal{
  margin:0;padding:0 14px 10px;font-size:10.5px;color:var(--muted);text-align:center;background:#fff;
}

/* The input row: WhatsApp on the left so a human is always one tap away. */
.chat-wa{
  width:44px;height:44px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  background:#25D366;color:#fff;transition:transform .15s ease;
}
.chat-wa:hover{transform:translateY(-2px)}
.chat-wa .ic{width:21px;height:21px}
.chat-send{
  width:44px;height:44px;border-radius:50%;border:0;flex:0 0 auto;cursor:pointer;
  background:var(--navy);color:#fff;font-size:17px;line-height:1;display:grid;place-items:center;
  transition:transform .15s ease,background .15s ease;
}
.chat-send:hover{background:var(--navy-2);transform:translateY(-2px)}

/* A face and a green dot. People talk to a person, not to a product name. */
.chat-head{
  background:linear-gradient(135deg,var(--navy),var(--navy-2));color:#fff;
  padding:14px 18px;display:flex;align-items:center;gap:12px;
}
.chat-head img{
  width:42px;height:42px;border-radius:50%;object-fit:cover;object-position:top center;
  border:2px solid rgba(255,255,255,.35);flex:0 0 auto;background:var(--pale);
}
.chat-head strong{display:block;font-size:15px}
.chat-head span{font-size:12px;color:#bdd2ee;display:flex;align-items:center;gap:5px}
.chat-head span:before{
  content:"";width:7px;height:7px;border-radius:50%;background:#34d399;
  box-shadow:0 0 0 3px rgba(52,211,153,.25);
}

/* The gate form */
.chat-gate{
  display:grid;gap:5px;background:#fff;border:1px solid var(--line);border-radius:18px;
  padding:16px;font-size:14px;
}
.chat-gate label{font-weight:700;font-size:12.5px;margin-top:8px}
.chat-gate label:first-child{margin-top:0}
.chat-gate label b{color:#dc2626}
.chat-gate label .opt{font-weight:500;color:var(--muted);font-size:11.5px}
.chat-gate input{
  border:1px solid var(--line);border-radius:12px;padding:10px 12px;font:inherit;font-size:14px;
  background:var(--gray);width:100%;
}
.chat-gate input:focus{outline:none;border-color:var(--navy);background:#fff;box-shadow:0 0 0 3px rgba(11,58,130,.10)}
.chat-gate .note{font-size:11px;color:var(--muted);line-height:1.45}
.chat-gate .btn{margin-top:12px;width:100%}
.chat-seg{display:flex;gap:6px}
.chat-seg button{
  flex:1;border:1px solid var(--line);background:var(--gray);border-radius:10px;
  padding:9px 6px;font:inherit;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;
}
.chat-seg button.on{background:var(--navy);border-color:var(--navy);color:#fff}

/* Account / password buttons */
.chat-acts{display:flex;gap:7px;flex-wrap:wrap;padding:2px 0}
.chat-acts button{
  border:1px solid var(--navy);background:var(--pale);color:var(--navy);border-radius:999px;
  padding:7px 13px;font:inherit;font-size:12.5px;font-weight:700;cursor:pointer;
}
.chat-acts button:hover{background:var(--navy);color:#fff}
.chat-msg.typing{letter-spacing:3px;color:var(--muted)}
.chat-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;background:var(--gray)}
.chat-msg{
  max-width:82%;padding:12px 15px;border-radius:17px;font-size:14px;line-height:1.5;
  animation:chatPop .25s cubic-bezier(.22,.61,.36,1);
}
.chat-msg.bot{background:#fff;border:1px solid var(--line);box-shadow:0 2px 8px rgba(8,32,73,.05);align-self:flex-start;border-bottom-left-radius:5px}
.chat-msg.me{background:var(--navy);color:#fff;align-self:flex-end;border-bottom-right-radius:5px}
@keyframes chatPop{from{opacity:0;transform:translateY(6px) scale(.97)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){ .chat-msg{animation:none} }
.chat-foot{padding:12px;border-top:1px solid var(--line);display:flex;gap:8px;align-items:center}
.chat-foot input{flex:1;height:46px;border:1px solid var(--line);border-radius:23px;padding:0 18px}
.chat-foot input:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 3px rgba(11,58,130,.10)}
.chat-foot input:disabled{background:#eef1f5;cursor:not-allowed}

/* Tappable suggestions — most of this audience would rather tap than type English */
.chat-chips{display:flex;flex-wrap:wrap;gap:7px;padding:2px 0}
.chat-chips button{
  background:#fff;border:1px solid #c9dcf4;color:var(--navy);
  border-radius:999px;padding:8px 13px;font-size:12.5px;font-weight:600;
  cursor:pointer;line-height:1.2;text-align:left;
}
.chat-chips button:hover{background:var(--pale)}

/* MCQ options inside a bot reply — one per line, tappable (client's ask: the
   old raw "**a) ... b) ...**" text bunched into one paragraph). Typing the
   answer still works too; this is just a faster way in. */
.chat-opts{display:grid;gap:7px;padding:2px 0;max-width:82%}
.chat-opt{
  display:block;width:100%;text-align:left;background:#fff;border:1px solid #c9dcf4;color:var(--ink);
  border-radius:13px;padding:10px 14px;font:inherit;font-size:13.5px;font-weight:600;
  cursor:pointer;line-height:1.4;transition:background .15s ease,border-color .15s ease,transform .15s ease;
}
.chat-opt:hover{background:var(--pale);border-color:var(--navy);transform:translateX(2px)}
.chat-msg a{color:inherit;text-decoration:underline;font-weight:700}

/* ── Alerts / empty / pager ─────────────────────────────────────────────── */
.alert{border-radius:12px;padding:14px 16px;margin:0 0 18px;font-size:14px;font-weight:600}
.alert-ok{background:#e4f8f0;color:#0a6b48;border:1px solid #b7e8d3}
.alert-err{background:#fdecec;color:#a52020;border:1px solid #f7c8c8}
.alert-info{background:var(--pale);color:var(--navy);border:1px solid #c9dcf4}

.empty{text-align:center;padding:60px 20px;color:var(--muted)}
.empty .ic{width:46px;height:46px;color:#b6c6da;margin-bottom:12px}

.pager{display:flex;gap:6px;align-items:center;justify-content:center;margin-top:30px;flex-wrap:wrap}
.pager a,.pager span{
  min-width:40px;height:40px;border-radius:11px;border:1px solid var(--line);
  display:grid;place-items:center;text-decoration:none;color:var(--navy);font-weight:700;font-size:14px;padding:0 12px;
}
.pager a.cur{background:var(--navy);color:#fff;border-color:var(--navy)}
.pager span.dis{color:#b6c0cc}

/* ══ ADMIN EXTRAS ════════════════════════════════════════════════════════
   The admin panel reuses the student-area shell (.app-shell/.sidebar/.main/
   .panel/.metric-grid/.table). Only the CRUD table and drawer need new rules,
   so there is deliberately no separate admin.css to keep in sync. */

.cb{width:38px;text-align:center}
.cb input{width:17px;height:17px;accent-color:var(--navy)}
.tbl-actions{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}
/* Icon plus a word. Four unlabelled glyphs in a row is a puzzle — the client
   should never have to hover to find out which button deletes. */
.ia{
  min-height:34px;border-radius:9px;border:1px solid var(--line);background:#fff;
  display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:var(--navy);
  text-decoration:none;font:600 12.5px/1 'DM Sans',sans-serif;padding:0 11px;white-space:nowrap;
}
.ia .ic{width:16px;height:16px;flex:0 0 auto}
.ia:hover{background:var(--pale);border-color:#c9dcf4}
.ia.del{color:var(--red)}
.ia.del:hover{background:#fef2f2;border-color:#fecaca}
.ia.del span[aria-hidden]{font-size:17px;line-height:0.8}
/* The drawer close button is the one place a bare glyph is right. */
.drawer .ia{padding:0 10px}
.ia.del:hover{background:#fdecec;border-color:#f7c8c8}
.ia .ic{width:16px;height:16px}

.bulkbar{
  display:none;align-items:center;gap:12px;background:var(--pale);border:1px solid #c9dcf4;
  border-radius:12px;padding:10px 14px;margin-bottom:14px;
}
.bulkbar.on{display:flex}
.bulkbar .sel{font-weight:700;font-size:13px;color:var(--navy);margin-right:auto}

.thumb-xs{width:46px;height:36px;border-radius:8px;object-fit:cover;background:var(--pale);display:block}
.grow{flex:1}

/* Slide-in drawer form */
.drawer-ov{position:fixed;inset:0;background:rgba(6,22,47,.55);z-index:150;opacity:0;pointer-events:none;transition:opacity .28s ease}
.drawer-ov.open{opacity:1;pointer-events:auto}
/* A centred modal. Thirty-one fields in a 560px strip pinned to the right edge
   was the complaint; at 900px the short fields pair up and the form halves.
   Still called .drawer — every module references that name. */
.drawer{
  position:fixed;left:50%;top:50%;z-index:160;
  width:min(900px,94vw);max-height:92vh;background:#fff;border-radius:20px;
  transform:translate(-50%,-50%) scale(.97);opacity:0;pointer-events:none;
  /* visibility, not just opacity: a closed modal must be genuinely inert. With
     opacity alone it stays in the tab order and a screen reader still reads all
     31 fields of a form nobody opened. */
  visibility:hidden;
  transition:opacity .2s ease,transform .24s cubic-bezier(.22,.61,.36,1),visibility 0s linear .24s;
  display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 40px 100px rgba(8,32,73,.34);
}
.drawer.open{opacity:1;transform:translate(-50%,-50%) scale(1);pointer-events:auto;
  visibility:visible;transition-delay:0s}
.drawer > form{display:flex;flex-direction:column;min-height:0;flex:1}
.drawer-h{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:20px 26px;border-bottom:1px solid var(--line);flex:0 0 auto;
}
.drawer-h h3{margin:0;font-size:20px}

/* Two columns for the short fields. A textarea, a rich-text box or an upload slot
   always takes the full width — splitting those makes them unusable. */
.drawer-b{
  padding:24px 26px;overflow-y:auto;flex:1;min-height:0;
  display:grid;grid-template-columns:1fr 1fr;gap:0 22px;align-content:start;
}
.drawer-b > .fld{grid-column:1 / -1}
.drawer-b > .fld.fld-half{grid-column:auto}
.drawer-b > input[type=hidden]{display:none}

/* Section heading: spans both columns, and the first one loses its top margin. */
.fld-sec{
  grid-column:1 / -1;margin:22px 0 14px;padding-top:18px;
  border-top:1px solid var(--line);
  font-size:12px;font-weight:800;letter-spacing:.10em;text-transform:uppercase;color:var(--navy);
}
.fld-sec:first-of-type{margin-top:0;padding-top:0;border-top:0}
.fld-sec span{
  display:block;margin-top:6px;font-size:12px;font-weight:500;letter-spacing:0;
  text-transform:none;color:var(--muted);line-height:1.5;
}

/* Sticky footer, so Save is never at the bottom of a long scroll. */
.drawer-f{
  display:flex;justify-content:flex-end;gap:10px;flex:0 0 auto;
  padding:16px 26px;border-top:1px solid var(--line);background:var(--gray);
}

@media(max-width:820px){
  .drawer{
    left:0;top:auto;bottom:0;transform:translateY(14px);
    width:100%;max-width:none;max-height:94dvh;border-radius:20px 20px 0 0;
  }
  .drawer.open{transform:translateY(0)}
  .drawer-b{grid-template-columns:1fr;padding:20px}
  .drawer-b > .fld.fld-half{grid-column:1 / -1}
  .drawer-h,.drawer-f{padding:16px 20px}
  .drawer-f .btn{flex:1}
}

.drawer .fld{margin-bottom:16px}
.drawer .fld > label{display:block;font-weight:700;font-size:13px;margin-bottom:6px}
.drawer .fld input[type=text],.drawer .fld input[type=number],.drawer .fld input[type=date],
.drawer .fld input[type=email],.drawer .fld select,.drawer .fld textarea{
  width:100%;border:1px solid var(--line);border-radius:11px;padding:12px 14px;background:#fff;color:var(--ink);
}
.drawer .fld textarea{min-height:110px;resize:vertical;line-height:1.55}
.drawer .fld input:focus,.drawer .fld select:focus,.drawer .fld textarea:focus{
  outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(11,58,130,.10);
}
.drawer .hint{font-size:12px;color:var(--muted);margin-top:6px;line-height:1.5}
.lookup-row{display:flex;gap:8px;align-items:center}
.lookup-row select{flex:1 1 auto;min-width:0}
.lookup-row .btn{flex:0 0 auto;white-space:nowrap}
.switch{display:flex;align-items:center;gap:10px;font-weight:700;font-size:14px;cursor:pointer}
.switch input{width:18px;height:18px;accent-color:var(--navy)}

.img-slot{border:1px dashed #c5d6ec;border-radius:12px;padding:14px;background:var(--gray)}
.img-prev-wrap{position:relative;display:inline-block;margin-bottom:12px}
.img-prev{max-width:180px;max-height:130px;border-radius:10px;display:block}
.img-x{
  position:absolute;top:-9px;right:-9px;width:28px;height:28px;border-radius:50%;
  border:2px solid #fff;background:var(--red);color:#fff;cursor:pointer;font-size:16px;line-height:1;
}
.file-cur{margin-bottom:10px;word-break:break-all}

/* Multi-select checkbox list (test/material → product mapping) */
.checklist{
  border:1px solid var(--line);border-radius:12px;padding:8px;max-height:220px;overflow-y:auto;background:#fff;
}
.checklist label{
  display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:9px;
  font-size:14px;font-weight:500;cursor:pointer;
}
.checklist label:hover{background:var(--pale)}
.checklist input{width:17px;height:17px;accent-color:var(--navy);flex:0 0 auto}

/* Question builder rows */
.qrow{border:1px solid var(--line);border-radius:14px;padding:18px;margin-bottom:14px;background:#fff}
.qrow .qhead{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px}
.qrow .opt{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.qrow .opt input[type=text]{flex:1}
.qrow .opt input[type=radio]{width:18px;height:18px;accent-color:var(--green);flex:0 0 auto}

@media(max-width:768px){
  .drawer{width:100vw}
  .bulkbar{flex-wrap:wrap}
}

/* ── Rich text from the CMS (blog posts, policy pages, course descriptions) ─ */
.post-body{font-size:17px;line-height:1.72;color:#33415c}
.post-body > :first-child{margin-top:0}
.post-body h2{font-size:clamp(24px,2.4vw,32px);margin:38px 0 14px;color:var(--ink)}
.post-body h3{font-size:21px;margin:30px 0 10px;color:var(--navy);font-style:normal}
.post-body p{margin:0 0 18px;color:inherit}
.post-body ul,.post-body ol{margin:0 0 20px;padding-left:22px}
.post-body li{margin-bottom:9px}
.post-body strong{color:var(--ink)}
.post-body a{color:var(--navy);font-weight:600;text-decoration:underline;text-underline-offset:3px}
.post-body img{border-radius:18px;margin:24px 0}
.post-body blockquote{
  margin:26px 0;padding:18px 24px;border-left:4px solid var(--orange);
  background:var(--pale);border-radius:0 14px 14px 0;font-style:italic;color:var(--ink);
}
.post-body table{width:100%;border-collapse:collapse;margin:24px 0;font-size:15px}
.post-body th,.post-body td{padding:12px;border-bottom:1px solid var(--line);text-align:left}
.post-body code{background:var(--gray);padding:2px 6px;border-radius:6px;font-size:.9em}
.post-body hr{border:0;border-top:1px solid var(--line);margin:34px 0}

/* ── Scroll animations (JS adds .in) ────────────────────────────────────────
   One base class plus directional variants. Stagger is done with an inline
   transition-delay on the element, so a grid needs no extra markup. */
/* FAIL-OPEN: the hidden state is scoped to .js, which an inline script in
   header.php sets. If JS never runs, is blocked, or errors before main.js, the
   content is simply visible. Content must never depend on JS to be seen. */
.js .reveal{opacity:0;transform:translateY(24px)}
.js .reveal-left{opacity:0;transform:translateX(-28px)}
.js .reveal-right{opacity:0;transform:translateX(28px)}
.js .reveal-zoom{opacity:0;transform:scale(.94)}
.js .reveal,.js .reveal-left,.js .reveal-right,.js .reveal-zoom{
  transition:opacity .65s cubic-bezier(.22,.61,.36,1),transform .65s cubic-bezier(.22,.61,.36,1);
}
.js .reveal.in,.js .reveal-left.in,.js .reveal-right.in,.js .reveal-zoom.in{opacity:1;transform:none}

/* Subtle 3D tilt on pointer devices — depth without gimmick */
@media (hover:hover) and (pointer:fine){
  .tilt{transition:transform .25s cubic-bezier(.22,.61,.36,1),box-shadow .25s ease;transform-style:preserve-3d;will-change:transform}
  .tilt:hover{box-shadow:0 30px 70px rgba(12,42,85,.16)}
}

/* Hero art float — slow, ignorable, never distracting */
@keyframes floatY{0%,100%{transform:translateY(0)}50%{transform:translateY(-12px)}}
.hero-art img{animation:floatY 7s ease-in-out infinite}

/* Marquee-free ticker for the stats band count-up: JS swaps the text, CSS just
   keeps the width from jumping */
.stat strong{font-variant-numeric:tabular-nums}

/* prefers-reduced-motion: honoured for what can genuinely unsettle someone —
   smooth scrolling, the pointer-tracking 3D tilt, and reveals that *slide*
   (they still fade in) — and for nothing else. On Windows this flag is set by
   "Adjust for best performance" / Animation effects off, which on most of this
   audience's laptops is a speed preference, not a medical one; with every
   animation keyed off it, the site read as dead on the client's own machines
   (2026-09-05: frozen ticker, static hero, reviews stopped, no reveals). The
   ticker, hero float and slides, reviews marquee, rotating word, count-up and
   hover transitions now run regardless. main.js has the matching split (`calm`).
   The few remaining reduced-motion rules below cover smooth scrolling (.shelf)
   and one-off pop-ins (chat, nudges) only. */
@media (prefers-reduced-motion:reduce){
  .js .reveal,.js .reveal-left,.js .reveal-right,.js .reveal-zoom{transform:none;transition:opacity .5s ease}
  html{scroll-behavior:auto}
  .tilt:hover{transform:none}
}

/* ── Tablet ─────────────────────────────────────────────────────────────── */
/* Between the phone breakpoint and a roomy desktop there is not enough width for
   logo + search box + nav + three buttons. The search icon keeps working there. */
@media(max-width:1180px){
  .hdr-inline{display:none}
  .nav{margin-left:auto}
}
@media(max-width:1024px){
  .wrap{width:calc(100% - 40px)}
  .section{padding:68px 0}
  .grid.four{grid-template-columns:repeat(2,1fr)}
  .hero-grid{grid-template-columns:1fr;gap:30px}
  .hero-art{height:400px;order:-1}
  .product-grid{grid-template-columns:1fr;gap:30px}
  .buy-box{position:static}
  .buy-col{align-self:auto}
  .player{grid-template-columns:1fr}
  .feature-split{grid-template-columns:1fr;gap:34px}
  .dashboard-grid{grid-template-columns:1fr}
  .metric-grid{grid-template-columns:repeat(2,1fr)}
  .app-shell{grid-template-columns:76px 1fr}
  .sidebar{padding:20px 12px}
  .sidebar .logo{height:36px}
  .menu-item span,.menu-title{display:none}
  .menu-item{justify-content:center;padding:14px 0}
  .auth-shell{grid-template-columns:1fr}
  .auth-art{padding:40px;min-height:280px}
  .auth-panel{padding:44px 28px}
}

/* ── Phone ──────────────────────────────────────────────────────────────── */
@media(max-width:768px){
  :root{--nav-h:70px}
  .wrap{width:calc(100% - 32px)}
  .header .logo{height:42px}
  .nav,.nav-actions,.hdr-inline{display:none}
  .mobile-menu{display:block}
  .bottom-nav{display:flex}
  body{padding-bottom:64px}
  /* Phone: the sidebar becomes a slide-in drawer opened from the topbar, so the
     client is never stranded on a screen with no menu. */
  .app-shell{display:block}
  .sidebar{
    position:fixed;top:0;left:0;bottom:0;width:min(280px,84vw);z-index:130;
    transform:translateX(-102%);transition:transform .3s cubic-bezier(.22,.61,.36,1);
    padding:22px 18px;height:100vh;
  }
  .sidebar.open{transform:translateX(0);box-shadow:24px 0 60px rgba(8,32,73,.3)}
  .sidebar .logo{height:44px;margin-bottom:22px}
  .menu-item span,.menu-title{display:revert}
  .menu-item{justify-content:flex-start;padding:13px 14px}
  .app-menu-btn{display:inline-grid}
  .sidebar-ov{
    display:block;position:fixed;inset:0;background:rgba(6,22,47,.55);z-index:125;
    opacity:0;pointer-events:none;transition:opacity .3s ease;
  }
  .sidebar-ov.open{opacity:1;pointer-events:auto}
  .main{padding:20px 16px 90px}

  .hero{padding:42px 0}
  .hero p{font-size:16px}
  .hero-actions{flex-direction:column;align-items:stretch}
  .hero-art{height:280px}
  .hero-art img{border-radius:22px}
  .trust-row{align-items:flex-start}

  .stats .wrap{grid-template-columns:1fr 1fr;padding:12px 0}
  .stat{padding:14px 10px;border-right:0;border-bottom:1px solid rgba(255,255,255,.15)}
  .stat strong{font-size:25px}

  .section{padding:48px 0}
  .section-head{display:block}
  .section-head p{margin-top:12px}

  /* Short cards read better as a 2×2 block than as a long single column —
     the page gets half as tall and nothing has to be scrolled past.
     Tall cards (course cards, comparison columns) still go full width. */
  .grid.four,.grid.two{grid-template-columns:1fr 1fr;gap:12px}
  .grid.three,.compare{grid-template-columns:1fr}
  .grid.four .card,.grid.two .card{padding:18px 14px}
  .grid.four .icon,.grid.two .icon{width:38px;height:38px;margin-bottom:12px;border-radius:11px}
  .grid.four .icon .ic,.grid.two .icon .ic{width:19px;height:19px}
  .grid.four h3,.grid.two h3{font-size:15px}
  .grid.four .tiny,.grid.two .tiny{font-size:11.5px;line-height:1.45}
  /* Course/blog cards keep a single readable column even inside .grid.two */
  .grid.two .course-card{grid-column:1/-1}

  /* …except where the client asked for two-up: the home page course row.
     Two full-size course cards side by side are unreadable, so everything
     inside them steps down — cover, title, meta, price — and the description
     drops out entirely. Four courses then fit in one screen instead of four. */
  .grid.courses-2up{grid-template-columns:1fr 1fr;gap:12px}
  .grid.courses-2up .course-card{grid-column:auto}
  /* No fixed height here either — the ratio keeps the art uncropped. */
  .grid.courses-2up .course-cover{aspect-ratio:16/9;border-radius:16px 16px 0 0}
  .grid.courses-2up .cover-badge{font-size:9px;padding:3px 6px;top:7px;left:7px}
  .grid.courses-2up .cover-off{font-size:9px;padding:3px 6px;top:7px;right:7px}
  .grid.courses-2up .course-body{padding:11px 11px 13px;gap:6px}
  .grid.courses-2up .course-body h3{font-size:13.5px;line-height:1.3}
  .grid.courses-2up .course-body p{display:none}
  /* The rating STAYS. Only the duration/lesson meta line goes, and the tag shrinks. */
  .grid.courses-2up .card-rate{margin-top:6px;gap:5px}
  .grid.courses-2up .card-rate .stars{font-size:11px}
  .grid.courses-2up .card-rate b{font-size:12px}
  .grid.courses-2up .card-rate i{font-size:11px}
  .grid.courses-2up .card-for{font-size:10.5px;padding:4px 7px;margin-top:6px}
  .grid.courses-2up .card-for .ic{width:12px;height:12px}
  .grid.courses-2up .meta{display:none}
  .grid.courses-2up .meta .ic{width:13px;height:13px}
  .grid.courses-2up .price-row{flex-direction:column;align-items:stretch;gap:8px}
  .grid.courses-2up .price{font-size:17px}
  .grid.courses-2up .price s{font-size:11px}
  .grid.courses-2up .price-row .btn{width:100%;text-align:center;padding:8px 10px;font-size:12px}

  /* Steps: 2×2 as well, with the number beside the text */
  .steps{grid-template-columns:1fr 1fr;gap:8px}
  .steps:before{display:none}
  .step{text-align:center;padding:16px 10px;margin:0;background:var(--gray);border-radius:16px}
  .step-no{width:40px;height:40px;margin:0 auto 10px;font-size:14px}
  .step h3{font-size:15px}
  .step p{font-size:11.5px;line-height:1.45}
  /* Deliberately NOT a height. A fixed height here was overriding aspect-ratio
     and stretching every cover — the same crop bug as the desktop 210px. */
  .course-cover{aspect-ratio:16/9;height:auto}
  .compare-col{padding:22px 18px}
  .compare-col h3{font-size:19px}
  .compare-col li{font-size:13.5px}

  .newsletter{padding:28px;display:block}
  .newsletter form{margin-top:16px}
  .newsletter input{width:100%}

  .footer-grid{grid-template-columns:1fr 1fr;gap:30px}
  .footer-grid>div:first-child{grid-column:1/-1}
  .footer-bot{flex-direction:column}

  .subhero{padding:38px 0}
  .subhero .wrap{display:block}
  .blobicon{display:none}
  .toolbar{display:grid;grid-template-columns:1fr}
  .filter,.search{min-width:0}
  .visual-panel{min-height:230px}

  .metric-grid{grid-template-columns:1fr 1fr}
  .metric{padding:16px}
  .metric .k{font-size:22px}
  .chart{height:200px;gap:8px;padding-top:16px}
  .course-row{grid-template-columns:52px 1fr}
  .course-row>:nth-child(n+3){display:none}
  .table{min-width:620px}
  .modal{padding:26px 22px}
  /* Superseded by the full-screen sheet above — this line was capping the phone
     panel at 520px and is why it stopped short of the bottom of the screen. */
  /* The bottom nav already has a Chat item — a floating bubble on top of it is
     just clutter, and it covers content. Desktop keeps the bubble. */
  .chat-fab{display:none}
  .vid-card{flex:0 0 200px;width:200px}

  /* Non-essential on a phone: long supporting copy, the third card metric, and
     the decorative avatar row. Everything load-bearing stays. */
  .hide-phone{display:none !important}
  .meta span:nth-child(n+3){display:none}
  .footer-grid{gap:22px}
  .footer h4{font-size:12.5px;margin-bottom:10px}
  .footer a{margin:7px 0;font-size:13.5px}
  .newsletter h2{font-size:24px}
  .quote{font-size:18px}
  .subhero h1{font-size:30px}
  .subhero p{font-size:15px}
  .buy-body{padding:20px}
  .buy-price b{font-size:28px}
  .panel{padding:18px}
  .card{padding:20px}
  .icon{width:40px;height:40px;margin-bottom:14px}
  h1{letter-spacing:-.02em}
}

/* Shown only on a phone — the counterpart to .hide-phone */
.only-phone{display:none}
@media(max-width:768px){ .only-phone{display:block} }

/* ── Chat Logs: conversation list + thread ────────────────────────────────── */
.chatlog-split{display:grid;grid-template-columns:340px 1fr;gap:18px;align-items:start}
.chatlog-list{max-height:calc(100vh - 230px);overflow-y:auto;padding:16px}
.chatlog-item{
  display:flex;align-items:center;gap:11px;padding:11px 10px;border-radius:12px;
  text-decoration:none;color:var(--ink);border-bottom:1px solid var(--line);
}
.chatlog-item:last-child{border-bottom:0}
.chatlog-item:hover{background:var(--gray)}
.chatlog-item.on{background:var(--pale);box-shadow:inset 3px 0 0 var(--navy)}
.chatlog-item .av{
  width:34px;height:34px;border-radius:10px;background:var(--navy);color:#fff;
  display:grid;place-items:center;font-weight:800;font-size:14px;flex:0 0 auto;
}
.chatlog-item .who{flex:1;min-width:0;display:block}
.chatlog-item .who b{display:block;font-size:13.5px;font-weight:700}
.chatlog-item .who i{display:block;font-style:normal;font-size:11.5px;color:var(--muted)}
.chatlog-item .who em{
  display:block;font-style:normal;font-size:12px;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px;
}
.chatlog-item .meta{text-align:right;flex:0 0 auto;display:grid;gap:4px;justify-items:end}
.chatlog-item .meta i{font-style:normal;font-size:11px;color:var(--muted)}

.chatlog-thread{padding:0;display:flex;flex-direction:column;max-height:calc(100vh - 230px)}
.chatlog-thread .panel-head{padding:16px 20px;margin:0;border-bottom:1px solid var(--line)}
.chatlog-body{flex:1;overflow-y:auto;padding:18px 20px;display:flex;flex-direction:column;gap:12px}
.chatlog-day{text-align:center;margin:6px 0}
.chatlog-day span{
  font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);background:var(--gray);border-radius:999px;padding:4px 12px;
}
.chatlog-msg{max-width:76%;border-radius:14px;padding:10px 13px;position:relative}
.chatlog-msg .lbl{
  display:block;font-size:10.5px;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;opacity:.6;margin-bottom:4px;
}
.chatlog-msg p{margin:0;font-size:14px;line-height:1.55;white-space:pre-wrap}
.chatlog-msg time{display:block;font-size:10.5px;opacity:.55;margin-top:6px}
.chatlog-msg.them{align-self:flex-start;background:var(--gray);border:1px solid var(--line)}
.chatlog-msg.us{align-self:flex-end;background:var(--navy);color:#fff}
.chatlog-msg.us .lbl,.chatlog-msg.us time{opacity:.7}
@media(max-width:1024px){
  .chatlog-split{grid-template-columns:1fr}
  .chatlog-list{max-height:340px}
  .chatlog-thread{max-height:none}
  .chatlog-msg{max-width:92%}
}

/* ── Checkout: payment mode + delivery address ────────────────────────────── */
.pay-modes,.ship-box{border:1px solid var(--line);border-radius:18px;padding:18px;margin:0}
.pay-modes legend,.ship-box legend{
  font-weight:800;font-size:12.5px;letter-spacing:.04em;text-transform:uppercase;
  color:var(--navy);padding:0 8px;
}
.pay-mode{
  display:flex;align-items:flex-start;gap:11px;padding:13px;border:1px solid var(--line);
  border-radius:13px;cursor:pointer;margin-top:10px;transition:border-color .2s ease,background .2s ease;
}
.pay-mode:first-of-type{margin-top:4px}
.pay-mode:hover{border-color:#c9dcf4;background:var(--pale)}
.pay-mode input{margin-top:3px;accent-color:var(--navy);flex:0 0 auto}
.pay-mode:has(input:checked){border-color:var(--navy);background:var(--pale);box-shadow:0 0 0 3px rgba(11,58,130,.08)}
.pay-mode b{display:block;font-size:14.5px}
.pay-mode em{display:block;font-style:normal;font-size:12.5px;color:var(--muted);margin-top:3px}
.ship-box textarea{
  width:100%;border:1px solid var(--line);border-radius:11px;padding:11px 13px;font:inherit;
  background:var(--gray);resize:vertical;
}
.ship-box textarea:focus{outline:none;border-color:var(--navy);background:#fff;box-shadow:0 0 0 3px rgba(11,58,130,.10)}

/* ── Course contents: the introduction, before chapter one ─────────────────── */
.intro-item{
  display:flex;gap:18px;align-items:center;padding:16px;margin-bottom:18px;
  border:1px solid var(--line);border-radius:20px;background:var(--pale);
}
.intro-thumb{
  position:relative;flex:0 0 200px;aspect-ratio:4/3;border:0;padding:0;cursor:pointer;
  border-radius:14px;overflow:hidden;background:#000;
}
.intro-thumb img{width:100%;height:100%;object-fit:cover;opacity:.9;transition:opacity .3s ease}
.intro-thumb:hover img{opacity:1}
.intro-thumb .vid-play{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:52px;height:52px;border-radius:50%;background:var(--orange);
  box-shadow:0 8px 22px rgba(245,130,32,.5);
}
.intro-thumb .vid-play:after{
  content:"";position:absolute;left:53%;top:50%;transform:translate(-50%,-50%);
  border-left:15px solid #fff;border-top:9px solid transparent;border-bottom:9px solid transparent;
}
.intro-copy{flex:1;min-width:0}
.intro-copy h3{margin:9px 0 5px;font-size:19px}
.intro-copy p{margin:0 0 13px;font-size:14px;color:var(--muted)}
@media(max-width:640px){
  .intro-item{flex-direction:column;align-items:stretch;gap:14px}
  .intro-thumb{flex:none;width:100%}
}

/* ── Help dots ────────────────────────────────────────────────────────────── */
.help-dot{
  display:inline-grid;place-items:center;width:17px;height:17px;border-radius:50%;
  border:1px solid var(--line);background:var(--gray);color:var(--muted);
  font:700 11px/1 inherit;cursor:pointer;padding:0;vertical-align:middle;
  margin-left:5px;flex:0 0 auto;transition:all .2s ease;
}
.help-dot:hover,.help-dot.on{background:var(--navy);border-color:var(--navy);color:#fff}
.help-pop{
  position:absolute;z-index:200;max-width:300px;background:var(--navy);color:#fff;
  border-radius:12px;padding:12px 14px;font-size:13px;line-height:1.55;font-weight:500;
  box-shadow:0 18px 44px rgba(6,22,47,.30);
}
.help-pop:after{
  content:"";position:absolute;top:-6px;left:14px;width:12px;height:12px;
  background:var(--navy);transform:rotate(45deg);border-radius:2px;
}

/* Media protection: only for visitors, never for the admin previewing the site. */
body:not(.is-admin) .vid-box img,
body:not(.is-admin) .reel-card img,
body:not(.is-admin) .intro-thumb img,
body:not(.is-admin) .hero-art img{
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;pointer-events:none;
}

/* ── Footer: icons, socials, trust strip ──────────────────────────────────── */
.footer-grid a{display:flex;align-items:center;gap:9px}
.footer-grid a.btn{display:inline-flex;gap:8px}
.footer-grid a .ic{width:16px;height:16px;flex:0 0 auto;opacity:.75}
.footer-brand .mr-line{font-size:13.5px;opacity:.8;margin:8px 0 0}
.footer-social{display:flex;gap:9px;margin-top:16px}
/* The marks carry their own brand colour now (brand_icon()), so the chip behind
   them is a plain white tile — coloured logos read cleanly on white and turn to
   mud on a tinted background. The old per-brand hover fills are gone for the
   same reason: a green icon on a green background is invisible. */
.footer-social .soc{
  width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  background:#fff;border:1px solid rgba(255,255,255,.16);
  transition:transform .25s ease,box-shadow .25s ease;
}
.footer-social .soc .ic{width:20px;height:20px;opacity:1}
.footer-social .soc:hover{transform:translateY(-3px);box-shadow:0 8px 20px rgba(0,0,0,.28)}

.footer-trust{
  display:flex;flex-wrap:wrap;gap:10px 26px;justify-content:center;
  margin:34px 0 6px;padding:18px 20px;border-radius:18px;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);
}
.footer-trust span{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;opacity:.9}
.footer-trust .ic{width:17px;height:17px;color:var(--orange)}
@media(max-width:768px){
  .footer-trust{gap:9px 16px;padding:14px 12px;margin-top:24px}
  .footer-trust span{font-size:11.5px}
  .footer-social{justify-content:flex-start}
}

/* ── Teacher section ──────────────────────────────────────────────────────── */
.teacher-panel{position:relative}
.teacher-badge{
  position:absolute;left:16px;bottom:16px;right:16px;
  display:flex;align-items:center;gap:9px;
  background:rgba(255,255,255,.94);backdrop-filter:blur(8px);
  border-radius:14px;padding:11px 14px;box-shadow:0 12px 30px rgba(8,32,73,.16);
}
.teacher-badge .ic{width:19px;height:19px;color:var(--orange);flex:0 0 auto}
.teacher-badge b{font-size:13px;color:var(--navy)}
.teacher-quote{
  margin:22px 0 0;padding:16px 20px;border-left:4px solid var(--orange);
  background:var(--pale);border-radius:0 16px 16px 0;
  font-family:'Lora',Georgia,serif;font-style:italic;font-size:17px;line-height:1.6;color:var(--navy);
}
.teacher-quote cite{
  display:block;margin-top:9px;font-family:'DM Sans',sans-serif;font-style:normal;
  font-size:12.5px;font-weight:700;color:var(--muted);
}
.teacher-fact{display:flex;align-items:center;gap:10px;padding:14px 16px;font-weight:600;font-size:14px}
.teacher-fact .ic{width:17px;height:17px;color:var(--green,#16a34a);flex:0 0 auto}

/* ── Announcement ticker ──────────────────────────────────────────────────────
   Same trick as the reviews wall: the list is printed twice and the track slides
   exactly half its width, so the loop has no seam. Pure CSS — nothing to break. */
.ann-bar{
  position:relative;overflow:hidden;color:#fff;
  background:linear-gradient(100deg,var(--navy-2) 0%,var(--navy) 45%,#123f8f 70%,var(--navy-2) 100%);
  box-shadow:inset 0 -1px 0 rgba(255,255,255,.10), 0 2px 14px rgba(6,22,47,.18);
}
/* A slow sheen across the bar — where the "3D / premium" feel comes from. */
.ann-bar:before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.13) 48%,transparent 62%);
  transform:translateX(-60%);animation:annSheen 7s ease-in-out infinite;
}
@keyframes annSheen{0%,70%{transform:translateX(-60%)}100%{transform:translateX(160%)}}
.ann-track{
  display:flex;width:max-content;align-items:center;
  animation:annLoop 42s linear infinite;
}
.ann-bar:hover .ann-track,.ann-bar:focus-within .ann-track{animation-play-state:paused}
@keyframes annLoop{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.ann-item{
  display:inline-flex;align-items:center;gap:9px;white-space:nowrap;
  padding:9px 26px;font-size:13.5px;font-weight:600;letter-spacing:.01em;
}
.ann-item i{
  width:6px;height:6px;border-radius:50%;background:var(--orange);flex:0 0 auto;
  box-shadow:0 0 0 3px rgba(245,130,32,.25);
}
.ann-item .orange{color:#ffc98a}
@media(max-width:768px){ .ann-item{padding:8px 18px;font-size:12.5px} }

/* ── Header search icon (opens #hdrSearch — the always-visible bar is gone) ── */
.hdr-search-btn{
  width:38px;height:38px;border-radius:10px;display:grid;place-items:center;flex:0 0 auto;
  border:1px solid var(--line);background:#fff;color:var(--navy);cursor:pointer;
  transition:background .2s ease,border-color .2s ease;
}
.hdr-search-btn .ic{width:18px;height:18px}
.hdr-search-btn:hover{background:var(--pale);border-color:#c9dcf4}

/* ── Header social icons ──────────────────────────────────────────────────── */
.hdr-social{display:inline-flex;gap:6px;margin-left:4px}
.hdr-social .soc{
  width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  border:1px solid var(--line);background:#fff;color:var(--navy);
  transition:transform .2s ease,background .2s ease,border-color .2s ease;
}
.hdr-social .soc .ic{width:18px;height:18px}
/* Brand colour lives in the mark itself now — hover just lifts it. */
.hdr-social .soc:hover{transform:translateY(-2px);box-shadow:0 6px 16px rgba(11,58,130,.16)}
@media(max-width:1320px){ .hdr-social{display:none} }

/* ── Phone header: menu · logo · search box · account ─────────────────────── */
.hdr-phone-search{display:none}
.mobile-menu.acct{display:none}
@media(max-width:768px){
  .header .wrap{gap:8px}
  .mobile-menu{margin-left:0;padding:6px;order:-1}
  /* The phone search box used to be the flex spacer between the hamburger and
     the account icon (flex:1 1 auto). It is gone (search lives in the drawer
     now), so .brand takes over that job with margin-right:auto instead. */
  .brand{order:0;margin-right:auto}
  .logo{height:40px}
  .mobile-menu.acct{display:grid;place-items:center;order:2;color:var(--navy)}
  .mobile-menu.acct .ic{width:24px;height:24px}
}

/* ── Drawer dropdowns (<details>, no JS) ──────────────────────────────────── */
.mnav-drop{border-bottom:1px solid var(--line)}
.mnav-drop > summary{
  display:flex;align-items:center;gap:12px;padding:14px 6px;cursor:pointer;
  font-weight:600;color:var(--ink);list-style:none;
}
.mnav-drop > summary::-webkit-details-marker{display:none}
.mnav-drop > summary .ic{color:var(--navy)}
.mnav-drop .caret{
  margin-left:auto;width:8px;height:8px;flex:0 0 auto;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg) translateY(-2px);transition:transform .2s ease;
}
.mnav-drop[open] .caret{transform:rotate(-135deg) translateY(-2px)}
.mnav-drop[open] > summary{color:var(--navy)}
.mnav-drop a,.mnav-drop .as-link{
  padding:11px 6px 11px 40px;font-size:14px;font-weight:500;color:var(--muted);border-bottom:0;
}
.mnav-drop a:hover,.mnav-drop .as-link:hover{color:var(--navy)}

/* ── Footer install block ─────────────────────────────────────────────────── */
.footer-app{
  display:flex;align-items:center;gap:18px;margin-top:34px;padding:20px 22px;
  border-radius:20px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);
}
.footer-app img{width:52px;height:52px;border-radius:14px;flex:0 0 auto}
.footer-app > div{flex:1;min-width:0}
.footer-app strong{display:block;font-size:16px}
.footer-app span{display:block;font-size:13px;opacity:.82;margin-top:2px}
.footer-app .mr-line{font-size:12.5px;opacity:.7;margin-top:4px}
.footer-app .btn{flex:0 0 auto}
@media(max-width:640px){
  .footer-app{flex-wrap:wrap;gap:14px;padding:16px}
  .footer-app .btn{width:100%;justify-content:center}
}

/* ── Rolling product shelf (ebooks / audiobooks / printed books) ───────────────
   A scroll container with snap points. No carousel library, no JS needed to
   swipe — the arrows are only a convenience for a mouse. The scrollbar is hidden
   because a visible one under a shelf reads as a mistake, and the cards are wide
   enough to be an obvious swipe affordance on their own. */
.shelf-sec .section-head{align-items:flex-end}
.shelf-nav{display:flex;align-items:center;gap:8px}
.shelf{
  display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:4px 2px 8px;margin-top:20px;
  scrollbar-width:none;-ms-overflow-style:none;overscroll-behavior-x:contain;
  scroll-behavior:smooth;
}
.shelf::-webkit-scrollbar{display:none}
.shelf:focus-visible{outline:2px solid var(--navy);outline-offset:4px;border-radius:20px}
.shelf-card{
  flex:0 0 232px;width:232px;scroll-snap-align:start;
  background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;
  text-decoration:none;color:inherit;display:flex;flex-direction:column;
  transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease;
}
.shelf-card:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(8,32,73,.13);border-color:#c9dcf4}
.shelf-cover{
  position:relative;aspect-ratio:4/3;background:linear-gradient(135deg,var(--navy),#3f7ad4);
  display:grid;place-items:center;
}
.shelf-cover img{width:100%;height:100%;object-fit:cover}
.shelf-ph .ic{width:40px;height:40px;color:rgba(255,255,255,.9)}
.shelf-cover .cover-badge{position:absolute;top:9px;left:9px;font-size:10px;padding:3px 8px}
.shelf-body{padding:13px 14px 15px;display:flex;flex-direction:column;gap:5px;flex:1}
.shelf-body h3{font-size:14.5px;line-height:1.35;margin:0}
.shelf-meta{font-size:11.5px;color:var(--muted)}
.shelf-price{margin-top:auto;font-weight:800;color:var(--navy);font-size:16px}
.shelf-price s{font-weight:500;font-size:12px;color:#9aa7b7;margin-left:6px}

@media(max-width:768px){
  /* Two at a time, as asked. The 16px gap is why it is not a flat 50%. */
  .shelf{gap:12px;margin-top:16px}
  .shelf-card{flex:0 0 calc(50% - 6px);width:calc(50% - 6px)}
  .shelf-body{padding:11px 12px 13px}
  .shelf-body h3{font-size:13px}
  .shelf-price{font-size:14.5px}
  .shelf-price s{display:none}
  .shelf-nav .btn{padding:8px 12px;font-size:12px}
}
@media(prefers-reduced-motion:reduce){ .shelf{scroll-behavior:auto} }

/* ── Chat bubble with her face ────────────────────────────────────────────────
   A speech-bubble glyph says "software". A face says "a teacher will answer",
   which is closer to the truth here and gets far more taps. */
.chat-fab.has-face{padding:0;overflow:visible;background:var(--navy)}
.chat-fab.has-face img{
  width:100%;height:100%;border-radius:50%;object-fit:cover;object-position:top center;
  border:2px solid #fff;display:block;
}
.chat-fab-dot{
  position:absolute;right:2px;bottom:3px;width:14px;height:14px;border-radius:50%;
  background:#34d399;border:2.5px solid #fff;
  animation:fabPulse 2.4s ease-in-out infinite;
}
@keyframes fabPulse{
  0%,100%{box-shadow:0 0 0 0 rgba(52,211,153,.55)}
  60%{box-shadow:0 0 0 9px rgba(52,211,153,0)}
}

/* ── Notification opt-in bar ──────────────────────────────────────────────────
   Sits above the install bar so the two never overlap. Slides up rather than
   appearing, because something that materialises silently reads as an ad. */
.push-ask{
  position:fixed;left:14px;right:14px;bottom:14px;z-index:97;
  display:flex;align-items:center;gap:13px;
  background:#fff;border:1px solid var(--line);border-radius:18px;padding:13px 15px;
  box-shadow:0 22px 60px rgba(8,32,73,.22);
  transform:translateY(140%);transition:transform .35s cubic-bezier(.22,.61,.36,1);
}
.push-ask.in{transform:translateY(0)}
.push-ask img{width:42px;height:42px;border-radius:12px;flex:0 0 auto}
.push-txt{flex:1;min-width:0}
.push-txt strong{display:block;font-size:14.5px;line-height:1.35}
.push-txt .mr-line{display:block;font-size:12px;color:var(--muted);margin-top:3px}
.push-ask .btn{flex:0 0 auto}
.push-x{
  background:none;border:0;font-size:22px;line-height:1;color:var(--muted);
  cursor:pointer;padding:2px 4px;flex:0 0 auto;
}
@media(min-width:769px){
  .push-ask{left:auto;right:20px;width:400px}
}
@media(max-width:768px){
  /* Above the bottom nav, and above the install bar if that is showing too. */
  .push-ask{bottom:74px;flex-wrap:wrap;gap:10px}
  .push-ask .btn{width:100%;justify-content:center;order:3}
  .push-txt strong{font-size:13.5px}
}
@media(prefers-reduced-motion:reduce){ .push-ask{transition:none} }

/* ── Course page: the band beside the tall purchase panel ─────────────────── */
.course-gap{
  margin-top:34px;padding:22px 24px;border-radius:20px;
  background:var(--pale);border:1px solid var(--line);max-width:560px;
}
.course-gap .eyebrow{display:block;margin-bottom:14px}
.gap-list{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.gap-list li{display:flex;align-items:flex-start;gap:11px;font-size:14.5px;line-height:1.5}
.gap-list .ic{width:18px;height:18px;color:var(--green,#16a34a);flex:0 0 auto;margin-top:2px}

/* ── Course page header, structured like the client's reference ────────────── */
.course-signals{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.course-rate{display:inline-flex;align-items:center;gap:7px}
.course-rate .stars{color:var(--orange);font-size:15px;letter-spacing:.5px}
.course-rate b{font-size:14.5px;color:var(--ink)}
.course-rate i{font-style:normal;font-size:13px;color:var(--muted)}
.course-enrolled{
  font-size:12.5px;font-weight:600;color:var(--navy);
  background:var(--pale);border-radius:999px;padding:5px 11px;
}
.course-lede{font-size:16.5px;line-height:1.65;color:var(--muted);max-width:60ch;margin:0 0 20px}
.course-facts{display:flex;flex-wrap:wrap;gap:12px 26px;margin-top:4px}
.course-facts span{display:inline-flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:var(--ink)}
.course-facts .ic{width:18px;height:18px;color:var(--navy);flex:0 0 auto}
.buy-media .buy-off{top:12px;right:12px}
.offer-countdown{
  display:flex;align-items:center;gap:7px;margin:8px 0 0;padding:8px 12px;
  background:#fff7ed;color:#8a5a20;border:1px solid #fde8cf;border-radius:10px;
  font-size:12.5px;font-weight:600;
}
.offer-countdown .ic{width:15px;height:15px;flex:0 0 auto}
.offer-countdown b{font-variant-numeric:tabular-nums;color:#c2410c}

/* Reads better on both breakpoints: plain title, description, the two action
   buttons, and only THEN the badge/rating row. Round 20 built this for phone
   only; the client asked for desktop to match, so it is unconditional now —
   `order` needs a flex/grid parent, hence `.course-main` becoming a column
   flexbox everywhere, not just under the phone media query any more. */
.course-main{display:flex;flex-direction:column}
.course-main h1{order:1}
.course-main .course-lede{order:2}
.course-main .hero-actions{order:3}
.course-main .course-signals{order:4}
.course-main .course-facts{order:5}
.course-main .card-for{order:6}
.course-main .setup-pending{order:7}
.course-main .course-gap{order:8}
/* Reordering with `order` moves an element visually but not the margin it
   was written with — .hero-actions and .course-signals both had ~0 margin
   because each used to sit right before something with its own top margin.
   In their new spots that read as the buttons and the badge row touching,
   which is exactly what the client flagged. Restoring the gap here, scoped
   to this reordered column so nothing else using these classes is affected
   (there is nowhere else — grep confirms course.php is the only user). */
.course-main .course-signals{margin-top:18px}
.course-main .course-facts{margin-top:14px}

/* This section's top gap read as too tall on a full desktop — the phone and
   tablet breakpoints, which already reduce .section's padding for their own
   reasons, were never part of the complaint and are untouched. */
@media(min-width:1025px){
  .section.course-hero-sec{padding-top:38px}
}

@media(max-width:768px){
  .course-signals{gap:10px}
  .course-lede{font-size:15px}
  .course-facts{gap:9px 16px}
  .course-facts span{font-size:12.5px}
  .course-facts .ic{width:15px;height:15px}

  /* The buy-box card (video, price, perks, Enroll) leads the page on phone —
     exactly as it already looks on desktop, not a redesigned duplicate — and
     the descriptive column (ordered above) follows it. .product-grid already
     stacks into one column at this width; these two `order` values just
     decide which of its two children comes first. Desktop keeps its normal
     side-by-side columns, since `order` only swaps them inside this query. */
  .course-title-phone{order:0}
  .product-grid > .buy-col{order:1}
  .product-grid > .course-main{order:2}
  /* The course name is the phone-only h1 above the card now, so the second
     copy inside the column would just repeat it. */
  .course-main h1.only-phone{display:none}

  /* ONE column on a phone. This has flipped once: an earlier round set 2x2 at
     the client's request ("more professional"); on 2026-09-12 the client saw it
     on a real phone — 14px titles cut to two lines, 10px meta, thumbnails the
     size of a stamp — and called it ugly. It is. A full-width card shows the
     whole title, a readable price and a thumbnail you can actually see. If
     anyone asks for 2x2 again, show them the screenshot first. */
  .courses-grid{grid-template-columns:1fr !important;gap:16px}
  /* Three lines is enough to know what it is; the rest is on the course page.
     Without the clamp, one long description made its card twice as tall as the
     card beside it. */
  .courses-grid .course-card p{
    font-size:11.5px;line-height:1.4;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
  }
  .courses-grid .course-body{padding:11px;gap:7px}
  .courses-grid .price-row{flex-direction:column;align-items:stretch;gap:7px}
  .courses-grid .price-row .price{font-size:15.5px}
  .courses-grid .price-row .price s{font-size:12px}
  .courses-grid .price-row .btn{padding:8px 10px;font-size:12px;justify-content:center}
  /* The two cover badges sat on the same line and collided at this width. */
  .courses-grid .cover-badge{font-size:9.5px;padding:2px 7px;max-width:58%;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .courses-grid .cover-off{font-size:9.5px;padding:2px 7px}
}

/* ── Player: module labels in the lesson sidebar ───────────────────────────── */
.lesson-mod{flex-wrap:wrap}
.mod-no{
  display:block;width:100%;font-size:10px;font-weight:800;letter-spacing:.10em;
  text-transform:uppercase;color:var(--muted);margin-bottom:3px;
}

/* ── Teacher: hover overlay and the story popup ────────────────────────────── */
.teacher-panel{
  display:block;width:100%;padding:0;border:0;background:none;
  cursor:pointer;text-align:left;font:inherit;color:inherit;
}
.teacher-hover{
  position:absolute;inset:auto 0 0 0;z-index:3;
  display:flex;flex-direction:column;gap:4px;padding:56px 22px 22px;
  background:linear-gradient(to top,rgba(6,26,58,.94),rgba(6,26,58,.72) 55%,transparent);
  color:#fff;opacity:0;transform:translateY(14px);
  transition:opacity .28s ease,transform .28s ease;
}
.teacher-hover b{font-size:17px;font-weight:800}
.teacher-hover b::after{content:" →";color:var(--orange)}
.teacher-hover i{font-style:normal;font-size:13px;opacity:.85;line-height:1.5}
.teacher-panel:hover .teacher-hover,
.teacher-panel:focus-visible .teacher-hover{opacity:1;transform:none}
/* The overlay and the "teaches every class herself" badge share the bottom edge,
   so the badge steps aside while the overlay is up. */
.teacher-badge{transition:opacity .2s ease}
.teacher-panel:hover .teacher-badge,
.teacher-panel:focus-visible .teacher-badge{opacity:0}
.teacher-panel:focus-visible{outline:3px solid var(--orange);outline-offset:4px;border-radius:24px}
/* No hover on a touch screen — show it, quietly, so the tap is discoverable. */
@media(hover:none){
  .teacher-hover{opacity:1;transform:none;padding-top:40px}
  .teacher-badge{display:none}
}

.teacher-modal .modal{max-width:620px;padding:0;overflow:hidden}
.tm-head{
  display:flex;gap:18px;align-items:center;padding:26px 28px;
  background:linear-gradient(135deg,var(--navy),#2f6fc5);color:#fff;
}
.tm-head img{width:86px;height:86px;border-radius:50%;object-fit:cover;flex:0 0 auto;
  border:3px solid rgba(255,255,255,.5)}
.tm-head h3{color:#fff}
.tm-head .muted,.tm-head .mr-line{color:rgba(255,255,255,.82)}
.tm-body{padding:26px 28px;max-height:46vh;overflow:auto}
.tm-facts{display:grid;gap:10px}
.tm-facts span{display:flex;gap:10px;align-items:flex-start;font-size:14.5px}
.tm-facts svg{width:18px;height:18px;flex:0 0 auto;color:var(--orange);margin-top:2px}
.tm-foot{display:flex;gap:12px;flex-wrap:wrap;padding:20px 28px;border-top:1px solid var(--line);
  background:var(--gray)}
@media(max-width:600px){
  .tm-head{padding:20px}
  .tm-head img{width:64px;height:64px}
  .tm-body,.tm-foot{padding:20px}
  .tm-foot .btn{flex:1 1 100%}
}

.how-to-modal{width:min(600px,100%)}
.how-to-steps{margin:0;padding-left:20px;line-height:1.6;color:var(--ink)}
.how-to-steps li{margin-bottom:12px}
.how-to-steps li:last-child{margin-bottom:0}
.how-to-video{
  margin-top:20px;border-radius:16px;overflow:hidden;background:#000;
  aspect-ratio:16/9;position:relative;
}
.how-to-video iframe,.how-to-video video{position:absolute;inset:0;width:100%;height:100%;border:0}

/* ── Log in / Create account: two tabs over one card ───────────────────────── */
.auth-tabs{
  display:grid;grid-template-columns:1fr 1fr;gap:4px;margin:0 0 26px;
  padding:4px;background:var(--gray);border:1px solid var(--line);border-radius:14px;
}
.auth-tabs a{
  padding:11px 8px;border-radius:10px;text-align:center;
  font-weight:700;font-size:14.5px;color:var(--muted);text-decoration:none;
  transition:background .18s ease,color .18s ease;
}
.auth-tabs a:hover{color:var(--navy)}
.auth-tabs a.on{background:#fff;color:var(--navy);box-shadow:0 1px 3px rgba(10,32,68,.12)}

/* ── "You are inside a student account" bar ────────────────────────────────
   Fixed to the bottom rather than the top: the header is already sticky, and a
   second sticky strip up there fights it on a phone. Bottom is also where the
   thumb is when the client is walking someone through a page on a call. */
.access-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:9000;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:12px 18px;background:#15233b;color:#fff;
  box-shadow:0 -8px 30px rgba(10,32,68,.28);
  font-size:14px;
}
.access-bar span{display:flex;align-items:center;gap:9px;min-width:0}
.access-bar svg{width:18px;height:18px;flex:0 0 auto;color:var(--orange)}
.access-bar strong{color:#fff}
.access-bar i{font-style:normal;color:#9fb8dd}
.access-bar .btn{background:var(--orange);color:#fff;border:0;flex:0 0 auto}
.access-bar .btn:hover{background:#e0740f}
/* Keep it clear of the phone's bottom nav and the buy bar. */
body:has(.access-bar) .bottom-nav{bottom:52px}
body:has(.access-bar) .chat-fab{bottom:110px}
@media(max-width:600px){
  .access-bar{font-size:12.5px;padding:10px 12px;gap:10px}
  .access-bar i{display:none}
}

/* The filled-in example is a two-column reference table, so it needs more room
   than the generic modal gives a paragraph of text. */
.crud-example .modal{max-width:760px;width:min(760px,94vw)}
.crud-example .table td{padding:11px 14px;font-size:13.5px}
.crud-example .table code{font-size:12.5px}
@media(max-width:600px){
  .crud-example .table td:first-child{width:auto}
  .crud-example .table td{display:block}
  .crud-example .table td:first-child{padding-bottom:2px}
  .crud-example .table td:last-child{padding-top:0}
}

/* ══════════════════════════════════════════════════════════════════════════════
   Round 8 — Browse grid, rails, Daily Doses, books, leaderboard, community
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Browse: doors into the site, right under the hero ────────────────────────
   Four across on a desktop, two on a phone. Every tile is a real link, and the
   icon lifts and tilts on hover and on tap — the "animated icons" the client
   asked for, done with transforms rather than a megabyte of 3D PNGs. */
.start-here-sec{padding-top:34px}

/* ── Homepage doors: two glowing cards linking to Practice / Courses ──────── */
.door-wrap{display:grid;grid-template-columns:1fr 1fr;gap:20px}
@media(max-width:820px){ .door-wrap{grid-template-columns:1fr} }

.door-card{
  position:relative;display:flex;align-items:center;gap:18px;
  padding:28px 26px;border-radius:24px;text-decoration:none;color:var(--ink);
  background:linear-gradient(#fff,#fff) padding-box,
             linear-gradient(135deg,var(--card-a),var(--card-b)) border-box;
  border:1.5px solid transparent;
  box-shadow:0 16px 40px rgba(12,42,85,.08),0 0 0 1px var(--card-glow);
  transition:transform .3s cubic-bezier(.22,.61,.36,1),box-shadow .3s ease;
}
.door-card:hover,.door-card:focus-visible{
  transform:translateY(-4px);
  box-shadow:0 24px 60px rgba(12,42,85,.16),0 0 0 4px var(--card-glow);
}
.door-navy{--card-a:var(--navy);--card-b:#4f8ff7;--card-glow:rgba(11,58,130,.14)}
.door-orange{--card-a:var(--orange);--card-b:#ffb066;--card-glow:rgba(245,130,32,.16)}

.door-ic{
  flex:0 0 auto;width:56px;height:56px;border-radius:16px;display:grid;place-items:center;
  background:linear-gradient(145deg,var(--card-a),var(--card-b));color:#fff;
  box-shadow:0 8px 20px var(--card-glow);
  transition:transform .3s cubic-bezier(.22,.61,.36,1);
}
.door-ic .ic{width:26px;height:26px}
.door-card:hover .door-ic{transform:scale(1.08) rotate(-4deg)}
.door-txt{flex:1;min-width:0}
.door-txt strong{display:block;font-size:20px;font-weight:800}
.door-txt i{display:block;font-style:normal;font-size:13.5px;color:var(--muted);margin-top:4px;line-height:1.4}
.door-arrow{
  flex:0 0 auto;width:20px;height:20px;color:var(--card-a);
  transform:rotate(-90deg);transition:transform .3s cubic-bezier(.22,.61,.36,1);
}
.door-card:hover .door-arrow{transform:rotate(-90deg) scale(1.2)}

@media(max-width:600px){
  .door-card{padding:20px;gap:14px}
  .door-ic{width:46px;height:46px;border-radius:13px}
  .door-txt strong{font-size:17px}
  .door-txt i{font-size:13px}
}

/* ── Practice Session's four cards (Tests · Daily Doses · AI · Contest) ────── */
.practice-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
@media(max-width:900px){ .practice-cards{grid-template-columns:repeat(2,1fr)} }

.browse-sec{padding-top:34px}
/* Three across, capped at six tiles (see render_browse_grid) — so it is always
   two clean rows of three on a desktop and three rows of two on a phone. Four
   across left the 6-tile case as 4 + 2, with two tiles stranded on their own
   row, which reads as a mistake rather than a layout. */
.browse-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:14px;
}
@media(max-width:700px){  .browse-grid{grid-template-columns:repeat(2,1fr);gap:11px} }

.browse-tile{
  display:flex;align-items:center;gap:13px;
  padding:16px;border-radius:18px;background:var(--pale);
  border:1px solid transparent;text-decoration:none;color:var(--ink);
  transition:transform .2s ease,box-shadow .2s ease,background .2s ease,border-color .2s ease;
}
.browse-tile:hover,.browse-tile:focus-visible{
  background:#fff;border-color:var(--line);
  transform:translateY(-3px);box-shadow:0 16px 36px rgba(11,58,130,.12);
}
.bt-ic{
  flex:0 0 auto;width:44px;height:44px;border-radius:13px;
  display:grid;place-items:center;background:#fff;color:var(--navy);
  box-shadow:0 4px 14px rgba(11,58,130,.14);
  transition:transform .28s cubic-bezier(.22,.61,.36,1),background .2s ease,color .2s ease;
}
.bt-ic svg{width:22px;height:22px}
/* Every tile turning the same orange on hover read as one big blob rather than
   eight different destinations. Cycling the brand's own colours instead. */
.browse-tile:nth-child(3n+1) .bt-ic{--tile-accent:var(--orange)}
.browse-tile:nth-child(3n+2) .bt-ic{--tile-accent:var(--navy)}
.browse-tile:nth-child(3n+3) .bt-ic{--tile-accent:var(--green)}
.browse-tile:hover .bt-ic,.browse-tile:focus-visible .bt-ic,.browse-tile:active .bt-ic{
  background:var(--tile-accent,var(--orange));color:#fff;
  transform:translateY(-2px) rotate(-8deg) scale(1.08);
}
.bt-txt{display:grid;gap:2px;min-width:0}
.bt-txt strong{font-size:14.5px;font-weight:800;line-height:1.25}
.bt-txt i{font-style:normal;font-size:12px;color:var(--muted)}
@media(max-width:700px){
  .browse-tile{flex-direction:column;align-items:flex-start;gap:10px;padding:14px}
  .bt-ic{width:40px;height:40px}
  .bt-txt strong{font-size:13.5px}
  .bt-txt i{font-size:11.5px}
}

/* ── Rail: a shelf you push along ─────────────────────────────────────────────
   scroll-snap, so a phone swipe is the browser's own gesture — momentum and
   rubber-banding for free. The arrows are enhancement; main.js hides them when
   there is nothing to scroll to. */
.rail{position:relative}
.rail-track{
  display:flex;gap:18px;overflow-x:auto;overflow-y:hidden;
  scroll-snap-type:x mandatory;scroll-behavior:smooth;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
  /* Room for the card shadow, and for the focus ring not to be clipped. */
  padding:6px 4px 18px;margin:0 -4px;
}
.rail-track::-webkit-scrollbar{display:none}
.rail-item{
  flex:0 0 auto;width:300px;scroll-snap-align:start;
}
@media(max-width:600px){
  .rail-track{gap:13px}
  /* Just under the viewport, so the next card peeks and the swipe is discoverable. */
  .rail-item{width:78vw;max-width:320px}
}
.rail-arw{
  position:absolute;top:38%;z-index:3;
  width:42px;height:42px;border-radius:50%;border:1px solid var(--line);
  background:#fff;color:var(--navy);font-size:17px;line-height:1;cursor:pointer;
  box-shadow:0 10px 26px rgba(8,32,73,.16);
  transition:background .18s ease,transform .18s ease;
}
.rail-arw:hover{background:var(--navy);color:#fff;transform:scale(1.06)}
.rail-arw.prev{left:-14px}
.rail-arw.next{right:-14px}
/* No arrows on a phone: the swipe is the interaction and they only cover a card. */
@media(max-width:820px){ .rail-arw{display:none} }

/* On the navy Courses band the arrows need to read against it. */
.courses-sec .rail-arw{border-color:rgba(255,255,255,.28)}

/* ── Daily Doses ───────────────────────────────────────────────────────────── */
.dose-topics{display:flex;gap:9px;flex-wrap:wrap;margin:0 0 26px}
.dose-topic{
  padding:8px 15px;border-radius:999px;border:1px solid var(--line);background:#fff;
  font-size:13.5px;font-weight:700;color:var(--muted);text-decoration:none;
}
.dose-topic:hover{color:var(--navy);border-color:var(--navy)}
.dose-topic.on{background:var(--navy);border-color:var(--navy);color:#fff}
.dose-topic i{font-style:normal;opacity:.6;margin-left:4px;font-size:12px}

.dose-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
@media(max-width:1080px){ .dose-grid{grid-template-columns:repeat(3,1fr)} }
@media(max-width:700px){  .dose-grid{grid-template-columns:repeat(2,1fr);gap:13px} }

.dose-card{
  display:block;text-decoration:none;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;
  transition:transform .2s ease,box-shadow .2s ease;
}
.dose-card:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(11,58,130,.14)}
.dose-art{
  position:relative;display:block;aspect-ratio:4/5;
  background:linear-gradient(135deg,var(--navy),#2f6fc5);overflow:hidden;
}
.dose-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.dose-count,.dose-tag{
  position:absolute;z-index:2;display:inline-flex;align-items:center;gap:5px;
  padding:5px 10px;border-radius:999px;font-size:11.5px;font-weight:800;
  background:rgba(255,255,255,.94);color:var(--navy);backdrop-filter:blur(6px);
}
.dose-count{right:10px;top:10px}
.dose-count svg{width:13px;height:13px}
.dose-tag{left:10px;top:10px;background:var(--orange);color:#fff}
.dose-meta{display:block;padding:14px 15px 16px}
.dose-meta strong{display:block;font-size:15px;line-height:1.3}
.dose-meta i{
  display:block;margin-top:5px;font-style:normal;font-size:12.5px;color:var(--muted);
  line-height:1.5;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
}

/* ── One dose, opened ──────────────────────────────────────────────────────── */
.dose-view{padding-top:30px}
.dose-head{display:flex;gap:16px;align-items:flex-start;margin-bottom:24px}
.dose-back{
  flex:0 0 auto;width:42px;height:42px;border-radius:50%;display:grid;place-items:center;
  background:var(--pale);color:var(--navy);font-size:19px;text-decoration:none;
}
.dose-back:hover{background:var(--navy);color:#fff}
.dose-head h1{font-size:clamp(24px,3vw,36px);margin:8px 0 6px}
.dose-head p{margin:0;color:var(--muted)}

/* A wide, page-width frame let a portrait screenshot float small with big grey
   gutters either side. Capping the stage to a phone-story width instead means
   the image fills the frame — no zoom needed to actually see it. */
/* Reels/Shorts-style: one tall box, slides stacked top-to-bottom, swipe (or
   arrows/keyboard) moves vertically. Capped narrow so it reads as a portrait
   "story" on a wide desktop screen too, exactly like YouTube Shorts does when
   it is not full-screen. */
.dose-stage{
  position:relative;max-width:420px;margin:0 auto;overflow:hidden;
  height:min(80vh,760px);border-radius:22px;background:#000;
  box-shadow:0 24px 60px rgba(8,32,73,.28);
}
.dose-track{
  display:flex;flex-direction:column;height:100%;overflow-y:auto;
  scroll-snap-type:y mandatory;scroll-behavior:smooth;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
.dose-track::-webkit-scrollbar{display:none}
.dose-track:focus-visible{outline:3px solid var(--orange);outline-offset:-4px}
.dose-slide{
  flex:0 0 100%;height:100%;scroll-snap-align:start;margin:0;
  display:grid;place-items:center;background:#000;
}
.dose-slide img{width:100%;height:100%;object-fit:contain;display:block}

/* Segmented progress bar, top — the Stories/Shorts read. */
.dose-progress{
  position:absolute;top:14px;left:14px;right:14px;z-index:4;display:flex;gap:5px;
}
.dose-progress span{
  flex:1 1 0;height:3px;border-radius:999px;background:rgba(255,255,255,.35);overflow:hidden;
}
.dose-progress span.on{background:#fff}

/* Stacked on the right edge, centred on the stage — clear of the progress bar
   at the top and the actions overlay at the bottom regardless of stage height. */
.dose-nav{
  position:absolute;right:14px;top:50%;z-index:3;
  width:40px;height:40px;border-radius:50%;border:0;cursor:pointer;
  background:rgba(255,255,255,.16);color:#fff;font-size:17px;backdrop-filter:blur(6px);
  transition:background .2s ease;
}
.dose-nav:hover{background:rgba(255,255,255,.3)}
.dose-nav.prev{transform:translateY(calc(-50% - 26px))}
.dose-nav.next{transform:translateY(calc(-50% + 26px))}
@media(hover:none){ .dose-nav{display:none} }   /* on a touch screen the swipe is the control */

/* Actions sit over the bottom of the image, reels-style — reachable on every
   slide without swiping all the way to the end. */
.dose-foot{
  position:absolute;left:0;right:0;bottom:0;z-index:4;
  display:flex;gap:10px;flex-wrap:wrap;padding:16px 16px 18px;
  background:linear-gradient(0deg,rgba(0,0,0,.72),rgba(0,0,0,0));
}
.dose-foot .btn{flex:1 1 auto;white-space:nowrap}

.dose-hint{text-align:center;margin:16px 0 26px}

/* ── Full-screen reel (dose.php builds its own shell; no header, no footer) ──
   The whole viewport is the stage. On a phone that is edge to edge; on a wide
   screen it is capped to a portrait column on black, exactly like YouTube Shorts
   when it is not full-screen. Client's ask: "just close, and scroll". */
html.dose-fs-page,body.dose-fs{height:100%;margin:0;background:#000;overflow:hidden}
body.dose-fs{display:grid;place-items:center}
.dose-stage-fs{
  max-width:none;width:100%;height:100vh;height:100dvh;border-radius:0;box-shadow:none;margin:0;
}
@media(min-width:760px){
  .dose-stage-fs{width:min(100vw, calc(100dvh * 9 / 16 + 120px));max-width:560px}
}
.dose-close{
  position:absolute;top:14px;right:14px;z-index:6;
  width:42px;height:42px;border-radius:50%;display:grid;place-items:center;
  background:rgba(255,255,255,.16);color:#fff;font-size:28px;line-height:1;text-decoration:none;
  backdrop-filter:blur(6px);transition:background .2s ease;
}
.dose-close:hover{background:rgba(255,255,255,.34);color:#fff}
/* progress bar makes room for the close button */
.dose-stage-fs .dose-progress{right:68px;top:20px}
/* .dose-fs-count, NOT .dose-count: that name already belongs to the "N slides"
   pill on the listing cards (top/right, blurred backdrop). Reusing it pinned this
   counter to all four edges and its backdrop-filter blurred the whole reel. */
.dose-fs-count{
  position:absolute;left:14px;bottom:14px;z-index:4;
  padding:5px 10px;border-radius:999px;background:rgba(0,0,0,.45);color:#fff;
  font-size:12px;letter-spacing:.04em;backdrop-filter:blur(6px);
}
.dose-fs-count b{font-weight:700}
.dose-fs-empty{color:#fff;text-align:center;padding:40px}
.dose-fs-empty p{margin:0 0 16px}


/* ── Books shelf ───────────────────────────────────────────────────────────── */
.book-card{
  display:block;text-decoration:none;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;
  transition:transform .2s ease,box-shadow .2s ease;
}
.book-card:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(11,58,130,.14)}
.book-art{position:relative;display:block;aspect-ratio:3/4;background:var(--gray);overflow:hidden}
.book-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.book-kind{
  position:absolute;left:10px;top:10px;z-index:2;
  padding:5px 10px;border-radius:999px;font-size:11px;font-weight:800;
  background:rgba(255,255,255,.94);color:var(--navy);backdrop-filter:blur(6px);
}
.book-meta{display:block;padding:14px 15px 16px}
.book-meta strong{display:block;font-size:15px;line-height:1.3}
.book-meta > i{
  display:-webkit-box;margin-top:5px;font-style:normal;font-size:12.5px;color:var(--muted);
  line-height:1.5;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;
}
.book-foot{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-top:12px}
.book-foot b{font-size:17px;font-weight:800;color:var(--navy)}
.book-foot s{font-size:13px;color:var(--muted)}
.book-foot em{
  font-style:normal;margin-left:auto;font-size:12.5px;font-weight:800;color:var(--orange);
}

/* ── Leaderboard ───────────────────────────────────────────────────────────── */
.board{
  display:grid;gap:2px;background:var(--line);
  border:1px solid var(--line);border-radius:18px;overflow:hidden;
}
.board-row{
  display:flex;align-items:center;gap:14px;padding:14px 18px;background:#fff;
}
.board-row.top{background:linear-gradient(90deg,#fff6ed,#fff)}
.board-rank{
  flex:0 0 auto;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  background:var(--pale);color:var(--navy);font-size:13px;font-weight:800;
}
.board-row.top .board-rank{background:var(--orange);color:#fff}
.board-who{flex:1;min-width:0}
.board-who strong{display:block;font-size:14.5px}
.board-who i{display:block;font-style:normal;font-size:12px;color:var(--muted);margin-top:2px}
.board-pct{font-size:17px;font-weight:800;color:var(--green)}
@media(max-width:600px){ .board-row{padding:12px 14px;gap:11px} }

/* ── Community band ────────────────────────────────────────────────────────── */
.community-band .cb-inner{
  display:flex;align-items:center;gap:24px;
  padding:30px 34px;border-radius:24px;
  background:linear-gradient(120deg,#0b3a82,#1b6bd0);color:#fff;
  box-shadow:var(--shadow);
}
.cb-ic{
  flex:0 0 auto;width:60px;height:60px;border-radius:18px;display:grid;place-items:center;
  background:#25D366;color:#fff;
}
.cb-ic svg{width:30px;height:30px}
.cb-txt{flex:1;min-width:0}
.cb-txt h2{color:#fff;font-size:clamp(21px,2.3vw,30px);margin:0 0 8px}
.cb-txt h2 .orange{color:#ffb266}
.cb-txt p{margin:0;color:rgba(255,255,255,.86);font-size:14.5px}
.cb-txt .mr-line{color:#cfe0f7 !important;margin-top:6px}
.community-band .btn.primary{flex:0 0 auto;background:#25D366;border-color:#25D366}
.community-band .btn.primary:hover{background:#1eb757}
@media(max-width:820px){
  .community-band .cb-inner{flex-direction:column;align-items:flex-start;padding:24px;gap:18px}
  .community-band .btn{width:100%;justify-content:center}
}

/* A WhatsApp-green button variant, for the hero. */
.btn.wa{background:#25D366;color:#fff;border:1px solid #25D366}
.btn.wa:hover{background:#1eb757;border-color:#1eb757;color:#fff}

/* ── "Still reading?" community nudge ──────────────────────────────────────────
   Fires once per session after twenty seconds. A bar, not a modal: it must never
   sit on top of what somebody is in the middle of reading. */
.join-nudge{
  position:fixed;left:14px;right:14px;bottom:14px;z-index:120;
  display:none;align-items:center;gap:14px;
  padding:14px 16px;border-radius:16px;background:#fff;
  border:1px solid var(--line);box-shadow:0 20px 50px rgba(8,32,73,.22);
}
.join-nudge.in{display:flex;animation:nudgeUp .4s cubic-bezier(.22,.61,.36,1)}
@keyframes nudgeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
.join-nudge .jn-ic{
  flex:0 0 auto;width:40px;height:40px;border-radius:12px;display:grid;place-items:center;
  background:#25D366;color:#fff;
}
.join-nudge .jn-ic svg{width:21px;height:21px}
.join-nudge p{margin:0;flex:1;font-size:13.5px;line-height:1.45}
.join-nudge p b{display:block;font-size:14.5px}
.join-nudge .jn-x{
  background:none;border:0;color:var(--muted);font-size:22px;line-height:1;cursor:pointer;padding:0 4px;
}
@media(min-width:821px){
  .join-nudge{left:auto;right:20px;bottom:20px;max-width:400px}
}
@media(max-width:820px){
  /* Clear of the phone bottom nav. */
  .join-nudge{bottom:70px}
  .join-nudge .btn{padding:9px 13px;font-size:13px}
}
@media(prefers-reduced-motion:reduce){ .join-nudge.in{animation:none} }

/* ── Chat teaser: a small speech bubble by the corner button ─────────────────
   Same show-once-per-session shape as .join-nudge, a different trigger, and
   desktop only — the corner button itself only exists on desktop (a phone
   reaches chat from the bottom nav instead). */
.chat-teaser{
  position:fixed;right:20px;bottom:88px;z-index:94;width:270px;
  display:none;gap:10px;grid-template-columns:36px 1fr;align-items:start;
  background:#fff;border-radius:16px;border:1px solid var(--line);
  box-shadow:0 20px 50px rgba(8,32,73,.22);padding:14px 30px 14px 14px;
}
.chat-teaser.in{display:grid;animation:nudgeUp .4s cubic-bezier(.22,.61,.36,1)}
.chat-teaser img{width:36px;height:36px;border-radius:50%;object-fit:cover;grid-row:1 / span 2}
.chat-teaser strong{display:block;font-size:13.5px}
.chat-teaser span{display:block;font-size:12.5px;color:var(--muted);margin-top:2px;line-height:1.4}
.chat-teaser .ct-go{
  grid-column:2;margin-top:9px;display:inline-block;background:var(--orange);color:#fff;
  border-radius:999px;padding:6px 13px;font-size:12px;font-weight:700;text-decoration:none;width:fit-content;
}
.chat-teaser .ct-x{
  position:absolute;top:6px;right:6px;background:none;border:0;color:var(--muted);
  font-size:16px;line-height:1;cursor:pointer;padding:6px;
}
@media(max-width:768px){ .chat-teaser{display:none !important} }   /* no corner button to anchor to */
@media(prefers-reduced-motion:reduce){ .chat-teaser.in{animation:none} }

/* The corner button's label fades between phrases, so it invites instead of
   sitting on one sentence. min-width stops the pill jumping as words change. */
.chat-fab span[data-fab-rotate]{
  transition:opacity .24s ease;min-width:9.5em;text-align:left;
}

/* ── Signed-in admin, on the public site ──────────────────────────────────────
   Their own name in the header, so it is never a guess which account is looking
   at the page. CSS-only <details>, like the nav dropdowns — no JS to break. */
.who-menu{position:relative}
.who-menu > summary{
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
}
.who-menu > summary::-webkit-details-marker{display:none}
.who-menu > summary .ic:last-child{width:14px;height:14px;transition:transform .2s ease}
.who-menu[open] > summary .ic:last-child{transform:rotate(180deg)}
.who-pop{
  position:absolute;right:0;top:calc(100% + 10px);z-index:120;
  min-width:262px;padding:14px;border-radius:16px;background:#fff;
  border:1px solid var(--line);box-shadow:0 22px 54px rgba(8,32,73,.20);
}
.who-pop a{
  display:flex;align-items:center;gap:10px;padding:10px 10px;border-radius:10px;
  font-size:13.5px;font-weight:600;color:var(--ink);text-decoration:none;
}
.who-pop a:hover{background:var(--pale);color:var(--navy)}
.who-pop a svg{width:17px;height:17px;flex:0 0 auto;color:var(--muted)}
.who-pop a:hover svg{color:var(--navy)}
@media(max-width:900px){ .who-pop{right:-8px;min-width:240px} }

/* A comprehension paragraph, readable while the questions are being answered.
   Sticky on a desktop; on a phone it simply sits above them, because a sticky
   block that eats half a small screen is worse than scrolling back. */
.test-passage{
  background:var(--pale);border:1px solid var(--line);border-radius:16px;
  padding:18px 20px;margin:0 0 26px;
}
.test-passage strong{
  display:block;margin-bottom:8px;font-size:11.5px;font-weight:800;
  letter-spacing:.10em;text-transform:uppercase;color:var(--navy);
}
.test-passage div{font-size:15px;line-height:1.75}
@media(min-width:900px){
  .test-passage{position:sticky;top:96px;z-index:2;max-height:38vh;overflow:auto}
}

/* ── Direct-to-Bunny upload widget (admin) ──────────────────────────────────
   The file input itself is invisible; its <label> is styled as the button, a
   standard vanilla technique that needs no JS to look right. */
.bunny-up{margin:10px 0}
.bunny-file-input{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0;
}
.bunny-file-input:focus-visible + label{outline:3px solid var(--orange);outline-offset:2px}
.bunny-up > label{cursor:pointer;display:inline-flex}
.bunny-bar{
  margin-top:9px;height:7px;border-radius:999px;background:var(--line);overflow:hidden;
}
.bunny-bar span{display:block;height:100%;width:0;background:var(--orange);transition:width .25s ease}
/* Was `tiny muted` — during a long upload that was the only feedback on screen
   and it read as nothing happening at all. */
.bunny-status{margin-top:7px !important;font-size:13px;font-weight:600;color:var(--ink)}
.bunny-status.err{color:var(--red)}
.bunny-status.done{color:var(--green);font-size:13.5px}

/* The three ways to attach a video, each visibly its own option. */
.vid-ways{display:grid;gap:12px;margin-top:4px}
.vid-way{border:1px solid var(--line);border-radius:12px;padding:12px 13px;background:var(--gray)}
.vid-way-t{display:block;font-size:12.5px;font-weight:800;color:var(--navy);margin-bottom:8px}
.vid-way input[type=file]{font-size:12.5px}
.vid-way .hint{margin-top:7px}
.vid-way .bunny-up{margin:0}
.bulk-up{display:flex;align-items:center;gap:12px;margin:10px 0 2px;flex-wrap:wrap}
.bulk-file{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
.bulk-file:focus-visible + label{outline:3px solid var(--orange);outline-offset:2px}
.bulk-up label{cursor:pointer;margin:0}
.upload-fallback{margin-top:10px}
.upload-fallback summary{cursor:pointer;font-size:12px;color:var(--muted)}
.upload-fallback summary:hover{color:var(--navy)}
.upload-fallback input[type=file]{margin-top:8px;font-size:12px}
