/* ============================================================================
   MEMORIZE MEDICINE — CANVAS OVERRIDE LAYER
   ----------------------------------------------------------------------------
   WHAT THIS FILE IS FOR, AND WHY IT IS SMALL NOW.

   In Pass 1 this file was the whole design system, loaded last so that it could
   outrank 4,159 lines of duplicated inline CSS on equal specificity. Pass 2
   extracted that duplicated block into `assets/app.css` and conformed it, so
   most of what used to be here is now stated once, in the right place, instead
   of being asserted twice.

   What is left is only what must still outrank a page's own <style> block.
   Load order is:

       assets/app.css      tokens, base, shared components
       <style> ... </style>page-bespoke CSS
       assets/canvas.css   THIS FILE — beats page-bespoke on equal specificity

   Anything that belongs to every page belongs in app.css. Put a rule here only
   when a page's inline stylesheet declares the same property on the same
   selector and has to lose. Each block below names the pages it is fighting.

   NO !important. Pass 1 shipped six — four of them on .float-card, fighting CSS
   it could have beaten on specificity, which is the exact trick Pass 1 itself
   had correctly avoided two hundred lines earlier for .btn.btn-x. Those four
   are gone, replaced by a selector that wins honestly. The two survivors in the
   reduced-motion block are gone too; app.css §3 now shortens durations rather
   than zeroing them, which is safer for panels whose visible state is an
   animation's end state.
   ========================================================================== */

/* --- body ---------------------------------------------------------------
   Every page declares `body{background:var(--bg);…;transition:background .3s}`
   inline. The transition has to lose: it smeared the entire page on every
   theme toggle, and it made colour auditing unreliable — the first Pass 2
   contrast run sampled mid-transition and reported 180 failures that were not
   real. The dot grid has to win, because it is the substrate the whole design
   sits on. Pages: all fifteen. */
html body{
  background-color:var(--paper);
  background-image:radial-gradient(circle at 1px 1px,var(--dot) 1.2px,transparent 1.3px);
  background-size:22px 22px;
  color:var(--text);
  font-family:var(--fb);
  font-size:15px; line-height:1.58;
  transition:none;
}

/* --- headings -----------------------------------------------------------
   Several pages restate the heading stack inline at 800 weight. Canvas tops
   out at 600; 800 in Space Grotesk reads as shouting at these sizes.
   Pages: admin, tutor, quiz, index, catalog, course, messages. */
h1,h2,h3,h4,.card-title,.topbar-title,.sect-title,.headline{
  font-family:var(--fd); font-weight:600; letter-spacing:-.011em; line-height:1.12;
}

/* --- atmosphere ---------------------------------------------------------
   index, catalog, course, login and payment each redeclare `.atmos` inline
   with the three blurred gradient orbs. Canvas keeps the dot grid only.
   Pages: index, catalog, course, login, payment, lecture-video. */
.atmos,[data-theme="light"] .atmos{
  background-color:var(--paper);
  background-image:radial-gradient(circle at 1px 1px,var(--dot) 1.2px,transparent 1.3px);
  background-size:22px 22px;
}
.atmos::before,[data-theme="light"] .atmos::before{content:none}
.orb{display:none}

/* --- progress -----------------------------------------------------------
   quiz and flashcards each carry their own `.progress`, `.progress-fill` and a
   `::after` shimmer keyframe. The shimmer has to go: a bar that is still
   moving after it has stopped filling reads as "still loading", which during a
   timed exam is a genuine misreading and not just a decoration.
   Pages: quiz, flashcards. */
.progress,[data-theme="light"] .progress{background:var(--surface-3);border-radius:0;height:6px}
.progress-fill{background:var(--brand);border-radius:0;box-shadow:none}
.progress-fill::after{content:none}

/* --- login split layout -------------------------------------------------
   The two feature cards were position:absolute at top:24%/right:8% and
   bottom:26%/right:16%, and at common laptop widths they landed on top of the
   <h1> — the headline was unreadable underneath "Exam-style blocks". They now
   sit in normal flow beneath the copy.

   Pass 1 did this with four !important declarations. It did not need them:
   login.html's rule is `.float-card` at (0,1,0), so `.float-strip .float-card`
   at (0,2,0) wins on its own. No content is lost; both cards keep their text
   and their icons. Page: login. */
.float-strip{display:flex;flex-wrap:wrap;gap:12px;margin-top:26px}
.float-strip .float-card{
  position:static; inset:auto; animation:none; transform:none;
  flex:1 1 240px; min-width:0;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-obj); box-shadow:var(--shadow);
  padding:12px 15px; font-size:13.5px; font-weight:600;
}
.float-strip .float-card::before{content:none}
.fc-icon{
  border-radius:var(--r-sm); background-color:var(--surface-3);
  background-image:var(--pat-hatch); box-shadow:none; border:1px solid var(--line);
}
.si-orange.fc-icon{background-image:var(--pat-stip)}
.si-green.fc-icon{background-image:var(--pat-cross)}

/* --- footer -------------------------------------------------------------
   index and catalog restate the footer inline. Page: index, catalog. */
.foot{border-top:1px solid var(--line)}
.foot .fcol b{
  font-family:var(--fm); font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; font-weight:500; color:var(--text3);
}
.foot .fcol a{color:var(--text2)}
.foot .fcol a:hover{color:var(--text)}
.foot-bottom{color:var(--text3);border-top:1px solid var(--line-2)}

/* --- the mark swaps with the theme -------------------------------------
   Two <img> stacked in one absolutely-positioned box; exactly one may be seen.

   Doing this with `display` starts a specificity arms race that cannot be won
   cleanly: index declares `.pnav-logo img{display:block}` at (0,1,1), messages
   declares `.threads-top .row a img{display:block}` at (0,3,1), and every page
   is free to add another. Pass 1 ended that race with !important; Pass 2's
   first attempt raised specificity twice and still lost on messages in dark,
   which is how the regression showed up -- BOTH marks rendered and the light
   one, later in the DOM, was the one on screen.

   `opacity` sidesteps it entirely: nothing anywhere in the app sets opacity on
   these images, so a single (0,2,0) rule wins on every page with no
   !important and no arms race. Pages: all fifteen. */
