/* ===================================================================
   Ebora — Site Redesign Mockups · shared design system
   Tokens lifted from the LIVE site (ebora-site-header.php) so these
   mockups match production, not a reinvented palette.
   =================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Space+Grotesk:wght@400;500;600;700&display=swap');

:root{
  /* --- brand (from production) --- */
  --eb-bg:#070b16;
  --eb-surface:#0c1326;
  --eb-surface-2:#10182e;
  --eb-blue:#2f6bff;
  --eb-cyan:#38bdf8;
  --eb-ink:#eef3ff;
  --eb-muted:#9fb0d0;
  --eb-line:rgba(132,166,255,.22);
  --eb-line-soft:rgba(132,166,255,.12);

  /* --- state --- */
  --eb-gold:#ffd24a;
  --eb-warm:#ff8a3d;
  --eb-rose:#ff3b5c;
  --eb-green:#34d399;

  /* --- layout --- */
  --gutter:clamp(16px,3.2vw,56px);
  --shell:min(1800px, 100% - (2 * var(--gutter)));
  --r-card:16px;
  --r-ctl:12px;
  --r-pill:999px;

  /* --- type scale (fluid) --- */
  --t-xs:12px;
  --t-sm:13px;
  --t-md:15px;
  --t-base:16px;
  --t-lg:clamp(17px,1.1vw,19px);
  --t-xl:clamp(20px,1.5vw,24px);
  --t-2xl:clamp(24px,2.2vw,32px);
  --t-3xl:clamp(30px,3.4vw,44px);
  --t-4xl:clamp(38px,5vw,62px);

  /* --- motion --- */
  --ease:cubic-bezier(.16,1,.3,1);
  --dur:180ms;

  --shadow-card:0 1px 0 rgba(255,255,255,.04) inset, 0 12px 34px rgba(0,0,0,.42);
  --shadow-pop:0 24px 70px rgba(0,0,0,.6);
}

/* ---------- LIGHT MODE ---------- */
[data-theme="light"]{
  --eb-bg:#f4f7fd;
  --eb-surface:#ffffff;
  --eb-surface-2:#eef3fc;
  --eb-ink:#0d1730;
  --eb-muted:#5a6b8c;
  --eb-line:rgba(23,54,120,.16);
  --eb-line-soft:rgba(23,54,120,.09);
  --shadow-card:0 1px 2px rgba(16,38,84,.06), 0 10px 26px rgba(16,38,84,.09);
  --shadow-pop:0 24px 70px rgba(16,38,84,.22);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--eb-bg);
  color:var(--eb-ink);
  font:400 var(--t-base)/1.6 Manrope,system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
h1,h2,h3,h4{font-family:'Space Grotesk',Manrope,sans-serif;font-weight:700;line-height:1.14;margin:0;letter-spacing:-.02em}
p{margin:0;text-wrap:pretty}
a{color:inherit;text-decoration:none}
button,input,select{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}
img{max-width:100%;display:block}
:focus-visible{outline:2px solid var(--eb-cyan);outline-offset:3px;border-radius:6px}

.shell{width:var(--shell);margin-inline:auto}
.muted{color:var(--eb-muted)}
.mono{font-family:'Space Grotesk',monospace;font-variant-numeric:tabular-nums}

/* ================= AMBIENT BACKDROP ================= */
.aura{position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.aura::before,.aura::after{
  content:'';position:absolute;width:60vw;height:60vw;border-radius:50%;
  filter:blur(90px);opacity:.20;
}
.aura::before{background:var(--eb-blue);top:-22vw;left:-12vw}
.aura::after{background:var(--eb-cyan);bottom:-28vw;right:-14vw;opacity:.13}
[data-theme="light"] .aura::before{opacity:.14}
[data-theme="light"] .aura::after{opacity:.10}

/* ================= HEADER ================= */
.hdr{
  position:sticky;top:0;z-index:60;
  background:color-mix(in oklab,var(--eb-bg) 82%, transparent);
  backdrop-filter:blur(16px) saturate(140%);
  border-bottom:1px solid var(--eb-line-soft);
}
.hdr__in{width:var(--shell);margin-inline:auto;display:flex;align-items:center;gap:14px;height:64px}
.brand{display:flex;align-items:center;gap:10px;font-family:'Space Grotesk';font-weight:700;font-size:var(--t-lg);letter-spacing:-.02em;flex:0 0 auto}
.brand__mark{
  width:34px;height:34px;border-radius:10px;flex:0 0 auto;
  background:linear-gradient(140deg,var(--eb-blue),var(--eb-cyan));
  display:grid;place-items:center;color:#fff;font-size:15px;font-weight:700;
  box-shadow:0 6px 18px rgba(47,107,255,.42);
}
.hdr__nav{display:flex;gap:4px;margin-left:10px}
.hdr__nav a{
  padding:8px 13px;border-radius:var(--r-pill);font-size:var(--t-md);font-weight:600;
  color:var(--eb-muted);transition:var(--dur) var(--ease);
}
.hdr__nav a:hover{color:var(--eb-ink);background:var(--eb-surface-2)}
.hdr__nav a[aria-current]{color:var(--eb-ink);background:var(--eb-surface-2)}
.hdr__sp{margin-left:auto}

.chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 12px;border-radius:var(--r-pill);
  background:var(--eb-surface-2);border:1px solid var(--eb-line-soft);
  font-size:var(--t-sm);font-weight:700;white-space:nowrap;
}
.chip svg{width:15px;height:15px;flex:0 0 auto}
.chip--ep{color:var(--eb-gold);border-color:color-mix(in oklab,var(--eb-gold) 34%,transparent)}
.chip--days{color:var(--eb-green);border-color:color-mix(in oklab,var(--eb-green) 34%,transparent)}
.chip--tier{color:var(--eb-cyan);border-color:color-mix(in oklab,var(--eb-cyan) 36%,transparent)}

.iconbtn{
  width:40px;height:40px;display:grid;place-items:center;border-radius:var(--r-ctl);
  border:1px solid var(--eb-line-soft);background:var(--eb-surface-2);color:var(--eb-muted);
  transition:var(--dur) var(--ease);
}
.iconbtn:hover{color:var(--eb-ink);border-color:var(--eb-line)}
.iconbtn svg{width:18px;height:18px}

