/*
Theme Name: Omar Elseoudy Academy
Theme URI: http://localhost/wordpress
Author: Omar Elseoudy
Author URI: https://example.com
Description: Custom LMS-style theme for Omar Elseoudy Math Academy — course pages, lessons, assignments, student dashboard, login/register, and past papers, built from the original site design.
Version: 1.0
Requires at least: 6.0
Requires PHP: 7.4
Text Domain: omarelseoudy
*/


/* ---------------------------------------------
   0. Tokens
--------------------------------------------- */
:root{
  --navy-950:#0a0e1a;
  --navy-900:#0d1224;
  --navy-800:#131a30;
  --navy-700:#1a2340;
  --navy-600:#232e52;
  --line-dark:#232b45;

  --ink-900:#101528;
  --ink-600:#5b6478;
  --ink-400:#8891a5;
  --ink-200:#dfe3ec;
  --paper:#ffffff;
  --paper-soft:#f5f6fa;

  --violet:#5b4fe9;
  --violet-600:#4a3fd6;
  --violet-100:#eceafc;
  --teal:#14b8a6;
  --teal-100:#dcf6f2;
  --amber:#f59e0b;
  --amber-100:#fef3dc;
  --rose:#ef4a6d;
  --green:#22c55e;

  --radius-lg:18px;
  --radius-md:12px;
  --radius-sm:8px;
  --shadow-card:0 10px 30px -12px rgba(11,15,30,.35);
  --font-display:'Sora', 'Segoe UI', sans-serif;
  --font-body:'Inter', 'Segoe UI', sans-serif;
}

*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}
/* Sticky footer: body is a full-viewport-height flex column with the
   header, .site-main and (optional) footer stacked in it. .site-main
   grows to fill whatever's left, so the footer always sits at the bottom
   of the viewport when a page's content is short, without ever needing
   fixed/absolute positioning. Individual pages don't need to know about
   this — they just render into .site-main like normal. */
body{
  margin:0;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  font-family:var(--font-body);
  color:var(--ink-900);
  background:var(--paper-soft);
  -webkit-font-smoothing:antialiased;
}
.site-main{flex:1;display:flex;flex-direction:column;}
img{max-width:100%;display:block;}
a{text-decoration:none;color:inherit;}
ul{list-style:none;margin:0;padding:0;}
h1,h2,h3,h4{font-family:var(--font-display);margin:0;line-height:1.15;}
p{margin:0;}
button{font-family:inherit;cursor:pointer;}
input,select{font-family:inherit;}

.container{max-width:1280px;margin:0 auto;padding:0 32px;}