.lock-mark .logo-l{opacity:0;pointer-events:none}
.lock-mark .logo-d{opacity:1}
[data-theme="light"] .lock-mark .logo-l{opacity:1}
[data-theme="light"] .lock-mark .logo-d{opacity:0;pointer-events:none}

/* ===================== 18. EXTRACTED STYLE ATTRIBUTES ==================

   These classes exist for one reason: a CSP that does not carry
   'unsafe-inline' in style-src forbids the style="…" attribute, and this
   app had 758 of them. Each class below is the exact declaration list of
   an attribute that was removed, in its original order, so the cascade it
   participates in is unchanged.

   TWO KINDS.
     u-*   one declaration. Shared atomic utility. Safe to reuse anywhere.
     cs-*  a multi-declaration list lifted verbatim from one or more
           attributes. NOT a design token — a faithful copy. The comment
           on each says which pages used it.

   A style attribute has specificity (1,0,0,0) and a class has (0,0,1,0),
   so anywhere a page rule already set the same property on the same
   element, the attribute used to win and the class does not. Every one of
   these was checked against a before/after computed-style snapshot in both
   themes, blocked AND hydrated. See REDESIGN-PASS3.md §A.

   WHY canvas.css AND WHY EVERY SELECTOR IS DOUBLED.  This block was written
   into app.css first. app.css loads BEFORE each page inline <style>, so every
   class here lost to any page rule touching the same property and the snapshot
   reported 390 changed elements. Load order alone does not fix it — order only
   breaks ties at EQUAL specificity, and the rules winning were things like
   `.card h2` at (0,0,1,1). So the block lives in canvas.css, which is exactly
   what canvas.css is for, and each selector is written twice for (0,0,2,0).
   Class count is compared before element count, so (0,0,2,0) beats (0,0,1,1).
   No !important, which stays banned.

   The honest long-term move is to fold cs-* into real component classes as
   the design settles. They are numbered by frequency so the ones worth
   naming first are at the top.
   ===================================================================== */