/* ================= BUTTONS ================= */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:46px;padding:0 20px;border-radius:var(--r-ctl);
  font-weight:700;font-size:var(--t-md);letter-spacing:.01em;
  transition:transform var(--dur) var(--ease),background var(--dur),box-shadow var(--dur);
  border:1px solid transparent;
}
.btn:active{transform:scale(.975)}
.btn svg{width:17px;height:17px;flex:0 0 auto}
.btn--primary{background:linear-gradient(135deg,var(--eb-blue),#5b8cff);color:#fff;box-shadow:0 8px 24px rgba(47,107,255,.36)}
.btn--primary:hover{box-shadow:0 12px 32px rgba(47,107,255,.5)}
.btn--ghost{background:var(--eb-surface-2);border-color:var(--eb-line);color:var(--eb-ink)}
.btn--ghost:hover{border-color:var(--eb-cyan)}
.btn--gold{background:linear-gradient(135deg,var(--eb-gold),var(--eb-warm));color:#2a1a00;box-shadow:0 8px 24px rgba(255,180,60,.32)}
.btn--block{width:100%}
.btn--sm{min-height:38px;padding:0 14px;font-size:var(--t-sm)}

/* ================= CARD PRIMITIVE ================= */
.card{
  background:var(--eb-surface);
  border:1px solid var(--eb-line-soft);
  border-radius:var(--r-card);
  box-shadow:var(--shadow-card);
  position:relative;
  overflow:hidden;
}

/* ================= SECTION HEADS ================= */
.sec{padding:clamp(38px,5vw,72px) 0}
.sec__head{display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;margin-bottom:24px}
.sec__head h2{font-size:var(--t-2xl)}
.sec__head p{color:var(--eb-muted);font-size:var(--t-md)}
.eyebrow{
  font-family:'Space Grotesk';font-size:var(--t-xs);font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--eb-cyan);margin-bottom:10px;
}

/* ================= SUBJECT CARD ================= */
.grid-subjects{
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(clamp(260px,24vw,330px),1fr));
}
.subj{
  display:flex;flex-direction:column;gap:12px;padding:18px;
  cursor:pointer;text-align:left;width:100%;
  transition:transform var(--dur) var(--ease),border-color var(--dur);
  --hue:214;
}
.subj::before{
  content:'';position:absolute;inset:0 0 auto 0;height:3px;
  background:linear-gradient(90deg,hsl(var(--hue) 92% 62%),hsl(calc(var(--hue) + 26) 92% 66%));
}
.subj::after{
  content:'';position:absolute;width:180px;height:180px;border-radius:50%;
  background:hsl(var(--hue) 92% 60%);filter:blur(64px);opacity:.13;
  top:-70px;right:-60px;pointer-events:none;transition:opacity var(--dur);
}
.subj:hover{transform:translateY(-3px);border-color:hsl(var(--hue) 80% 60% / .48)}
.subj:hover::after{opacity:.24}
.subj__top{display:flex;align-items:flex-start;gap:12px;padding-right:84px}
.subj__ico{
  width:44px;height:44px;flex:0 0 auto;border-radius:12px;display:grid;place-items:center;
  background:hsl(var(--hue) 92% 60% / .14);color:hsl(var(--hue) 92% 68%);
  border:1px solid hsl(var(--hue) 92% 60% / .3);
}
.subj__ico svg{width:22px;height:22px}
.subj__name{display:block;font-size:var(--t-lg);font-weight:700;font-family:'Space Grotesk';line-height:1.2}
.subj__full{display:block;font-size:var(--t-sm);color:var(--eb-muted);margin-top:3px}
.subj__meta{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto;padding-top:4px}
.tag{
  font-size:var(--t-xs);font-weight:700;padding:4px 9px;border-radius:var(--r-pill);
  background:var(--eb-surface-2);color:var(--eb-muted);border:1px solid var(--eb-line-soft);
}
.tag--hue{background:hsl(var(--hue) 92% 60% / .12);color:hsl(var(--hue) 92% 72%);border-color:hsl(var(--hue) 92% 60% / .26)}
[data-theme="light"] .tag--hue{color:hsl(var(--hue) 70% 38%)}
[data-theme="light"] .subj__ico{color:hsl(var(--hue) 70% 40%)}

.subj__state{
  position:absolute;top:14px;right:14px;
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-xs);font-weight:700;padding:4px 9px;border-radius:var(--r-pill);
}
.subj__state svg{width:12px;height:12px}
.is-owned .subj__state{background:color-mix(in oklab,var(--eb-green) 18%,transparent);color:var(--eb-green)}
.is-locked{opacity:.72}
.is-locked .subj__state{background:var(--eb-surface-2);color:var(--eb-muted)}
.is-locked:hover{opacity:1}

/* A subject carrying a FREE SAMPLE CHAPTER. The padlock in the corner is still
   true — the subject is locked — but the card must not be dimmed to the same
   "nothing for you here" grey as the rest, because this one is the card we most
   want tapped. Green, in flow, never in the 84px corner slot: "Chapter 1 free"
   is far too long for that chip and would sit on top of the subject name. */
.tag--free{
  background:color-mix(in oklab,var(--eb-green) 16%,transparent);color:var(--eb-green);
  border-color:color-mix(in oklab,var(--eb-green) 34%,transparent);
}
.tag--free svg{width:12px;height:12px;vertical-align:-2px}
.subj.is-locked.has-free{opacity:.9}

/* A hub that has not opened yet. Deliberately NOT the locked treatment: locked
   says "buy this and it opens", which would be a lie. This one is flat, has no
   hover lift and no pointer, and wears the date instead of a padlock. */
.subj.is-soon{opacity:.6;cursor:default;border-style:dashed}
.subj.is-soon:hover{transform:none;border-color:var(--eb-line-soft)}
.subj.is-soon .subj__state{
  background:color-mix(in oklab,var(--eb-gold) 14%,transparent);color:var(--eb-gold);
  /* Out of the absolute corner and into normal flow. `.subj__top` reserves
     84px on the right, which fits "Owned" and "Locked" but not
     "Opens next semester" — that overlapped the title on any card whose name
     fits on one line. In flow it cannot collide at any badge length. */
  position:static;align-self:flex-start;margin-bottom:12px}
.subj.is-soon .subj__top{padding-right:0}
.subj.is-soon .subj__ico{filter:saturate(.35)}

/* ================= VIDEO CARD ================= */
.grid-videos{
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(clamp(250px,20vw,300px),1fr));
}
/* Every page that renders a .vid opens a player from it, so it is a control. */
.vid{display:flex;flex-direction:column;cursor:pointer;transition:transform var(--dur) var(--ease),border-color var(--dur)}
.vid:hover{transform:translateY(-3px);border-color:var(--eb-line)}
/* Figure plate stays white in BOTH themes — these are textbook line drawings
   on white; a dark plate would invert them into mush. Fixed aspect keeps
   every card in a row the same height. */