/* Buttons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:12px 22px;border-radius:10px;border:1px solid transparent;
  font-weight:600;font-size:14.5px;cursor:pointer;transition:.15s ease;
  white-space:nowrap;
}
.btn-primary{background:var(--violet);color:#fff;}
.btn-primary:hover{background:var(--violet-600);}
.btn-ghost{background:transparent;color:var(--ink-200);border-color:rgba(255,255,255,.18);}
.btn-ghost:hover{border-color:rgba(255,255,255,.4);}
.btn-outline{background:transparent;color:var(--ink-900);border-color:#dfe3ec;}
.btn-outline:hover{border-color:var(--violet);color:var(--violet);}
.btn-block{width:100%;}
.btn-sm{padding:8px 14px;font-size:13px;border-radius:8px;}
:focus-visible{outline:2px solid var(--violet);outline-offset:2px;}

/* Badges / pills */
.pill{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;padding:5px 12px;border-radius:999px;}
.pill-violet{background:var(--violet-100);color:var(--violet-600);}
.pill-teal{background:var(--teal-100);color:#0d8f80;}
.pill-amber{background:var(--amber-100);color:#a2660a;}

/* Progress bar */
.progress{height:6px;border-radius:99px;background:#e7e9f2;overflow:hidden;}
.progress > span{display:block;height:100%;background:var(--violet);border-radius:99px;}

/* Card */
.card{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);}

/* ---------------------------------------------
   1. Public top navigation (site header)
--------------------------------------------- */
.site-header{background:var(--navy-950);position:sticky;top:0;z-index:50;border-bottom:1px solid var(--line-dark);}
.site-header .container{display:flex;align-items:center;justify-content:space-between;height:76px;}
.brand{display:flex;align-items:center;gap:10px;color:#fff;font-family:var(--font-display);font-weight:700;font-size:17px;}
.brand-logo{height:34px;width:auto;display:block;flex-shrink:0;}
.brand-logo-icon{display:none;}
.main-nav{display:flex;gap:34px;}
.main-nav a{color:var(--ink-200);font-size:14.5px;font-weight:500;opacity:.85;}
.main-nav a:hover,.main-nav a.active{opacity:1;color:#fff;}
.header-actions{display:flex;align-items:center;gap:12px;}
/* Was a plain <a>, now a <button> so it can toggle the dropdown below it —
   same visual circle either way, just resetting the default button chrome
   (border/padding) a browser would otherwise add. */
.avatar-btn{width:38px;height:38px;border-radius:50%;background:var(--violet);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:13px;border:0;padding:0;overflow:hidden;}
.avatar-btn img{width:100%;height:100%;object-fit:cover;display:block;}
.nav-toggle{display:none;background:none;border:0;color:#fff;font-size:22px;}

/* Avatar dropdown menu — dark theme matching the header itself (the
   nearest "dark" element on an otherwise light site), not the light
   .card system the rest of the page content uses. Same opacity/visibility/
   pointer-events transition technique as .main-nav.open above (no
   display:none/[hidden] toggling — that can't be transitioned), plus a
   translateY for the fade+slide-down look. */
.user-menu{position:relative;}
.user-menu-dropdown{
  position:absolute;
  top:calc(100% + 12px);
  right:0;
  min-width:220px;
  background:var(--navy-900);
  border:1px solid var(--line-dark);
  border-radius:18px;
  box-shadow:0 20px 44px -12px rgba(0,0,0,.5);
  padding:8px;
  opacity:0;
  visibility:hidden;
  transform:translateY(-8px);
  pointer-events:none;
  transition:opacity .2s ease, transform .2s ease, visibility 0s linear .2s;
  z-index:200;
}
.user-menu-dropdown.is-open{
  opacity:1;
  visibility:visible;
  transform:translateY(0);
  pointer-events:auto;
  transition:opacity .2s ease, transform .2s ease;
}
.user-menu-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;font-size:14px;font-weight:500;color:var(--ink-200);transition:background-color .15s ease,color .15s ease;}
.user-menu-item:hover{background:var(--navy-700);color:#fff;}
.user-menu-icon{font-size:15px;width:18px;text-align:center;flex-shrink:0;}
.user-menu-divider{height:1px;background:var(--line-dark);margin:6px 4px;}
.user-menu-item-danger{color:#ff8fa3;}
.user-menu-item-danger:hover{background:rgba(239,74,109,.15);color:#ff8fa3;}

/* Tablet + mobile: the hamburger reveals a floating dropdown panel
   below the navbar. The navbar row itself (.site-header .container) is
   completely untouched here — no flex-wrap, no reordering, no height
   change — Logo/Login/Register/hamburger stay exactly as on desktop,
   on one row. The panel is position:absolute (anchored to the navbar
   row, which is given position:relative here only), so it floats over
   the page instead of being part of the document flow: opening it
   can never shift, resize, or reflow anything underneath. */
@media (max-width:1024px){
  .nav-toggle{display:block;}
  .site-header .container{position:relative;}

  /* Closed state has to guarantee zero rendered pixels, not just rely on
     max-height:0 + overflow:hidden — .main-nav is a flex column whose <a>
     children have an explicit min-height:48px, and that combination
     stops some browsers from actually collapsing the flex container to
     0px during the max-height transition (it was measurably rendering
     at ~16px, just enough to expose part of the active link's ::after
     underline). visibility:hidden + opacity:0 remove it from paint
     entirely regardless of that box-height quirk. */
  .main-nav{
    position:absolute;
    top:100%;
    left:4%;
    right:4%;
    width:92%;
    box-sizing:border-box;
    flex-direction:column;
    gap:2px;
    background:rgba(10,12,24,.96);
    border-radius:0 0 16px 16px;
    box-shadow:0 20px 44px -12px rgba(0,0,0,.5);
    padding:4px 8px 12px;
    max-height:0;
    overflow:hidden;
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transition:max-height .28s ease,opacity .2s ease,visibility 0s linear .28s;
    z-index:80;
  }
  .main-nav.open{
    max-height:420px;
    opacity:1;
    visibility:visible;
    pointer-events:auto;
    transition:max-height .28s ease,opacity .2s ease;
  }
  .main-nav a{
    display:flex;
    align-items:center;
    min-height:48px;
    padding:0 16px;
    border-radius:10px;
    text-align:left;
    transition:background-color .15s ease,color .15s ease;
  }
  .main-nav a:hover,.main-nav a:focus-visible{background:rgba(255,255,255,.08);}
  .main-nav a.active{background:rgba(91,79,233,.22);}
}

/* Mobile navbar branding pass: phones were rendering the logo at the
   same 34px height as desktop, where "ELSEOUDY ACADEMY" is basically
   unreadable, while Login/Register kept full desktop padding/gap. Phones
   get a ~35% larger logo (aspect ratio untouched — height-only, width:
   auto) and tighter button spacing to make room for it, all inside the
   existing ≤1024px hamburger range so desktop is completely untouched.
   The row's height (76px, set above) and align-items:center are already
   inherited unchanged, so vertical centering and navbar height hold
   automatically — nothing here needs to re-declare them.

   The container's justify-content:space-between alone pushed .brand and
   .header-actions to opposite ends, but at narrow widths there's no
   guaranteed minimum space between them — the logo ended up flush
   against Login once both blocks' natural widths summed to the full
   container width. flex `gap` acts as a floor space-between will only
   add to, never shrink below, so it guarantees breathing room between
   logo and buttons at every width without touching space-between's
   left/right alignment. */
@media (max-width:768px){
  .site-header .container{gap:16px;}

  /* Guest (Login/Register showing): logo down ~13% from the previous
     46px, freeing width for more generous gaps around it. Logged-in
     (avatar showing instead) gets the opposite: ~13% larger, since a
     fixed-size avatar circle + hamburger leave more room than two text
     buttons do — the :has() check on the row reads which state rendered
     without needing a body/page class. */
  .brand-logo{height:40px;}
  .site-header .container:has(.user-menu) .brand-logo{height:52px;}

  .header-actions{gap:12px;}
  .site-header .container:has(.user-menu) .header-actions{gap:14px;}

  /* Second pass: the previous 44px-tall/18px-padding buttons read as
     oversized next to the rest of the row. Fixed height (not just
     min-height) plus purely horizontal padding gives a smaller, more
     precise ~40px pill — vertical centering comes from the flex
     align-items:center already on .btn (base rule), not from padding,
     so the exact height holds regardless of font metrics. Same .btn-sm
     class keeps border-radius and Login/Register color styling
     (background, border) completely untouched — only the box shrinks. */
  .header-actions .btn-sm{
    height:40px;
    padding:0 12px;
    font-size:14.5px;
    font-weight:600;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
}

/* Below ~480px the full "ELSEOUDY ACADEMY" wordmark is simply too wide
   to sit on the same row as Login+Register+hamburger (or even avatar+
   hamburger at the larger logged-in size) without either overlapping
   them or forcing horizontal scroll — both explicitly ruled out. Rather
   than let flexbox silently squash the logo out of its own aspect ratio
   to make it fit (which is what was happening before this pass — the
   image was being flex-shrunk narrower than its intrinsic ratio, i.e.
   quietly distorted), swap to the standalone "EA" mark here, sized up
   proportionally for the same "prominent branding" intent, and let the
   full wordmark own the space above this breakpoint where it actually
   fits undistorted. The icon mark is far narrower than the wordmark, so
   there's no need to shrink the now-larger Login/Register buttons back
   down at these widths — they keep the same bigger size set above. */
@media (max-width:480px){
  .brand-logo-full{display:none;}
  .brand-logo-icon{display:block;height:34px;}
  .site-header .container:has(.user-menu) .brand-logo-icon{height:42px;}
}

/* Pre-existing overflow at the smallest phone widths: the container's
   normal 32px side padding alone ate too much of the ~320px viewport.
   The icon-mark swap above (≤480px) already frees up most of the room
   Login/Register/hamburger need, so this tier only has to trim the
   outer edges now, not the navbar content itself. */
@media (max-width:340px){
  .container{padding:0 16px;}
}

/* ---------------------------------------------
   2. Home page
--------------------------------------------- */
.hero{background:var(--navy-950);color:#fff;padding:72px 0 90px;}
.hero .container{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center;}
.eyebrow{display:inline-flex;align-items:center;gap:8px;background:rgba(91,79,233,.15);border:1px solid rgba(91,79,233,.4);color:#b7b1f8;font-size:12.5px;font-weight:600;padding:6px 14px;border-radius:99px;margin-bottom:22px;}
.hero h1{font-size:44px;font-weight:700;letter-spacing:-.02em;}
.hero h1 .accent{color:#8b7ffb;display:block;}
.hero p.lead{color:var(--ink-400);font-size:16.5px;line-height:1.7;margin:20px 0 30px;max-width:480px;}
.hero-cta{display:flex;gap:14px;margin-bottom:52px;}
.hero-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;}
.hero-stats .stat{display:flex;gap:12px;}
.hero-stats .stat .ic{width:38px;height:38px;border-radius:10px;background:var(--navy-700);display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.hero-stats .stat h4{font-size:14px;font-weight:600;}
.hero-stats .stat p{font-size:12.5px;color:var(--ink-400);margin-top:2px;}
.hero-art .decor-eq{position:absolute;left:7%;bottom:12%;color:#8b7ffb;font-family:var(--font-display);font-size:clamp(20px,2.6vw,32px);font-weight:700;letter-spacing:.02em;}

.section{padding:80px 0;}
.section-head{max-width:600px;margin:0 auto 44px;text-align:center;}
.section-head h2{font-size:30px;}
.section-head p{color:var(--ink-600);margin-top:10px;}

/* Full-height centered message (account status / access-control notices —
   see Omar_Access_Control::render_message()). .site-main is already a flex
   column, so flex:1 here fills all remaining space between the header and
   footer, and the flex centering puts the card in the middle of it. */
.omar-message-section{flex:1;display:flex;align-items:center;justify-content:center;}

/* Course grid + cards (also used on Courses page).

   grid-template-columns uses auto-fit + a fixed min/max instead of a
   rigid repeat(3,1fr): with a plain 3-column split, 1 or 2 courses would
   still stretch to fill their column's full 1/3 share, sitting flush
   left with a large empty gap where the missing cards would've been.
   auto-fit only ever creates as many tracks as there are cards to fill
   (up to the max width), and justify-content:center centers that whole
   row — 1 course centers alone, 2 sit centered as a pair, 3+ wrap into
   additional centered rows, all without any per-count CSS class. */
.course-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,340px));justify-content:center;gap:24px;}
/* .course-card is a plain div, not a link, since a card can now contain
   two separate destinations: the card-link area (thumb/title/description/
   meta/progress, → course details) and the Continue/Start/Review button
   (→ straight into the course), which can't both live inside one <a> —
   nested anchors are invalid HTML and break click handling. */
.course-card{background:#fff;border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card);transition:transform .15s;display:flex;flex-direction:column;}
.course-card:hover{transform:translateY(-4px);}
.course-card-link{display:block;}
.course-thumb{aspect-ratio:16/9;position:relative;display:flex;align-items:center;justify-content:center;color:#fff;overflow:hidden;}
.course-thumb svg{opacity:.55;}
.course-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
.thumb-violet{background:linear-gradient(135deg,#3a2f8f,#5b4fe9);}
.thumb-purple{background:linear-gradient(135deg,#4a2f8f,#8b6ce9);}
.thumb-teal{background:linear-gradient(135deg,#0d8f80,#14b8a6);}
.course-body{padding:20px 22px 24px;}
.course-card-cta{padding:0 22px 22px;margin-top:auto;}
/* Fixed-height title/description (line-clamp), so a short one-line title
   and a long two-line title both leave the description — and everything
   below it — starting at the same Y position on every card, instead of
   drifting based on how much each course's own text happens to wrap. */
.course-body h3{
  font-size:17px;
  margin-bottom:8px;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  min-height:2.35em;
  line-height:1.175;
}
.course-body p{
  font-size:13.5px;
  color:var(--ink-600);
  line-height:1.6;
  margin-bottom:16px;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  min-height:3.2em;
}
.course-meta{display:flex;align-items:center;justify-content:space-between;font-size:12.5px;color:var(--ink-400);margin-bottom:10px;}
.course-meta .status{font-weight:600;}
.status-progress{color:var(--violet);}
.status-new{color:var(--ink-400);}

/* Feature strip */
.feature-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
.feature-strip .feature{display:flex;gap:14px;}
.feature .ic{width:44px;height:44px;border-radius:12px;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:#fff;}
.feature h4{font-size:15.5px;margin-bottom:5px;}
.feature p{font-size:13px;color:var(--ink-600);line-height:1.6;}

.course-grid.single{grid-template-columns:minmax(0,420px);justify-content:center;}

/* About section */
.about-section{background:var(--navy-950);color:#fff;padding:80px 0;}
.about-grid{display:grid;grid-template-columns:.7fr 1.3fr;gap:52px;align-items:start;}
.about-photo{border-radius:20px;overflow:hidden;background:linear-gradient(160deg,#1a2340,#0d1224);aspect-ratio:3/3.3;max-width:340px;display:flex;align-items:flex-end;justify-content:center;}
.about-photo img{width:100%;height:100%;object-fit:cover;object-position:top center;}
.about-copy .eyebrow{margin-bottom:18px;}
.about-copy h2{font-size:28px;margin-bottom:16px;}
.about-copy p{color:var(--ink-400);font-size:14.5px;line-height:1.8;margin-bottom:16px;}

.achievements{margin-top:56px;}
.achievements > .ach-head{margin-bottom:22px;}
.achievements > .ach-head h3{font-size:20px;margin-bottom:6px;}
.achievements > .ach-head p{color:var(--ink-400);font-size:13.5px;}
.ach-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;}
.ach-card{background:var(--navy-800);border:1px solid var(--line-dark);border-radius:16px;padding:22px;}
.ach-card .trophy{font-size:26px;margin-bottom:10px;}
.ach-card h4{font-size:16px;margin-bottom:4px;}
.ach-card .rank{color:var(--amber);font-weight:700;font-size:13px;margin-bottom:6px;}
.ach-card .exam{color:var(--ink-400);font-size:12.5px;}

@media (max-width:900px){
  .about-grid{grid-template-columns:1fr;}
  .ach-grid{grid-template-columns:1fr;}
}

.site-footer{background:var(--navy-950);color:var(--ink-400);padding:48px 0;font-size:13.5px;text-align:center;border-top:1px solid var(--line-dark);}

/* ---------------------------------------------
   3. Courses index page (light)
--------------------------------------------- */
.page-head-bar{background:#fff;border-bottom:1px solid #eceef4;padding:34px 0;}
.page-head-bar .container{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:16px;}
.page-head-bar h1{font-size:26px;}
.page-head-bar p{color:var(--ink-600);font-size:14px;margin-top:6px;}

/* ---------------------------------------------
   4. Course detail page (breadcrumb + tabs + lesson list)
--------------------------------------------- */
.crumb-bar{background:#fff;border-bottom:1px solid #eceef4;padding:18px 0;font-size:13.5px;color:var(--ink-600);}
.crumb-bar a{color:var(--ink-600);}
.crumb-bar .sep{margin:0 6px;color:var(--ink-400);}
.crumb-bar .current{color:var(--ink-900);font-weight:600;}

.course-completed-banner{display:flex;align-items:center;gap:14px;background:#eafaf0;border:1px solid #b7ebc9;color:#146c3a;border-radius:var(--radius-lg);padding:16px 20px;font-size:14.5px;}
.course-completed-banner__icon{font-size:24px;line-height:1;}
.course-hero-card{display:flex;gap:22px;align-items:center;padding:26px;}
.course-hero-card .thumb{width:150px;height:110px;border-radius:12px;flex-shrink:0;}
.course-hero-card .info{flex:1;}
.course-hero-card h1{font-size:23px;margin-bottom:6px;}
.course-hero-card p{color:var(--ink-600);font-size:13.5px;margin-bottom:14px;}
.progress-row{display:flex;align-items:center;gap:14px;}
.progress-row .progress{flex:1;max-width:260px;}
.progress-row .pct{font-size:12.5px;font-weight:700;color:var(--ink-600);}

/* Harmonize Tutor's own native add-to-cart button (kept unmodified for its
   AJAX cart JS) with this theme's button look, without touching its markup. */
.omar-tutor-add-to-cart .tutor-btn{background:var(--violet);border-color:var(--violet);border-radius:10px;font-family:var(--font-body);}
.omar-tutor-add-to-cart .tutor-btn:hover{background:var(--violet-600);border-color:var(--violet-600);}

.tabs{display:flex;gap:6px;margin:26px 0 18px;border-bottom:1px solid #eceef4;}
.tabs button{background:none;border:0;padding:12px 18px;font-size:14px;font-weight:600;color:var(--ink-600);border-bottom:2px solid transparent;}
.tabs button.active{color:var(--violet);border-color:var(--violet);}

/* Replaces the tabs strip on the Course Details page — with only one
   real section (Lessons) left, a static heading reads better than a
   single-item tab control. */
.course-content-heading{font-size:20px;margin:26px 0 14px;}

/* Course Content topic accordion — each topic is its own card (the old
   .lesson-list outer card + flat .chapter-label dividers are gone now
   that every topic carries its own background/shadow/radius below). */
.lesson-list{background:transparent;}
.topic-accordion{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);overflow:hidden;margin-bottom:14px;}
.topic-header{
  width:100%;
  display:flex;
  align-items:center;
  gap:14px;
  background:var(--paper-soft);
  border:0;
  padding:18px 22px;
  min-height:64px;
  text-align:left;
  cursor:pointer;
  font-family:inherit;
  color:inherit;
}
.topic-arrow{
  flex-shrink:0;
  width:20px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  color:var(--ink-600);
  transform:rotate(-90deg);
  transition:transform .28s ease;
}
.topic-accordion.is-open .topic-arrow{transform:rotate(0deg);}
.topic-heading{display:flex;flex-direction:column;gap:2px;min-width:0;}
.topic-name{font-size:15px;font-weight:700;color:var(--ink-900);}
.topic-meta{font-size:12.5px;color:var(--ink-600);}
.topic-panel{overflow:hidden;transition:max-height .28s ease;}
.lesson-row{display:flex;align-items:center;gap:14px;padding:15px 22px;border-top:1px solid #f0f1f6;font-size:14px;}
.lesson-row .fileic{width:32px;height:32px;border-radius:8px;background:var(--violet-100);color:var(--violet);display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.lesson-row .lname{flex:1;font-weight:500;}
.lesson-row .ltype{color:var(--ink-400);font-size:12.5px;width:70px;}
.lesson-row .ltime{color:var(--ink-400);font-size:12.5px;width:60px;text-align:right;}
.lesson-row .ltime.ltime-date{width:auto;white-space:nowrap;}
.lesson-row .lstate{width:24px;text-align:center;}
.lesson-row.locked{color:var(--ink-400);}
.lesson-row.locked .lname{color:var(--ink-400);}

/* ---------------------------------------------
   Course Details page — tablet & mobile (<=1024px)

   Scoped with .course-details-page (added to the <section> in
   tutor/single-course.php) rather than the bare component classes,
   since .course-hero-card/.lesson-row/.tabs are also referenced by the
   unreachable, deprecated page-course.php mockup — this must only
   touch the real, live course page. Desktop is untouched above.
--------------------------------------------- */
@media (max-width:1024px){
  .course-details-page .container{padding:0 18px;}

  .course-details-page .course-hero-card{flex-direction:column;text-align:center;padding:22px 18px;gap:14px;}
  .course-details-page .course-hero-card .thumb{width:120px;height:120px;aspect-ratio:1/1;}
  .course-details-page .course-hero-card .info{width:100%;}
  .course-details-page .course-hero-card h1{font-size:19px;line-height:1.3;}
  .course-details-page .course-hero-card p{font-size:13.5px;line-height:1.6;max-width:460px;margin:0 auto 14px;}
  .course-details-page .course-hero-card .btn{width:100%;text-align:center;}

  .course-details-page .progress-row{flex-wrap:wrap;justify-content:space-between;gap:6px 0;}
  .course-details-page .progress-row .pct:first-child{order:1;}
  .course-details-page .progress-row .pct:last-child{order:2;}
  .course-details-page .progress-row .progress{order:3;flex-basis:100%;width:100%;max-width:none;}

  .course-details-page .course-content-heading{font-size:18px;margin:22px 0 12px;padding:0 2px;}

  /* Lessons stay inside the shared topic-accordion card (see .topic-
     accordion) as simple divided rows — not separate nested cards —
     just stacked (title+lock on one line, type/time below) and given a
     comfortable touch target. */
  .course-details-page .lesson-row{
    flex-wrap:wrap;
    padding:16px 18px;
    min-height:56px;
    row-gap:4px;
  }
  .course-details-page .lesson-row .fileic{order:1;}
  .course-details-page .lesson-row .lname{order:2;flex:1 1 auto;min-width:0;width:auto;}
  .course-details-page .lesson-row .lstate{order:3;width:auto;margin-left:8px;font-size:16px;}
  /* flex-basis forces these onto their own new line every time,
     regardless of how short the title is — not just when content
     happens not to fit on one line. The basis is reduced by the same
     46px as the margin-left so the two together still total 100% of
     the row's width instead of overflowing it. */
  .course-details-page .lesson-row .ltype{order:4;flex:1 0 calc(100% - 46px);width:auto;margin-left:46px;text-align:left;}
  .course-details-page .lesson-row .ltime{order:5;flex:0 0 auto;width:auto;margin-left:8px;text-align:left;white-space:normal;}
  .course-details-page .lesson-row .ltime.ltime-date{margin-left:46px;flex:1 0 calc(100% - 46px);}
}

@media (max-width:375px){
  .course-details-page .container{padding:0 16px;}
  .course-details-page .course-hero-card .thumb{width:100px;height:100px;}
}

/* Past Papers accordion (grouped by exam session) */
.papers-accordion{display:flex;flex-direction:column;gap:16px;}
.paper-session{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);overflow:hidden;transition:box-shadow .2s ease;}
.paper-session:hover{box-shadow:0 20px 34px -16px rgba(11,15,30,.22);}
.paper-session-header{display:flex;align-items:center;gap:14px;width:100%;padding:18px 22px;background:#fff;border:0;cursor:pointer;text-align:left;font-family:inherit;}
.paper-session-header:hover{background:var(--paper-soft);}
.paper-session-icon{width:42px;height:42px;border-radius:12px;background:linear-gradient(135deg,#3a2f8f,#5b4fe9);color:#fff;display:flex;align-items:center;justify-content:center;font-size:19px;flex-shrink:0;}
.paper-session-title{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0;}
.paper-session-name{font-size:15px;font-weight:700;color:var(--ink-900);font-family:var(--font-display);}
.paper-session-count{font-size:12px;color:var(--ink-400);}
.chevron-btn{width:52px;height:40px;border-radius:10px;background:var(--paper-soft);border:1px solid #e5e7f0;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:background-color .2s ease,border-color .2s ease,transform .2s ease;}
.paper-session-header:hover .chevron-btn{background:var(--violet-100);border-color:var(--violet);}
.paper-session-header .chevron{display:block;color:var(--ink-600);font-size:18px;line-height:1;transition:transform .25s ease;}
.paper-session.expanded .chevron-btn{background:var(--violet);border-color:var(--violet);}
.paper-session.expanded .paper-session-header .chevron{transform:rotate(180deg);color:#fff;}
.paper-session-body{
  max-height:0;
  opacity:0;
  overflow:hidden;
  transition:max-height .4s cubic-bezier(.4,0,.2,1), opacity .25s ease;
}
.paper-session.expanded .paper-session-body{
  max-height:600px;
  opacity:1;
  transition:max-height .4s cubic-bezier(.4,0,.2,1), opacity .35s ease .1s;
}
.paper-row{
  display:flex;align-items:center;gap:14px;padding:14px 22px;border-top:1px solid #f0f1f6;font-size:14px;
  transform:translateY(-6px);
  opacity:0;
  transition:transform .3s ease, opacity .3s ease;
}
.paper-session.expanded .paper-row{
  transform:translateY(0);
  opacity:1;
}
.paper-session.expanded .paper-row:nth-child(1){transition-delay:.08s;}
.paper-session.expanded .paper-row:nth-child(2){transition-delay:.13s;}
.paper-session.expanded .paper-row:nth-child(3){transition-delay:.18s;}
.paper-session.expanded .paper-row:nth-child(4){transition-delay:.23s;}
.paper-row .fileic{width:32px;height:32px;border-radius:8px;background:var(--paper-soft);color:var(--violet);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:14px;}
.paper-row .lname{flex:1;font-weight:500;color:var(--ink-900);}
.paper-row .paper-links{display:flex;gap:8px;flex-shrink:0;}
.paper-row .paper-links a{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;padding:7px 14px;border-radius:20px;text-decoration:none;transition:background-color .2s ease,color .2s ease,transform .15s ease;}
.paper-row .paper-links a.paper-link-pdf{background:var(--violet-100);color:var(--violet-600);}
.paper-row .paper-links a.paper-link-pdf:hover{background:var(--violet);color:#fff;transform:translateY(-1px);}
.paper-row .paper-links a.paper-link-ms{background:var(--paper-soft);color:var(--ink-600);border:1px solid #dfe3ec;}
.paper-row .paper-links a.paper-link-ms:hover{background:#eef0f7;border-color:var(--violet);color:var(--violet);transform:translateY(-1px);}

/* ---------------------------------------------
   5. Lesson video page
--------------------------------------------- */
.lesson-layout{display:grid;grid-template-columns:1fr 320px;gap:24px;padding:26px 0 60px;}
.video-shell{background:var(--navy-950);border-radius:var(--radius-lg);overflow:hidden;position:relative;}

/* Plyr replaces the browser's native <video controls> (see
   js/video-protection.js) — themed here via its own documented CSS custom
   properties rather than fighting its stylesheet with !important. Its
   container (.plyr) is what actually goes fullscreen, which is exactly
   what lets our watermark (moved into that same container once Plyr
   initializes) stay visible in fullscreen: it's a real descendant of the
   fullscreen element, not a sibling left behind outside it. */
.plyr{
  --plyr-color-main: var(--violet);
  --plyr-video-background: var(--navy-950);
  --plyr-menu-background: #fff;
  --plyr-menu-color: var(--ink-900);
  --plyr-menu-arrow-color: var(--ink-400);
  --plyr-tooltip-background: var(--navy-950);
  --plyr-tooltip-color: #fff;
  --plyr-control-radius: 10px;
  --plyr-control-spacing: 16px;
  --plyr-control-icon-size: 22px;
  --plyr-range-thumb-height: 15px;
  border-radius: var(--radius-lg);
  /* Kills the default translucent tap-highlight WebKit/Blink draw on any
     touch target on tap — on mobile this is what read as a colored
     "ripple/flash" on every button press. */
  -webkit-tap-highlight-color: transparent;
}

/* Bigger, evenly-spaced, real touch-target-sized buttons (Plyr's own
   defaults are 18px icons / 10px spacing, sized for a generic embed, not a
   premium full-width lesson player). min-width/min-height give every
   button a real 44x44px hit area (WCAG's minimum) regardless of its
   icon's natural size, and vertical centering is already inherited from
   Plyr's own .plyr__controls{align-items:center}. */
.plyr__control{
  min-width:44px;
  min-height:44px;
  display:flex;
  align-items:center;
  justify-content:center;
  transition:opacity .18s ease, transform .12s ease;
  -webkit-tap-highlight-color:transparent;
}
/* Subtle press feedback only — no colored flash/ripple, no background
   highlight. This replaces Plyr's default violet focus-visible outline
   (its color is literally our own --plyr-color-main, which is exactly
   the "purple flash" reported) with a barely-there neutral ring that
   still satisfies keyboard-accessibility focus indication without
   reading as an animation. */
.plyr__control:not(.plyr__control--overlaid):active{
  opacity:.75;
  transform:scale(.98);
}
.plyr__control:focus-visible{
  outline:2px solid rgba(255,255,255,.5);
  outline-offset:1px;
}

/* Center play/pause button: minimal single-button design (no rewind/
   forward flanking it — those were removed in favor of a cleaner
   interface; still reachable via Plyr's own ArrowLeft/ArrowRight
   shortcuts). Semi-transparent black + blur reads as modern/premium
   (YouTube/Netflix-style) instead of Plyr's default solid brand-color
   circle. Icon color is already white via Plyr's own
   --plyr-video-control-color default, untouched here.
   z-index is bumped above the watermark's (5) so the button is never
   visually buried under watermark text on the rare cycle where the
   watermark's "pos-center" position coincides with it — the watermark
   still has pointer-events:none either way, so this is purely visual.
   Transition is opacity-only (no transform/background-color in the
   list) — a subtle fade between play/pause states, deliberately with
   nothing that could read as a scale, morph, or ripple. */
.plyr__control--overlaid{
  background:rgba(0,0,0,.45) !important;
  border-radius:100% !important;
  box-shadow:0 4px 16px rgba(0,0,0,.35);
  -webkit-backdrop-filter:blur(6px);
  backdrop-filter:blur(6px);
  z-index:6 !important;
  transition:opacity .2s ease !important;
}
/* Plyr nudges this button's icon 2px right via position:relative — a
   deliberate optical correction for the play triangle (its bounding box
   is symmetric, but a triangle's visual weight sits left-of-center, so
   shifting it right makes it read as centered). The pause icon's two
   bars have no such asymmetry and don't need the nudge, so sharing that
   rule left it 2px off-center. Zeroing it out here centers both icons
   exactly on the button's true center — measured directly, not assumed. */
.plyr__control--overlaid svg{
  left:0 !important;
}
/* No :active press-feedback here — no scale/ripple/flash, just the
   plain opacity fade above when toggling between play and pause. */

/* This button is now the ONLY play/pause control (video-body clicks no
   longer toggle playback — see clickToPlay:false in video-protection.js),
   so it needs to stay available during playback too. Plyr's own default
   hides it outright while playing (.plyr--playing .plyr__control--
   overlaid{opacity:0;visibility:hidden}); here its visibility instead
   follows the same hide-controls cycle as the rest of the control row —
   always shown while paused (hide-controls never engages while paused),
   shown on tap/mousemove while playing, and fading out on inactivity. */
.plyr__control--overlaid{
  opacity:1 !important;
  visibility:visible !important;
  pointer-events:auto !important;
}
.plyr--hide-controls .plyr__control--overlaid{
  opacity:0 !important;
  visibility:hidden !important;
  pointer-events:none !important;
}
@media (max-width:480px){
  .omar-skip-btn{width:44px !important;height:44px !important;}
  .omar-skip-btn svg{width:18px;height:18px;}
  .omar-skip-back{left:calc(50% - 74px);}
  .omar-skip-forward{left:calc(50% + 30px);}
}

/* Always-visible timeline (YouTube/Vimeo-style): Plyr's own stylesheet
   fades .plyr__controls as a single unit — buttons AND the progress bar
   together — via `.plyr--hide-controls .plyr__controls{opacity:0}`. That
   makes the seek bar all but invisible until the viewer moves the mouse.
   Here we undo that fade on the row itself and instead fade only its
   button/label children, keeping .plyr__progress__container (the
   timeline) permanently visible and draggable — mouse and touch both,
   since it's still the same native <input type="range">, just no longer
   hidden. */
.plyr--hide-controls .plyr__controls{
  /* !important because Plyr's own equal-specificity rule for this exact
     selector is enqueued after our stylesheet on lesson pages, so it would
     otherwise win the cascade on load order alone. A parent stuck at
     opacity:0 makes every descendant invisible no matter what opacity the
     descendant itself declares, which is why this has to be fixed here and
     not just on .plyr__progress__container below. */
  opacity:1 !important;
  pointer-events:none !important;
  transform:none !important;
  background:linear-gradient(transparent, rgba(0,0,0,.45)) !important;
}
.plyr--hide-controls .plyr__controls > *:not(.plyr__progress__container){
  opacity:0;
  transition:opacity .3s ease;
}
.plyr__progress__container{
  opacity:1 !important;
  pointer-events:auto !important;
}
.plyr__progress__container input[type="range"]::-webkit-slider-thumb{
  transition:transform .15s ease;
}
.plyr__progress__container:hover input[type="range"]::-webkit-slider-thumb,
.plyr__progress__container input[type="range"]:active::-webkit-slider-thumb{
  transform:scale(1.3);
}
.plyr__progress__container input[type="range"]::-moz-range-thumb{
  transition:transform .15s ease;
}
.plyr__progress__container:hover input[type="range"]::-moz-range-thumb,
.plyr__progress__container input[type="range"]:active::-moz-range-thumb{
  transform:scale(1.3);
}

/* Click/tap-to-reveal volume (YouTube-style), all screen sizes — not just
   mobile. The slider is still Plyr's own native <input type="range">
   (dragging/accessibility unchanged); js/video-protection.js just toggles
   `.is-open` on the mute button's click. Width/opacity animate together
   so it slides open next to the speaker icon rather than popping in. */
.plyr__volume{overflow:visible;}
/* !important throughout: Plyr's own equal-specificity rule for this exact
   selector (setting min-width:60px/max-width:90px) is enqueued after our
   stylesheet on lesson pages and would otherwise win the min/max-width
   tug-of-war on load order alone, same issue as the hide-controls fix
   above. */
.plyr__volume input[type="range"]{
  width:0 !important;
  min-width:0 !important;
  max-width:0 !important;
  opacity:0 !important;
  margin-left:0 !important;
  margin-right:0 !important;
  pointer-events:none !important;
  transition:width .2s ease, opacity .15s ease, margin .2s ease;
}
.plyr__volume.is-open input[type="range"]{
  width:80px !important;
  min-width:60px !important;
  max-width:90px !important;
  opacity:1 !important;
  margin-left:5px !important;
  margin-right:5px !important;
  pointer-events:auto !important;
}

@media (max-width:600px){
  .plyr{
    --plyr-control-spacing: 10px;
    --plyr-control-icon-size: 20px;
  }
}

/* Per-student dynamic watermark overlay (see inc/video-watermark.php and
   js/video-protection.js). Text-only, no background box, so it never
   visually competes with the lesson content underneath — the low text
   opacity is the point, not a background tint. pointer-events:none keeps
   it from ever intercepting a click meant for the player controls.
   Positioned as a percentage of the player + a self-centering transform,
   so it scales naturally with the player at any screen size without
   needing separate breakpoint math, and the transform never changes
   between positions (only top/left do) — a deliberate choice, since
   animating transform itself is what causes the sub-pixel blur-during-
   transition some browsers exhibit on small text. */
.omar-video-watermark{
  position:absolute;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);
  z-index:5;
  pointer-events:none;
  user-select:none;
  color:rgba(139,0,0,.5);
  font-family:var(--font-body);
  font-size:15px;
  font-weight:600;
  line-height:1.5;
  text-align:center;
  text-shadow:0 1px 3px rgba(0,0,0,.8);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  white-space:nowrap;
  opacity:0;
  transition:opacity .6s ease, top .8s ease, left .8s ease;
}
.omar-video-watermark.is-visible{opacity:1;}
.omar-video-watermark.pos-center{top:50%;left:50%;}
.omar-video-watermark.pos-center-left{top:50%;left:32%;}
.omar-video-watermark.pos-center-right{top:50%;left:68%;}
.omar-video-watermark.pos-upper-center{top:28%;left:50%;}
.omar-video-watermark.pos-lower-center{top:68%;left:50%;}

@media (max-width:900px){
  .omar-video-watermark{font-size:12px;}
}
@media (max-width:600px){
  .omar-video-watermark{font-size:10.5px;line-height:1.4;}
}
.video-frame{aspect-ratio:16/9;background:linear-gradient(160deg,#101833,#080b17);position:relative;display:flex;align-items:center;justify-content:center;color:#fff;}
.video-frame .board-eq{text-align:center;color:#8b7ffb;font-family:var(--font-display);}
.video-frame .board-eq h3{font-size:22px;letter-spacing:.04em;margin-bottom:14px;}
.video-frame .board-eq .frac{font-size:34px;color:#fff;}
.video-frame .board-eq .lock-icon{font-size:38px;margin-bottom:12px;}
.video-frame .board-eq .release-date-text{color:#fff;font-size:14px;font-family:var(--font-body);margin-top:8px;}
.video-controls{display:flex;align-items:center;gap:14px;padding:14px 20px;color:#fff;font-size:13px;}
.video-controls .bar{flex:1;height:4px;background:rgba(255,255,255,.2);border-radius:99px;position:relative;}
.video-controls .bar span{position:absolute;left:0;top:0;bottom:0;width:52%;background:var(--violet);border-radius:99px;}
.video-controls button{background:none;border:0;color:#fff;font-size:16px;}
/* Single centered "Mark as Complete" pill (Previous/Next Lesson removed).
   Sized to its own content — no forced width/flex-basis math needed now
   that there's only one item, which is also what keeps this correct at
   every breakpoint without any media queries: a content-sized, centered
   button can't overflow a viewport the way a multi-item flex row could. */
.lesson-actions{
  display:flex;
  justify-content:center;
  margin-top:16px;
  width:100%;
}
.lesson-actions form{
  display:flex;
  margin:0;
  max-width:100%;
}
.lesson-actions .btn{
  min-width:200px;
  max-width:100%;
  padding:12px 36px;
  white-space:normal;
  text-align:center;
  min-height:44px;
}

.lesson-side{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:20px;height:fit-content;}
.lesson-side h4{font-size:14px;margin-bottom:12px;}
.lesson-side .chapter-label{padding:10px 0 6px;font-size:12px;font-weight:700;color:var(--ink-600);text-transform:uppercase;letter-spacing:.02em;}
.side-lesson{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 12px;border-radius:8px;font-size:13.5px;color:var(--ink-600);margin-bottom:4px;}
.side-lesson.active{background:var(--violet-100);color:var(--violet-600);font-weight:600;}
.side-lesson-text{display:flex;flex-direction:column;gap:2px;min-width:0;}
.side-lesson-meta{font-size:11px;color:var(--ink-400);font-weight:400;}
.side-lesson.locked{color:var(--ink-400);cursor:not-allowed;}
.side-lesson .side-state{flex-shrink:0;font-size:12px;}
.downloads-block{margin-top:20px;padding-top:18px;border-top:1px solid #f0f1f6;}
.download-item{display:flex;align-items:center;gap:10px;font-size:13.5px;padding:8px 0;color:var(--ink-900);}
a.download-item:hover{color:var(--violet);}

/* Materials panel (lesson page sidebar) — two cards: Notes and
   Classified Questions, each with instructions + a file list. */
.materials-card{background:#fff;border:1px solid #eceef4;border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:16px;margin-bottom:14px;}
.materials-card:last-of-type{margin-bottom:0;}
.materials-card h5{font-size:14px;margin-bottom:10px;}
.materials-instructions{font-size:13px;color:var(--ink-600);line-height:1.6;margin-bottom:12px;white-space:pre-line;}
.materials-file-list{list-style:none;margin:0 0 10px;padding:0;}
.materials-file-list li{display:flex;align-items:center;gap:8px;padding:8px 0;border-top:1px solid #f5f6fa;font-size:13px;}
.materials-file-list li:first-child{border-top:0;}
.materials-file-list a{color:var(--ink-900);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.materials-file-list a:hover{color:var(--violet);}
.materials-empty{color:var(--ink-400);font-style:italic;}
.materials-remove{display:flex;align-items:center;}

.materials-admin-form textarea{width:100%;border:1px solid #dfe3ec;border-radius:8px;padding:10px 12px;font-size:13px;font-family:inherit;margin-bottom:10px;resize:vertical;}
.materials-admin-form textarea:focus{outline:none;border-color:var(--violet);box-shadow:0 0 0 3px var(--violet-100);}
.materials-upload-btn{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;color:var(--violet);cursor:pointer;padding:6px 0;}
.materials-upload-btn:hover{color:var(--violet-600);}
.materials-upload-filenames{display:block;font-size:11.5px;color:var(--ink-400);margin-top:2px;}
.materials-admin-form .btn-block{margin-top:4px;}

.materials-locked-card{background:#fff;border:1px solid #eceef4;border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:24px 20px;text-align:center;}
.materials-locked-card .lock-ic{font-size:28px;margin-bottom:10px;}
.materials-locked-card p{font-size:13.5px;color:var(--ink-600);margin-bottom:10px;line-height:1.6;}
.materials-locked-card .upgrade-copy{font-weight:600;color:var(--ink-900);margin-bottom:6px;}
.materials-locked-card ul{list-style:none;margin:0 0 16px;padding:0;text-align:left;font-size:13px;color:var(--ink-600);}
.materials-locked-card ul li{padding:4px 0;}
.materials-locked-card ul li::before{content:"• ";color:var(--violet);}

/* ---------------------------------------------
   6. Assignment page
--------------------------------------------- */
.assignment-layout{display:grid;grid-template-columns:1fr 300px;gap:24px;padding:30px 0 60px;}
.assignment-main{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:30px;}
.due-badge{display:inline-flex;align-items:center;gap:8px;color:#c53030;background:#fdeceb;font-size:12.5px;font-weight:600;padding:6px 12px;border-radius:8px;margin:10px 0 20px;}
.q-block{margin-bottom:26px;padding-bottom:24px;border-bottom:1px solid #f0f1f6;}
.q-block h5{font-size:14.5px;margin-bottom:10px;}
.q-block .eq{font-family:var(--font-display);color:var(--ink-900);margin-bottom:12px;}
.answer-box{width:100%;border:1px solid #dfe3ec;border-radius:10px;padding:14px;font-size:14px;min-height:64px;resize:vertical;}
.upload-box{border:1.5px dashed #dfe3ec;border-radius:10px;padding:16px;font-size:13px;color:var(--ink-600);display:flex;align-items:center;justify-content:space-between;}

.assignment-side .card-block{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:20px;margin-bottom:20px;}
.assignment-side h4{font-size:14px;margin-bottom:14px;}
.attempt-row{display:flex;justify-content:space-between;font-size:13px;color:var(--ink-600);padding:8px 0;border-top:1px solid #f5f6fa;}

/* ---------------------------------------------
   7. Auth pages (login / register)

   Desktop: the page occupies exactly one viewport. The sticky header
   keeps its natural height and .auth-shell fills whatever's left, so nothing
   above .auth-form-wrap ever needs the whole document to scroll. Only
   .auth-form-wrap scrolls internally — the branding panel and the header
   never move. `:has()` scopes this to pages that actually render an
   auth shell; browsers without :has() support just fall back to the
   original whole-page-scrolls behavior (still fully usable, just not
   sticky), so nothing breaks in older browsers.
--------------------------------------------- */
body:has(.auth-shell){height:100vh;overflow:hidden;display:flex;flex-direction:column;}
body:has(.auth-shell) .site-header{flex:0 0 auto;}
body:has(.auth-shell) .site-main{min-height:0;overflow:hidden;}

.auth-shell{flex:1;min-height:0;display:flex;overflow:hidden;}
.auth-visual{flex:1;background:var(--navy-950);color:#fff;display:flex;flex-direction:column;justify-content:center;padding:60px;position:sticky;top:0;height:100%;overflow:hidden;}
.auth-visual .brand{margin-bottom:34px;}
.auth-visual h2{font-size:30px;margin-bottom:12px;}
.auth-visual p{color:var(--ink-400);font-size:14.5px;line-height:1.7;max-width:340px;}
.auth-visual .deco{margin-top:50px;opacity:.9;}
.auth-form-wrap{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;justify-content:safe center;padding:40px;background:#fff;overflow-y:auto;overflow-x:hidden;}
.auth-form{width:100%;max-width:360px;}
.auth-form.auth-form-wide{max-width:460px;}
.auth-form h1{font-size:26px;margin-bottom:8px;}
.auth-form > p.sub{color:var(--ink-600);font-size:14px;margin-bottom:30px;}
.field{margin-bottom:18px;}
.field label{display:block;font-size:13px;font-weight:600;margin-bottom:7px;}
.field input,.field select,.field textarea{width:100%;border:1px solid #dfe3ec;border-radius:10px;padding:12px 14px;font-size:14px;font-family:inherit;background:#fff;transition:border-color .2s ease,box-shadow .2s ease;}
.field textarea{resize:vertical;min-height:120px;}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--violet);box-shadow:0 0 0 3px var(--violet-100);}

.field-row{display:flex;justify-content:space-between;align-items:center;}
.field-row a{font-size:12.5px;color:var(--violet);font-weight:600;}
.field-2col{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.field-hint{font-weight:400;color:var(--ink-400);font-size:12px;}
.auth-form .btn{margin-top:6px;}
.auth-switch{text-align:center;margin-top:22px;font-size:13.5px;color:var(--ink-600);}
.auth-switch a{color:var(--violet);font-weight:700;transition:color .15s ease;}
.auth-switch a:hover{color:var(--violet-600);}
.device-note{display:flex;gap:10px;background:var(--violet-100);border-radius:10px;padding:12px 14px;font-size:12px;color:var(--violet-600);margin-top:20px;line-height:1.5;}
.form-section-label{font-size:11.5px;font-weight:700;color:var(--ink-400);text-transform:uppercase;letter-spacing:.05em;margin-bottom:14px;}
.form-section-label.with-divider{margin-top:28px;padding-top:22px;border-top:1px solid #eceef4;}

/* Phone field: country selector + local number merged into a single field */
.phone-field-row{display:flex;align-items:stretch;border:1px solid #dfe3ec;border-radius:10px;background:#fff;transition:border-color .2s ease,box-shadow .2s ease;}
.phone-field-row:focus-within{border-color:var(--violet);box-shadow:0 0 0 3px var(--violet-100);}
.phone-field-row .omar-country-select{flex:0 0 118px;}
.phone-field-row input[type="tel"]{flex:1;border:0;background:transparent;border-radius:0 10px 10px 0;padding:12px 14px;font-size:14px;min-width:0;}
.phone-field-row input[type="tel"]:focus{outline:none;}
.phone-field-row .omar-dd-btn{border-right:1px solid #dfe3ec;border-radius:10px 0 0 10px;padding:12px 10px;}

/* Grade field: the exact same custom dropdown as the country selector
   (see js/searchable-dropdown.js), just styled as a standalone field
   instead of one half of a merged row. */
.omar-grade-select .omar-dd-btn{border:1px solid #dfe3ec;border-radius:10px;padding:12px 14px;}

/* Generic searchable dropdown component (progressive enhancement over a
   real <select>), shared by the Country and Grade selectors. The panel is
   rendered into document.body by JS (a "portal") rather than nested
   inside the form, so it can never be clipped or trapped by an ancestor's
   overflow/transform/stacking context. Its top, left and width are set
   inline by JS via getBoundingClientRect() — the CSS below only styles
   its fixed look, not its position. */
.omar-country-select,.omar-grade-select,.omar-country-select-plain{position:relative;}
.omar-dd-native-hidden{position:absolute;opacity:0;pointer-events:none;height:1px;width:1px;overflow:hidden;}
/* The 1px width above doesn't actually take effect on a <select> in every
   engine tested (it keeps sizing to its wrapper's width instead) — mostly
   invisible in practice since opacity:0 + pointer-events:none already hide
   and disable it, but .omar-country-select-plain's wrapper spans 100% of
   the field (unlike the phone selects' narrower "Code" button width), so
   its full-width hidden select was wide enough to cause real horizontal
   page overflow on narrow screens. !important forces the collapse. */
.omar-country-select-plain select.omar-dd-native-hidden{width:1px !important;min-width:0 !important;}
.omar-dd-widget{position:relative;height:100%;}
.omar-dd-btn{width:100%;height:100%;text-align:left;border:0;background:transparent;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink-900);font-size:13.5px;font-family:inherit;transition:border-color .2s ease,background-color .2s ease,box-shadow .2s ease;}
.omar-dd-btn:hover{background:var(--paper-soft);}
.omar-dd-btn:focus{outline:none;background:var(--paper-soft);}
.omar-dd-panel{position:absolute;z-index:99999;background:#fff;border:1px solid #e5e7f0;border-radius:12px;box-shadow:var(--shadow-card);overflow:hidden;animation:omarPanelIn .16s cubic-bezier(.2,0,.2,1) both;}
@keyframes omarPanelIn{from{opacity:0;transform:scale(.97) translateY(-4px);}to{opacity:1;transform:none;}}
.omar-dd-search{width:100%;border:0;border-bottom:1px solid #f0f1f6;padding:12px 14px;font-size:13.5px;font-family:inherit;}
.omar-dd-search:focus{outline:none;background:var(--paper-soft);}
.omar-dd-list{list-style:none;margin:0;padding:6px;max-height:300px;overflow-y:auto;}
.omar-dd-item{padding:9px 10px;font-size:13.5px;border-radius:8px;cursor:pointer;white-space:normal;}
.omar-dd-item:hover,.omar-dd-item.is-active{background:var(--violet-100);color:var(--violet-600);}

/* OTP entry input */
.otp-input{letter-spacing:10px;font-size:22px;font-weight:700;text-align:center;font-family:var(--font-display);}

/* Entrance animation for the auth card + a light stagger across its direct
   children. Pure CSS (no IntersectionObserver, no JS dependency) so the
   form is never left invisible if JS fails to run — it just always plays
   automatically as the page renders. */
@keyframes omarFadeUp{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
.auth-visual{animation:omarFadeUp .5s cubic-bezier(.4,0,.2,1) both;}
.auth-form > *{animation:omarFadeUp .45s cubic-bezier(.4,0,.2,1) both;}
.auth-form form > *{animation:omarFadeUp .45s cubic-bezier(.4,0,.2,1) both;}
.auth-form form > *:nth-child(1){animation-delay:.03s;}
.auth-form form > *:nth-child(2){animation-delay:.06s;}
.auth-form form > *:nth-child(3){animation-delay:.09s;}
.auth-form form > *:nth-child(4){animation-delay:.12s;}
.auth-form form > *:nth-child(5){animation-delay:.15s;}
.auth-form form > *:nth-child(6){animation-delay:.18s;}
.auth-form form > *:nth-child(7){animation-delay:.21s;}
.auth-form form > *:nth-child(8){animation-delay:.24s;}
.auth-form form > *:nth-child(9){animation-delay:.27s;}
.auth-form form > *:nth-child(10){animation-delay:.3s;}
.auth-form form > *:nth-child(11){animation-delay:.33s;}
.auth-form form > *:nth-child(12){animation-delay:.36s;}
.auth-form form > *:nth-child(13){animation-delay:.39s;}
.auth-form form > *:nth-child(14){animation-delay:.42s;}
.auth-form > form{animation:none;} /* the form element itself shouldn't also fade — only its children stagger */
.auth-form .device-note,.auth-form .auth-switch{animation:omarFadeUp .45s cubic-bezier(.4,0,.2,1) .3s both;}

/* Notice / error / success messages */
.auth-notice{animation:omarFadeUp .3s ease both;}
.auth-notice-error{animation:omarFadeUp .3s ease both, omarShake .4s ease .3s both;}
@keyframes omarShake{0%,100%{transform:translateX(0);}20%{transform:translateX(-4px);}40%{transform:translateX(4px);}60%{transform:translateX(-3px);}80%{transform:translateX(3px);}}

/* Submit button loading state (added by main.js on submit, degrades to a
   normal submit with no spinner if JS doesn't run) */
.btn.is-loading{position:relative;color:transparent !important;pointer-events:none;}
.btn.is-loading::after{content:"";position:absolute;top:50%;left:50%;width:18px;height:18px;margin:-9px 0 0 -9px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:omarSpin .7s linear infinite;}
.btn-outline.is-loading::after{border-color:rgba(91,79,233,.25);border-top-color:var(--violet);}
@keyframes omarSpin{to{transform:rotate(360deg);}}

@media (max-width:1024px){
  /* Fixed/sticky-panel layout only makes sense side-by-side. Below this
     width, drop it entirely: stack both sections and let the whole page
     scroll normally, same as any other page. */
  body:has(.auth-shell){height:auto;overflow:visible;display:block;}
  body:has(.auth-shell) .site-main{display:block;overflow:visible;}
  .auth-shell{display:block;height:auto;overflow:visible;}
  .auth-visual{position:static;height:auto;width:100%;}
  .auth-form-wrap{height:auto;overflow:visible;}

  /* Stacked hero: the small logo+academy-name row is redundant right below
     the navbar, and a full desktop-sized dark panel is just empty space
     above the fold. Drop the brand row, shrink the padding down to a
     ~160-180px band, and bring the form up close behind it — same
     colors/copy/typography, just far less vertical real estate. */
  .auth-visual{padding:48px 24px;}
  .auth-visual .brand{display:none;}
  .auth-visual .deco{display:none;}
  .auth-form-wrap{padding:24px 24px 40px;}
}

@media (max-width:520px){
  .field-2col{grid-template-columns:1fr;}
  .phone-field-row .omar-country-select{flex:0 0 100px;}
  .omar-country-list{max-height:45vh;}
}

/* ---------------------------------------------
   8. Dashboard shell (student + admin share this)
--------------------------------------------- */
.dash-shell{display:grid;grid-template-columns:250px 1fr;min-height:100vh;background:var(--paper-soft);}
.dash-sidebar{background:var(--navy-950);color:var(--ink-200);padding:26px 18px;}
.dash-sidebar .brand{margin-bottom:34px;padding-left:6px;}
.dash-nav a{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:10px;font-size:14px;margin-bottom:3px;color:var(--ink-400);font-weight:500;}
.dash-nav a:hover{color:#fff;}
.dash-nav a.active{background:var(--violet);color:#fff;}
.dash-nav .ic{width:18px;text-align:center;flex-shrink:0;}
.dash-nav .logout{margin-top:20px;border-top:1px solid var(--line-dark);padding-top:16px;}

.dash-main{padding:26px 30px 50px;}
.dash-topbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:26px;}
.dash-topbar h1{font-size:22px;}
.dash-topbar .role{font-size:13px;color:var(--ink-600);}

.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-bottom:26px;}
.stat-card{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:20px;}
.stat-card .top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:14px;}
.stat-card .ic{width:36px;height:36px;border-radius:10px;display:flex;align-items:center;justify-content:center;}
.stat-card .label{font-size:12.5px;color:var(--ink-600);}
.stat-card .value{font-size:24px;font-weight:700;font-family:var(--font-display);margin-top:2px;}
.stat-card .delta{font-size:11.5px;font-weight:700;color:var(--green);}

.dash-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
.panel{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:22px;}
.panel h3{font-size:15px;margin-bottom:16px;}

.continue-card{display:flex;align-items:center;gap:14px;padding:12px;border-radius:12px;background:var(--paper-soft);margin-bottom:10px;}
.continue-card .thumb{width:48px;height:48px;border-radius:10px;flex-shrink:0;}
.continue-card .info{flex:1;}
.continue-card .info h5{font-size:13.5px;}
.continue-card .info p{font-size:11.5px;color:var(--ink-600);margin:2px 0 6px;}

.activity-row{display:flex;align-items:flex-start;gap:12px;padding:10px 0;border-top:1px solid #f5f6fa;font-size:13px;}
.activity-row .ic{width:30px;height:30px;border-radius:8px;background:var(--violet-100);color:var(--violet);display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.activity-row .time{margin-left:auto;color:var(--ink-400);font-size:11.5px;white-space:nowrap;}

.table-simple{width:100%;border-collapse:collapse;font-size:13.5px;}
.table-simple th{text-align:left;color:var(--ink-600);font-weight:600;padding:10px 8px;border-bottom:1px solid #eceef4;font-size:12.5px;}
.table-simple td{padding:12px 8px;border-bottom:1px solid #f5f6fa;}

@media (max-width:1000px){
  .dash-shell{grid-template-columns:1fr;}
  .dash-sidebar{display:none;}
  .stat-grid{grid-template-columns:repeat(2,1fr);}
  .dash-grid{grid-template-columns:1fr;}
}

@media (max-width:900px){
  .course-grid{grid-template-columns:1fr;}
  .feature-strip{grid-template-columns:1fr;}
  /* minmax(0,1fr), not a bare 1fr: a plain 1fr track's minimum is auto
     (its content's min-content size), so wide unshrinkable content inside
     (like .lesson-actions used to be) would grow this track — and the
     whole page — past the viewport instead of being constrained by it. */
  .lesson-layout,.assignment-layout{grid-template-columns:minmax(0,1fr);}
}

.hero-art{
  position:relative;
  border-radius:24px;
  overflow:hidden;
  aspect-ratio:1/.95;
  background:linear-gradient(160deg,#1a2340,#0d1224);
}
.hero-art .decor-circle{
  position:absolute;top:8%;right:10%;
  width:34%;aspect-ratio:1;border-radius:50%;
  background:rgba(91,79,233,.28);
}

.hero-photo{
  position:absolute;
  inset:0;              /* fill the entire box, not just bottom-right */
  width:100%;
  height:100%;
  object-fit:cover;      /* crop to fill instead of leaving gaps */
  object-position:top center; /* keeps the face/head in frame */
}

/* optional: fade the bottom of the photo into the dark panel so it feels blended, not pasted on */
.hero-art::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(to top, rgba(10,14,26,.55) 0%, rgba(10,14,26,0) 35%);
  pointer-events:none;
}

/* ---------------------------------------------
   Home page hero — mobile only (<=767px)

   Tablets (768px+, e.g. 768/820/1024) keep the exact same side-by-side
   "laptop" layout as desktop — only phones get this dedicated stacked
   layout: text first, image below, everything centered, padding cut way
   back so the hero doesn't dominate the screen before the fold.
--------------------------------------------- */
@media (max-width:767px){
  .hero{padding:40px 0;}
  .hero .container{grid-template-columns:1fr;justify-items:center;text-align:center;gap:28px;}
  .hero h1{font-size:2.25rem;}
  .hero p.lead{font-size:15.5px;line-height:1.65;margin:14px auto 22px;max-width:440px;}
  .hero-cta{justify-content:center;flex-wrap:wrap;gap:12px;margin-bottom:28px;}
  .hero-stats{grid-template-columns:repeat(2,1fr);gap:16px;width:100%;max-width:480px;}
  .hero-stats .stat{text-align:left;}
  .hero-art{width:100%;max-width:420px;aspect-ratio:4/3;}
}

/* ---------------------------------------------
   Home page hero — iPad portrait only (768-1024px width, AND portrait
   orientation specifically). A dedicated tablet design, not the desktop
   grid shrunk down and not the phone's stacked layout: still two columns
   (text / image) like desktop, but rebalanced — smaller image, tighter
   spacing, a shorter hero that fits the first screen. Requires portrait
   so a landscape tablet or a small laptop window at this same width
   still gets the untouched desktop layout above.
--------------------------------------------- */
@media (min-width:768px) and (max-width:1024px) and (orientation:portrait){
  .hero{padding:36px 0;}
  .hero .container{grid-template-columns:1.05fr 1fr;gap:28px;align-items:center;}
  .hero h1{font-size:2.25rem;}
  .hero p.lead{font-size:15px;line-height:1.6;margin:12px 0 20px;max-width:340px;}
  .hero-cta{gap:10px;margin-bottom:24px;flex-wrap:nowrap;}
  .hero-stats{grid-template-columns:repeat(2,1fr);gap:22px;}
  .hero-art{max-width:320px;width:100%;margin:0 auto;aspect-ratio:1/.95;}
  .hero-art .decor-eq{font-size:clamp(16px,2vw,22px);}

  /* Shorter hero means "All Courses" should start closer behind it. */
  .hero + .section{padding-top:40px;}
}

/* ---------------------------------------------
   Home page "All Courses" — iPad portrait only (768-1024px, portrait).

   Scoped with `.home` (WordPress's own body class for the designated
   front page) rather than just `.course-grid`/`.course-card`, because
   those same classes are reused on the Courses archive page — this must
   only touch the Home page's section, not the archive.

   A dedicated tablet card: 2 columns, a shorter thumbnail, and a
   compacted body so the card reads as "tablet-native" rather than a
   shrunk desktop card.
--------------------------------------------- */
@media (min-width:768px) and (max-width:1024px) and (orientation:portrait){
  .home .section-head{margin-bottom:24px;}
  .home .course-grid{grid-template-columns:repeat(2,1fr);gap:18px;}
  .home .course-thumb{aspect-ratio:12/5;}
  .home .course-body{padding:14px 16px 16px;}
  .home .course-body h3{font-size:16px;margin-bottom:6px;line-height:1.3;}
  .home .course-body p{
    font-size:13px;
    line-height:1.5;
    margin-bottom:10px;
    display:-webkit-box;
    -webkit-box-orient:vertical;
    -webkit-line-clamp:3;
    overflow:hidden;
  }
  .home .course-meta{margin-bottom:8px;}
}

/* Phones: the title can afford to be closer to desktop size again (per
   spec — tablet is the one that's "slightly smaller", not mobile), while
   the rest of the tablet-tier rules above still apply. */
/* +2px buffers on these device-width breakpoints: some browsers report an
   integer innerWidth (e.g. 414) while the underlying value used to
   evaluate the media query is a fraction of a pixel higher (device-pixel-
   ratio rounding), which makes an exact `max-width:414px` silently fail to
   match on the very device it's meant for. */
@media (max-width:416px){
  .hero h1{font-size:2.75rem;}
}
@media (max-width:392px){
  .hero h1{font-size:2.65rem;}
}
@media (max-width:377px){
  .hero h1{font-size:2.5rem;}
}
@media (max-width:322px){
  .hero h1{font-size:2.5rem;}
  .hero-stats{grid-template-columns:1fr;}
}

/* ---------------------------------------------
   9. Animations & Transitions
--------------------------------------------- */

/* Page enter/exit (works even before JS loads) */
@keyframes fadeInPage{
  from{opacity:0;transform:translateY(8px);}
  to{opacity:1;transform:translateY(0);}
}
@keyframes fadeOutPage{
  to{opacity:0;transform:translateY(-8px);}
}
body{animation:fadeInPage .5s cubic-bezier(.22,.61,.36,1) both;}
body.page-exit{animation:fadeOutPage .22s ease forwards;}

/* Header gains depth once you scroll */
.site-header{transition:box-shadow .3s ease, background-color .3s ease;}
.site-header.is-scrolled{box-shadow:0 10px 26px -14px rgba(0,0,0,.55);}

/* Nav link underline sweep */
.main-nav a{position:relative;transition:color .2s ease, opacity .2s ease;}
.main-nav a::after{
  content:"";position:absolute;left:0;right:100%;bottom:-6px;height:2px;
  background:var(--violet);border-radius:2px;transition:right .25s cubic-bezier(.4,0,.2,1);
}
.main-nav a:hover::after,.main-nav a.active::after{right:0;}

.dash-nav a{transition:background-color .2s ease, color .2s ease, transform .15s ease;}
.dash-nav a:hover{transform:translateX(3px);}

.avatar-btn{transition:transform .2s ease, box-shadow .2s ease;}
.avatar-btn:hover{transform:scale(1.08);box-shadow:0 6px 14px -4px rgba(91,79,233,.55);}

/* Buttons: lift + ripple */
.btn{position:relative;overflow:hidden;transition:transform .15s ease, background-color .15s ease, border-color .15s ease, box-shadow .15s ease;}
.btn-primary:hover{transform:translateY(-2px);box-shadow:0 10px 20px -8px rgba(91,79,233,.55);}
.btn-outline:hover,.btn-ghost:hover{transform:translateY(-2px);}
.btn:active{transform:translateY(0) scale(.98);}
.btn-ripple{
  position:absolute;border-radius:50%;background:currentColor;opacity:.28;
  transform:scale(0);animation:rippleEffect .6s ease-out forwards;pointer-events:none;
}
@keyframes rippleEffect{to{transform:scale(2.6);opacity:0;}}
@keyframes popScale{0%{transform:scale(1);}50%{transform:scale(1.07);}100%{transform:scale(1);}}
.btn.pop{animation:popScale .35s ease;}

/* Cards: consistent hover lift */
.course-card,.stat-card,.panel,.ach-card,.card-block,.assignment-main,.lesson-side,
.continue-card,.card,.connect-card,.info-card{
  transition:transform .25s cubic-bezier(.4,0,.2,1), box-shadow .25s ease;
}
.course-card:hover{transform:translateY(-6px);box-shadow:0 20px 34px -16px rgba(11,15,30,.4);}
.stat-card:hover,.panel:hover,.ach-card:hover,.card-block:hover,.connect-card:hover,.info-card:hover{transform:translateY(-4px);box-shadow:0 16px 28px -14px rgba(11,15,30,.35);}
.continue-card:hover{transform:translateX(4px);}

.course-thumb svg path{transition:stroke-width .3s ease;}
.course-card:hover .course-thumb svg path{stroke-width:2.2;}

.ach-card:hover .trophy{animation:trophyBounce .6s ease;}
@keyframes trophyBounce{
  0%,100%{transform:translateY(0) rotate(0deg);}
  30%{transform:translateY(-6px) rotate(-8deg);}
  60%{transform:translateY(0) rotate(6deg);}
}

.lesson-row{transition:background-color .2s ease, transform .2s ease;}
.lesson-row:hover{background:var(--paper-soft);transform:translateX(4px);}
.side-lesson{transition:background-color .2s ease, color .2s ease, transform .2s ease;}
.side-lesson:hover{background:var(--paper-soft);transform:translateX(3px);}

.activity-row .ic{transition:transform .2s ease;}
.activity-row:hover .ic{transform:scale(1.12);}

/* Progress bars animate their fill in */
.progress > span{transition:width 1s cubic-bezier(.4,0,.2,1);}

/* Video controls */
.video-controls button{transition:transform .15s ease, opacity .15s ease;}
.video-controls button:hover{transform:scale(1.15);}

/* Scroll-reveal (driven by main.js IntersectionObserver) */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .6s cubic-bezier(.22,.61,.36,1), transform .6s cubic-bezier(.22,.61,.36,1);}
.reveal.in-view{opacity:1;transform:translateY(0);}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;}
}

/* ---------------------------------------------
   Contact page

   Reuses the site's existing patterns rather than inventing new ones:
   .hero/.eyebrow/.hero-art/.decor-circle (same dark-navy hero band as the
   homepage), .card/.field/.field-2col (same form styling as auth pages),
   .btn/.section/.section-head, and .reveal (existing scroll-fade-in,
   picked up automatically by main.js's IntersectionObserver — no JS
   changes needed since it just watches for the class, not a fixed list
   of pages). The hero itself fades in immediately on load via the same
   omarFadeUp keyframe already used on the login/register page's visual
   panel, rather than waiting for a scroll trigger above the fold.
--------------------------------------------- */
.contact-hero .container{align-items:center;}
.contact-hero > .container > *{animation:omarFadeUp .5s cubic-bezier(.4,0,.2,1) both;}
/* .hero h1 .accent is display:block site-wide (the homepage's "Step by
   Step" relies on that to sit on its own line) — this page needs the
   opposite, so it's overridden here only, scoped to .contact-hero-title,
   rather than touching the shared .hero rule other pages depend on. */
.contact-hero-title{white-space:nowrap;}
.hero h1.contact-hero-title .accent{display:inline;}
.contact-hero-art{display:flex;align-items:center;justify-content:center;}
.contact-hero-art .decor-circle-sm{width:16%;top:auto;bottom:10%;left:10%;right:auto;background:rgba(139,127,251,.3);}
.contact-illustration{position:relative;width:80%;max-width:320px;}

.contact-grid{display:grid;grid-template-columns:11fr 9fr;gap:28px;align-items:start;margin-bottom:60px;}
.contact-form-card{padding:32px;}
.contact-form-card h2{font-size:21px;margin-bottom:22px;}
.contact-form .btn{width:100%;margin-top:6px;}
.omar-hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}
.contact-form-notice{border-radius:10px;padding:12px 16px;font-size:13.5px;font-weight:600;margin-bottom:18px;}
.contact-form-notice-success{background:#e3faec;color:#146c3a;}
.contact-form-notice-error{background:#fde6e6;color:#9c1c1c;}

.connect-panel h2{font-size:21px;margin-bottom:22px;}
.connect-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;}
.connect-card{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:22px 20px;border-top:3px solid var(--accent,var(--violet));display:flex;flex-direction:column;}
.connect-icon{width:44px;height:44px;border-radius:12px;background:var(--accent-soft,var(--violet-100));display:flex;align-items:center;justify-content:center;color:var(--accent,var(--violet));margin-bottom:14px;}
.connect-icon svg{width:22px;height:22px;fill:currentColor;}
.connect-card h3{font-size:15.5px;margin-bottom:6px;}
.connect-card p{font-size:13px;color:var(--ink-600);line-height:1.55;margin-bottom:16px;flex:1;}
.connect-card .btn{background:var(--accent,var(--violet));color:#fff;font-size:13px;padding:10px 16px;width:100%;}
.connect-card .btn:hover{filter:brightness(1.08);}
.connect-whatsapp{--accent:#25d366;--accent-soft:#e3faec;}
.connect-youtube{--accent:#ff0000;--accent-soft:#fde6e6;}
.connect-facebook{--accent:#1877f2;--accent-soft:#e6f0fe;}
.connect-tiktok{--accent:#111827;--accent-soft:#e9eaec;}

/* Two cards now (Support Hours removed) — flex+justify-content:center
   instead of a 3-col grid, so they sit wider, centered as a pair, with
   equal gap between them, and wrap to stacked on narrow screens on their
   own via flex-wrap (still backed by the max-width:900px override below
   for a clean, deliberate breakpoint rather than relying on wherever the
   flex-basis happens to wrap). */
.info-grid{display:flex;flex-wrap:wrap;justify-content:center;gap:22px;}
.info-card{padding:26px;flex:1 1 380px;max-width:440px;}
.info-card h3{font-size:15.5px;margin-bottom:12px;display:flex;align-items:center;gap:8px;}
.info-card .info-primary{font-size:14.5px;font-weight:600;color:var(--ink-900);line-height:1.6;margin-bottom:8px;}
.info-card .info-primary a{color:var(--violet);}
.info-card .info-primary a:hover{text-decoration:underline;}
.info-card .info-hint{font-size:12.5px;color:var(--ink-400);}
.country-list{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px;}
.country-list li{font-size:12px;font-weight:600;color:var(--ink-600);background:var(--paper-soft);border-radius:99px;padding:5px 12px;}

@media (max-width:900px){
  .contact-hero .container{grid-template-columns:1fr;text-align:center;gap:28px;}
  .contact-hero-art{order:-1;max-width:280px;margin:0 auto;}
  .contact-grid{grid-template-columns:1fr;}
  .info-card{flex-basis:100%;max-width:480px;}
}
@media (max-width:600px){
  .connect-grid{grid-template-columns:1fr;}
  .contact-form-card{padding:24px 20px;}
}

/* ---------------------------------------------
   Settings page

   Reuses the same .card/.field/.field-2col/.form-section-label patterns
   as the auth pages rather than inventing new ones — the only genuinely
   new pieces here are the read-only email field's lock treatment, the
   avatar upload preview circle, and the toast component (nothing existing
   in the theme did either of those yet).
--------------------------------------------- */
.settings-card{max-width:640px;margin:0 auto;padding:36px;}
.field-readonly{position:relative;}
.field-readonly input{background:var(--paper-soft);color:var(--ink-400);padding-right:38px;cursor:not-allowed;}
.field-readonly .field-lock{position:absolute;right:12px;top:38px;color:var(--ink-400);font-size:14px;pointer-events:none;}
.field-readonly .field-hint{display:block;margin-top:6px;}

.avatar-upload-row{display:flex;align-items:center;gap:18px;margin-bottom:4px;}
.avatar-upload-preview{width:64px;height:64px;border-radius:50%;background:var(--violet);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:22px;flex-shrink:0;overflow:hidden;}
.avatar-upload-preview img{width:100%;height:100%;object-fit:cover;display:block;}
.avatar-upload-controls .btn{font-size:13px;padding:9px 16px;}
.avatar-upload-controls input[type="file"]{display:none;}
.avatar-upload-hint{font-size:12px;color:var(--ink-400);margin-top:6px;}

.settings-card .btn-primary.btn-block:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none;}

/* Toast: fixed bottom-center, fades + rises in, matching the site's
   existing radius/shadow tokens rather than new ones. */
.omar-toast{
  position:fixed;
  left:50%;
  bottom:28px;
  transform:translate(-50%,12px);
  background:var(--navy-900);
  color:#fff;
  padding:14px 22px;
  border-radius:var(--radius-md);
  box-shadow:0 20px 40px -12px rgba(0,0,0,.5);
  font-size:14px;
  font-weight:600;
  opacity:0;
  z-index:999;
  transition:opacity .25s ease, transform .25s ease;
}
.omar-toast.is-visible{opacity:1;transform:translate(-50%,0);}
.omar-toast-error{background:#9c1c1c;}

@media (max-width:700px){
  .settings-card{padding:26px 20px;}
}

/* ---------------------------------------------
   Past Papers: subject cards (hub page + Board/Level fallback archives)

   Deliberately modeled on .course-card's own tokens (--radius-lg,
   --shadow-card, the same translateY(-4px) hover lift) per "match Course
   Card styling", but simplified to icon + name only — no thumb image,
   no meta row, no CTA button, since a subject card only ever has one
   destination (its own page) and no stats to show.
--------------------------------------------- */
.subject-section-container{max-width:1100px;}
.subject-card-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,200px);
  justify-content:center;
  gap:24px;
}
.subject-card{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:14px;
  background:#fff;
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);
  padding:36px 20px;
  text-align:center;
  transition:transform .2s ease,box-shadow .2s ease;
}
.subject-card:hover{transform:translateY(-6px);box-shadow:0 26px 40px -16px rgba(11,15,30,.25);}
.subject-card-icon{
  width:64px;
  height:64px;
  border-radius:16px;
  background:linear-gradient(135deg,#3a2f8f,#5b4fe9);
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:30px;
  flex-shrink:0;
  transition:transform .2s ease;
}
.subject-card:hover .subject-card-icon{transform:scale(1.08);}
.subject-card h3{font-size:15px;margin:0;color:var(--ink-900);}
.subject-card-badge{
  display:inline-flex;
  align-items:center;
  background:var(--violet);
  color:#fff;
  font-size:11.5px;
  font-weight:700;
  letter-spacing:.02em;
  padding:4px 12px;
  border-radius:999px;
}

@media (max-width:480px){
  .subject-card-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;}
  .subject-card{padding:26px 14px;}
}

/* Level sub-heading within a Board section (hub page) — smaller/quieter
   than the Board's own <h2>, with a divider line trailing off to the
   right so "O Level" / "A Level" read as a sub-grouping, not a peer of
   "Cambridge" above it. */
.subject-level-head{
  display:flex;
  align-items:center;
  gap:14px;
  margin:0 0 20px;
  color:var(--ink-600);
  font-family:var(--font-display);
  font-size:14px;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.04em;
}
.subject-level-head::after{content:"";flex:1;height:1px;background:#e7e9f2;}
.subject-level-section{margin-bottom:36px;}
.subject-level-section:last-child{margin-bottom:0;}

/* "Coming Soon" placeholder card — same footprint/tokens as .subject-card
   (so it lines up in the same grid) but visually inert: dashed border,
   muted icon circle, no hover lift, cursor default — reads clearly as
   "not a real link yet" rather than a broken/empty subject. */
.subject-coming-soon-card{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:14px;
  background:var(--paper-soft);
  border:1.5px dashed #c7cce0;
  border-radius:var(--radius-lg);
  padding:36px 20px;
  text-align:center;
  cursor:default;
}
.subject-coming-soon-icon{
  width:64px;
  height:64px;
  border-radius:16px;
  background:#e7e9f2;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:28px;
  flex-shrink:0;
}
.subject-coming-soon-card h3{font-size:15px;margin:0;color:var(--ink-900);}
.subject-coming-soon-card p{font-size:12.5px;margin:0;color:var(--ink-400);}

/* ---------------------------------------------
   Past Papers: multi-level nav dropdown (Board -> Level -> Subject)

   Desktop (>1024px, same breakpoint the hamburger nav itself switches
   at): a dark flyout panel (matching the header/navbar, same technique
   as .user-menu-dropdown elsewhere in this file), opened on :hover
   (mouse) or .is-open (click/tap/keyboard — see main.js), with nested
   submenus opening to the right. The trigger and panel/submenus touch
   with zero gap between them (top:100%/left:100%, no margin) — a gap
   there is exactly what let the cursor "lose" the hover state crossing
   from one to the next; any visual breathing room instead comes from
   padding *inside* each panel, which is still part of the hoverable box.

   Mobile (<=1024px, inside the existing #main-nav slide-down panel):
   the same markup instead lays out in-flow as a nested accordion —
   .is-open drives a max-height reveal at every level, indentation
   shows depth, and there's no absolute positioning at all.
--------------------------------------------- */
.nav-dropdown-item{position:relative;}
.nav-dropdown-trigger{
  display:flex;
  align-items:center;
  gap:6px;
  padding:0;
  border:0;
  background:transparent;
  font-family:inherit;
  color:var(--ink-200);
  font-size:14.5px;
  font-weight:500;
  opacity:.85;
  cursor:pointer;
  transition:opacity .15s ease,color .15s ease;
}
.nav-dropdown-trigger:hover,
.nav-dropdown-trigger.active,
.nav-dropdown-item.is-open > .nav-dropdown-trigger{opacity:1;color:#fff;}
.nav-caret{transition:transform .2s ease;}
.nav-dropdown-item.is-open > .nav-dropdown-trigger .nav-caret{transform:rotate(180deg);}

@media (min-width:1025px){
  .nav-dropdown-item{height:100%;display:flex;align-items:center;}
  .nav-dropdown-trigger{height:100%;}

  /* The panel itself starts flush against the trigger (top:100%, zero
     real gap) so the cursor never crosses dead space and loses :hover —
     the visible 16px "detached" look instead comes from padding-top on
     this same box (still inside the hoverable area) plus an inner
     wrapper that carries the actual background/shadow/radius. Moving
     from the navbar down through that padding never leaves the box. */
  .nav-dropdown-panel{
    position:absolute;
    top:100%;
    left:50%;
    padding-top:16px;
    transform:translateX(-50%) translateY(-6px);
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transition:opacity .2s ease,transform .2s ease,visibility 0s linear .2s;
    z-index:200;
  }
  /* JS-controlled only (.is-open) — see js/main.js. Deliberately not
     also keyed off :hover here: independent per-element :hover state is
     exactly what let sibling submenus (Cambridge/Edexcel, O Level/A
     Level) stay open at the same time, since CSS has no way to express
     "close my sibling when I open." */
  .nav-dropdown-item.is-open > .nav-dropdown-panel{
    opacity:1;
    visibility:visible;
    transform:translateX(-50%) translateY(0);
    pointer-events:auto;
    transition:opacity .2s ease,transform .2s ease;
  }
  .nav-dropdown-panel-inner{
    min-width:230px;
    background:var(--navy-900);
    border:1px solid var(--line-dark);
    border-radius:16px;
    box-shadow:0 20px 44px -12px rgba(0,0,0,.5);
    padding:16px 8px 8px;
  }

  .nav-dd-item{position:relative;}
  .nav-dd-trigger{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:14px;
    width:100%;
    padding:10px 14px;
    border:0;
    background:transparent;
    border-radius:10px;
    font-family:inherit;
    font-size:14px;
    font-weight:500;
    color:var(--ink-200);
    cursor:pointer;
    text-align:left;
    transition:background-color .15s ease,color .15s ease;
  }
  .nav-dd-trigger:hover,.nav-dd-item.is-open > .nav-dd-trigger{background:var(--violet);color:#fff;}
  .nav-caret-right{color:var(--ink-400);flex-shrink:0;transition:color .15s ease;}
  .nav-dd-trigger:hover .nav-caret-right,.nav-dd-item.is-open > .nav-dd-trigger .nav-caret-right{color:#fff;}

  .nav-dd-submenu{
    position:absolute;
    top:-8px;
    left:100%;
    min-width:210px;
    background:var(--navy-900);
    border:1px solid var(--line-dark);
    border-radius:16px;
    box-shadow:0 20px 44px -12px rgba(0,0,0,.5);
    padding:8px;
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transform:translateX(-6px);
    transition:opacity .2s ease,transform .2s ease,visibility 0s linear .2s;
  }
  /* JS-controlled only (.is-open) — same reasoning as .nav-dropdown-panel
     above: exclusivity between sibling Boards/Levels is enforced in
     JS (openDdItemExclusive), so this can't also open on :hover. */
  .nav-dd-item.is-open > .nav-dd-submenu{
    opacity:1;
    visibility:visible;
    transform:translateX(0);
    pointer-events:auto;
    transition:opacity .2s ease,transform .2s ease;
  }

  .nav-dd-link,.nav-dd-soon{
    display:block;
    padding:10px 14px;
    border-radius:10px;
    font-size:14px;
    color:var(--ink-200);
    white-space:nowrap;
    transition:background-color .15s ease,color .15s ease;
  }
  .nav-dd-link:hover{background:var(--violet);color:#fff;}
  .nav-dd-soon{color:var(--ink-400);font-style:italic;cursor:default;}
}

@media (max-width:1024px){
  /* Restores the plain vertical accordion: every level is a full-width
     block stacked under the one before it, indentation shows depth,
     nothing sits side-by-side. .nav-dropdown-panel-inner is a transparent
     pass-through here (no background/radius/shadow) — that box styling
     is desktop-only, where it's a floating flyout; on mobile everything
     already lives inside the existing dark #main-nav slide-down panel. */
  .nav-dropdown-trigger{
    display:flex;
    align-items:center;
    justify-content:space-between;
    width:100%;
    min-height:48px;
    padding:0 16px;
    border-radius:10px;
    text-align:left;
    transition:background-color .15s ease,color .15s ease;
  }
  .nav-dropdown-trigger:hover,.nav-dropdown-trigger:focus-visible{background:rgba(255,255,255,.08);}
  .nav-dropdown-item.is-open > .nav-dropdown-trigger{background:rgba(91,79,233,.22);}

  .nav-dropdown-panel{
    display:block;
    max-height:0;
    overflow:hidden;
    transition:max-height .28s ease;
  }
  .nav-dropdown-item.is-open > .nav-dropdown-panel{max-height:70vh;overflow-y:auto;}
  .nav-dropdown-panel-inner{display:block;padding:4px 0 8px;}
  .nav-dd-item{display:block;}

  .nav-dd-trigger{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:10px;
    width:100%;
    min-height:44px;
    padding:0 16px 0 28px;
    border:0;
    background:transparent;
    border-radius:10px;
    font-family:inherit;
    font-size:14px;
    font-weight:500;
    color:#fff;
    cursor:pointer;
    text-align:left;
  }
  .nav-dd-trigger:hover,.nav-dd-item.is-open > .nav-dd-trigger{background:rgba(255,255,255,.08);}
  .nav-caret-right{color:var(--ink-400);transition:transform .2s ease;}
  .nav-dd-item.is-open > .nav-dd-trigger .nav-caret-right{transform:rotate(90deg);}

  .nav-dd-submenu{
    display:block;
    max-height:0;
    overflow:hidden;
    transition:max-height .28s ease;
  }
  .nav-dd-item.is-open > .nav-dd-submenu{max-height:400px;}

  .nav-dd-link,.nav-dd-soon{
    display:flex;
    align-items:center;
    min-height:44px;
    padding:0 16px 0 40px;
    font-size:13.5px;
    color:var(--ink-200);
  }
  .nav-dd-link:hover,.nav-dd-link:focus-visible{background:rgba(255,255,255,.08);color:#fff;}
  .nav-dd-soon{color:var(--ink-400);font-style:italic;}
}

/* ---------------------------------------------
   Toast notifications (js/toast.js — window.omarToast)
   Reusable across the site for success/error/info messages.
   Named "omar-notify" (not "omar-toast") to avoid colliding with the
   pre-existing bottom-center .omar-toast component used by
   js/settings-form.js and js/video-protection.js.
--------------------------------------------- */
#omar-notify-container{
  position:fixed;
  top:20px;
  right:20px;
  z-index:9999;
  display:flex;
  flex-direction:column;
  gap:12px;
  width:360px;
  max-width:calc(100vw - 32px);
  pointer-events:none;
}

.omar-notify{
  display:flex;
  align-items:flex-start;
  gap:12px;
  width:100%;
  padding:16px 18px;
  background:var(--paper);
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);
  pointer-events:auto;
  opacity:0;
  transform:translateX(24px);
  transition:opacity .35s ease, transform .35s ease;
}
.omar-notify--visible{opacity:1;transform:translateX(0);}
.omar-notify--hiding{opacity:0;transform:translateX(24px);}

.omar-notify__icon{
  flex:none;
  display:flex;
  align-items:center;
  justify-content:center;
  width:28px;
  height:28px;
  border-radius:50%;
  font-size:14px;
  font-weight:700;
  line-height:1;
  color:#fff;
  background:var(--green);
}
.omar-notify--error .omar-notify__icon{background:var(--rose);}
.omar-notify--info .omar-notify__icon{background:var(--violet);}

.omar-notify__text{flex:1;min-width:0;}
.omar-notify__title{
  margin:0 0 4px 0;
  font-family:var(--font-display);
  font-size:14.5px;
  font-weight:700;
  color:var(--ink-900);
}
.omar-notify__body{
  margin:0;
  font-family:var(--font-body);
  font-size:13px;
  line-height:1.55;
  color:var(--ink-600);
}

.omar-notify__close{
  flex:none;
  border:0;
  background:transparent;
  padding:0;
  margin:-4px -2px 0 0;
  font-size:18px;
  line-height:1;
  color:var(--ink-400);
  cursor:pointer;
}
.omar-notify__close:hover{color:var(--ink-900);}

@media screen and (max-width:600px){
  #omar-notify-container{
    top:12px;
    right:12px;
    left:12px;
    width:auto;
    max-width:none;
  }
}

/* ---------------------------------------------
   Password field: visibility toggle + strength meter
   (Create New Password page — js/password-field.js)
--------------------------------------------- */
.password-input-wrap{position:relative;}
.password-input-wrap input{padding-right:44px !important;}
.password-toggle{
  position:absolute;
  top:50%;
  right:6px;
  transform:translateY(-50%);
  border:0;
  background:transparent;
  padding:8px;
  font-size:16px;
  line-height:1;
  color:var(--ink-400);
  cursor:pointer;
}
.password-toggle:hover{color:var(--ink-900);}

.password-strength{margin-top:9px;}
.password-strength-bar{height:4px;border-radius:2px;background:#eceef4;overflow:hidden;}
.password-strength-bar span{
  display:block;
  height:100%;
  width:0%;
  border-radius:2px;
  background:var(--rose);
  transition:width .2s ease, background-color .2s ease;
}
.password-strength-label{margin:6px 0 0 0;font-size:12px;color:var(--ink-400);}
.password-strength-label.is-weak{color:var(--rose);}
.password-strength-label.is-medium{color:var(--amber);}
.password-strength-label.is-strong{color:var(--green);}

.password-match-msg{margin:6px 0 0 0;font-size:12px;}
.password-match-msg.is-match{color:var(--green);}
.password-match-msg.is-mismatch{color:var(--rose);}