/* --- atomic utilities ------------------------------------------------- */
.u-as-center.u-as-center{align-self:center}
.u-bdc-rgba-207-110-18-5.u-bdc-rgba-207-110-18-5{border-color:rgba(207,110,18,.5)}
.u-bdc-rgba-207-110-18-55.u-bdc-rgba-207-110-18-55{border-color:rgba(207,110,18,.55)}
.u-bdc-rgba-231-135-43-4.u-bdc-rgba-231-135-43-4{border-color:rgba(231,135,43,.4)}
.u-bdc-rgba-231-135-43-45.u-bdc-rgba-231-135-43-45{border-color:rgba(231,135,43,.45)}
.u-bg-blue.u-bg-blue{background:var(--blue)}
.u-bg-green.u-bg-green{background:var(--green)}
.u-bg-orange.u-bg-orange{background:var(--orange)}
.u-bg-x317ec2.u-bg-x317ec2{background:#317EC2}
.u-bg-x5aaa46.u-bg-x5aaa46{background:#5AAA46}
.u-bg-xe7872b.u-bg-xe7872b{background:#E7872B}
.u-bg-xe86a62.u-bg-xe86a62{background:#E86A62}
.u-bg-xf2c14e.u-bg-xf2c14e{background:#F2C14E}
.u-c-amber.u-c-amber{color:var(--amber)}
.u-c-green-hi.u-c-green-hi{color:var(--green-hi)}
/* R26 Pass 4 — ITEM D. This was `var(--red,#c0392b)`, a faithful copy of the
   original style attribute. `--red` is defined nowhere in either theme, so the
   fallback fired every time and the colour was #c0392b — a hex neither theme
   owns, unchanged between light and dark, and therefore invisible to
   dark-review only because dark-review reads tokens, not literals. Pass 3 kept
   it byte-faithful on purpose so the conversion stayed provably inert. It is
   folded into --crimson here, and this is the ONE element the Pass 4 snapshot
   is expected to move: student.html's `.small.u-c-red` denial reason.
   #c0392b -> #B93B42 light / #E8757C dark. */
.u-c-red.u-c-red{color:var(--crimson)}
.u-c-text2.u-c-text2{color:var(--text2)}
.u-c-text3.u-c-text3{color:var(--text3)}
.u-cur-pointer.u-cur-pointer{cursor:pointer}
.u-d-none.u-d-none{display:none}
.u-flex-1.u-flex-1{flex:1}
.u-fs-12-5px.u-fs-12-5px{font-size:12.5px}
.u-fs-12px.u-fs-12px{font-size:12px}
.u-fs-13-5px.u-fs-13-5px{font-size:13.5px}
.u-fs-13px.u-fs-13px{font-size:13px}
.u-fs-14px.u-fs-14px{font-size:14px}
.u-fs-15px.u-fs-15px{font-size:15px}
.u-fs-16px.u-fs-16px{font-size:16px}
.u-fs-17px.u-fs-17px{font-size:17px}
.u-fs-30px.u-fs-30px{font-size:30px}
.u-fsh-0.u-fsh-0{flex-shrink:0}
.u-fw-wrap.u-fw-wrap{flex-wrap:wrap}
.u-fwt-600.u-fwt-600{font-weight:600}
.u-gap-6px.u-gap-6px{gap:6px}
.u-gap-7px.u-gap-7px{gap:7px}
.u-gap-8px.u-gap-8px{gap:8px}
.u-gap-9px.u-gap-9px{gap:9px}
.u-gc-1-1.u-gc-1-1{grid-column:1/-1}
.u-gtc-1fr.u-gtc-1fr{grid-template-columns:1fr}
.u-h-40px.u-h-40px{height:40px}
.u-lh-1-9.u-lh-1-9{line-height:1.9}
.u-lh-2.u-lh-2{line-height:2}
.u-m-0.u-m-0{margin:0}
.u-m-0-0-8px.u-m-0-0-8px{margin:0 0 8px}
.u-m-10px-0-0-16px.u-m-10px-0-0-16px{margin:10px 0 0 16px}
.u-m-10px-0-4px.u-m-10px-0-4px{margin:10px 0 4px}
.u-m-12px-0-0.u-m-12px-0-0{margin:12px 0 0}
.u-m-18px-0-8px.u-m-18px-0-8px{margin:18px 0 8px}
.u-m-4px-0.u-m-4px-0{margin:4px 0}
.u-m-6px-0-14px.u-m-6px-0-14px{margin:6px 0 14px}
.u-m-6px-0-16px.u-m-6px-0-16px{margin:-6px 0 16px}
.u-m-8px-0.u-m-8px-0{margin:8px 0}
.u-maxw-130px.u-maxw-130px{max-width:130px}
.u-maxw-180px.u-maxw-180px{max-width:180px}
.u-maxw-200px.u-maxw-200px{max-width:200px}
.u-maxw-220px.u-maxw-220px{max-width:220px}
.u-maxw-280px.u-maxw-280px{max-width:280px}
.u-maxw-300px.u-maxw-300px{max-width:300px}
.u-maxw-460px.u-maxw-460px{max-width:460px}
.u-maxw-520px.u-maxw-520px{max-width:520px}
.u-mb-0.u-mb-0{margin-bottom:0}
.u-mb-10px.u-mb-10px{margin-bottom:10px}
.u-mb-12px.u-mb-12px{margin-bottom:12px}
.u-mb-14px.u-mb-14px{margin-bottom:14px}
.u-mb-4px.u-mb-4px{margin-bottom:4px}
.u-mb-5px.u-mb-5px{margin-bottom:5px}
.u-mb-6px.u-mb-6px{margin-bottom:6px}
.u-mb-7px.u-mb-7px{margin-bottom:7px}
.u-mb-8px.u-mb-8px{margin-bottom:8px}
.u-minw-130px.u-minw-130px{min-width:130px}
.u-mis-8px.u-mis-8px{margin-inline-start:8px}
.u-mis-auto.u-mis-auto{margin-inline-start:auto}
.u-ml-14px.u-ml-14px{margin-left:14px}
.u-ml-8px.u-ml-8px{margin-left:8px}
.u-ml-auto.u-ml-auto{margin-left:auto}
.u-mr-8px.u-mr-8px{margin-right:8px}
.u-mt-0.u-mt-0{margin-top:0}
.u-mt-10px.u-mt-10px{margin-top:10px}
.u-mt-14px.u-mt-14px{margin-top:14px}
.u-mt-26px.u-mt-26px{margin-top:26px}
.u-mt-5px.u-mt-5px{margin-top:5px}
.u-mt-8px.u-mt-8px{margin-top:8px}
.u-mt-9px.u-mt-9px{margin-top:9px}
.u-op-6.u-op-6{opacity:.6}
.u-op-85.u-op-85{opacity:.85}
.u-ovx-auto.u-ovx-auto{overflow-x:auto}
.u-p-10px-0.u-p-10px-0{padding:10px 0}
.u-p-12px-0.u-p-12px-0{padding:12px 0}
.u-p-14px-16px.u-p-14px-16px{padding:14px 16px}
.u-p-18px.u-p-18px{padding:18px}
.u-p-20px-20px-0.u-p-20px-20px-0{padding:20px 20px 0}
.u-p-5px-10px.u-p-5px-10px{padding:5px 10px}
.u-p-8px.u-p-8px{padding:8px}
.u-pl-18px.u-pl-18px{padding-left:18px}
.u-rz-vertical.u-rz-vertical{resize:vertical}
.u-ta-center.u-ta-center{text-align:center}
.u-ta-end.u-ta-end{text-align:end}
.u-ta-right.u-ta-right{text-align:right}
.u-td-none.u-td-none{text-decoration:none}
.u-td-underline.u-td-underline{text-decoration:underline}
.u-trs-stroke-dasharray-5s.u-trs-stroke-dasharray-5s{transition:stroke-dasharray .5s}
.u-trs-stroke-dasharray-5s-stroke-dashoffset-5s.u-trs-stroke-dasharray-5s-stroke-dashoffset-5s{transition:stroke-dasharray .5s,stroke-dashoffset .5s}
.u-trs-stroke-dashoffset-1-1s-cubic-bezier-2-7-3-1.u-trs-stroke-dashoffset-1-1s-cubic-bezier-2-7-3-1{transition:stroke-dashoffset 1.1s cubic-bezier(.2,.7,.3,1)}
.u-w-0pc.u-w-0pc{width:0%}
.u-w-110px.u-w-110px{width:110px}
.u-w-130px.u-w-130px{width:130px}
.u-w-240px.u-w-240px{width:240px}
.u-w-30pc.u-w-30pc{width:30%}
.u-w-78px.u-w-78px{width:78px}
.u-w-90px.u-w-90px{width:90px}
.u-w-auto.u-w-auto{width:auto}
.u-ws-nowrap.u-ws-nowrap{white-space:nowrap}

/* --- lifted declaration lists ----------------------------------------- */
/* 23×  admin.html, student.html, support.html, tutor.html */
.cs-1.cs-1{font-size:21px;font-weight:800}
/* 15×  admin.html, student.html, tutor.html */
.cs-2.cs-2{gap:8px;flex-wrap:wrap}
/* 13×  admin.html, qbank.html, student.html, tutor.html */
.cs-3.cs-3{flex:1;min-width:0}
/* 12×  admin.html, tutor.html */
.cs-4.cs-4{padding:6px 12px;font-size:11.5px}
/* 7×  admin.html, messages.html, tutor.html */
.cs-5.cs-5{font-weight:800;margin-bottom:12px}
/* 7×  admin.html, tutor.html */
.cs-6.cs-6{padding:5px 11px;font-size:11px}
/* 6×  admin.html, tutor.html */
.cs-7.cs-7{color:#e5484d;font-weight:800}
/* 6×  admin.html, tutor.html */
.cs-8.cs-8{gap:10px;margin-top:16px;flex-wrap:wrap}
/* 5×  admin.html, tutor.html */
.cs-9.cs-9{gap:10px;flex-wrap:wrap}
/* 5×  admin.html, catalog.html, student.html, support.html */
.cs-10.cs-10{grid-column:1/-1;text-align:center}
/* 4×  admin.html, qbank.html, student.html, tutor.html */
.cs-11.cs-11{display:flex;align-items:center;gap:10px}
/* 4×  admin.html, tutor.html */
.cs-12.cs-12{font-weight:800;margin-top:8px}
/* 3×  admin.html, flashcards.html, tutor.html */
.cs-13.cs-13{border:1px solid var(--stroke);border-radius:12px;background:var(--glass2);padding:13px 15px}
/* 3×  admin.html, flashcards.html, tutor.html */
.cs-14.cs-14{font-size:9.5px;font-weight:800;letter-spacing:1.4px;text-transform:uppercase}
/* 3×  admin.html, tutor.html */
.cs-15.cs-15{gap:6px;display:none}
/* 3×  admin.html, tutor.html */
.cs-16.cs-16{gap:8px;display:none}
/* 3×  messages.html, student.html */
.cs-17.cs-17{padding:18px;text-align:center}
/* 3×  messages.html */
.cs-18.cs-18{padding:26px 16px;text-align:center}
/* 3×  qbank.html */
.cs-19.cs-19{padding:4px 10px;font-size:11px}
/* 3×  login.html */
.cs-20.cs-20{text-align:center;margin-top:10px}
/* 3×  messages.html */
.cs-21.cs-21{width:100%;padding:11px;background:linear-gradient(120deg,var(--blue),var(--green));color:#fff;border:none}
/* 2×  admin.html, tutor.html */
.cs-22.cs-22{border:1px solid rgba(255,255,255,.14);border-radius:10px;padding:5px}
/* 2×  support.html, tutor.html */
.cs-23.cs-23{display:none;margin-top:10px}
/* 2×  admin.html, course.html */
.cs-24.cs-24{flex:1;font-size:12.5px;font-weight:700}
/* 2×  flashcards.html, tutor.html */
.cs-25.cs-25{flex:1;min-width:0;background:none;border:none;border-bottom:1px solid var(--stroke);color:inherit;font:inherit;padding:2px 4px}
/* 2×  course.html, qbank.html */
.cs-26.cs-26{font-size:12.5px;font-weight:700}
/* 2×  qbank.html, student.html */
.cs-27.cs-27{font-size:12.5px;line-height:1.65;color:var(--text2)}
/* 2×  student.html */
.cs-28.cs-28{font-size:30px;font-weight:800}
/* 2×  student.html */
.cs-29.cs-29{font-size:34px;margin-bottom:8px}
/* 2×  admin.html */
.cs-30.cs-30{font-weight:800;margin-bottom:4px}
/* 2×  qbank.html */
.cs-31.cs-31{gap:12px;flex-wrap:wrap}
/* 2×  admin.html, tutor.html */
.cs-32.cs-32{gap:4px;margin-top:5px;align-items:center}
/* 2×  student.html */
.cs-33.cs-33{gap:6px;margin-bottom:8px}
/* 2×  admin.html, tutor.html */
.cs-34.cs-34{gap:7px;align-items:flex-start}
/* 2×  admin.html */
.cs-35.cs-35{gap:8px;align-items:center;margin-bottom:12px;cursor:pointer}
/* 2×  admin.html */
.cs-36.cs-36{gap:8px;padding:7px 0;border-bottom:1px solid var(--stroke)}
/* 2×  tutor.html */
.cs-37.cs-37{height:100%;width:0%;border-radius:99px;background:linear-gradient(90deg,var(--orange),var(--orange-hi));transition:width .2s}
/* 2×  tutor.html */
.cs-38.cs-38{height:8px;background:var(--stroke);border-radius:99px;overflow:hidden}
/* 2×  admin.html */
.cs-39.cs-39{margin-bottom:6px;color:#e5484d}
/* 2×  qbank.html, quiz.html */
.cs-40.cs-40{margin-left:auto;font-family:var(--fm);font-size:10.5px;color:var(--text3);background:var(--glass2);border:1px solid var(--stroke);border-radius:20px;padding:2px 8px}
/* 2×  admin.html, tutor.html */
.cs-41.cs-41{margin:9px 0 0 18px;line-height:1.7}
/* 2×  admin.html, support.html */
.cs-42.cs-42{max-width:100%;max-height:230px;border-radius:10px;display:block}
/* 2×  admin.html, tutor.html */
.cs-43.cs-43{max-width:150px;max-height:120px;border-radius:8px;display:block}
/* 2×  admin.html, tutor.html */
.cs-44.cs-44{max-width:200px;max-height:150px;border-radius:8px;margin-top:4px}
/* 2×  index.html */
.cs-45.cs-45{min-width:100%;text-align:center}
/* 2×  admin.html, tutor.html */
.cs-46.cs-46{padding:10px 6px;max-width:150px;word-break:break-all}
/* 2×  login.html */
.cs-47.cs-47{text-align:center;margin-top:12px}
/* 2×  student.html */
.cs-48.cs-48{text-align:center;padding:14px 0}
/* 2×  qbank.html */
.cs-49.cs-49{width:100%;min-height:78px;resize:vertical}
/* 2×  lecture-pdf.html */
.cs-50.cs-50{width:100%;min-height:78px;resize:vertical;border-radius:10px;border:1px solid var(--stroke-hi,rgba(255,255,255,.22));background:var(--glass,rgba(255,255,255,.05));color:inherit;font:inherit;font-size:13px;padding:9px 10px}
/* 2×  admin.html */
.cs-51.cs-51{width:15px;height:15px}
/* 2×  admin.html, tutor.html */
.cs-52.cs-52{width:34px;height:34px;font-size:12px}
/* 1×  admin.html */
.cs-53.cs-53{accent-color:var(--orange);width:16px;height:16px}
/* 1×  admin.html */
.cs-54.cs-54{border:1.5px dashed var(--stroke);border-radius:14px;padding:26px;text-align:center;cursor:pointer}
/* 1×  quiz.html */
.cs-55.cs-55{border:1px dashed var(--text3);background:none}
/* 1×  app.js */
.cs-56.cs-56{color:#8d99a8;font-size:13.5px;margin:0 0 18px}
/* 1×  app.js */
.cs-57.cs-57{color:#c8d2df;margin:0 0 14px}
/* 1×  app.js */
.cs-58.cs-58{color:#c8d2df;margin:0 0 18px;padding-inline-start:20px}
/* 1×  admin.html */
.cs-59.cs-59{color:var(--amber);font-weight:700;margin-bottom:6px}
/* 1×  messages.html */
.cs-60.cs-60{display:block;font-size:11.5px;font-weight:800;margin-bottom:5px}
/* 1×  qbank.html */
.cs-61.cs-61{display:block;font-size:11px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:var(--text3);margin-bottom:5px}
/* 1×  qbank.html */
.cs-62.cs-62{display:block;font-size:11px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:var(--text3);margin:12px 0 5px}
/* 1×  lecture-pdf.html */
.cs-63.cs-63{display:block;font-size:11px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:var(--text3,#8d99a8);margin-bottom:5px}
/* 1×  lecture-pdf.html */
.cs-64.cs-64{display:block;font-size:11px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:var(--text3,#8d99a8);margin:12px 0 5px}
/* 1×  messages.html */
.cs-65.cs-65{display:flex;align-items:center;gap:8px;font-size:12.5px;margin-bottom:12px}
/* 1×  qbank.html */
.cs-66.cs-66{display:flex;align-items:center;gap:9px}
/* 1×  messages.html */
.cs-67.cs-67{display:flex;align-items:center;justify-content:center;text-decoration:none}
/* 1×  support.html */
.cs-68.cs-68{display:flex;flex-direction:column;gap:10px;max-height:420px;overflow-y:auto;padding:4px 2px 10px}
/* 1×  admin.html */
.cs-69.cs-69{display:flex;flex-direction:column;gap:16px}
/* 1×  messages.html */
.cs-70.cs-70{display:flex;flex:1;min-width:0}
/* 1×  flashcards.html */
.cs-71.cs-71{display:flex;gap:11px;align-items:flex-start}
/* 1×  qbank.html */
.cs-72.cs-72{display:flex;gap:6px;margin-top:8px}
/* 1×  app.js */
.cs-73.cs-73{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap;margin-top:16px}
/* 1×  app.js */
.cs-74.cs-74{display:inline-block;background:#317ec2;color:#fff;text-decoration:none;padding:11px 18px;border-radius:11px;font-weight:700}
/* 1×  lecture-pdf.html */
.cs-75.cs-75{display:none;align-items:center;gap:10px}
/* 1×  qbank.html */
.cs-76.cs-76{display:none;border-color:rgba(231,135,43,.4)}
/* 1×  tutor.html */
.cs-77.cs-77{display:none;margin-top:12px}
/* 1×  student.html */
.cs-78.cs-78{flex-wrap:wrap;gap:10px}
/* 1×  admin.html */
.cs-79.cs-79{flex:1;min-width:140px}
/* 1×  admin.html */
.cs-80.cs-80{flex:1;min-width:150px}
/* 1×  admin.html */
.cs-81.cs-81{flex:1;min-width:160px}
/* 1×  tutor.html */
.cs-82.cs-82{flex:1;min-width:180px}
/* 1×  course.html */
.cs-83.cs-83{flex:1;min-width:200px}
/* 1×  qbank.html */
.cs-84.cs-84{flex:1;min-width:220px}
/* 1×  support.html */
.cs-85.cs-85{flex:1;resize:vertical}
/* 1×  qbank.html */
.cs-86.cs-86{font-family:var(--fm);font-size:24px;font-weight:700}
/* 1×  qbank.html */
.cs-87.cs-87{font-size:11.5px;color:var(--text3);margin-top:9px}
/* 1×  lecture-pdf.html */
.cs-88.cs-88{font-size:11.5px;color:var(--text3,#8d99a8);margin-top:9px}
/* 1×  lecture-pdf.html */
.cs-89.cs-89{font-size:12.5px;line-height:1.65;color:var(--text2,#c8d2df)}
/* 1×  qbank.html */
.cs-90.cs-90{font-size:12px;color:var(--text3);margin-bottom:10px}
/* 1×  lecture-pdf.html */
.cs-91.cs-91{font-size:12px;color:var(--text3,#8d99a8);margin-bottom:10px}
/* 1×  qbank.html */
.cs-92.cs-92{font-size:12px;line-height:1.55;color:var(--text2);border-left:3px solid var(--orange);padding-left:9px;margin-bottom:6px}
/* 1×  qbank.html */
.cs-93.cs-93{font-size:13.5px;font-weight:800}
/* 1×  qbank.html */
.cs-94.cs-94{font-size:13px;font-weight:700}
/* 1×  student.html */
.cs-95.cs-95{font-size:17px;font-weight:800;margin:20px 0 10px}
/* 1×  student.html */
.cs-96.cs-96{font-size:17px;font-weight:800;margin:8px 0 10px}
/* 1×  quiz.html */
.cs-97.cs-97{font-size:18px;font-weight:800;margin-bottom:8px}
/* 1×  qbank.html */
.cs-98.cs-98{font-size:19px;font-weight:800;margin-bottom:4px}
/* 1×  admin.html */
.cs-99.cs-99{font-size:19px;letter-spacing:2px;user-select:all;word-break:break-all}
/* 1×  support.html */
.cs-100.cs-100{font-size:21px;font-weight:800;margin-bottom:14px}
/* 1×  app.js */
.cs-101.cs-101{font-size:21px;font-weight:800;margin:0 0 10px}
/* 1×  flashcards.html */
.cs-102.cs-102{font-size:25px;font-weight:800}
/* 1×  quiz.html */
.cs-103.cs-103{font-size:25px;font-weight:800;margin-top:18px}
/* 1×  student.html */
.cs-104.cs-104{font-size:25px;font-weight:800;margin:3px 0 18px}
/* 1×  quiz.html */
.cs-105.cs-105{font-size:30px;line-height:1;margin-bottom:12px}
/* 1×  app.js */
.cs-106.cs-106{font-size:34px;margin-bottom:10px}
/* 1×  catalog.html */
.cs-107.cs-107{font-size:40px;margin-bottom:12px}
/* 1×  support.html */
.cs-108.cs-108{font-weight:700;margin-bottom:4px}
/* 1×  catalog.html */
.cs-109.cs-109{font-weight:700;margin-inline-end:4px}
/* 1×  admin.html */
.cs-110.cs-110{font-weight:700;margin-top:6px}
/* 1×  app.js */
.cs-111.cs-111{font-weight:800;font-size:15px;margin-bottom:12px}
/* 1×  admin.html */
.cs-112.cs-112{font-weight:800;margin-bottom:10px}
/* 1×  admin.html */
.cs-113.cs-113{font-weight:800;margin-bottom:2px}
/* 1×  messages.html */
.cs-114.cs-114{font-weight:800;margin-bottom:6px}
/* 1×  messages.html */
.cs-115.cs-115{font-weight:800;opacity:.8}
/* 1×  qbank.html */
.cs-116.cs-116{gap:10px;align-items:center;flex-wrap:wrap}
/* 1×  qbank.html */
.cs-117.cs-117{gap:10px;margin-top:20px;flex-wrap:wrap;align-items:center}
/* 1×  lecture-video.html */
.cs-118.cs-118{gap:18px;flex-wrap:wrap;margin-top:14px}
/* 1×  course.html */
.cs-119.cs-119{gap:18px;margin-top:18px}
/* 1×  admin.html */
.cs-120.cs-120{gap:6px;display:none;flex-wrap:wrap}
/* 1×  admin.html */
.cs-121.cs-121{gap:8px;align-items:center;margin-bottom:6px}
/* 1×  tutor.html */
.cs-122.cs-122{gap:8px;cursor:pointer}
/* 1×  tutor.html */
.cs-123.cs-123{gap:8px;cursor:pointer;margin-top:10px}
/* 1×  tutor.html */
.cs-124.cs-124{gap:8px;cursor:pointer;margin-top:8px}
/* 1×  tutor.html */
.cs-125.cs-125{gap:8px;flex-wrap:wrap;display:none}
/* 1×  support.html */
.cs-126.cs-126{gap:8px;margin-top:12px;flex-wrap:wrap}
/* 1×  support.html */
.cs-127.cs-127{gap:8px;margin-top:8px}
/* 1×  admin.html */
.cs-128.cs-128{gap:8px;padding:6px 0}
/* 1×  admin.html */
.cs-129.cs-129{gap:8px;padding:6px 0;border-bottom:1px solid var(--stroke)}
/* 1×  admin.html */
.cs-130.cs-130{gap:9px;align-items:center;padding:9px 0;border-bottom:1px solid var(--stroke);flex-wrap:wrap}
/* 1×  course.html */
.cs-131.cs-131{gap:9px;align-items:center;padding:9px 10px;margin-bottom:7px;border:1px solid var(--stroke);border-radius:12px;cursor:pointer}
/* 1×  admin.html */
.cs-132.cs-132{gap:9px;cursor:pointer;margin-bottom:16px;align-items:center}
/* 1×  admin.html */
.cs-133.cs-133{gap:9px;flex-wrap:wrap}
/* 1×  support.html */
.cs-134.cs-134{gap:9px;margin-top:10px;align-items:flex-end}
/* 1×  login.html */
.cs-135.cs-135{grid-template-columns:1fr;margin-top:8px}
/* 1×  admin.html */
.cs-136.cs-136{height:38%;animation-delay:.05s}
/* 1×  admin.html */
.cs-137.cs-137{height:47%;animation-delay:.1s}
/* 1×  admin.html */
.cs-138.cs-138{height:58%;animation-delay:.15s}
/* 1×  admin.html */
.cs-139.cs-139{height:66%;animation-delay:.3s}
/* 1×  admin.html */
.cs-140.cs-140{height:68%;animation-delay:.25s}
/* 1×  admin.html */
.cs-141.cs-141{height:70%;animation-delay:.2s}
/* 1×  flashcards.html */
.cs-142.cs-142{justify-content:center;gap:10px}
/* 1×  quiz.html */
.cs-143.cs-143{justify-content:center;gap:10px;margin-top:6px}
/* 1×  quiz.html */
.cs-144.cs-144{justify-content:center;gap:9px}
/* 1×  login.html */
.cs-145.cs-145{letter-spacing:.5em;font-family:var(--fm);font-size:20px;text-align:center}
/* 1×  messages.html */
.cs-146.cs-146{margin-inline-start:auto;display:flex;gap:7px}
/* 1×  qbank.html */
.cs-147.cs-147{margin-top:7px;padding:6px 9px;border-radius:8px;font-size:11.5px;background:rgba(231,135,43,.12);border:1px solid rgba(231,135,43,.45);color:var(--orange,#e7872b)}
/* 1×  tutor.html */
.cs-148.cs-148{margin:0 0 6px 16px;width:calc(100% - 16px)}
/* 1×  app.js */
.cs-149.cs-149{margin:0;background:#0b0f16;color:#eef2f7;font:15px/1.65 -apple-system,Segoe UI,Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;padding:24px}
/* 1×  support.html */
.cs-150.cs-150{margin:10px 0 0;white-space:pre-wrap}
/* 1×  support.html */
.cs-151.cs-151{margin:8px 0;white-space:pre-wrap}
/* 1×  admin.html */
.cs-152.cs-152{max-height:230px;overflow:auto}
/* 1×  admin.html */
.cs-153.cs-153{max-width:180px;border-radius:10px;display:block;margin-bottom:8px}
/* 1×  admin.html */
.cs-154.cs-154{max-width:190px;font-size:12px}
/* 1×  messages.html */
.cs-155.cs-155{max-width:220px;border-radius:10px;display:block}
/* 1×  quiz.html */
.cs-156.cs-156{max-width:420px;margin:0 auto 18px}
/* 1×  messages.html */
.cs-157.cs-157{max-width:440px;width:100%;max-height:76vh;overflow:auto;padding:20px;border-radius:16px}
/* 1×  admin.html */
.cs-158.cs-158{max-width:460px;width:100%;max-height:80vh;overflow:auto;padding:22px;border-radius:16px}
/* 1×  admin.html */
.cs-159.cs-159{max-width:480px;width:100%;max-height:80vh;overflow:auto;padding:22px;border-radius:16px}
/* 1×  student.html */
.cs-160.cs-160{max-width:520px;margin:8px auto 0}
/* 1×  tutor.html */
.cs-161.cs-161{max-width:520px;width:100%;max-height:84vh;overflow:auto;padding:22px;border-radius:16px}
/* 1×  flashcards.html */
.cs-162.cs-162{max-width:920px;margin:0 auto}
/* 1×  quiz.html */
.cs-163.cs-163{opacity:1;margin-left:10px}
/* 1×  catalog.html */
.cs-164.cs-164{padding:0;overflow:hidden}
/* 1×  admin.html */
.cs-165.cs-165{padding:11px 0;border-bottom:1px solid var(--stroke);gap:10px;align-items:center;flex-wrap:wrap}
/* 1×  qbank.html */
.cs-166.cs-166{padding:12px 13px;margin-bottom:9px}
/* 1×  admin.html */
.cs-167.cs-167{padding:12px;margin-top:10px;border:1px solid var(--amber)}
/* 1×  support.html */
.cs-168.cs-168{padding:7px 0;border-top:1px solid var(--stroke)}
/* 1×  admin.html */
.cs-169.cs-169{padding:9px 0;border-bottom:1px solid var(--stroke)}
/* 1×  lecture-pdf.html */
.cs-170.cs-170{text-align:center;margin:26px 0 10px}
/* 1×  quiz.html */
.cs-171.cs-171{text-align:center;padding:46px 22px}
/* 1×  lecture-pdf.html */
.cs-172.cs-172{text-align:center;padding:60px 0}
/* 1×  student.html */
.cs-173.cs-173{text-align:center;padding:8px 0}
/* 1×  tutor.html */
.cs-174.cs-174{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 1×  tutor.html */
.cs-175.cs-175{width:100%;box-sizing:border-box;background:var(--glass2);border:1px solid var(--stroke);border-radius:10px;padding:10px 12px;color:var(--text);font-family:inherit;font-size:13px}
/* 1×  catalog.html */
.cs-176.cs-176{width:100%;height:100%;object-fit:cover}
/* 1×  lecture-pdf.html */
.cs-177.cs-177{width:100%;height:calc(100vh - 160px);border:0;border-radius:12px;background:#fff}
/* 1×  qbank.html */
.cs-178.cs-178{width:100%;margin-bottom:10px}
/* 1×  lecture-pdf.html */
.cs-179.cs-179{width:11px;height:11px}
/* 1×  quiz.html */
.cs-180.cs-180{width:170px;height:170px;margin:0 auto}
/* 1×  app.js */
/* R26 Pass 3: was .cs-181, the signed-in nav avatar built by app.js. It set
   `color:#fff` over `linear-gradient(--blue, --green)`. Both tokens invert
   between themes, the white did not: measured against each gradient stop by
   hand, DARK theme gives 2.50:1 and 2.35:1 at 11px against a 4.5 floor.
   The automated audit could not catch this — a gradient lives in
   background-image and the contrast walker reads backgroundColor — which is
   why it is now reported as UNMEASURABLE and checked by hand instead of being
   silently measured against the page behind the gradient. Four such nodes
   exist; this was the one that failed.
   The flat --brand with --brand-on is a designed pair, contrasts correctly in
   both themes, and loses nothing but a gradient nobody asked for. */
.navav.navav{
  width:24px; height:24px; border-radius:var(--r-btn); flex-shrink:0;
  background:var(--brand); color:var(--brand-on);
  display:inline-flex; align-items:center; justify-content:center;
  font-weight:700; font-size:11px;
}
/* 1×  lecture-pdf.html */
.cs-182.cs-182{width:4px;height:4px}
/* 1×  lecture-pdf.html */
.cs-183.cs-183{width:7px;height:7px}

/* ============ 19. FORMER JS-STRING STYLESHEETS AND PALETTES (Pass 3) ================
   These replace declaration lists that were held in JavaScript variables and
   interpolated into style attributes. CSP blocks the attribute regardless of
   how the string was built, and a stylesheet living in a `var` is one the
   browser cannot cache, the theme cannot reach, and no linter can see.
   Selectors are doubled and this block lives in canvas.css for the same reason
   as section 18: the attributes these replace were (1,0,0,0) and beat every
   page rule; a single class is (0,0,1,0) and beats almost none of them.
   ===================================================================== */

/* messages.html — was `var INPUT_CSS`, interpolated into 9 style attributes
   across the new-ticket, new-announcement and escalate dialogs. */
.mfield.mfield{
  width:100%; box-sizing:border-box;
  background:var(--glass2); border:1px solid var(--stroke);
  border-radius:10px; padding:10px 12px;
  color:var(--text); font-family:var(--fb); font-size:13px;
}
.mfield-v.mfield-v{resize:vertical}

/* Note-highlight palette — lecture-pdf.html and quiz.html.
   Colour is the MEANING here, not decoration: the student picks the colour and
   it is how they find the note again. That is why these stay hues while
   department markers became hatch patterns — a department is a category the
   system assigns, a highlight colour is a choice the student made and would not
   recognise as a pattern. The four values are the app's existing
   COLORS/QN_COLORS maps, unchanged, so the conversion is inert. */
/* NOTE: .hlsw carries NO declarations. The swatch already gets its size, shape
   and cursor from the page's own `.nf-colors i` / `.swz i` rules; the style
   attribute it replaces set ONLY a background. A first version of this block
   gave .hlsw a width, height, border-radius and border "to be helpful" and
   would have resized every swatch in the app — a design change smuggled into a
   conversion that is supposed to be inert. If you want the swatches restyled,
   do it deliberately and re-run the snapshot. */
.hl-yellow.hl-yellow{background:#F2C14E}
.hl-green.hl-green{background:#5AAA46}
.hl-blue.hl-blue{background:#317EC2}
.hl-red.hl-red{background:#E86A62}

.hlq-yellow.hlq-yellow{border-left-color:#F2C14E}
.hlq-green.hlq-green{border-left-color:#5AAA46}
.hlq-blue.hlq-blue{border-left-color:#317EC2}
.hlq-red.hlq-red{border-left-color:#E86A62}

/* --- conditional branches lifted out of style attributes (Pass 3) -------
   Each of these was a ternary inside a style attribute, e.g.
       style="align-self:' + (mine ? 'flex-end' : 'flex-start') + '"
   A conditional STYLE is a conditional CLASS with extra steps: the branch was
   already being decided in JavaScript, so all that changes is which token the
   template emits. Values are copied verbatim from the attributes they replace.
   Doubled selectors for the same specificity reason as section 18. */

/* admin.html — module/section rename rows */
.cf-row.cf-row{gap:6px;margin:0 0 6px 0}
.cf-row-in.cf-row-in{margin-left:16px}

/* index.html — tutor avatar tones. These are the app's TONES array, which is
   gradients; Pass 2 kept nine deliberate gradients and these are among them.
   THERE ARE FOUR. The array had four entries and the first conversion emitted
   `i % 6 + 1`, which would have left two avatars in every six with no
   background. If you add a tone here, change the modulus in index.html. */
.tone-1.tone-1{background:linear-gradient(135deg,var(--blue),#2463A0)}
.tone-2.tone-2{background:linear-gradient(135deg,var(--green),#478A36)}
.tone-3.tone-3{background:linear-gradient(135deg,var(--orange),#C96812)}
.tone-4.tone-4{background:linear-gradient(135deg,var(--blue),var(--green))}

/* qbank.html — note body, and the placeholder state when there is no note */
.qbn-body.qbn-body{font-size:12.5px;line-height:1.6;white-space:pre-wrap}
.qbn-empty.qbn-empty{color:var(--text3);font-style:italic}

/* student.html — study-planner rest-day chip */
.spchip.spchip{cursor:pointer}
.spchip-rest.spchip-rest{border-color:var(--orange)}

/* support.html — ticket chat bubbles */
.tkb.tkb{align-self:flex-start;max-width:78%}
.tkb-mine.tkb-mine{align-self:flex-end}
.tkb-who.tkb-who{margin-bottom:2px}
.tkb-who-mine.tkb-who-mine{text-align:end}
.tkb-body.tkb-body{padding:9px 13px;border-radius:13px;font-size:13px;white-space:pre-wrap}
.tkb-body-mine.tkb-body-mine{background:linear-gradient(120deg,rgba(49,126,194,.25),rgba(90,170,70,.12))}

/* tutor.html — recent-conversation rows; the last one has no separator */
.tvrow.tvrow{padding:12px 0;text-decoration:none;color:inherit}
.tvrow-sep.tvrow-sep{border-bottom:1px solid var(--stroke)}

/* --- the global modal (app.js M.modal) ---------------------------------
   Built by app.js with setAttribute('style', …) until Pass 3. Three separate
   problems, only one of which was the CSP:
     - setAttribute('style') is blocked by style-src like any other attribute;
     - the modal had never been conformed to Canvas — 16px radius, a 70px
       shadow, font-weight 800;
     - its var() fallbacks hardcoded the old dark palette, so on any page where
       app.css failed to load it rendered a dark modal on the light theme.
   Radii are the locked Pass 1 values. Doubled selectors, same reason as §18.
   TOKEN NAMES ARE NOT GUESSABLE: the first draft of this block used --scrim,
   --sh-obj, --surface-1 and --accent-ink-as-foreground. Three of those do not
   exist in app.css and the fourth is a hover colour, not a text colour on a
   filled button (that is --accent-on). An undefined var() with no fallback
   makes the whole declaration invalid at computed-value time, so the modal
   would have had NO background and NO shadow — invisible against the page,
   and only on the screens that open a modal. Check the token list in app.css
   section 2 before using a name. */
.m-modal-ov.m-modal-ov{
  position:fixed; inset:0; z-index:9999;
  background:rgba(6,10,18,.62);
  display:flex; align-items:center; justify-content:center; padding:20px;
}
.m-modal-box.m-modal-box{
  width:min(520px,100%); max-height:86vh; overflow:auto;
  border-radius:var(--r-obj);
  background:var(--surface); border:1px solid var(--line);
  box-shadow:var(--shadow);
  padding:18px 18px 16px; color:var(--text); font-family:inherit;
}
.m-modal-btn.m-modal-btn{
  padding:8px 15px; border-radius:var(--r-btn);
  font-weight:600; font-size:12.5px; cursor:pointer; font-family:inherit;
  border:1px solid var(--line); background:transparent; color:var(--text2);
}
.m-modal-btn-primary.m-modal-btn-primary{
  border-color:transparent; background:var(--accent); color:var(--accent-on);
}

/* --- the device-limit screen (app.js) ----------------------------------
   Reached only when register_device rejects a sign-in, which is why it went
   through two full redesign passes untouched: no page visit renders it, so no
   audit sees it. Until Pass 3 it hardcoded the pre-Canvas dark palette
   (#0b0f16 paper, #eef2f7 ink, #317ec2 button) and a system font stack, so it
   ignored the theme entirely — a light-theme user hitting the device limit was
   shown a black page. It also destroyed its own stylesheet link; see the note
   at the call site. Tokens now, so it follows the theme like every other
   screen. Doubled selectors, same reason as §18. */
.dlim-body.dlim-body{
  margin:0; background:var(--paper); color:var(--text);
  font-family:var(--fb); font-size:15px; line-height:1.65;
  display:flex; align-items:center; justify-content:center;
  min-height:100vh; padding:24px;
}
.dlim-icon.dlim-icon{margin-bottom:10px}
.dlim-icon.dlim-icon .ic{width:34px;height:34px}
.dlim-h.dlim-h{
  font-family:var(--fd); font-size:21px; font-weight:600;
  margin:0 0 10px; color:var(--text);
}
.dlim-p.dlim-p{color:var(--text2);margin:0 0 14px}
.dlim-list.dlim-list{color:var(--text2);margin:0 0 18px;padding-inline-start:20px}
.dlim-note.dlim-note{color:var(--text3);font-size:13.5px;margin:0 0 18px}
.dlim-cta.dlim-cta{
  display:inline-block; background:var(--accent); color:var(--accent-on);
  text-decoration:none; padding:11px 18px;
  border-radius:var(--r-btn); font-weight:600;
}

/* --- the global toast (app.js M.toast) ---------------------------------
   Surfaced by the hydrated dark-review in Pass 3 and by no audit before it: it
   is built with style.cssText — a CSSOM write, correctly outside the CSP style
   attribute census — and it exists for only 3.1 seconds, so no static pass
   could see it. It carried three hardcoded hexes from the pre-Canvas palette,
   identical in both themes, plus system-ui type that bypassed the self-hosted
   stack. Doubled selectors, same reason as §18. */
.m-toast.m-toast{
  position:fixed; bottom:24px; left:50%; transform:translateX(-50%);
  z-index:9999; max-width:92vw; text-align:center;
  padding:12px 20px; border-radius:var(--r-obj);
  font-family:var(--fb); font-weight:600; font-size:14px; line-height:1.3;
  box-shadow:var(--shadow); border:1px solid var(--line);
}
.m-toast-err.m-toast-err {background:var(--crimson-soft); color:var(--crimson); border-color:var(--crimson)}
.m-toast-ok.m-toast-ok  {background:var(--jade-soft);    color:var(--jade);    border-color:var(--jade)}
.m-toast-info.m-toast-info{background:var(--brand-soft); color:var(--brand);   border-color:var(--brand)}