.vid__fig{
  aspect-ratio:4/3;background:#fff;position:relative;flex:0 0 auto;
  display:grid;place-items:center;border-bottom:1px solid var(--eb-line-soft);
  overflow:hidden;
}
.vid__fig img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:9px}
.vid__figlabel{
  font-size:var(--t-xs);color:var(--eb-muted);font-family:'Space Grotesk';
  letter-spacing:.06em;text-transform:uppercase;text-align:center;padding:0 14px;
}
.vid__play{
  position:absolute;inset:0;display:grid;place-items:center;
  background:radial-gradient(circle at 50% 50%,rgba(0,0,0,.34),rgba(0,0,0,.06));
  opacity:0;transition:opacity var(--dur);
}
.vid:hover .vid__play{opacity:1}
.vid__playdot{
  width:52px;height:52px;border-radius:50%;display:grid;place-items:center;
  background:var(--eb-blue);color:#fff;box-shadow:0 10px 28px rgba(47,107,255,.55);
}
.vid__playdot svg{width:22px;height:22px;margin-left:2px}
.vid__body{padding:13px 14px 14px;display:flex;flex-direction:column;gap:8px;flex:1}
.vid__topic{font-size:var(--t-xs);font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--eb-cyan)}
[data-theme="light"] .vid__topic{color:#1667b8}
.vid__text{font-size:var(--t-sm);line-height:1.5;color:var(--eb-ink);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.vid__foot{display:flex;align-items:center;gap:8px;margin-top:auto;padding-top:4px}
.diff{font-size:var(--t-xs);font-weight:700;padding:3px 8px;border-radius:var(--r-pill)}
.diff--Easy{background:color-mix(in oklab,var(--eb-green) 16%,transparent);color:var(--eb-green)}
.diff--Intermediate{background:color-mix(in oklab,var(--eb-gold) 16%,transparent);color:var(--eb-gold)}
.diff--Hard{background:color-mix(in oklab,var(--eb-rose) 16%,transparent);color:var(--eb-rose)}

/* The sitting a past-board solution came from — a bare month and year, drawn as
   its own quiet chip beside the difficulty. Deliberately the most muted thing in
   the footer: it is a finding aid for a student who remembers a date, not a
   badge. It never names a board or a course, and there is no filter behind it. */
.sitting{
  font-size:var(--t-xs);font-weight:700;letter-spacing:.04em;padding:3px 8px;
  border-radius:var(--r-pill);white-space:nowrap;
  background:color-mix(in oklab,var(--eb-muted) 14%,transparent);color:var(--eb-muted);
}

.heart{
  margin-left:auto;width:36px;height:36px;border-radius:10px;display:grid;place-items:center;
  color:var(--eb-muted);border:1px solid transparent;transition:var(--dur) var(--ease);
}
.heart:hover{color:var(--eb-rose);background:color-mix(in oklab,var(--eb-rose) 12%,transparent)}
.heart svg{width:19px;height:19px}
.heart[aria-pressed="true"]{color:var(--eb-rose)}
.heart[aria-pressed="true"] svg{fill:currentColor}
@keyframes pop{0%{transform:scale(1)}44%{transform:scale(1.32)}100%{transform:scale(1)}}
.heart.did svg{animation:pop 340ms var(--ease)}

/* --- locked video ---
   The thumbnail is OUR artwork and it is the best advertisement the page has,
   so a locked card shows it at full colour and full brightness. Only the
   padlock and the muted caption say "locked". The card used to wear
   `opacity:.72` + `grayscale(1) brightness(.62)` on the figure + a 62% scrim
   with `backdrop-filter:blur(2px)` — four dimmers stacked, which turned a
   guest's whole grid into grey mush and sold nothing. */
.vid.is-locked{opacity:1}
.vid.is-locked .vid__text{color:var(--eb-muted)}
.vid__lock{
  /* Still covers the plate so a tap anywhere on it hits the card's upsell
     handler — but paints NOTHING. No background, no backdrop-filter. */
  position:absolute;inset:0;display:grid;place-items:center;gap:8px;
}
.vid__lockbadge{
  width:46px;height:46px;border-radius:50%;display:grid;place-items:center;
  background:var(--eb-surface-2);border:1px solid var(--eb-line);color:var(--eb-muted);
  /* With the scrim gone the badge sits directly on the white figure plate, so
     it carries its own contrast: opaque fill in both themes plus a shadow. */
  box-shadow:0 4px 14px rgba(7,11,22,.30);
}
.vid__lockbadge svg{width:20px;height:20px}

/* ================= FILTER RAIL ================= */
.libwrap{display:grid;gap:22px;grid-template-columns:1fr;align-items:start}
@media(min-width:1100px){ .libwrap{grid-template-columns:264px 1fr} }

.rail{display:flex;flex-direction:column;gap:18px;position:sticky;top:80px}
@media(max-width:1099px){ .rail{position:static} }
.rail__grp{display:flex;flex-direction:column;gap:9px}
.rail__lbl{font-size:var(--t-xs);font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--eb-muted)}
.opt{
  display:flex;align-items:center;gap:9px;min-height:40px;padding:6px 11px;border-radius:10px;
  font-size:var(--t-md);font-weight:600;color:var(--eb-muted);width:100%;text-align:left;
  border:1px solid transparent;transition:var(--dur) var(--ease);
}
.opt:hover{color:var(--eb-ink);background:var(--eb-surface-2)}
.opt[aria-pressed="true"]{color:var(--eb-ink);background:var(--eb-surface-2);border-color:var(--eb-line)}
.opt__n{margin-left:auto;font-size:var(--t-xs);font-weight:700;color:var(--eb-muted);font-variant-numeric:tabular-nums}
.opt__dot{width:8px;height:8px;border-radius:50%;background:hsl(var(--hue,214) 92% 62%);flex:0 0 auto}

.searchbar{position:relative;margin-bottom:16px}
.searchbar svg{position:absolute;left:14px;top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--eb-muted)}
.searchbar input{
  width:100%;min-height:50px;padding:0 16px 0 44px;border-radius:var(--r-ctl);
  background:var(--eb-surface);border:1px solid var(--eb-line-soft);font-size:var(--t-base);
  transition:var(--dur) var(--ease);
}
.searchbar input:focus{outline:none;border-color:var(--eb-cyan);box-shadow:0 0 0 4px color-mix(in oklab,var(--eb-cyan) 15%,transparent)}
.searchbar input::placeholder{color:var(--eb-muted)}

