/* =========================================================================
   DECK.CSS - shared CONTENT components for the design deck, built on top of
   praxis.css tokens. These are the reusable pieces (subject tags, level cards,
   classroom cards, section headers) that recur across many app pages; they'll
   graduate into praxis.css proper once the designs are approved.
   ========================================================================= */

/* make a page's single view visible (real app uses @yield) */
.view.show { display: block; }

/* topbar role-switch chip (deck-only aid, not in the real app) */
.deck-roleswitch { text-decoration:none; white-space:nowrap; }
@media (max-width:860px){ .deck-roleswitch{ display:none; } }

/* section sub-heading inside a page */
.sec-head { display:flex; align-items:center; gap:12px; margin:26px 0 14px; }
.sec-head h2 { font-size:18px; font-weight:700; letter-spacing:-.01em; }
.sec-head .sec-act { margin-left:auto; }

/* ---- subject tag pills (map the app's subject colours to Praxis palette) ---- */
.sub-tag { display:inline-flex; align-items:center; gap:7px; padding:5px 11px; border-radius:999px; font-size:12px; font-weight:600; }
.sub-tag .count { font-weight:700; background:rgba(0,0,0,.10); border-radius:999px; padding:0 7px; font-size:11px; }
.sub-en { background:var(--yellow-tint); color:var(--warn-ink); }         /* English */
.sub-ma { background:var(--blue-tint);   color:#2C6F8E; }                 /* Mathematics */
.sub-sc { background:var(--purple-tint); color:#6C39B8; }                /* Science */
.sub-cn { background:var(--good-tint);   color:var(--good-ink); }        /* Chinese */
.sub-ge { background:var(--accent-tint); color:var(--accent-strong); }   /* other/general */

/* ---- level card (used in Question Bank + educator Overview) ---- */
.lvl-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:16px; }
.lvl-card { border:1px solid var(--line); border-radius:var(--r-lg); padding:18px; background:var(--surface); transition:box-shadow .16s ease,transform .12s ease,border-color .16s ease; }
.lvl-card:hover { box-shadow:var(--shadow-md); border-color:var(--line-strong); transform:translateY(-2px); }
.lvl-card .lvl-top { display:flex; align-items:center; gap:10px; margin-bottom:14px; }
.lvl-card .lvl-ico { width:38px; height:38px; border-radius:11px; display:grid; place-items:center; background:var(--accent-tint); color:var(--accent-strong); font-size:16px; }
.lvl-card .lvl-name { font-weight:700; font-size:15px; }
.lvl-card .lvl-subs { display:flex; flex-wrap:wrap; gap:8px; }

/* ---- classroom card (educator Overview + Classrooms list) ---- */
.class-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); gap:16px; }
.class-card { border:1px solid var(--line); border-radius:var(--r-lg); padding:18px; background:var(--surface); display:flex; gap:14px; transition:box-shadow .16s ease,transform .12s ease,border-color .16s ease; }
.class-card:hover { box-shadow:var(--shadow-md); border-color:var(--line-strong); transform:translateY(-2px); }
.class-card .cc-ico { width:46px; height:46px; flex:none; border-radius:13px; display:grid; place-items:center; background:var(--ink); color:var(--yellow); font-size:20px; }
.class-card .cc-name { font-weight:700; font-size:15.5px; }
.class-card .cc-meta { display:flex; align-items:center; gap:14px; margin:6px 0 12px; color:var(--ink-muted); font-size:12.5px; font-weight:600; }
.class-card .cc-meta i { margin-right:5px; color:var(--ink-faint); }
.class-card .cc-subs { display:flex; flex-wrap:wrap; gap:7px; }

/* empty-state note */
.empty-note { border:1.5px dashed var(--line-strong); border-radius:var(--r-lg); padding:26px; text-align:center; color:var(--ink-muted); font-size:14px; }
.empty-note a { color:var(--accent-strong); font-weight:600; }

/* small labelled definition rows (subscription card etc.) */
.def-list { display:flex; flex-direction:column; gap:2px; }
.def-row { display:flex; align-items:baseline; justify-content:space-between; gap:12px; padding:11px 0; border-bottom:1px solid var(--line); }
.def-row:last-child { border-bottom:0; }
.def-row .dt { color:var(--ink-muted); font-size:13px; }
.def-row .dd { font-weight:700; font-size:14px; text-align:right; }

/* a tiny "design note" ribbon so you can tell proposed enhancements from as-is */
.deck-note { display:inline-flex; align-items:center; gap:7px; font-size:11.5px; font-weight:600; color:var(--accent-strong); background:var(--accent-tint); border-radius:999px; padding:4px 11px; }

/* =========================================================================
   TABLE / DATATABLES layer (Praxis). We load DataTables JS only (no DataTables
   CSS), so we style the generated chrome ourselves - no !important battles.
   ========================================================================= */
.card-tools{ display:flex; align-items:center; gap:10px; margin-left:auto; flex-wrap:wrap; }
.btn-sm{ padding:9px 14px; font-size:13px; }

/* our own search box (wired to table.search()) */
.dt-search{ position:relative; display:inline-flex; align-items:center; }
.dt-search i{ position:absolute; left:13px; font-size:13px; color:var(--ink-faint); pointer-events:none; }
.dt-search input{ font:inherit; font-size:13.5px; font-weight:500; color:var(--ink); background:var(--surface); border:1.5px solid var(--line-strong); border-radius:12px; padding:9px 14px 9px 36px; min-width:220px; outline:none; transition:border-color .15s ease, box-shadow .15s ease; }
.dt-search input::placeholder{ color:var(--ink-faint); font-weight:500; }
.dt-search input:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-tint); }

/* the table itself. Header is transparent (no grey band) with even padding and a
   single divider; first/last cells carry the card gutter so nothing floats. */
table.dtable thead th{ text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-faint); font-weight:700; padding:14px; background:transparent; white-space:nowrap; border-bottom:1px solid var(--line); }
table.dtable tbody td{ padding:14px; border-top:0; border-bottom:1px solid var(--line); vertical-align:middle; font-size:13.5px; color:var(--ink-2); }
table.dtable thead th:first-child, table.dtable tbody td:first-child{ padding-left:22px; }
table.dtable thead th:last-child, table.dtable tbody td:last-child{ padding-right:22px; }
table.dtable tbody tr:last-child td{ border-bottom:0; }
table.dtable tbody tr:hover td{ background:var(--surface-2); }
table.dtable .ws-name{ display:flex; align-items:center; gap:10px; font-weight:600; color:var(--ink); }
table.dtable .ws-name .fi{ width:30px;height:30px;border-radius:9px;background:var(--accent-tint);color:var(--accent-strong);display:grid;place-items:center;font-size:13px;flex:none; }
table.dtable .muted{ color:var(--ink-muted); }
table.dtable .num{ text-align:center; font-weight:700; color:var(--ink); }
table.dtable td.end{ text-align:right; }