.chiprow{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.fchip{
  min-height:38px;padding:0 14px;border-radius:var(--r-pill);
  background:var(--eb-surface);border:1px solid var(--eb-line-soft);
  font-size:var(--t-sm);font-weight:700;color:var(--eb-muted);
  display:inline-flex;align-items:center;gap:7px;transition:var(--dur) var(--ease);
}
.fchip:hover{color:var(--eb-ink);border-color:var(--eb-line)}
.fchip[aria-pressed="true"]{background:var(--eb-blue);border-color:var(--eb-blue);color:#fff}
.fchip svg{width:15px;height:15px}

/* ================= UPGRADE BANNER ================= */
.upsell{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding:18px 20px;border-radius:var(--r-card);
  background:linear-gradient(120deg,color-mix(in oklab,var(--eb-blue) 18%,var(--eb-surface)),var(--eb-surface));
  border:1px solid color-mix(in oklab,var(--eb-blue) 34%,transparent);
}
.upsell__ico{
  width:46px;height:46px;flex:0 0 auto;border-radius:12px;display:grid;place-items:center;
  background:color-mix(in oklab,var(--eb-gold) 18%,transparent);color:var(--eb-gold);
}
.upsell__ico svg{width:22px;height:22px}
.upsell h3{font-size:var(--t-lg);margin-bottom:3px}
.upsell p{font-size:var(--t-sm);color:var(--eb-muted)}
.upsell .btn{margin-left:auto}
@media(max-width:640px){ .upsell .btn{margin-left:0;width:100%} }

/* ================= EMPTY STATE ================= */
.empty{
  display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center;
  padding:clamp(34px,6vw,64px) 24px;border-radius:var(--r-card);
  border:1px dashed var(--eb-line);background:var(--eb-surface);
}
.empty__ico{
  width:56px;height:56px;border-radius:16px;display:grid;place-items:center;
  background:var(--eb-surface-2);color:var(--eb-muted);
}
.empty__ico svg{width:26px;height:26px}
.empty h3{font-size:var(--t-xl)}
.empty p{color:var(--eb-muted);font-size:var(--t-md);max-width:52ch}

/* ================= MODAL ================= */
.scrim{
  position:fixed;inset:0;z-index:200;display:none;place-items:center;padding:20px;
  background:rgba(3,6,14,.72);backdrop-filter:blur(6px);
}
.scrim.on{display:grid}
.modal{
  width:min(520px,100%);max-height:90vh;overflow:auto;
  background:var(--eb-surface);border:1px solid var(--eb-line);
  border-radius:20px;box-shadow:var(--shadow-pop);padding:24px;
  animation:rise 260ms var(--ease);
}
@keyframes rise{from{opacity:0;transform:translateY(14px) scale(.97)}to{opacity:1;transform:none}}
.modal__x{position:absolute;top:14px;right:14px}

/* ================= REVIEW BAR (mockup-only) ================= */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

/* ================= MOBILE ================= */
@media(max-width:820px){
  .hdr__nav{display:none}
  .hdr__in{height:58px;gap:8px;min-width:0}


  .sec{padding:26px 0}
  .grid-videos{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:11px}
  .vid__body{padding:10px 11px 11px}
  .vid__text{-webkit-line-clamp:2;font-size:var(--t-xs)}
  .grid-subjects{grid-template-columns:1fr;gap:12px}
}
/* Shed header chips by value as width drops — the brand mark and EP balance
   always survive; tier is inferable, days-left is the first to go. */
@media(max-width:560px){ .chip--tier{display:none} }
@media(max-width:430px){ .chip--days{display:none} }
@media(max-width:400px){
  .grid-videos{grid-template-columns:1fr 1fr}
}
/* belt-and-braces: nothing may widen the page on a phone */
html,body{max-width:100%}
.shell{max-width:100%}

/* A closed hub pointing at where its videos actually live. The <a> has to sit
   above .is-soon's pointer-events:none, or the one useful link on a dead card
   is itself dead. */
.subj__detour{margin-top:10px;padding-top:10px;border-top:1px solid var(--eb-line-soft);
  font-size:var(--t-xs);line-height:1.55;color:var(--eb-muted)}
.subj__detour a{color:hsl(var(--hue) 88% 68%);font-weight:700;white-space:nowrap;
  pointer-events:auto;position:relative;z-index:2}
.card.subj.is-soon .subj__detour a{pointer-events:auto}
.tag--soft{color:var(--eb-muted);border-style:dashed}
.tag--soft svg{width:12px;height:12px;vertical-align:-2px}

/* ════════════════════════════════════════════════════════════════════════
   1st Sem instructor notes — the rows inside the Notes card on cc1/cc2,
   and the three modal levels behind them (instructor -> set -> player).
   Shared, because the two subject pages must not drift apart.
   ════════════════════════════════════════════════════════════════════════ */

/* the player. Was page-local to the video library; the notes modal needs the
   same box, so it lives here now and the library keeps its own copy harmlessly. */
.player{position:relative;aspect-ratio:16/9;border-radius:var(--r-ctl);overflow:hidden;
  background:#000;border:1px solid var(--eb-line-soft)}
.player iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* ---- level 1: rows in the card ---- */
/* minmax(0,1fr), not the implicit `auto`: an auto track takes its floor from the
   row's MIN-CONTENT, so a long sub-line (CC2's "MODULE 1 · 20 problems") pushed
   every row 63px past the card and cut the count off the right edge. */
.nrows{display:grid;grid-template-columns:minmax(0,1fr);gap:7px;margin-top:2px}
.nrow{display:flex;align-items:center;gap:11px;width:100%;text-align:left;cursor:pointer;
  padding:9px 11px;border-radius:var(--r-ctl);font:inherit;color:inherit;
  background:var(--eb-surface-2);border:1px solid var(--eb-line-soft);
  transition:var(--dur) var(--ease)}
.nrow:hover{border-color:hsl(var(--nh,266) 80% 60% / .55);transform:translateX(2px)}
.nrow__av{width:32px;height:32px;flex:0 0 auto;border-radius:10px;display:grid;place-items:center;
  font-family:'Space Grotesk';font-size:var(--t-xs);font-weight:800;letter-spacing:.02em;
  color:hsl(var(--nh,266) 92% 72%);background:hsl(var(--nh,266) 88% 56% / .16);
  border:1px solid hsl(var(--nh,266) 88% 60% / .34)}
.nrow__nm{min-width:0;flex:1}
.nrow__nm b{display:block;font-size:var(--t-md);font-weight:700;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nrow__sub{display:block;font-size:var(--t-xs);color:var(--eb-muted);line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nrow__stat{flex:0 0 auto;text-align:right}
.nrow__stat b{display:block;font-family:'Space Grotesk';font-size:var(--t-md);font-weight:700;line-height:1.1}
.nrow__stat span{display:block;font-size:9px;text-transform:uppercase;letter-spacing:.08em;color:var(--eb-muted)}
.nrow__go{flex:0 0 auto;width:15px;height:15px;color:var(--eb-muted);display:grid;place-items:center}
.nrow__go svg{width:15px;height:15px}
/* The CC2 card's sixth row is the mock exam, and it LEAVES the card while every
   other row goes one level deeper. It carries an icon in the avatar slot rather
   than a number or a pair of initials, and a tinted edge so the eye reads it as
   a different kind of thing without a heading to say so. */
.nrow--go{background:linear-gradient(180deg,hsl(var(--nh,274) 88% 56% / .14),var(--eb-surface-2));
  border-color:hsl(var(--nh,274) 80% 60% / .38)}
.nrow--go .nrow__av svg{width:17px;height:17px}
/* A module row truncates to "Resultant of Forces & …" and loses nothing — the
   number in the avatar already identifies it. This row's NAME is the thing, and
   on a 390px phone the shared ellipsis cut it to "Mock Departmental …", which
   could be anything. So this one row wraps instead. */
.nrow--go .nrow__nm b,
.nrow--go .nrow__sub{white-space:normal;overflow:visible;text-overflow:clip}
.nrow--go .nrow__nm b{line-height:1.2}
.nrow--go .nrow__sub{margin-top:2px}

/* Locked: the name stays, every content signal goes. With no number above it,
   "Locked" has to carry the slot on its own, so it stops being the 9px caption
   that sat under a figure and becomes the label itself. */
.nrows--locked .nrow__stat span{font-size:var(--t-xs);font-weight:700;letter-spacing:.04em;
  text-transform:none;color:var(--eb-muted)}
.nrows--locked .nrow{cursor:pointer}
.nrows--locked .nrow:hover{transform:none;border-color:hsl(var(--nh,266) 80% 60% / .38)}
[data-theme="light"] .nrow__av{color:hsl(var(--nh,266) 70% 40%)}

/* The provenance + "send me the next one" line under the rows. Deliberately
   quiet — it is an aside, not a CTA competing with the rows above it. */
.nnote{font-size:var(--t-xs);line-height:1.6;color:var(--eb-muted);margin-top:4px;
  padding:10px 12px;border-radius:var(--r-ctl);
  background:var(--eb-surface-2);border:1px dashed var(--eb-line-soft)}

/* ---- a time-boxed free window on one instructor (notesFree in notes-ui.js) ----
   The row is lit from inside in its own hue and a soft ring breathes round it,
   so it is the thing a scrolling thumb stops on. The ribbon is a flex item at
   100% basis: the row keeps its one-line shape above it, and a 390px phone never
   has to fit the name, the tag and the clock on one line. */
.nrow--free{flex-wrap:wrap;row-gap:8px;
  background:linear-gradient(135deg,hsl(var(--nh,150) 88% 50% / .22),hsl(var(--nh,150) 88% 50% / .06) 60%,var(--eb-surface-2));
  border-color:hsl(var(--nh,150) 85% 58% / .8);
  box-shadow:0 0 0 1px hsl(var(--nh,150) 85% 58% / .3),0 8px 24px -10px hsl(var(--nh,150) 90% 50% / .6);
  animation:nfreeGlow 2.6s ease-in-out infinite}
@keyframes nfreeGlow{
  0%,100%{box-shadow:0 0 0 1px hsl(var(--nh,150) 85% 58% / .3),0 8px 24px -10px hsl(var(--nh,150) 90% 50% / .6)}
  50%{box-shadow:0 0 0 4px hsl(var(--nh,150) 85% 58% / .14),0 10px 32px -8px hsl(var(--nh,150) 90% 50% / .85)}}
@media (prefers-reduced-motion:reduce){ .nrow--free{animation:none} }
.nrow--free:hover,
.nrows--locked .nrow--free:hover{border-color:hsl(var(--nh,150) 85% 64%);transform:translateX(2px)}
.nrow--free .nrow__av{background:hsl(var(--nh,150) 88% 50% / .3);border-color:hsl(var(--nh,150) 88% 60% / .65)}
.nrow--free .nrow__go{color:hsl(var(--nh,150) 90% 68%)}
/* Inside a locked card the stat caption is restyled into the "Locked" label. A
   free row carries a real count, so it gets the ordinary small caption back. */
.nrows--locked .nrow--free .nrow__stat span{font-size:9px;font-weight:400;letter-spacing:.08em;
  text-transform:uppercase}

.nfree{flex:1 0 100%;display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;
  padding:7px 9px;border-radius:9px;font-size:var(--t-xs);line-height:1.35;
  background:hsl(var(--nh,150) 88% 50% / .13);border:1px dashed hsl(var(--nh,150) 85% 60% / .55)}
.nfree__tag{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:var(--r-pill);
  font-size:10.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;line-height:1.3;
  color:#04140d;background:hsl(var(--nh,150) 78% 54%);white-space:nowrap}
.nfree__tag svg{width:11px;height:11px;flex:0 0 auto}
.nfree__until{color:var(--eb-muted);flex:1 1 auto;min-width:0}
.nfree__clock{display:inline-flex;align-items:center;gap:5px;margin-left:auto;white-space:nowrap;
  font-weight:700;color:hsl(var(--nh,150) 90% 70%)}
.nfree__clock svg{width:13px;height:13px;flex:0 0 auto}
.nfree__clock b{font-family:'Space Grotesk';font-variant-numeric:tabular-nums;font-size:var(--t-sm)}
[data-theme="light"] .nfree__clock,
[data-theme="light"] .nrow--free .nrow__go{color:hsl(var(--nh,150) 70% 30%)}

/* The same window, said again inside the drill-in, with the clock. */
.nfreebar{margin:0 0 12px;padding:11px 13px;border-radius:var(--r-ctl);
  background:linear-gradient(135deg,hsl(var(--nh,150) 88% 50% / .2),hsl(var(--nh,150) 88% 50% / .05));
  border:1px solid hsl(var(--nh,150) 85% 58% / .6)}
.nfreebar p{font-size:var(--t-sm);line-height:1.75;color:var(--eb-muted)}
.nfreebar p b{color:var(--eb-ink)}
.nfreebar .nfree__tag{margin-right:4px;vertical-align:1px}
.nfreebar .nfree__clock{margin-left:4px;vertical-align:-1px}
.nfreebar .nfree__clock b{color:hsl(var(--nh,150) 90% 70%)}
.nfreebar__more{display:inline-flex;align-items:center;gap:6px;margin-top:6px;padding:0;
  background:none;border:0;font:inherit;font-size:var(--t-xs);font-weight:700;line-height:1.5;
  text-align:left;cursor:pointer;color:hsl(var(--nh,150) 90% 70%)}
.nfreebar__more svg{width:13px;height:13px;flex:0 0 auto}
[data-theme="light"] .nfreebar .nfree__clock b,
[data-theme="light"] .nfreebar__more{color:hsl(var(--nh,150) 70% 30%)}

/* ---- level 2: the instructor sheet ---- */
.nhead{display:flex;align-items:center;gap:13px;margin-bottom:14px;padding-right:34px}
.nhead__av{width:46px;height:46px;flex:0 0 auto;border-radius:14px;display:grid;place-items:center;
  font-family:'Space Grotesk';font-size:var(--t-md);font-weight:800;
  color:hsl(var(--nh,266) 92% 72%);background:hsl(var(--nh,266) 88% 56% / .16);
  border:1px solid hsl(var(--nh,266) 88% 60% / .34)}
[data-theme="light"] .nhead__av{color:hsl(var(--nh,266) 70% 40%)}

.nnotice{font-size:var(--t-sm);line-height:1.6;color:var(--eb-muted);margin-bottom:14px;
  padding:11px 13px;border-radius:var(--r-ctl);background:var(--eb-surface-2);
  border:1px dashed var(--eb-line-soft)}
.nnotice b{color:var(--eb-ink)}
.nprose{font-size:var(--t-md);line-height:1.6;color:var(--eb-muted);margin-bottom:16px}

/* Says what the sets ARE, before one is opened. The drill-in behind them looks
   like the video library on purpose, and a library-looking grid reads as "videos
   about this topic" — this line is what makes it read as "your handout". */
.nlead{display:flex;gap:10px;align-items:flex-start;font-size:var(--t-sm);line-height:1.6;
  color:var(--eb-muted);margin:0 0 12px;padding:11px 13px;border-radius:var(--r-ctl);
  background:hsl(var(--nh,266) 88% 56% / .1);
  border:1px solid hsl(var(--nh,266) 88% 60% / .28)}
.nlead b{color:var(--eb-ink)}
.nlead svg{width:17px;height:17px;flex:0 0 auto;margin-top:1px;color:hsl(var(--nh,266) 92% 72%)}
[data-theme="light"] .nlead svg{color:hsl(var(--nh,266) 70% 40%)}

.nsets{display:grid;gap:7px;max-height:min(56vh,460px);overflow-y:auto;
  margin:0 -4px;padding:0 4px}
.nset{display:flex;align-items:center;gap:11px;width:100%;text-align:left;cursor:pointer;
  padding:10px 12px;border-radius:var(--r-ctl);font:inherit;color:inherit;
  background:var(--eb-surface-2);border:1px solid var(--eb-line-soft);
  transition:var(--dur) var(--ease)}
.nset:hover{border-color:hsl(var(--nh,266) 80% 60% / .55)}
.nset__code{flex:0 0 auto;font-family:'Space Grotesk';font-size:var(--t-xs);font-weight:800;
  padding:4px 8px;border-radius:var(--r-pill);color:hsl(var(--nh,266) 92% 72%);
  background:hsl(var(--nh,266) 88% 56% / .14);white-space:nowrap}
.nset__nm{min-width:0;flex:1}
.nset__nm b{display:block;font-size:var(--t-md);font-weight:600;line-height:1.3}
.nset__nm span{font-size:var(--t-xs);color:var(--eb-muted)}
.nset__go{flex:0 0 auto;width:15px;height:15px;color:var(--eb-muted)}
.nset__go svg{width:15px;height:15px}

.nback{display:inline-flex;align-items:center;gap:6px;background:none;border:0;cursor:pointer;
  font:inherit;font-size:var(--t-sm);font-weight:700;color:var(--eb-muted);
  padding:0;margin-bottom:12px;transition:var(--dur)}
.nback:hover{color:var(--eb-ink)}
.nback svg{width:14px;height:14px}

/* ---- level 3: a set's problems, as a mini video library ----
   Marvin, 2026-08-19. The drill-in used to be a grid of small picture tiles. It
   is now the LIBRARY's card — same .vid markup, same figure box, same
   difficulty chip, same heart — so a student who has learned one surface has
   learned both. What this one adds is the handout's own headings and the
   question number, because here the paper in their hand is the index. */

/* The problem grid is the one picture-first modal, so it gets a wider box than
   the 520px the text modals use — at 520px the thumbnails were too small to
   read, which is the whole reason they are there. */
.modal--wide{width:min(1040px,100%)}
/* The player is between the two: the grid's 1040px puts a 16:9 frame 585px tall
   and pushes Save and Share off a laptop screen, while the text modal's 520px
   makes a worked board too small to read. */
.modal--player{width:min(760px,100%)}

.nlhead{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap;margin:0 0 13px}
.nlhead h3{font-family:'Space Grotesk';font-size:var(--t-xl);line-height:1.15}
.nlhead p{font-size:var(--t-sm);color:var(--eb-muted);margin-top:5px;max-width:62ch;line-height:1.55}
.nlhead__n{flex:0 0 auto;text-align:right}
.nlhead__n b{display:block;font-family:'Space Grotesk';font-size:var(--t-2xl);font-weight:700;
  line-height:1;color:hsl(var(--nh,266) 92% 72%);font-variant-numeric:tabular-nums}
.nlhead__n span{display:block;font-size:9px;text-transform:uppercase;letter-spacing:.1em;
  color:var(--eb-muted);margin-top:3px}
[data-theme="light"] .nlhead__n b{color:hsl(var(--nh,266) 70% 40%)}

/* Search + difficulty, the library's controls at modal scale. No subject rail:
   a set IS one subject, so the only filters that can still narrow it are these. */
.nfbar{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin:0 0 12px}
.nfsearch{margin:0;flex:1 1 190px;min-width:0}
.nfsearch input{min-height:42px}
.nfchips{display:flex;gap:7px;flex-wrap:wrap}
.nfchips .fchip{min-height:38px}

/* The scroller is the WHOLE list, not each grid — with a heading between every
   run of cards, per-grid scrollbars would cut the sections into little windows. */
.nlib{max-height:min(62vh,640px);overflow-y:auto;margin:0 -4px;padding:0 4px 2px}
@media(max-width:640px){ .nlib{max-height:none} }

/* One printed heading off the handout. Sticky, because the whole point is that a
   student scrolling past card forty still knows whether they are in the lecture
   list or the practice run — both of which are numbered from 1. */
.nsec{position:sticky;top:0;z-index:2;margin:16px 0 10px;padding:9px 2px 7px;
  background:var(--eb-surface);border-bottom:1px solid var(--eb-line-soft)}
.nsec:first-child{margin-top:2px}
.nsec h4{display:flex;align-items:center;gap:9px;font-family:'Space Grotesk';
  font-size:var(--t-md);font-weight:700;line-height:1.2}
.nsec__n{font-family:'Space Grotesk';font-size:var(--t-xs);font-weight:800;
  padding:2px 8px;border-radius:var(--r-pill);color:var(--eb-muted);
  background:var(--eb-surface-2);border:1px solid var(--eb-line-soft)}
.nsec p{font-size:var(--t-xs);color:var(--eb-muted);margin-top:3px;line-height:1.5}

/* Desktop: ~250px tiles, so a 1040px modal shows three big ones per row rather
   than three cramped ones. Phones get ONE column (Marvin, 2026-08-13) — 2-up on
   a 390px screen left each thumbnail ~140px wide, far too small to read a
   problem statement off. */
.ngrid{display:grid;gap:11px;grid-template-columns:repeat(auto-fill,minmax(min(100%,250px),1fr))}
@media(max-width:640px){ .ngrid{grid-template-columns:1fr} }

/* Same rule the library card follows: our own 16:9 Manim title frames get the
   21:10 box that crops the logo band off and fills, so the title renders about
   40% larger on a phone; anything else keeps 4:3 and letterboxes inside it. */
.ngrid .vid__fig{aspect-ratio:4/3}
.ngrid .vid__fig--frame{aspect-ratio:21/10}
.ngrid .vid__fig--frame img{object-fit:cover;object-position:top center;padding:0}

/* The number off the handout, leading the topic line. It was on the figure
   first and that was wrong: our own title frames carry the problem title across
   the top, and a badge in the corner ate the first letter of every one. */
.nvid__no{display:inline-grid;place-items:center;min-width:21px;height:21px;padding:0 6px;
  margin-right:7px;vertical-align:-5px;border-radius:var(--r-pill);
  font-family:'Space Grotesk';font-size:11px;font-weight:800;letter-spacing:0;
  color:hsl(var(--nh,266) 92% 74%);background:hsl(var(--nh,266) 88% 56% / .18);
  border:1px solid hsl(var(--nh,266) 88% 60% / .4)}
[data-theme="light"] .nvid__no{color:hsl(var(--nh,266) 70% 38%)}
.nvid .vid__topic{line-height:1.5}
.nvid__t{font-size:var(--t-sm);font-weight:700;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.nvid .vid__text{-webkit-line-clamp:3}
.nvid .vid__body{gap:6px}

/* A problem whose video has not been recorded yet. It keeps its thumbnail —
   statement on top, figure under it — because that is the half a student can
   already use; it just must not look like it will play. No hover lift, no play
   dot, no heart, and the figure sits back a little so a grid reads at a glance
   as "these five are ready, those fifteen are coming". */
.nvid--soon{cursor:default}
.nvid--soon:hover{transform:none;border-color:var(--eb-line-soft)}
.nvid--soon .vid__fig{filter:saturate(.9)}
.nvid--soon .vid__fig::after{content:"";position:absolute;inset:0;background:rgba(12,18,32,.05)}
[data-theme="light"] .nvid--soon .vid__fig::after{background:rgba(12,18,32,.045)}
.nsoon{
  margin-left:auto;display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-xs);font-weight:700;padding:3px 9px;border-radius:var(--r-pill);
  color:hsl(38 92% 62%);background:hsl(38 92% 56% / .14);border:1px solid hsl(38 92% 58% / .34);
}
[data-theme="light"] .nsoon{color:hsl(32 84% 36%);background:hsl(38 92% 56% / .16)}
.nsoon svg{width:13px;height:13px;flex:0 0 auto}

/* Same figure, different given values. Deliberately NOT amber — amber is "no
   video yet", and this card does play. Cyan reads as a note rather than a
   warning, which is right: the video is useful, it just ends on a different
   number. It sits at the LEFT of the foot and takes no margin-left:auto, so the
   heart keeps the single auto margin that pins it right (see the note below).
   The foot is a flex row and this chip is its long item. It WRAPS rather than
   ellipsising: at 360px "Video solves P = 50 kN, and the reaction at D" truncated
   to "…and the r", which throws away the half a student actually needs. A note
   is allowed to be two lines; the heart keeps its auto margin and stays pinned
   right, the foot just gets taller. */
.nvary{
  display:inline-block;min-width:0;line-height:1.45;
  font-size:var(--t-xs);font-weight:700;padding:3px 9px;border-radius:12px;
  color:hsl(190 80% 62%);background:hsl(190 80% 52% / .13);border:1px solid hsl(190 80% 56% / .32);
}
[data-theme="light"] .nvary{color:hsl(196 78% 30%);background:hsl(190 80% 52% / .15)}
.nvary svg{width:13px;height:13px;vertical-align:-2px;margin-right:4px}

/* ---- the player, below the frame ----
   The same three rows the library's player shows, so the two do not drift: the
   tags, the statement, then the actions. Page-local in the library HTML before
   this; the notes modal needs them too, and the library's own copy is a
   harmless duplicate. */
.pmeta{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
.ptitle{font-size:var(--t-md);font-weight:700;line-height:1.4;margin:0 0 6px}
.pstate{font-size:var(--t-md);line-height:1.6;color:var(--eb-ink);margin-bottom:14px;
  max-height:34vh;overflow:auto}
.nalso{font-size:var(--t-xs);line-height:1.6;color:var(--eb-muted);margin:-6px 0 14px;
  padding:9px 12px;border-radius:var(--r-ctl);
  background:var(--eb-surface-2);border:1px dashed var(--eb-line-soft)}
.nalso b{color:var(--eb-ink)}
/* Flex, not a fixed grid: the production build strips the off-site link out of
   the library's row, and a grid-template-columns rule would leave the remaining
   buttons parked in the wrong columns once it goes. The phrase that link carries
   is banned in shipped bytes — do not name it in a comment either. */
.pactions{display:flex;gap:9px;flex-wrap:wrap}
.pactions .btn{flex:1 1 140px;justify-content:center}

/* ---------- production header (authored: /lessons/ is a static dir, so the
   ebora-site-header.php mu-plugin never runs here) ---------- */
.eb-hdr{position:sticky;top:0;z-index:200;background:color-mix(in oklab,var(--eb-bg) 88%,transparent);
  backdrop-filter:blur(14px);border-bottom:1px solid var(--eb-line-soft)}
.eb-hdr__in{max-width:1240px;margin:0 auto;padding:0 clamp(14px,3vw,26px);height:62px;
  display:flex;align-items:center;gap:18px}
.eb-hdr__brand{display:flex;align-items:center;gap:9px;font-family:'Space Grotesk';
  font-weight:700;font-size:var(--t-lg);text-decoration:none;color:var(--eb-ink)}
.eb-hdr__mark{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--eb-accent),var(--eb-cyan));color:#fff;font-size:15px}
.eb-hdr__nav{display:flex;gap:4px;margin-left:8px}
.eb-hdr__nav a{padding:7px 13px;border-radius:var(--r-pill);font-size:var(--t-sm);
  font-weight:600;color:var(--eb-muted);text-decoration:none}
.eb-hdr__nav a:hover{color:var(--eb-ink)}
.eb-hdr__nav a.is-on{background:var(--eb-surface-2);color:var(--eb-ink)}
.eb-hdr__right{margin-left:auto;display:flex;align-items:center;gap:8px}
.eb-hdr__chip{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;
  border-radius:var(--r-pill);font-size:var(--t-xs);font-weight:700;
  border:1px solid var(--eb-line);color:var(--eb-muted)}
.eb-hdr__chip.is-on{color:var(--eb-green);border-color:color-mix(in oklab,var(--eb-green) 40%,transparent)}
.eb-hdr__chip svg{width:13px;height:13px}
.eb-hdr__cta{padding:7px 15px;border-radius:var(--r-pill);font-size:var(--t-xs);font-weight:700;
  background:var(--eb-accent);color:#fff;text-decoration:none;white-space:nowrap}
.eb-hdr__ico{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  background:none;border:1px solid var(--eb-line);color:var(--eb-muted);cursor:pointer}
.eb-hdr__ico svg{width:16px;height:16px}
.eb-hdr__burger{display:none}
.eb-hdr__drawer{display:none;flex-direction:column;gap:2px;padding:8px clamp(14px,3vw,26px) 14px;
  border-top:1px solid var(--eb-line-soft)}
.eb-hdr__drawer a{padding:11px 13px;border-radius:var(--r-ctl);font-size:var(--t-md);
  font-weight:600;color:var(--eb-muted);text-decoration:none}
.eb-hdr__drawer a.is-on{background:var(--eb-surface-2);color:var(--eb-ink)}
/* The mockup header had NO mobile nav at all — .hdr__nav{display:none} below
   820px with no hamburger. This one has one. */
@media(max-width:820px){
  .eb-hdr__nav{display:none}
  .eb-hdr__burger{display:grid}
  body.eb-nav-open .eb-hdr__drawer{display:flex}
}
.tierrow{display:flex;align-items:center;gap:10px;padding:10px 13px;border-radius:var(--r-ctl);
  background:var(--eb-surface-2);border:1px solid var(--eb-line-soft);font-size:var(--t-sm)}
.tierrow b:last-child{margin-left:auto}


/* ===================================================================
   SITE HEADER — lifted verbatim from ebora-site-header.php at build time.
   Do not edit here; edit the mu-plugin and rebuild.
   =================================================================== */
.eb-hdr, .eb-hdr * { box-sizing: border-box; }
.eb-hdr {
  --eb-bg:#070b16; --eb-bg-2:#0c1326; --eb-blue:#2f6bff; --eb-cyan:#38bdf8;
  --eb-ink:#eef3ff; --eb-muted:#9fb0d0; --eb-line:rgba(132,166,255,.22);
  position: sticky; top: 0; z-index: 1000; width: 100%;
  font-family: "Space Grotesk", "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
  background: #070b16;
  border-bottom: 1px solid var(--eb-line);
  box-shadow: 0 10px 30px -22px rgba(0,0,0,.9);
  -webkit-font-smoothing: antialiased;
  transition: transform .28s ease;   /* for auto-hide on scroll */
  will-change: transform;
}
.eb-hdr.eb-hdr--hidden { transform: translateY(-100%); }
.eb-hdr__inner { max-width: 1840px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 11px clamp(18px,4vw,84px); min-height: 64px; }
.eb-hdr__brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--eb-ink); flex: 0 1 auto; min-width: 0; }
.eb-hdr__mark { flex: none; width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font-family: "Space Grotesk", sans-serif; font-weight: 700; font-size: 22px; color: #fff; background: linear-gradient(135deg, var(--eb-blue), var(--eb-cyan)); box-shadow: 0 6px 18px -6px rgba(47,107,255,.7); }
.eb-hdr__logo { flex: none; width: 40px; height: 40px; object-fit: cover; border-radius: 11px; display: block; }
.eb-hdr__name { font-family: "Space Grotesk", sans-serif; font-weight: 600; font-size: clamp(15px,1.3vw,19px); letter-spacing: -.01em; color: var(--eb-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eb-hdr__nav { display: flex; align-items: center; gap: clamp(14px,1.8vw,30px); }
.eb-hdr__link { position: relative; font-family: "Space Grotesk", sans-serif; font-weight: 500; font-size: 15px; color: var(--eb-muted); text-decoration: none; padding: 6px 2px; transition: color .18s ease; }
.eb-hdr__link:hover, .eb-hdr__link.is-active { color: var(--eb-ink); }
.eb-hdr__link::after { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 2px; background: var(--eb-cyan); transform: scaleX(0); transform-origin: left; transition: transform .2s ease; }
.eb-hdr__link:hover::after, .eb-hdr__link.is-active::after { transform: scaleX(1); }
.eb-hdr__btn { font-family: "Space Grotesk", sans-serif; font-weight: 600; font-size: 15px; color: #fff; text-decoration: none; white-space: nowrap; padding: 10px 20px; border-radius: 10px; background: linear-gradient(135deg, var(--eb-blue), #4f86ff); box-shadow: 0 8px 22px -10px rgba(47,107,255,.85), inset 0 1px 0 rgba(255,255,255,.25); transition: transform .15s ease, box-shadow .2s ease; }
.eb-hdr__btn:hover { transform: translateY(-2px); box-shadow: 0 14px 28px -10px rgba(47,107,255,.95), inset 0 1px 0 rgba(255,255,255,.3); }
/* Video-access days-left chip (shown only to active cc2 subscribers). margin-left:auto
   pushes it + the nav to the right while the brand stays left — so it stays visible on
   mobile, sitting just left of the hamburger. */
.eb-hdr__sub { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; flex: none; font-family: "Space Grotesk", sans-serif; font-weight: 600; font-size: 13px; color: #bfe3ff; text-decoration: none; white-space: nowrap; padding: 7px 13px; border-radius: 999px; background: rgba(56,189,248,.12); border: 1px solid rgba(56,189,248,.35); transition: background .18s ease, color .18s ease; }
.eb-hdr__sub:hover { background: rgba(56,189,248,.2); color: #eaf6ff; }
.eb-hdr__sub--low { color: #ffd9b0; background: rgba(245,158,11,.14); border-color: rgba(245,158,11,.45); }
/* Final 24 hours — red, and the counter breathes. A student on the last day has to
   notice without being told, and the amber ≤5-day state is not distinct enough once
   the number has switched from days to hours. */
.eb-hdr__sub--crit { color: #ffd2da; background: rgba(255,59,92,.16); border-color: rgba(255,59,92,.55); }
.eb-hdr__sub--crit:hover { background: rgba(255,59,92,.26); color: #fff; }
/* The countdown pill inside the tier chip: "✓ Ancient Supporter [12d]". */
.eb-hdr__days { flex: none; margin-left: 1px; padding: 2px 7px; border-radius: 999px; font-weight: 800; font-size: 11.5px; letter-spacing: .01em; line-height: 1.45; font-variant-numeric: tabular-nums;
  color: #eaf6ff; background: rgba(56,189,248,.22); box-shadow: inset 0 0 0 1px rgba(56,189,248,.32); }
.eb-hdr__sub--low  .eb-hdr__days { color: #fff1dc; background: rgba(245,158,11,.28); box-shadow: inset 0 0 0 1px rgba(245,158,11,.5); }
.eb-hdr__sub--crit .eb-hdr__days { color: #fff; background: rgba(255,59,92,.42); box-shadow: inset 0 0 0 1px rgba(255,59,92,.7); animation: eb-days-pulse 1.9s ease-in-out infinite; }
@keyframes eb-days-pulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .eb-hdr__sub--crit .eb-hdr__days { animation: none; } }
/* chips group (days-left + notes) — stays right of the brand, left of the hamburger.
   The .eb-hdr__chat and .eb-hdr__chat-badge rules that lived here went with the chat chips
   on 2026-08-25; the bubble (ebora-chat-dock.php) styles its own badge. */
.eb-hdr__chips { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; flex: none; }
.eb-hdr__chips .eb-hdr__sub { margin-left: 0; }
/* Extra nav rows — backup entry points, shown ONLY in the mobile hamburger
   (the always-visible chip already covers desktop, so hide it there to avoid duplicates). */
.eb-hdr__navchat { display: none; }
/* CC2 Summer Notes chip — amber, to match the notes page's summer theme. */
.eb-hdr__notes { color:#ffe1bf; background:rgba(255,138,61,.16); border-color:rgba(255,138,61,.42); }
.eb-hdr__notes:hover { background:rgba(255,138,61,.28); color:#fff; }
/* Floating "Summer Notes" awareness bubble — shown to cc2 subscribers on every page except the notes page. */
.eb-notes-fab { position:fixed; right:16px; bottom:16px; z-index:1200; display:inline-flex; align-items:center; gap:8px; max-width:calc(100vw - 32px);
  font-family:"Space Grotesk","Manrope",system-ui,sans-serif; font-weight:700; font-size:14px; line-height:1.1; color:#10131c; text-decoration:none;
  padding:11px 14px; border-radius:999px; background:linear-gradient(135deg,#ff8a3d,#ffd24a);
  box-shadow:0 14px 32px -10px rgba(255,138,61,.75), 0 4px 12px rgba(0,0,0,.35);
  animation:eb-notes-pop .45s cubic-bezier(.2,.9,.3,1.3) both; }
.eb-notes-fab:hover { transform:translateY(-2px); box-shadow:0 18px 38px -10px rgba(255,138,61,.9), 0 6px 14px rgba(0,0,0,.4); }
.eb-notes-fab__ico { font-size:16px; flex:none; }
.eb-notes-fab__x { flex:none; margin-left:2px; width:20px; height:20px; border-radius:50%; display:grid; place-items:center; background:rgba(16,19,28,.18); color:#10131c; font-size:12px; font-weight:800; line-height:1; }
.eb-notes-fab__x:hover { background:rgba(16,19,28,.34); }
@keyframes eb-notes-pop { from { transform:translateY(14px) scale(.92); opacity:0 } to { transform:none; opacity:1 } }
@media (max-width:480px) { .eb-notes-fab { font-size:12.5px; padding:10px 12px; right:12px; bottom:12px; } }
.eb-hdr__toggle { display: none; }
@media (max-width: 880px) {
  .eb-hdr__toggle { display: inline-flex; flex-direction: column; justify-content: center; gap: 5px; width: 44px; height: 44px; padding: 11px; background: rgba(132,166,255,.06); border: 1px solid var(--eb-line); border-radius: 10px; cursor: pointer; flex: none; }
  .eb-hdr__toggle span { display: block; height: 2px; width: 100%; background: var(--eb-ink); border-radius: 2px; transition: transform .2s ease, opacity .2s ease; }
  .eb-hdr__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .eb-hdr__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .eb-hdr__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .eb-hdr__nav { position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: stretch; gap: 2px; background: #070b16; border-bottom: 1px solid var(--eb-line); padding: 8px clamp(18px,4vw,84px) 18px; transform: translateY(-10px); opacity: 0; pointer-events: none; transition: transform .2s ease, opacity .2s ease; }
  .eb-hdr__nav.is-open { transform: none; opacity: 1; pointer-events: auto; }
  .eb-hdr__link { padding: 13px 2px; font-size: 16px; }
  .eb-hdr__navchat { display: block; }
  .eb-hdr__link::after { display: none; }
  .eb-hdr__btn { margin-top: 10px; text-align: center; padding: 14px; font-size: 16px; }
}
@media (max-width: 880px) { .eb-hdr__name { font-size: 13px; } .eb-hdr__sub { font-size: 12px; padding: 6px 11px; margin-right: 8px; } }
@media (max-width: 480px) { .eb-hdr__sub .eb-hdr__sub-lbl { display: none; } }

/* Hub-only additions the mu-plugin has no need for: the current-page marker,
   the theme toggle, and the mobile drawer (the real header's own JS does not
   ship to a static directory, so the runtime wires the hamburger itself). */
.eb-hdr__link[aria-current]{color:var(--eb-ink)}
.eb-hdr__link[aria-current]::after{content:'';position:absolute;left:2px;right:2px;bottom:-2px;
  height:2px;border-radius:2px;background:linear-gradient(90deg,var(--eb-blue),var(--eb-cyan))}
.eb-hdr__ico{display:inline-grid;place-items:center;width:36px;height:36px;flex:none;
  border-radius:10px;border:1px solid var(--eb-line);background:transparent;
  color:var(--eb-muted);cursor:pointer;font-size:15px;line-height:1}
.eb-hdr__ico:hover{color:var(--eb-ink)}
@media (max-width:880px){
  .eb-hdr__nav{position:absolute;top:100%;left:0;right:0;display:none;flex-direction:column;
    align-items:flex-start;gap:2px;padding:10px clamp(18px,4vw,84px) 16px;
    background:#070b16;border-bottom:1px solid var(--eb-line)}
  body.eb-nav-open .eb-hdr__nav{display:flex}
}