/* DataTables sort indicator (we add carets ourselves) */
/* The sort arrow is absolutely positioned at the right edge, so the space it
   reserves has to be mirrored on the left - otherwise a centred header label
   sits ~6px off-centre on every sortable column. */
table.dtable thead th.sorting,table.dtable thead th.sorting_asc,table.dtable thead th.sorting_desc{ cursor:pointer; position:relative; padding-left:26px; padding-right:26px; }
table.dtable thead th.sorting::after,table.dtable thead th.sorting_asc::after,table.dtable thead th.sorting_desc::after{ content:"\f0dc"; font-family:"Font Awesome 6 Free"; font-weight:900; position:absolute; right:12px; top:50%; transform:translateY(-50%); font-size:10px; opacity:.4; }
table.dtable thead th.sorting_asc::after{ content:"\f0de"; opacity:1; color:var(--accent); }
table.dtable thead th.sorting_desc::after{ content:"\f0dd"; opacity:1; color:var(--accent); }

/* horizontal scroller that holds ONLY the table, so the footer/pager never scrolls.
   No side padding here - the table spans the full card width and the first/last
   cells carry the 22px gutter (so header + rows align with the card-head). */
.dt-scroll{ overflow-x:auto; }

/* DataTables info + pagination */
.dt-foot{ display:flex; align-items:center; justify-content:space-between; gap:14px; padding:16px 22px 10px; flex-wrap:wrap; }
.dataTables_info{ font-size:12.5px; color:var(--ink-muted); }
.dataTables_paginate{ display:flex; gap:6px; }
.dataTables_paginate .paginate_button{ min-width:36px; height:36px; padding:0 10px; border-radius:10px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink-2); font-weight:600; font-size:13px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; box-sizing:border-box; user-select:none; text-decoration:none; }
.dataTables_paginate .paginate_button.current{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.dataTables_paginate .paginate_button.disabled{ opacity:.4; cursor:not-allowed; }
.dataTables_paginate .paginate_button:hover:not(.current):not(.disabled){ background:var(--surface-2); }

/* difficulty tier pills (basic / intermediate / advanced counts) */
.diff-cell{ display:inline-flex; gap:6px; flex-wrap:wrap; }
.dpill{ display:inline-flex; align-items:center; gap:5px; padding:3px 9px 3px 6px; border-radius:8px; font-size:12px; font-weight:700; }
/* The tier (1/2/3) is printed INSIDE the star so a single star reads its own level -
   no 1/2/3 star icons to get messy. The trailing number is the question count. */
.dpill i{ position:relative; font-size:16px; line-height:1; }
.dpill i::after{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; padding-top:2px; font-family:'Kodchasan', system-ui, sans-serif; font-weight:800; font-size:8px; color:#fff; }
.dpill.d1{ background:var(--good-tint); color:var(--good-ink); }
.dpill.d2{ background:var(--yellow-tint); color:var(--warn-ink); }
.dpill.d3{ background:var(--bad-tint); color:var(--bad-ink); }
.dpill.d1 i{ color:var(--good-ink, #1a7f43); }
.dpill.d2 i{ color:var(--warn-ink, #8a5a00); }
.dpill.d3 i{ color:var(--bad-ink, #c0341a); }
.dpill.d1 i::after{ content:"1"; }
.dpill.d2 i::after{ content:"2"; }
.dpill.d3 i::after{ content:"3"; }
/* Standalone numbered star for single-difficulty displays (e.g. Question Bank cards):
   one star whose level (1/2/3) is printed inside it, instead of 1/2/3 star icons. */
.lvl-star{ position:relative; display:inline-grid; place-items:center; width:20px; height:20px; vertical-align:middle; }
.lvl-star i{ font-size:19px; line-height:1; }
.lvl-star i::after{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; padding-top:2px; font-family:'Kodchasan', system-ui, sans-serif; font-weight:800; font-size:9.5px; color:#fff; }
.lvl-star.d1 i{ color:var(--good-ink,#1a7f43); } .lvl-star.d1 i::after{ content:"1"; }
.lvl-star.d2 i{ color:var(--warn-ink,#8a5a00); } .lvl-star.d2 i::after{ content:"2"; }
.lvl-star.d3 i{ color:var(--bad-ink,#c0341a); } .lvl-star.d3 i::after{ content:"3"; }
.lvl-label{ font-size:12px; font-weight:600; color:var(--ink-muted); }
/* Bootstrap's .btn-check hides the radio/checkbox so its paired label acts as a button;
   Praxis doesn't load that component CSS, so hide it here (else a stray radio shows). */
.btn-check{ position:absolute; clip:rect(0,0,0,0); clip-path:inset(50%); width:1px; height:1px; overflow:hidden; margin:0; padding:0; border:0; opacity:0; pointer-events:none; }

/* row action icon buttons */
.row-actions{ display:inline-flex; gap:7px; justify-content:flex-end; flex-wrap:nowrap; }
.row-actions > *{ flex:0 0 auto; }   /* an action control must never shrink in a tight column */
/* praxis.css ALSO defines an older icon-rail variant of this class:
   `.row-actions button{ width:30px;height:30px;display:grid;color:var(--ink-faint) }`.
   That selector out-specifies plain `.btn`, so on rows that mix a text button with an
   .icon-btn (the student Practice list) it squashed the "Practise" <button> into a grey
   30px square with its label overflowing. Re-assert the button's real size/colour - the
   child selectors out-specify `.row-actions button`, and this file loads after praxis.css. */
.row-actions > .btn{ width:auto; height:auto; border-radius:var(--r-md); display:inline-flex; }
.row-actions > .btn-primary{ color:var(--on-accent); }
.row-actions > .btn-ghost{ color:var(--ink); }
.icon-btn{ width:34px; height:34px; border-radius:10px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink-muted); display:inline-grid; place-items:center; cursor:pointer; transition:border-color .14s ease,color .14s ease,background .14s ease; text-decoration:none; font-size:13px; }
.icon-btn:hover{ border-color:var(--line-strong); color:var(--ink); background:var(--surface-2); }
.icon-btn.danger:hover{ color:var(--bad-ink); border-color:var(--bad-ink); background:var(--bad-tint); }

/* =========================================================================
   FORM + PRACTICE helpers (Question Studio "setting" page + Do-Worksheet page).
   Most of these pages reuse praxis.css's .studio / .q-card kits; these fill gaps.
   ========================================================================= */
select.input{ appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23847F7C' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; }
.seg button.is-active:not([data-d]){ background:var(--surface); box-shadow:var(--shadow-sm); }

.dropzone{ border:1.5px dashed var(--line-strong); border-radius:var(--r-md); padding:22px; text-align:center; color:var(--ink-muted); font-size:13px; font-weight:600; background:var(--surface-2); cursor:pointer; transition:border-color .15s,color .15s,background .15s; }
.dropzone:hover{ border-color:var(--accent); color:var(--accent-strong); background:var(--accent-tint); }
.dropzone i{ font-size:20px; display:block; margin-bottom:6px; color:var(--ink-faint); }

.switch{ display:inline-flex; align-items:center; gap:10px; cursor:pointer; font-weight:600; font-size:13.5px; }
.switch input{ position:absolute; opacity:0; }
.switch .track{ width:40px; height:23px; border-radius:999px; background:var(--line-strong); position:relative; transition:background .16s; flex:none; }
.switch .track::after{ content:""; position:absolute; top:2px; left:2px; width:19px; height:19px; border-radius:50%; background:#fff; transition:transform .16s; box-shadow:0 1px 3px rgba(0,0,0,.2); }
.switch input:checked + .track{ background:var(--accent); }
.switch input:checked + .track::after{ transform:translateX(17px); }

/* doing-questions: written / draw answer + working box */
.ans-modebar{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; flex-wrap:wrap; }
.work-box{ border:1.5px dashed var(--line-strong); border-radius:var(--r-lg); background:var(--surface-2); padding:14px 16px; margin-bottom:16px; }
.work-box .wb-head{ display:flex; align-items:center; gap:8px; font-weight:600; font-size:13px; color:var(--ink-muted); margin-bottom:10px; }
.work-box .wb-req{ margin-left:auto; font-size:11px; font-weight:700; color:var(--accent-strong); background:var(--accent-tint); border-radius:999px; padding:3px 9px; }
.work-canvas{ height:140px; border-radius:var(--r-md); background:var(--surface) repeating-linear-gradient(0deg,transparent,transparent 27px,var(--line) 28px); border:1px solid var(--line); }
.work-tools{ display:flex; gap:8px; margin-top:10px; }
.work-tools .tbtn{ width:34px; height:34px; border-radius:9px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink-muted); display:grid; place-items:center; cursor:pointer; }
.work-tools .tbtn.active{ border-color:var(--accent); color:var(--accent-strong); background:var(--accent-tint); }

/* =========================================================================
   CALENDAR side agenda (calendar page: month grid + "Upcoming" list beside it)
   ========================================================================= */
.cal-layout{ display:grid; grid-template-columns:1fr 330px; gap:20px; align-items:start; }
@media(max-width:1080px){ .cal-layout{ grid-template-columns:1fr; } }
.agenda-list{ display:flex; flex-direction:column; gap:2px; padding:8px; max-height:640px; overflow:auto; }
.agenda-item{ display:flex; align-items:flex-start; gap:12px; padding:11px 12px; border-radius:12px; cursor:pointer; transition:background .14s; }
.agenda-item:hover{ background:var(--surface-2); }
.agenda-day{ flex:none; width:40px; text-align:center; }
.agenda-day .d{ font-size:18px; font-weight:700; line-height:1; color:var(--ink); font-variant-numeric:tabular-nums; }
.agenda-day .m{ font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint); font-weight:700; margin-top:3px; }
.agenda-body{ flex:1; border-left:3px solid var(--line); padding-left:12px; min-width:0; }
.agenda-title{ font-weight:600; font-size:13.5px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.agenda-sub{ font-size:11.5px; color:var(--ink-muted); margin-top:3px; display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
.agenda-dot{ width:8px; height:8px; border-radius:3px; display:inline-block; flex:none; }
.agenda-today{ font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--accent-strong); background:var(--accent-tint); border-radius:999px; padding:2px 7px; }
.agenda-empty{ padding:26px 12px; text-align:center; color:var(--ink-faint); font-size:13px; }

/* =========================================================================
   NOTIFICATIONS - bell dropdown in the topbar (built by deck-shell.js) +
   Announcements list/detail. Mirrors the app's bell → announcements system.
   ========================================================================= */
.notif{ position:relative; }
.notif-badge{ position:absolute; top:-3px; right:-3px; min-width:16px; height:16px; padding:0 4px; border-radius:999px; background:var(--accent); color:#fff; font-size:10px; font-weight:800; display:grid; place-items:center; line-height:1; box-shadow:0 0 0 2px var(--paper); }
.notif-badge.hide{ display:none; }
.notif-panel{ position:absolute; top:calc(100% + 10px); right:0; width:344px; max-width:92vw; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow-lg); z-index:200; overflow:hidden; display:none; }
.notif-panel.show{ display:block; animation:rise .16s ease; }
.notif-head{ display:flex; align-items:center; justify-content:space-between; padding:14px 16px; border-bottom:1px solid var(--line); }
.notif-head strong{ font-size:14.5px; }
.notif-new{ font-size:11px; font-weight:700; color:#fff; background:var(--accent); border-radius:999px; padding:2px 9px; }
.notif-new.hide{ display:none; }
.notif-list{ max-height:360px; overflow-y:auto; }
.notif-item{ display:flex; gap:12px; padding:13px 16px; border-bottom:1px solid var(--line); text-decoration:none; transition:background .14s; }
.notif-item:hover{ background:var(--surface-2); }
.notif-ico{ width:36px; height:36px; border-radius:11px; flex:none; display:grid; place-items:center; background:var(--accent-tint); color:var(--accent-strong); font-size:15px; }
.notif-body{ flex:1; min-width:0; }
.notif-title,.notif-snip,.notif-time{ display:block; }
.notif-title{ font-weight:600; font-size:13.5px; color:var(--ink); }
.notif-snip{ font-size:12px; color:var(--ink-muted); margin-top:2px; line-height:1.4; }
.notif-time{ font-size:11px; color:var(--ink-faint); margin-top:4px; }
.notif-item.unread{ background:color-mix(in srgb, var(--accent-tint) 40%, transparent); }
.notif-item.unread .notif-title::after{ content:""; display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--accent); margin-left:7px; vertical-align:middle; }
.notif-foot{ display:block; text-align:center; padding:12px; font-weight:600; font-size:13px; color:var(--accent-strong); text-decoration:none; }
.notif-foot:hover{ background:var(--surface-2); }
/* mobile: dock the notification panel just under the sticky navbar, right-aligned */
@media(max-width:860px){ .notif-panel{ position:fixed; top:58px; right:10px; left:auto; bottom:auto; width:min(340px, calc(100vw - 20px)); max-height:72vh; } }

/* Announcements list + detail */
.ann-row{ display:flex; align-items:flex-start; gap:14px; padding:16px 4px; border-bottom:1px solid var(--line); text-decoration:none; transition:background .14s; }
.ann-row:last-child{ border-bottom:0; }
.ann-row:hover{ background:var(--surface-2); }
.ann-ico{ width:42px; height:42px; border-radius:12px; flex:none; display:grid; place-items:center; background:var(--accent-tint); color:var(--accent-strong); font-size:17px; }
.ann-main{ flex:1; min-width:0; }
.ann-title{ font-weight:700; font-size:15.5px; color:var(--ink); display:flex; align-items:center; gap:9px; }
.ann-snip{ font-size:13.5px; color:var(--ink-muted); margin-top:4px; line-height:1.5; }
.ann-meta{ font-size:12px; color:var(--ink-faint); margin-top:6px; }
.ann-new{ font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#fff; background:var(--accent); border-radius:999px; padding:2px 8px; }

/* =========================================================================
   MOBILE: force every 2-column layout to a single column. Uses !important so
   it beats the inline grid-template-columns some pages set (which was hiding
   the right-hand column - trickiest questions, subscription table, etc.).
   ========================================================================= */
@media(max-width:900px){
  .ins-grid, .studio, .practice, .qb-layout, .cd-grid, .pf-grid,
  .sub-grid, .wc-grid, .cal-layout, .fb-cols, .rev-cols, .row2{ grid-template-columns:1fr !important; }
}

/* =========================================================================
   MOBILE OVERFLOW HARDENING
   - grid children get min-width:0 so an inner overflow-x scroller (a wide table)
     can't force its whole column - and the page - wider than the viewport.
   - card headers wrap so legends/tools don't spill off the card edge.
   - a safety net clips any residual horizontal scroll on small screens.
   ========================================================================= */
.ins-grid > *, .sub-grid > *, .qb-layout > *, .cd-grid > *, .pf-grid > *,
.wc-grid > *, .cal-layout > *, .practice > *, .studio > *, .kpi-row > *{ min-width:0; }
.card-head{ flex-wrap:wrap; row-gap:8px; }
.apexcharts-canvas, .apexcharts-canvas svg{ max-width:100%; }
/* safety clip on the content area only (NOT html/body/topbar) so the sticky
   navbar keeps working while any residual horizontal spill is contained */
@media(max-width:900px){ .stage{ overflow-x:hidden; } }

/* =========================================================================
   PRAXIS SELECT - native <select> is upgraded by deck-shell.js into this
   custom dropdown so the OPEN list is styled (native option lists can't be).
   The original <select> is kept (hidden) so value + change events still work.
   ========================================================================= */
.pselect{ position:relative; display:inline-flex; vertical-align:middle; }
.pselect-btn{ display:flex; align-items:center; gap:10px; width:100%; font-family:inherit; font-size:13px; font-weight:600; color:var(--ink-2); background:var(--surface); border:1.5px solid var(--line-strong); border-radius:10px; padding:9px 12px; cursor:pointer; text-align:left; transition:border-color .15s ease, box-shadow .15s ease; }
.pselect-btn:hover{ border-color:var(--ink-muted); }
.pselect.open .pselect-btn{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-tint); }
.pselect-label{ flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pselect-caret{ font-size:11px; color:var(--ink-faint); transition:transform .18s ease; }
.pselect.open .pselect-caret{ transform:rotate(180deg); color:var(--accent); }
/* mirrors the read-only .ro look used on disabled <input>s */
.pselect.is-disabled .pselect-btn{ background:var(--surface-2); border-color:var(--line); color:var(--ink-muted); cursor:not-allowed; }
.pselect.is-disabled .pselect-btn:hover{ border-color:var(--line); }
.pselect.is-disabled .pselect-caret{ opacity:.45; }

/* form-field selects match the larger .input look */
.field .pselect{ display:flex; width:100%; }
.field .pselect-btn{ background:var(--surface-2); border-color:var(--line); border-radius:var(--r-md); padding:12px 14px; font-size:14px; font-weight:500; }

.pselect-menu{ position:absolute; top:calc(100% + 6px); left:0; min-width:100%; width:max-content; max-width:min(280px, calc(100vw - 32px)); background:var(--surface); border:1.5px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); padding:6px; z-index:300; display:none; max-height:280px; overflow-y:auto; }
.pselect.open .pselect-menu{ display:block; animation:rise .14s ease; }
.pselect-opt{ display:flex; align-items:center; gap:10px; width:100%; text-align:left; font-family:inherit; font-size:13.5px; font-weight:500; color:var(--ink-2); background:none; border:0; border-radius:8px; padding:9px 11px; cursor:pointer; white-space:nowrap; }
.pselect-opt > span{ flex:1; }
.pselect-opt > i{ font-size:11px; color:var(--accent); opacity:0; flex:none; }
.pselect-opt:hover{ background:var(--surface-2); color:var(--ink); }
.pselect-opt.is-selected{ color:var(--ink); font-weight:600; background:var(--accent-tint); }
.pselect-opt.is-selected > i{ opacity:1; }

/* =========================================================================
   BOOTSTRAP-COMPONENT COMPAT (Praxis-styled). The praxis-app layout loads
   Bootstrap's JS but NOT its CSS, so converted pages that keep Bootstrap
   modals / dropdowns / forms get their structure + Praxis look from here.
   ========================================================================= */
/* modal */
.modal{ position:fixed; inset:0; z-index:1055; display:none; width:100%; height:100%; overflow-x:hidden; overflow-y:auto; outline:0; }
.modal-dialog{ position:relative; width:auto; margin:1.75rem auto; max-width:540px; pointer-events:none; }
.modal-dialog-centered{ display:flex; align-items:center; min-height:calc(100% - 3.5rem); }
/* phones: width:auto + margin:auto made the dialog touch both screen edges */
@media(max-width:575.98px){ .modal-dialog{ margin:.75rem; } .modal-dialog-centered{ min-height:calc(100% - 1.5rem); } }
.modal-lg{ max-width:820px; } .modal-xl{ max-width:1160px; }
.modal-content{ position:relative; display:flex; flex-direction:column; width:100%; pointer-events:auto; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-xl); box-shadow:var(--shadow-lg); }
.modal-header{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:18px 22px; border-bottom:1px solid var(--line); }
/* margin:0 - an <h5> title would otherwise keep the browser's heading margins (praxis.css only
   resets h1-h4), which made every h5-titled modal header about 100px tall */
.modal-title{ font-weight:700; font-size:18px; line-height:1.3; margin:0; }
.modal-body{ padding:20px 22px; }
.modal-footer{ display:flex; align-items:center; justify-content:flex-end; flex-wrap:wrap; gap:8px; padding:14px 22px; border-top:1px solid var(--line); }
.modal-backdrop{ position:fixed; inset:0; z-index:1050; width:100vw; height:100vh; background:#151313; }
.modal-backdrop.fade{ opacity:0; transition:opacity .15s linear; } .modal-backdrop.show{ opacity:.45; }
.modal.fade .modal-dialog{ transition:transform .2s ease-out; transform:translateY(-12px); } .modal.show .modal-dialog{ transform:none; }
.btn-close{ width:32px; height:32px; border:0; border-radius:9px; background:var(--surface-2); color:var(--ink-2); cursor:pointer; font-size:0; position:relative; }
.btn-close::before{ content:"\00d7"; font-size:22px; line-height:1; }
.btn-close:hover{ background:var(--surface-inset); }
/* dropdown (Bootstrap JS + Popper positions it; we style it) */
.dropdown-menu{ display:none; position:absolute; z-index:1000; min-width:11rem; background:var(--surface); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); padding:8px; font-size:13.5px; color:var(--ink-2); }
.dropdown-menu.show{ display:block; }
.dropdown-menu-dark{ background:var(--rail); border-color:rgba(255,255,255,.1); color:var(--on-dark); }
.dropdown-item{ display:block; width:100%; padding:8px 11px; border-radius:8px; color:var(--ink-2); text-decoration:none; background:none; border:0; text-align:left; cursor:pointer; }
.dropdown-item:hover{ background:var(--surface-2); color:var(--ink); }
/* forms */
.form-control, .form-select{ display:block; width:100%; background:var(--surface-2); border:1.5px solid var(--line); border-radius:var(--r-md); padding:10px 12px; font-size:14px; font-family:inherit; color:var(--ink); outline:none; transition:border-color .15s, box-shadow .15s; }
.form-control:focus, .form-select:focus{ border-color:var(--accent); background:var(--surface); box-shadow:0 0 0 3px var(--accent-tint); }
.form-check-input{ width:16px; height:16px; accent-color:var(--accent); }
.form-label{ font-weight:600; font-size:13.5px; margin-bottom:6px; display:inline-block; }

/* =========================================================================
   APP-CLASS COMPAT - maps the old app's utility/button/subject/alert classes
   to Praxis tokens, so converted pages that keep old markup (modals, AJAX-
   injected HTML) render in the Praxis look. Bootstrap grid/utilities cover the
   structural classes (d-flex, row, col, spacing); this covers the app-specific
   ones. Progressively rewrite key pages to native Praxis classes over time.
   ========================================================================= */
/* text colour + size + weight utilities */
.text-70{ color:var(--ink-muted); } .text-7e{ color:var(--ink-faint); } .text-c4{ color:var(--ink-faint); }
.text-13,.text-17,.text-21{ color:var(--ink); } .text-33{ color:var(--ink-2); } .text-73{ color:var(--ink); }
.text-yellow{ color:var(--yellow); } .text-danger{ color:var(--bad-ink); } .text-success{ color:var(--good-ink); }
.main-heading{ font-size:28px; font-weight:700; letter-spacing:-.02em; color:var(--ink); }
.fw_400{font-weight:400}.fw_500{font-weight:500}.fw_700{font-weight:700}.fw_900{font-weight:800}.fw-semibold{font-weight:600}
.fs_9{font-size:9px}.fs_11{font-size:11px}.fs_13{font-size:13px}.fs_14{font-size:14px}.fs_16{font-size:16px}.fs_18{font-size:18px}.fs_20{font-size:20px}.fs_21{font-size:21px}.fs_22{font-size:22px}.fs_24{font-size:23px}.fs_37{font-size:34px}.fs_46{font-size:40px}.fs_48{font-size:44px}.fs_70{font-size:56px}.fs_100{font-size:80px}
.md-10{margin-bottom:10px}.md-20{margin-bottom:20px}.md-30{margin-bottom:26px}
.pud-20{padding:20px}.pud-50{padding:36px}
/* app button variants -> Praxis look (they sit on the app's own .btn; give them a base too) */
.btn-secondary,.btn-cancel,.btn-new,.btn-dark,.btn-success,.btn-danger,.btn-warning,.btn-table-icon,.view-btn{ display:inline-flex; align-items:center; justify-content:center; gap:8px; padding:11px 18px; border-radius:var(--r-md); font-weight:600; font-size:14px; border:1.5px solid transparent; cursor:pointer; text-decoration:none; white-space:nowrap; transition:transform .12s ease, background .16s ease; }
.btn-secondary{ background:var(--accent); color:var(--on-accent); box-shadow:0 8px 20px rgba(255,87,52,.28); }
.btn-secondary:hover{ background:var(--accent-strong); color:var(--on-accent); }
.btn-cancel{ background:var(--surface); border-color:var(--line-strong); color:var(--ink); }
.btn-cancel:hover{ background:var(--surface-2); }
.btn-dark{ background:var(--ink); color:var(--paper); }
.btn-success{ background:var(--good); color:#fff; }
.btn-danger{ background:var(--bad); color:#fff; }
.btn-warning{ background:var(--yellow); color:#151313; }
.view-btn{ background:var(--surface); border-color:var(--line-strong); color:var(--ink); }
.btn-table-icon{ width:36px; height:36px; padding:0; border-radius:10px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink-muted); }
.btn-table-icon:hover{ border-color:var(--line-strong); color:var(--ink); background:var(--surface-2); }
.btn-new{}
/* subject tags used in old markup */
[class^="subject-"], [class*=" subject-"]{ display:inline-flex; align-items:center; padding:4px 11px; border-radius:999px; font-size:12px; font-weight:600; background:var(--surface-inset); color:var(--ink-2); }
.subject-en{ background:var(--yellow-tint); color:var(--warn-ink); }
.subject-ma{ background:var(--blue-tint); color:#2C6F8E; }
.subject-sc{ background:var(--purple-tint); color:#6C39B8; }
.subject-ch,.subject-cn{ background:var(--good-tint); color:var(--good-ink); }
.subject-teacher{ display:flex; flex-wrap:wrap; gap:6px; }
/* alerts + badges */
.alert{ padding:12px 16px; border-radius:var(--r-md); font-size:14px; border:1px solid var(--line); margin-bottom:16px; }
.alert-info{ background:var(--blue-tint); color:#2C6F8E; border-color:color-mix(in srgb,var(--blue) 40%,var(--line)); }
.alert-success{ background:var(--good-tint); color:var(--good-ink); border-color:color-mix(in srgb,var(--good) 40%,var(--line)); }
.alert-danger{ background:var(--bad-tint); color:var(--bad-ink); border-color:color-mix(in srgb,var(--bad) 40%,var(--line)); }
.alert-warning{ background:var(--yellow-tint); color:var(--warn-ink); }
.badge{ display:inline-flex; align-items:center; padding:3px 9px; border-radius:999px; font-size:11px; font-weight:700; background:var(--surface-inset); color:var(--ink-2); }
.rounded-pill{ border-radius:999px; }
.bg-34{ background:var(--blue-tint); color:#2C6F8E; }

/* Bootstrap's .dropdown{position:relative} lives in component CSS we don't load,
   so Popper's absolutely-positioned menu attached to the wrong ancestor (opened
   top-left). Restore it. Also give the menu a sane min-width and end-alignment. */
.dropdown{ position:relative; }
.dropdown-menu-end{ right:0; left:auto; }

/* dropdown menu: kill the <li> bullets (Bootstrap's list reset isn't loaded), and
   position it for data-bs-display="static" (no Popper). End-align wins via specificity. */
.dropdown-menu{ top:100%; left:0; margin-top:4px; list-style:none; }
.dropdown-menu li{ list-style:none; margin:0; }
.dropdown-menu.dropdown-menu-end{ right:0; left:auto; }

/* =========================================================================
   PX-MENU - generic action menu positioned position:fixed by praxis-shell.js,
   so it escapes any overflow/scroll container (e.g. a horizontally-scrolling
   DataTable on mobile). Use: <button data-px-menu>…</button><div class="px-menu">…</div>
   ========================================================================= */
.px-menu{ position:fixed; display:none; z-index:1200; min-width:186px; background:var(--surface); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); padding:6px; }
.px-menu.open{ display:block; animation:rise .14s ease; }
.px-menu a, .px-menu button{ display:block; width:100%; text-align:left; padding:9px 11px; border-radius:8px; font-size:13.5px; font-weight:500; color:var(--ink-2); text-decoration:none; background:none; border:0; cursor:pointer; white-space:nowrap; }
.px-menu a:hover, .px-menu button:hover{ background:var(--surface-2); color:var(--ink); }
.px-menu a.danger, .px-menu button.danger{ color:var(--bad-ink); }
.px-menu a.danger:hover, .px-menu button.danger:hover{ background:var(--bad-tint); }
.px-menu li{ list-style:none; display:block; margin:0; }

/* more app component classes (classroom/student detail + their modals) */
.card-title{ font-weight:700; font-size:16px; color:var(--ink); }
.card-header{ padding:16px 22px; }
.title-class-crh{ font-weight:700; font-size:18px; color:var(--ink); }
.teacher-icon-crh{ font-size:42px; color:var(--accent); }
.class-content-crd{ display:flex; align-items:center; gap:8px; color:var(--ink-muted); font-size:13px; margin-top:6px; }
.class-content-crd i{ color:var(--ink-faint); }
.classroom-crd{ border:1px solid var(--line); border-radius:var(--r-lg); padding:18px; background:var(--surface); }
.bg-bf{ background:var(--ink) !important; }
.no_found{ text-align:center; color:var(--ink-muted); padding:24px; font-weight:600; }
.breadcrumb{ display:flex; gap:8px; list-style:none; padding:0; margin:0; font-size:13px; }
.breadcrumb-item{ color:var(--ink-muted); }
.breadcrumb-item a{ color:var(--ink-muted); text-decoration:none; }
.breadcrumb-item + .breadcrumb-item::before{ content:"/"; margin-right:8px; color:var(--ink-faint); }
.student-check-label{ border:1.5px solid var(--line); border-radius:12px; padding:12px 8px; text-align:center; transition:border-color .15s, background .15s; cursor:pointer; }
.form-check-input:checked ~ .student-check-label{ border-color:var(--accent); background:var(--accent-tint); }

/* App tooltip compat: the old theme hid `.tooltiptext` and revealed it on hover; without
   that rule the helper text leaks inline (e.g. "No. of months" on purchase pages). */
.tooltip1, .tooltip2{ position:relative; display:inline-block; }
.tooltiptext{ display:none; position:absolute; z-index:200; bottom:135%; left:50%; transform:translateX(-50%); background:var(--ink); color:#fff; padding:9px 11px; border-radius:9px; font-size:12px; font-weight:500; line-height:1.45; width:max-content; max-width:250px; box-shadow:var(--shadow-lg); text-align:left; }
.tooltip1:hover .tooltiptext, .tooltip2:hover .tooltiptext{ display:block; }

/* ---- Purchase / subscription flow shared bits ---- */
.psum{ display:flex; align-items:center; flex-wrap:wrap; }
.psum-fact{ padding:2px 28px; border-right:1px solid var(--line); }
.psum-fact:first-of-type{ padding-left:0; }
.psum-fact.last{ border-right:0; }
.psum-label{ font-size:13px; color:var(--ink-muted); font-weight:500; margin-bottom:5px; line-height:1.3; }
.psum-val{ font-size:28px; font-weight:800; color:var(--ink); line-height:1; }
.psum-val sup{ font-size:.45em; top:-1em; margin-right:1px; }
.plans{ display:flex; align-items:stretch; justify-content:center; gap:8px; flex-wrap:wrap; }
.plan-opt{ flex:1 1 340px; max-width:520px; text-align:center; padding:20px 24px; }
.plan-tag{ font-size:18px; font-weight:600; color:var(--ink-2); margin-bottom:10px; }
.plan-price{ font-size:44px; font-weight:800; color:var(--accent-strong); line-height:1; margin-bottom:2px; }
.plan-price sup{ font-size:.42em; top:-1.1em; }
.plan-price del{ font-size:.36em; color:var(--ink-faint); font-weight:500; margin-left:8px; }
.plan-sub{ font-size:20px; color:var(--ink-2); font-weight:500; margin-bottom:14px; }
.plan-desc{ font-size:14px; color:var(--ink-muted); max-width:520px; margin:0 auto 20px; line-height:1.65; }
.plan-desc .amount-Bold-text{ color:var(--ink); font-weight:800; white-space:nowrap; }
.or-line{ display:flex; align-items:center; justify-content:center; font-weight:700; color:var(--ink-muted); font-size:14px; padding:0 6px; }
.or-line span{ display:grid; place-items:center; width:40px; height:40px; border-radius:50%; border:1.5px solid var(--line); background:var(--surface-2); }
.subs-plan{ background:var(--accent-tint); border-radius:14px; padding:22px; }
.subs-plan .sp-label{ font-size:13px; color:var(--ink-muted); font-weight:500; }
.subs-plan .sp-name{ font-size:22px; font-weight:700; color:var(--accent-strong); margin-top:2px; }
.subs-plan .sp-amt{ font-size:26px; font-weight:800; color:var(--ink); margin-top:2px; }
.subs-plan .sp-amt sup{ font-size:.5em; top:-.8em; }
/* result (status) pages */
.pstatus{ text-align:center; padding:44px 24px; max-width:520px; margin:0 auto; }
.pstatus .ps-ico{ width:84px; height:84px; border-radius:50%; display:grid; place-items:center; font-size:38px; margin:0 auto 18px; }
.pstatus .ps-ico.ok{ background:var(--good-tint,#d9f2e4); color:var(--good-ink,#1a7f43); }
.pstatus .ps-ico.bad{ background:var(--bad-tint,#fde5e0); color:var(--bad-ink,#c0341a); }
.pstatus h1{ font-size:24px; font-weight:700; margin-bottom:8px; }
.pstatus p{ color:var(--ink-muted); font-size:14.5px; line-height:1.6; margin-bottom:22px; }
/* ---- uploaded question / answer images: enforce a minimum size ----
   Images pasted into the question or answer editor render at whatever size they were
   uploaded, so a small file shows up postage-stamp sized and unreadable. Floor the BOX
   at 240x200 and let object-fit:contain scale the image up inside it - the ratio is
   preserved, so nothing stretches. This is a minimum, never a cap: larger images keep
   their own size (max-width:100% still stops them overflowing the card).
   min() on the width so a narrow card/phone can't be forced into a horizontal scroll.
   Covers the four Praxis surfaces that render question/answer HTML: the test page
   (.question-text), the Question Bank card (.lib-question-stem / .lib-answer-value)
   and the review/score pages, which share .question-text.

   IMPORTANT - the :not() below. Question HTML embeds maths as tiny inline SVGs from
   latex.codecogs.com, e.g. <img title="\frac{1}{6}" src="...svg.image?\frac{1}{6}">.
   Those are glyphs, not illustrations: a fraction is ~20x40px. Flooring them at 240x200
   inflated every fraction, cm^2 and \div in the question bank to 200px tall, which is
   what made worksheets unreadable. The floor is for pasted photos/diagrams only. */
.question-text img:not([src*="latex.codecogs.com"]),
.lib-question-stem img:not([src*="latex.codecogs.com"]),
.lib-answer-value img:not([src*="latex.codecogs.com"]){
  min-width:min(240px, 100%);
  min-height:200px;
  height:auto;
  max-width:100%;
  object-fit:contain;
  object-position:left;
}

/* Inline maths glyphs: natural size, never floored. max-width guards an oversized
   expression on a narrow screen; height:auto keeps its aspect ratio. */
.question-text img[src*="latex.codecogs.com"],
.lib-question-stem img[src*="latex.codecogs.com"],
.lib-answer-value img[src*="latex.codecogs.com"]{
  max-width:100%;
  height:auto;
}

/* generic app <table class="table"> */
.table{ width:100%; border-collapse:collapse; }
.table th{ text-align:center; font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint); font-weight:700; padding:12px 10px; white-space:nowrap; }
.table td{ padding:12px 10px; border-top:1px solid var(--line); font-size:13.5px; color:var(--ink-2); vertical-align:middle; }

/* =========================================================================
   TOPACC-BUILD-3  <- deployment marker: search the served CSS for this string to confirm
   the browser/server has this version (DevTools > Sources, or view-source the .css URL).

   Accuracy-by-topic widget (Overview). A sorted, full-width bar list - the
   "Top students" acc-bar pattern scaled up so it can rank many topics and read
   at a glance. Deliberately generic: it renders {label, percent, count} rows, so
   the same markup can back other data-driven Overview widgets later.
   ========================================================================= */
.topacc-head{display:flex;align-items:center;gap:10px;margin-bottom:4px;}
/* The free space lives on this note, NOT as margin-left:auto on the select: praxis-shell.js
   enhanceSelects() replaces every native <select> with a .pselect wrapper and copies only
   INLINE styles across, so a class-based auto margin is silently dropped and the dropdown
   ends up hugging the text. Letting the note grow pushes whatever follows to the right
   whether or not the select has been enhanced. */
.topacc-note{flex:1 1 auto;min-width:0;}
/* The 22px gutter lives in ONE place - .topacc-row / .topacc-pending below - not split
   between this container and the row. Splitting it (16px here + 6px there) worked out to the
   same number but made the alignment hard to verify and easy to break from either side. */
.topacc-list{display:flex;flex-direction:column;gap:3px;padding:10px 0 14px;}
/* Label column is CAPPED, not a raw fraction - at 1.1fr it grew with the card and left a
   wide gap between a short topic name and its bar on desktop. */
/* 22px horizontal = the same gutter as .card-head, so a topic name lines up directly under
   the card title and the answer-count clears the right edge. Row spans the full card width,
   so the hover highlight reads like a table row. */
.topacc-row{display:grid;grid-template-columns:minmax(110px,230px) minmax(120px,1fr) auto auto;align-items:center;gap:16px;padding:9px 22px;}
.topacc-row:hover{background:var(--surface-2);}
.topacc-label{font-size:13.5px;font-weight:600;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.topacc-track{height:9px;border-radius:999px;background:var(--surface-inset);overflow:hidden;}
.topacc-track i{display:block;height:100%;border-radius:999px;transition:width .5s cubic-bezier(.2,.7,.2,1);}
.topacc-pct{font-size:13.5px;font-weight:700;color:var(--ink);min-width:38px;text-align:right;}
.topacc-count{font-size:11.5px;color:var(--ink-faint);min-width:66px;text-align:right;white-space:nowrap;}
.topacc-empty{padding:26px 22px;text-align:center;color:var(--ink-muted);font-size:13.5px;}
.topacc-pending{padding:12px 22px 0;margin-top:4px;border-top:1px solid var(--line);font-size:11.5px;color:var(--ink-faint);text-align:right;}

/* Teaching companion chat */
.cp-msg{display:flex;gap:12px;margin-bottom:18px;align-items:flex-start;}
.cp-msg.cp-user{justify-content:flex-end;}
.cp-avatar{width:34px;height:34px;border-radius:11px;flex:none;display:grid;place-items:center;background:var(--accent-tint);color:var(--accent-strong);font-size:14px;}
.cp-bubble{max-width:min(74ch,86%);background:var(--surface-2);border:1px solid var(--line);border-radius:14px;padding:13px 16px;font-size:14px;line-height:1.55;color:var(--ink-2);}
.cp-user .cp-bubble{background:var(--ink);color:var(--on-dark);border-color:var(--ink);}
.cp-bubble p{margin:0 0 9px;}
.cp-bubble p:last-child,.cp-bubble ul:last-child{margin-bottom:0;}
.cp-bubble strong{color:var(--ink);font-weight:700;}
.cp-user .cp-bubble strong{color:var(--on-dark);}
.cp-thinking{color:var(--ink-faint);font-style:italic;}
.cp-tools{margin-top:11px;padding-top:9px;border-top:1px solid var(--line);font-size:11.5px;color:var(--ink-faint);display:flex;flex-wrap:wrap;gap:6px;align-items:center;}
.cp-tool{background:var(--surface-inset);border-radius:999px;padding:2px 9px;white-space:nowrap;}
.cp-tool em{font-style:normal;opacity:.7;}
/* Starter chips float over the bottom of the log instead of occupying their own row -
   a row would paint a full-width strip of card surface behind them. The strip is
   transparent and click-through; only the chips themselves are solid, because a chip
   sitting over message text still has to be readable. */
.cp-logwrap{position:relative;flex:1;min-height:0;display:flex;flex-direction:column;}
.cp-logwrap > .cp-scroll{flex:1;}
.cp-logwrap.has-chips > .cp-scroll{padding-bottom:58px;}
#cpChips{position:absolute;left:0;right:0;bottom:0;padding:0 20px 12px;display:flex;gap:8px;flex-wrap:wrap;background:transparent;pointer-events:none;}
#cpChips:empty{display:none;}
.cp-chip{pointer-events:auto;cursor:pointer;font-size:12.5px;background:var(--surface);border-color:var(--line);box-shadow:var(--shadow-sm);}
.cp-chip:hover{background:var(--surface-2);}
.cp-conv{display:flex;align-items:flex-start;gap:10px;width:100%;text-align:left;padding:10px 11px;border-radius:11px;color:var(--ink-2);transition:background .12s ease;}
.cp-conv:hover{background:var(--surface-2);}
.cp-conv.is-active{background:var(--accent-tint);color:var(--accent-strong);}
.cp-conv > i{font-size:12px;margin-top:3px;flex:none;opacity:.7;}
.cp-conv-body{min-width:0;flex:1;}
.cp-conv-title{display:block;font-size:13px;font-weight:600;line-height:1.35;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;}
.cp-conv-sub{display:block;font-size:11.5px;opacity:.65;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.cp-scopetag{display:inline-block;font-size:11.5px;color:var(--ink-faint);margin-top:2px;}
/* Tables and charts inside an answer. Both scroll inside their own box so a wide
   table never makes the chat pane scroll sideways. */
.cp-tablewrap{overflow-x:auto;margin:10px 0;}
.cp-table{width:100%;border-collapse:collapse;font-size:13px;}
.cp-table th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-faint);font-weight:700;padding:0 10px 7px;white-space:nowrap;}
.cp-table td{padding:8px 10px;border-top:1px solid var(--line);vertical-align:top;}
.cp-table tr:hover td{background:var(--surface);}
.cp-chart{margin:12px 0 6px;padding:0;}
.cp-chart figcaption{font-size:12.5px;font-weight:700;color:var(--ink);margin-bottom:2px;}
.cp-chart-src{font-size:11px;color:var(--ink-faint);text-align:right;margin-top:-4px;}
@media (max-width:760px){
  .cp-bubble{max-width:88%;}
}

/* Learning-gap matrix (students x topics). Column count varies, so JS sets
   grid-template-columns inline; everything else lives here. Topic headers run
   vertically because ten horizontal labels never fit without truncating to noise. */
.gapmx{overflow-x:auto;padding-top:8px;}
.gapmx-grid{display:grid;gap:4px;min-width:max-content;}
.gapmx-h{font-size:11px;color:var(--ink-faint);font-weight:700;letter-spacing:.04em;writing-mode:vertical-rl;transform:rotate(180deg);height:84px;display:flex;align-items:flex-end;justify-content:center;white-space:nowrap;overflow:hidden;}
.gapmx-h.is-flat{writing-mode:horizontal-tb;transform:none;height:auto;min-height:26px;align-items:flex-end;justify-content:center;text-align:center;white-space:normal;line-height:1.25;padding:0 4px;}
.gapmx-name{font-size:12.5px;font-weight:600;color:var(--ink-2);line-height:1.3;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;padding-right:12px;align-self:center;}
.gapmx-cell{height:34px;border-radius:7px;display:grid;place-items:center;font-size:11.5px;font-weight:700;color:#151313;}
.gapmx-cell.is-empty{background:var(--surface-inset);color:var(--ink-faint);font-weight:500;}
.gapmx-legend{display:flex;gap:16px;align-items:center;justify-content:flex-end;margin-top:16px;font-size:11.5px;color:var(--ink-faint);flex-wrap:wrap;}
.gapmx-key{display:inline-flex;align-items:center;gap:6px;}
.gapmx-key i{width:14px;height:14px;border-radius:4px;display:inline-block;}
@media (max-width:760px){
  .gapmx-name{font-size:12px;padding-right:8px;}
  .gapmx-h{height:70px;}
}
/* Tablet down: the qualifier note ("your students · assigned work · weakest first") is the
   first thing to squash the header and push the subject picker onto its own line. Drop it -
   the title and the picker are the only actionable parts at this width. */
@media (max-width:720px){
  .topacc-note{display:none;}
}
/* Phone: two columns, label+% on one line and the bar+count beneath, so a long topic name
   still gets the full width. count stays right-aligned so it sits under the %. */
@media (max-width:560px){
  /* gutter stays 22px - .card-head keeps padding:18px 22px on mobile (no small-screen
     override), so the rows must match it at every breakpoint or they drift out of line */
  .topacc-list{padding:8px 0 12px;}
  .topacc-row{grid-template-columns:1fr auto;grid-template-areas:"label pct" "track count";row-gap:7px;column-gap:12px;padding:10px 22px;}
  .topacc-label{grid-area:label;white-space:normal;line-height:1.35;}
  .topacc-pct{grid-area:pct;}
  .topacc-track{grid-area:track;}
  .topacc-count{grid-area:count;min-width:0;}
  .topacc-empty{padding:22px 8px;}
}
