*{box-sizing:border-box;margin:0;padding:0}
/* base tokens from theme.css */
body{background:var(--bg);color:var(--text);font-family:'Space Grotesk',system-ui,sans-serif;min-height:100vh;min-height:100dvh}
header{display:flex;align-items:center;justify-content:space-between;padding:14px 28px;background:var(--hdr-bg);backdrop-filter:blur(12px);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:100}
.hdr-r{display:flex;align-items:center;gap:12px;font-size:.82rem;color:var(--dim)}
.cls-sel{background:var(--surf2);border:1px solid var(--border);border-radius:8px;padding:6px 12px;font-family:inherit;font-size:.85rem;color:var(--text);outline:none;cursor:pointer}
.btn-sm{border-radius:8px;padding:6px 14px;font-family:inherit;font-size:.82rem;cursor:pointer;font-weight:600;transition:all .2s}
.btn-refresh{background:rgba(124,92,191,.15);border:1px solid var(--accent);color:var(--accent)}
.btn-refresh:hover{background:rgba(124,92,191,.25)}
.btn-danger{background:rgba(239,68,68,.12);border:1px solid rgba(239,68,68,.3);color:var(--red)}
.btn-danger:hover{background:rgba(239,68,68,.2)}
.btn-success{background:rgba(34,197,94,.12);border:1px solid rgba(34,197,94,.3);color:var(--green)}
.btn-success:hover{background:rgba(34,197,94,.2)}
main{max-width:1200px;margin:0 auto;padding:28px 24px}
.tab-panel{display:none}.tab-panel.active{display:block}
.login-wrap{display:flex;align-items:center;justify-content:center;min-height:100vh;min-height:100dvh}
.login-card{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:36px;width:100%;max-width:360px;text-align:center}
.pw-inp{width:100%;background:var(--surf2);border:1px solid var(--border);border-radius:9px;padding:12px 14px;font-family:inherit;font-size:.95rem;color:var(--text);outline:none;margin-bottom:12px;text-align:center;letter-spacing:3px}
.pw-inp:focus{border-color:var(--accent)}
.pw-btn{width:100%;background:var(--grad);border:none;border-radius:9px;padding:13px;font-family:inherit;font-size:.95rem;font-weight:700;color:#fff;cursor:pointer}
.pw-err{color:var(--red);font-size:.82rem;margin-top:8px}
.section-title{font-size:.7rem;text-transform:uppercase;letter-spacing:1.3px;color:var(--dim);font-weight:700;margin-bottom:12px;margin-top:28px}
.section-title:first-child{margin-top:0}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.card{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:20px}
.card h3{font-size:.85rem;font-weight:700;margin-bottom:14px;color:var(--text)}
.kpi{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:18px}
.kpi .val{font-size:2rem;font-weight:800;margin-bottom:2px}
.kpi .lbl{font-size:.75rem;color:var(--dim)}
.kpi .sub{font-size:.78rem;color:var(--dim);margin-top:4px}
.kpi.green .val{color:var(--green)} .kpi.blue .val{color:var(--accent)}
.kpi.yellow .val{color:var(--yellow)} .kpi.purple .val{color:var(--accent2)}
.chart-card{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:20px}
.chart-card h3{font-size:.82rem;font-weight:700;margin-bottom:16px}
.chart-wrap{position:relative;height:220px}
.tbl-wrap{
  background:var(--surf);border:1px solid var(--border);border-radius:var(--r);
  overflow-x:auto;overflow-y:hidden;
  position:relative;
  /* Right-edge scroll hint */
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent);
}
@media(min-width:768px){
  .tbl-wrap{-webkit-mask-image:none;mask-image:none}
}
table{width:100%;border-collapse:collapse}
th{background:var(--surf2);padding:10px 14px;font-size:.72rem;text-transform:uppercase;letter-spacing:1px;color:var(--dim);font-weight:700;text-align:left;white-space:nowrap}
td{padding:10px 14px;font-size:.85rem;border-top:1px solid var(--border);vertical-align:middle}
tr:hover td{background:rgba(255,255,255,.02)}
.badge{display:inline-block;border-radius:6px;padding:2px 9px;font-size:.72rem;font-weight:700}
.badge.ok{background:rgba(34,197,94,.15);color:var(--green)}
.badge.mid{background:rgba(245,158,11,.15);color:var(--yellow)}
.badge.bad{background:rgba(239,68,68,.12);color:var(--red)}
.badge.gray{background:var(--surf2);color:var(--dim)}
.badge.blue{background:rgba(124,92,191,.15);color:var(--accent)}
.trend.up{color:var(--green)} .trend.down{color:var(--red)} .trend.flat{color:var(--dim)}
.total-row{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-radius:9px;font-size:.88rem;font-weight:700}
.total-row.ok{background:rgba(34,197,94,.1);border:1px solid rgba(34,197,94,.3);color:var(--green)}
.total-row.bad{background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);color:var(--red)}
.save-btn{width:100%;background:var(--grad);border:none;border-radius:10px;padding:13px;font-family:inherit;font-size:.92rem;font-weight:700;color:#fff;cursor:pointer;margin-top:12px;transition:opacity .2s}
.save-btn:hover{opacity:.9}
.save-btn:disabled{opacity:.4;cursor:not-allowed}
.sbar-leg-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.sbar-inp-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.sbar-inp-label{flex:1;font-size:.83rem}
.sbar-inp{width:68px;background:var(--surf2);border:1px solid var(--border);border-radius:8px;padding:7px 8px;font-family:inherit;font-size:.95rem;font-weight:700;color:var(--accent);text-align:center;outline:none}
.sbar-inp:focus{border-color:var(--accent)}
.class-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px}
.cls-pill{padding:7px 16px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);font-size:.82rem;font-weight:600;color:var(--dim);cursor:pointer;transition:all .2s}
.cls-pill.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}
.src-skill-pill{padding:5px 13px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);font-size:.76rem;font-weight:600;color:var(--dim);cursor:pointer;transition:all .2s}
.src-skill-pill.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}
.preview-bar{display:flex;height:24px;border-radius:8px;overflow:hidden;gap:2px;margin:14px 0}
.preview-seg{display:flex;align-items:center;justify-content:center;font-size:.68rem;font-weight:700;color:#fff;transition:flex .3s;min-width:0;overflow:hidden}
.srs-alert{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.25);border-radius:var(--r);padding:12px 16px;margin-bottom:8px;display:flex;align-items:center;gap:10px;font-size:.84rem}
.word-chip{background:var(--surf2);border:1px solid var(--border);border-radius:99px;padding:5px 12px;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;margin:4px}
.word-chip .wc-cnt{background:var(--red);color:#fff;border-radius:99px;padding:1px 7px;font-size:.7rem;font-weight:700}
/* Feature 5 — writing-progress view toggle + table */
.wp-vtab{padding:5px 13px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);font-size:.76rem;font-weight:600;color:var(--dim);cursor:pointer;transition:all .2s}
.wp-vtab.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}
.wp-spark{display:block;width:110px;height:30px}
.wp-band{font-variant-numeric:tabular-nums;font-weight:700}
.loading{text-align:center;padding:40px;color:var(--dim)}
.spinner{width:28px;height:28px;border:3px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin 1s linear infinite;margin:0 auto 12px}
@keyframes spin{to{transform:rotate(360deg)}}
/* Discoverability nudge (item#8): "Chế độ làm bài" hint links here → briefly
   highlight the Test Room button so the jump doesn't land on dead silence. */
.hw-pulse{animation:hwPulse 1.6s ease-out}
@keyframes hwPulse{0%{box-shadow:0 0 0 0 rgba(124,92,191,.55)}100%{box-shadow:0 0 0 12px rgba(124,92,191,0)}}
.empty-state{text-align:center;padding:32px;color:var(--dim);font-size:.88rem}
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:200;display:none;align-items:center;justify-content:center}
.modal-overlay.show{display:flex}
.modal{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:28px;max-width:380px;width:90%;text-align:center}
.modal h3{margin-bottom:8px} .modal p{color:var(--dim);font-size:.85rem;margin-bottom:20px}
.modal-btns{display:flex;gap:10px}
.modal-btns button{flex:1;padding:11px;border-radius:9px;font-family:inherit;font-size:.88rem;font-weight:700;cursor:pointer}
.modal-btns .m-cancel{background:var(--surf2);border:1px solid var(--border);color:var(--text)}
.modal-btns .m-confirm{background:var(--red);border:none;color:#fff}
/* ── Per-student detail modal (galaxy snapshot, QoL #2) ── */
.stu-modal{max-width:540px;width:94%;text-align:left;max-height:88vh;overflow-y:auto;padding:22px}
.stu-modal-hd{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:14px}
.stu-modal-sub{color:var(--dim);font-size:.82rem;margin-top:3px}
.stu-modal-x{background:var(--surf2);border:1px solid var(--border);color:var(--text);width:32px;height:32px;border-radius:8px;cursor:pointer;font-size:.9rem;flex-shrink:0}
.stu-kpis{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-bottom:14px}
.stu-kpi{background:var(--surf2);border:1px solid var(--border);border-radius:10px;padding:10px;text-align:center}
.stu-kpi .v{font-size:1.3rem;font-weight:800;line-height:1}
.stu-kpi .l{font-size:.64rem;color:var(--dim);text-transform:uppercase;letter-spacing:.5px;margin-top:4px}
.stu-galaxy-wrap{position:relative;width:220px;max-width:70%;margin:4px auto;aspect-ratio:1/1}
.stu-galaxy-svg{width:100%;height:100%;display:block}
.stu-galaxy-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}
/* The center sits on the FIXED dark disc (#0F1729) drawn inside the SVG, so its
   text must use fixed light colors — not theme vars, which turn dark in the
   light-theme dashboard and make the total vanish into the disc. */
.stu-g-total{font-size:1.5rem;font-weight:800;color:#F1F5F9;line-height:1}
.stu-g-lbl{font-size:.62rem;color:#94A3B8}
.stu-gal-legend{display:flex;justify-content:center;gap:14px;flex-wrap:wrap;margin:8px 0 16px;font-size:.72rem;color:var(--dim)}
.stu-gal-legend span{display:inline-flex;align-items:center;gap:5px}
.stu-gal-dot{width:10px;height:10px;border-radius:50%;display:inline-block;background:#7C5CBF}
.stu-sec-hd{font-size:.7rem;text-transform:uppercase;letter-spacing:1px;color:var(--dim);margin:6px 0 8px;font-weight:700}
.stu-unit-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:.78rem}
.stu-unit-name{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text)}
.stu-unit-track{width:70px;height:6px;background:var(--surf2);border-radius:99px;overflow:hidden;flex-shrink:0}
.stu-unit-fill{height:100%;background:linear-gradient(90deg,#7C5CBF,#22c55e)}
.stu-unit-cnt{min-width:42px;text-align:right;color:var(--dim);font-weight:700;flex-shrink:0}
.stu-empty{color:var(--dim);font-size:.82rem;text-align:center;padding:14px}
.pf-card{cursor:pointer;transition:border-color .15s}
.pf-card:hover{border-color:var(--accent,#7C5CBF)}
#pfRankBody tr{cursor:pointer}
#pfRankBody tr:hover td{background:var(--surf2)}
.class-item{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:16px 20px;display:flex;align-items:center;justify-content:space-between;gap:12px;transition:border-color .2s}
.ci-info{flex:1;min-width:0}
.ci-code{font-weight:800;font-size:1rem;margin-bottom:2px}
.ci-label{font-size:.8rem;color:var(--dim)}
.ci-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
.move-sel{background:var(--surf2);border:1px solid var(--border);border-radius:8px;padding:5px 8px;font-family:inherit;font-size:.82rem;color:var(--text);outline:none;cursor:pointer}
.btn-icon{background:transparent;border:1px solid var(--border);border-radius:8px;padding:5px 10px;font-family:inherit;font-size:.78rem;cursor:pointer;color:var(--dim);transition:all .2s}
.btn-icon:hover{border-color:var(--accent);color:var(--accent)}
.attend-class-block{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);margin-bottom:14px;overflow:hidden}
.attend-class-hd{background:var(--surf2);padding:10px 16px;display:flex;align-items:center;gap:10px;border-bottom:1px solid var(--border)}
.attend-class-hd b{font-size:.9rem}
.attend-unit-row{padding:10px 16px;border-bottom:1px solid rgba(42,47,74,.5);display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap}
.attend-unit-row:last-child{border-bottom:none}
.attend-unit-name{font-size:.78rem;font-weight:700;color:var(--text2);min-width:220px;flex-shrink:0;padding-top:2px}
.attend-badges{display:flex;gap:5px;flex-wrap:wrap;flex:1}
.attend-std-block{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);margin-bottom:10px;overflow:hidden}
.attend-std-hd{background:var(--surf2);padding:11px 16px;display:flex;align-items:center;gap:10px;cursor:pointer;list-style:none;user-select:none}
.attend-std-hd::-webkit-details-marker{display:none}
.attend-std-hd b{font-size:.9rem}
.attend-std-block details>.attend-std-hd .attend-caret{transition:transform .2s}
.attend-std-block details[open]>.attend-std-hd .attend-caret{transform:rotate(90deg)}
.attend-prog-row{padding:11px 16px;border-bottom:1px solid rgba(42,47,74,.5)}
.attend-prog-row:last-child{border-bottom:none}
.attend-prog-name{font-size:.8rem;font-weight:700;color:var(--text);margin-bottom:6px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.attend-track-row{display:flex;align-items:center;gap:6px;margin:2px 0}
.attend-track{width:90px;height:4px;background:var(--surf2);border-radius:99px;overflow:hidden;flex-shrink:0}
.attend-track-fill{height:100%;border-radius:99px;transition:width .4s}
.attend-track-lbl{font-size:.66rem;color:var(--dim)}
/* Attendance v2 — grid unit cards + hover popover (chi tiết 3 track) */
.attend-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:8px;padding:12px 16px}
.attend-cell{position:relative;background:var(--surf2);border:1px solid var(--border);border-radius:9px;padding:9px 11px;cursor:default}
.attend-cell:hover{border-color:var(--accent)}
.attend-cell-name{font-size:.74rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:6px}
.attend-mini{position:relative;height:6px;background:var(--surf);border-radius:99px;overflow:hidden;margin-bottom:6px}
.attend-mini-fill{position:absolute;left:0;top:0;height:100%;border-radius:99px}
.attend-cell-nums{font-size:.66rem;color:var(--dim);white-space:nowrap}
.attend-pop{display:none;position:absolute;left:50%;transform:translateX(-50%);bottom:calc(100% + 6px);z-index:50;background:var(--bg);border:1px solid var(--accent);border-radius:9px;padding:10px 12px;min-width:200px;box-shadow:0 8px 24px rgba(0,0,0,.45)}
.attend-cell:hover .attend-pop{display:block}
.toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--surf2);border:1px solid var(--border);border-radius:9px;padding:10px 18px;font-size:.83rem;color:var(--text);z-index:999;opacity:0;transition:opacity .3s;white-space:nowrap;pointer-events:none}
.toast.show{opacity:1}
.pf-card{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:18px;transition:border-color .2s}
.pf-card:hover{border-color:var(--accent)}
.pf-card-name{font-weight:800;font-size:.95rem;margin-bottom:4px}
.pf-card-class{font-size:.72rem;color:var(--dim);margin-bottom:12px}
.pf-stat-row{display:flex;justify-content:space-between;font-size:.78rem;padding:4px 0;border-bottom:1px solid rgba(42,47,74,.5)}
.pf-stat-row:last-child{border-bottom:none}
.pf-stat-label{color:var(--dim)}
.pf-stat-val{font-weight:700}
.pf-topic-bar{display:flex;align-items:center;gap:8px;margin:3px 0;font-size:.75rem}
.pf-topic-track{flex:1;height:6px;background:var(--surf2);border-radius:99px;overflow:hidden}
.pf-topic-fill{height:100%;border-radius:99px;transition:width .4s}
.rank-medal{font-size:1.1rem;text-align:center}
@media(max-width:768px){
  #pfStudentCards{grid-template-columns:1fr}
  .grid-4{grid-template-columns:1fr 1fr}.grid-3{grid-template-columns:1fr 1fr}
  .grid-2{grid-template-columns:1fr} main{padding:16px}
  /* iOS auto-zoom fix */
  input[type=text],input[type=email],input[type=password],
  input[type=number],input[type=search],select,textarea{font-size:16px}
  .cls-pill{padding:9px 16px;min-height:38px;display:inline-flex;align-items:center}
  /* Class pill row horizontal scroll */
  [class*="cls-row"],div[style*="cls-pill"]{overflow-x:auto;-webkit-overflow-scrolling:touch;flex-wrap:nowrap!important}
}
@media(max-width:480px){
  .grid-4{grid-template-columns:1fr}.grid-3{grid-template-columns:1fr}
  main{padding:14px}
}

/* ═══ LIGHT MODE CONTRAST ═══ */
[data-theme="light"] .kpi{border-color:#c8c2d8;box-shadow:0 1px 4px rgba(0,0,0,.07)}
[data-theme="light"] .kpi .lbl,[data-theme="light"] .kpi .sub{color:#475569}
[data-theme="light"] .chart-card{border-color:#c8c2d8;box-shadow:0 1px 4px rgba(0,0,0,.07)}
[data-theme="light"] .section-title{color:#1a1a2e}
[data-theme="light"] .t2-sidebar{background:#F5F0FF;border-color:#c8c2d8}
[data-theme="light"] .pf-card{border-color:#c8c2d8;box-shadow:0 1px 4px rgba(0,0,0,.07)}
[data-theme="light"] .pf-stat-row{border-bottom-color:#c8c2d8}
[data-theme="light"] .pf-stat-label{color:#475569}
[data-theme="light"] .cls-sel{background:#F5F0FF;border-color:#c8c2d8;color:#1a1a2e}
[data-theme="light"] .btn-refresh{background:rgba(91,63,160,.12);border-color:#5B3FA0;color:#5B3FA0}

/* ═══ FIX 3 — collapsible "💡 Cách sửa" sub-bullet under a weakness bullet ═══ */
/* The weakness <li> now stacks: a flex "bline" row (number + text + ✨) on top,
   then the collapsible fix, then the AI-panel slot. Overrides the flex-row rule
   that hw-crit-bullets li carries in homework.js's injected style. */
.hw-crit-bullets li[data-wk-bi]{flex-direction:column;align-items:stretch}
.hw-crit-bline{display:flex;gap:5px;align-items:flex-start;width:100%}
details.hw-wkfix{margin:3px 0 0 18px}
details.hw-wkfix>summary{list-style:none;display:inline-flex;align-items:center;gap:4px;cursor:pointer;
  font-size:.72rem;font-weight:600;color:var(--teal);user-select:none;width:fit-content}
details.hw-wkfix>summary::-webkit-details-marker{display:none}
details.hw-wkfix>summary::before{content:'▸';color:var(--teal);transition:transform .15s;font-size:.7rem}
details.hw-wkfix[open]>summary::before{transform:rotate(90deg)}
details.hw-wkfix>summary:hover{text-decoration:underline}
.hw-wkfix-body{margin-top:3px;padding:5px 8px;font-size:.76rem;line-height:1.45;color:var(--text);
  background:var(--surf2);border:1px solid var(--border);border-left:3px solid var(--teal);border-radius:7px;
  white-space:pre-wrap;word-break:break-word}

/* ═══ FIX 1 — expandable grouped comment card: per-occurrence edit/delete ═══ */
/* ▸ toggle beside the "(N chỗ)" badge (does NOT trigger the card's group-highlight) */
/* multi cards wrap the snippet line so the ▸ toggle is never clipped by the
   default nowrap+overflow:hidden on .hw-cmt-ex */
.hw-cmt-ex.has-expand{white-space:normal;overflow:visible}
.hw-cmt-expand{background:none;border:1px solid var(--border);border-radius:6px;color:var(--accent);
  font-size:.66rem;line-height:1;padding:1px 5px;margin-left:4px;cursor:pointer;transition:transform .15s,border-color .15s}
.hw-cmt-expand:hover{border-color:var(--accent)}
.hw-cmt-expand.is-open{transform:rotate(90deg)}
.hw-cmt-occs{margin-top:6px;padding-left:4px;border-left:2px solid var(--border);display:flex;flex-direction:column;gap:4px}
.hw-cmt-occ{display:flex;align-items:center;gap:5px;padding:3px 5px;border:1px solid var(--border);border-radius:7px;
  background:var(--surf2);cursor:pointer;transition:border-color .15s}
.hw-cmt-occ:hover{border-color:var(--accent)}
.hw-cmt-occ.is-editing{cursor:default}
.hw-cmt-occ-ex{flex:1 1 auto;min-width:0;font-size:.74rem;color:var(--dim);font-style:italic;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hw-cmt-occ-inp{flex:1 1 auto;min-width:0;box-sizing:border-box;font-family:inherit;font-size:.76rem;color:var(--text);
  background:var(--surf);border:1px solid var(--accent);border-radius:6px;padding:2px 6px;outline:none}

/* ═══════════════════════════════════════════════════════════════
   DASHBOARD V2 SHELL — sidebar + subnav + accordion (teacher-dashboard-v2)
   Tokens come from theme.css (--bg --surf --surf2 --accent --border --r).
   ═══════════════════════════════════════════════════════════════ */
.t2-layout{display:flex;align-items:stretch;min-height:calc(100dvh - var(--t2-hdr,61px))}
.t2-sidebar{position:sticky;top:var(--t2-hdr,61px);align-self:flex-start;height:calc(100dvh - var(--t2-hdr,61px));
  width:228px;flex-shrink:0;display:flex;flex-direction:column;gap:4px;
  background:var(--surf);border-right:1px solid var(--border);padding:14px 10px;overflow-y:auto}
.t2-main{flex:1;min-width:0}
.t2-classbox{padding:0 4px 10px;border-bottom:1px solid var(--border);margin-bottom:8px}
.t2-classbox-lbl{font-size:.66rem;text-transform:uppercase;letter-spacing:1px;color:var(--dim);font-weight:700;margin-bottom:6px}
.t2-class-sel{width:100%;background:var(--surf2);border:1px solid var(--border);border-radius:9px;padding:8px 10px;
  font-family:inherit;font-size:.85rem;font-weight:600;color:var(--text);outline:none;cursor:pointer}
.t2-class-sel:focus{border-color:var(--accent)}
.t2-nav{display:flex;flex-direction:column;gap:2px}
.t2-nav-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;border:none;background:transparent;
  color:var(--dim);font-family:inherit;font-size:.88rem;font-weight:600;cursor:pointer;text-align:left;text-decoration:none;
  white-space:nowrap;transition:background .15s,color .15s}
.t2-nav-item:hover{color:var(--text);background:var(--surf2)}
.t2-nav-item.active{background:rgba(124,92,191,.15);color:var(--accent)}
.t2-nav-ico{font-size:1.02rem;width:22px;text-align:center;flex-shrink:0}
.t2-foot{margin-top:auto;padding:10px 4px 2px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:8px}
.t2-foot #lastUpdate{color:var(--dim);font-size:.7rem;white-space:normal}
.t2-subnav{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-bottom:20px}
.t2-subtab{padding:8px 16px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);
  font-family:inherit;font-size:.82rem;font-weight:600;color:var(--dim);cursor:pointer;text-decoration:none;transition:all .2s}
.t2-subtab:hover{color:var(--text)}
.t2-subtab.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}
/* ── Homework Hub skill tabs (hwhub-skilltabs.js) ──────────────────────
   One row of pills above 📥 Chấm bài / 📤 Giao bài, picking which skill's
   panel is shown. Styled off .t2-subtab (same pill language as the zone
   sub-nav directly above it) but a BUTTON, not a link — these switch a
   client-side filter, not the route, so they must not look bookmarkable.
   Defined at top level, not under .hwhub: the strip lives in
   #panel-hwhub-skilltabs, whose own class list is `tab-panel hwhub`, so a
   `.hwhub .hh-skilltab` rule would need the panel to be an ANCESTOR — it is
   the element itself. (See TEACHER_GATEWAY_REFERENCE §5.4 for the scoping
   trap this avoids.) */
.hh-skilltabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px;
  border-bottom:1px solid var(--border);padding-bottom:14px}
.hh-skilltab{padding:8px 16px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);
  font-family:inherit;font-size:.85rem;font-weight:600;color:var(--dim);cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;transition:all .2s}
.hh-skilltab:hover{color:var(--text)}
.hh-skilltab.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}
.hh-skilltab-n{background:var(--accent);color:#fff;border-radius:99px;
  font-size:.72rem;font-weight:700;padding:1px 7px;line-height:1.5}
.hh-skilltab.active .hh-skilltab-n{background:var(--accent)}

.t2-banner{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.3);color:var(--yellow);
  border-radius:10px;padding:10px 14px;margin-bottom:16px;font-size:.84rem;font-weight:600}
details.t2-acc{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);margin-top:18px}
details.t2-acc>summary{cursor:pointer;padding:14px 18px;font-size:.74rem;font-weight:700;color:var(--dim);
  text-transform:uppercase;letter-spacing:1.2px;list-style:none;user-select:none;display:flex;align-items:center;gap:8px}
details.t2-acc>summary::-webkit-details-marker{display:none}
details.t2-acc>summary::before{content:'▸';color:var(--accent);transition:transform .15s}
details.t2-acc[open]>summary::before{transform:rotate(90deg)}
details.t2-acc>summary:hover{color:var(--text)}
.t2-acc-body{padding:2px 18px 18px}
.t2-acc-body>.section-title:first-child{margin-top:8px}
[data-theme="light"] .t2-classbox,[data-theme="light"] .t2-foot{border-color:#c8c2d8}
[data-theme="light"] details.t2-acc{border-color:#c8c2d8}

/* ═══════════════════════════════════════════════════════════════
   🔔 VIỆC CẦN LÀM — sidebar badge (t2SetClass box) + board panel
   (vocab/teacher/todo-board.js). Prefix tdb- for board-body markup;
   the sidebar chip keeps the t2- prefix since it lives inside the
   existing sidebar chrome, not the panel.
   ═══════════════════════════════════════════════════════════════ */
.t2-todo-badge{display:flex;align-items:center;gap:8px;justify-content:center;width:100%;
  margin-bottom:10px;padding:9px 10px;border-radius:10px;border:1px solid rgba(245,158,11,.4);
  background:rgba(245,158,11,.12);color:var(--yellow);font-family:inherit;font-weight:700;
  font-size:.85rem;cursor:pointer;transition:all .2s}
.t2-todo-badge:hover{background:rgba(245,158,11,.22)}
.t2-todo-badge.tdb-zero{border-color:var(--border);background:var(--surf2);color:var(--dim)}
.t2-todo-badge.t2-todo-badge-err{border-color:rgba(239,68,68,.4);background:rgba(239,68,68,.12);color:var(--red)}
.tdb-err-banner{background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.3);color:var(--red);
  border-radius:10px;padding:12px 16px;margin-bottom:16px;font-size:.84rem;line-height:1.5}
.tdb-acc{margin-top:0;margin-bottom:12px}
.tdb-acc-body{display:flex;flex-direction:column;gap:8px;padding-top:6px}
.tdb-item{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;
  background:var(--surf2);border:1px solid var(--border);border-radius:10px;padding:10px 14px}
.tdb-item-main{flex:1;min-width:220px;font-size:.85rem;line-height:1.5}
.tdb-item-sub{font-size:.75rem;color:var(--dim);margin-top:3px}
.tdb-fam-badge{display:inline-block;background:rgba(124,92,191,.15);color:var(--accent);
  border-radius:6px;padding:1px 8px;font-size:.7rem;font-weight:700;margin-right:6px}
.tdb-item-ctl{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex-shrink:0}
.tdb-actions{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.tdb-snooze-sel{background:var(--surf);border:1px solid var(--border);border-radius:7px;
  padding:5px 6px;font-family:inherit;font-size:.76rem;color:var(--text)}
@media(max-width:768px){
  .t2-todo-badge .t2-nav-lbl{display:none}
  .t2-todo-badge{padding:9px 4px}
}
[data-theme="light"] .tdb-item{border-color:#c8c2d8}
[data-theme="light"] .tdb-snooze-sel{border-color:#c8c2d8}
/* ── Gom việc theo bài tập + phân mục tồn đọng/mới (2026-08-02) ────── */
.tdb-bucket{margin-bottom:14px}
.tdb-bucket-hdr{display:flex;align-items:center;gap:8px;font-weight:800;font-size:.82rem;
  letter-spacing:.01em;margin:2px 0 8px;color:var(--text)}
.tdb-bucket--old .tdb-bucket-hdr{color:var(--red)}
.tdb-cls-block{margin:0 0 10px;padding-left:10px;border-left:2px solid var(--border)}
.tdb-cls-hdr{display:flex;align-items:center;gap:7px;font-size:.78rem;font-weight:700;
  color:var(--dim);margin:6px 0 6px}
.tdb-group{margin-bottom:8px}
.tdb-group--old{border-left:3px solid var(--red)}
.tdb-n-pill{display:inline-block;background:rgba(124,92,191,.18);color:var(--accent);
  border-radius:999px;padding:1px 8px;font-size:.7rem;font-weight:800;margin-left:6px}
.tdb-group-kids{margin-top:8px;display:flex;flex-direction:column;gap:4px;
  padding-top:7px;border-top:1px dashed var(--border)}
.tdb-kid{display:flex;align-items:center;gap:8px;font-size:.78rem}
.tdb-kid-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tdb-kid-when{color:var(--dim);font-size:.72rem;flex-shrink:0}
[data-theme="light"] .tdb-cls-block{border-left-color:#c8c2d8}
[data-theme="light"] .tdb-group-kids{border-top-color:#c8c2d8}
/* ═══════════════════════════════════════════════════════════════
   📖 LUYỆN ĐỀ R/L TAB (rl-tab.js) — assignment card grid + heatmap.
   All classes prefixed .rlz- (additions only, per file-ownership rule).
   ═══════════════════════════════════════════════════════════════ */
.rlz-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px}
details.rlz-asg-card{margin-top:0}
details.rlz-asg-card>summary.rlz-asg-summary{display:flex;align-items:center;gap:10px;text-transform:none;letter-spacing:normal;font-weight:700}
.rlz-skill-ico{font-size:1.05rem;flex-shrink:0}
.rlz-asg-title{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text);font-size:.86rem}
.rlz-asg-body{padding-top:2px}
.rlz-asg-meta{display:flex;flex-wrap:wrap;gap:6px 16px;font-size:.78rem;color:var(--dim);margin-bottom:10px}
.rlz-asg-meta b{color:var(--text)}
.rlz-asg-detail-slot{margin-top:4px}
.rlz-heat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:6px}
.rlz-heat-cell{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  border-radius:8px;padding:8px 4px;font-size:.7rem;font-weight:700;cursor:default;border:1px solid transparent}
.rlz-heat-q{font-size:.66rem;opacity:.85}
.rlz-heat-pct{font-size:.82rem}
.rlz-heat-ok{background:rgba(34,197,94,.14);border-color:rgba(34,197,94,.35);color:var(--green)}
.rlz-heat-mid{background:rgba(245,158,11,.14);border-color:rgba(245,158,11,.35);color:var(--yellow)}
.rlz-heat-bad{background:rgba(239,68,68,.12);border-color:rgba(239,68,68,.3);color:var(--red)}
[data-theme="light"] .rlz-asg-title{color:#1a1a2e}
[data-theme="light"] .rlz-asg-meta b{color:#1a1a2e}

/* ═══════════════════════════════════════════════════════════════
   ⚙️ QUẢN LÝ ĐỀ R/L (rl-manage.js) — ported from the old standalone
   rl/teacher/index.html page. All classes prefixed .rlm- (additions
   only, per file-ownership rule) — deliberately NOT reusing .rlz-*
   (that prefix belongs to rl-tab.js's read-only analytics cards) and
   NOT scoped under .hwhub (that prefix belongs to the Homework Hub).
   Tables/badges reuse the Dashboard's own generic table/.badge rules.
   ═══════════════════════════════════════════════════════════════ */
.rlm-list{display:flex;flex-direction:column;gap:14px}
.rlm-card{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);overflow:hidden;margin-bottom:14px}
.rlm-card-head{display:flex;align-items:center;gap:12px;padding:16px 18px;cursor:pointer;flex-wrap:wrap}
.rlm-card-head:hover{background:var(--surf2)}
.rlm-skill-ico{font-size:1.3rem;line-height:1;flex-shrink:0}
.rlm-card-main{flex:1;min-width:200px}
.rlm-card-title{font-weight:700;font-size:1rem}
.rlm-card-meta{color:var(--dim);font-size:.78rem;margin-top:3px}
.rlm-chip{display:inline-flex;align-items:center;gap:4px;font-size:.72rem;font-weight:700;padding:3px 10px;border-radius:999px;white-space:nowrap}
.rlm-chip-open{background:rgba(34,197,94,.15);color:var(--green)}
.rlm-chip-closed{background:rgba(239,68,68,.15);color:var(--red)}
.rlm-chip-unlocked{background:rgba(124,92,191,.18);color:var(--accent)}
.rlm-chip-locked{background:var(--surf2);color:var(--dim);border:1px solid var(--border)}
.rlm-expand{color:var(--dim);font-size:.9rem;transition:transform .15s;flex-shrink:0}
.rlm-card.open .rlm-expand{transform:rotate(90deg)}
.rlm-card-body{display:none;border-top:1px solid var(--border);padding:14px 18px 18px}
.rlm-card.open .rlm-card-body{display:block}
.rlm-instr{color:var(--dim);font-size:.82rem;margin-bottom:12px;white-space:pre-wrap}
.rlm-btn{border:1px solid var(--border);background:var(--surf2);color:var(--text);border-radius:9px;padding:7px 14px;font-family:inherit;font-size:.78rem;font-weight:700;cursor:pointer;transition:border-color .15s;white-space:nowrap}
.rlm-btn:hover{border-color:var(--accent)}
.rlm-btn.on{background:rgba(124,92,191,.18);color:var(--accent);border-color:var(--accent)}
.rlm-btn.danger{background:rgba(239,68,68,.15);color:var(--red);border-color:var(--red)}
.rlm-btn.return{background:rgba(245,158,11,.18);color:var(--yellow);border-color:var(--yellow)}
.rlm-btn.done{background:rgba(34,197,94,.18);color:var(--green);border-color:var(--green)}
.rlm-btn:disabled{opacity:.5;cursor:not-allowed}
.rlm-detailcell{background:var(--surf2);border-radius:10px;padding:14px;margin:4px 0}
.rlm-flag{font-size:.68rem;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--surf);border:1px solid var(--border);color:var(--dim);white-space:nowrap}
.rlm-gradeform{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;margin-top:10px}
.rlm-gradefield{display:flex;flex-direction:column;gap:4px}
.rlm-gradefield label{font-size:.7rem;font-weight:700;color:var(--dim);text-transform:uppercase;letter-spacing:.5px}
.rlm-gradefield input[type="number"]{width:90px;background:var(--surf);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:7px 9px;font-family:inherit;font-size:.85rem}
.rlm-gradefield textarea{width:280px;max-width:70vw;min-height:56px;background:var(--surf);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:7px 9px;font-family:inherit;font-size:.82rem;resize:vertical}
.rlm-gradenote{color:var(--dim);font-size:.74rem;margin-top:8px}
.rlm-form{margin-bottom:18px}
.rlm-grid{display:flex;flex-wrap:wrap;gap:12px}
.rlm-field{display:flex;flex-direction:column;gap:4px;min-width:220px;flex:1}
.rlm-field.full{flex-basis:100%}
.rlm-field label{font-size:.7rem;font-weight:700;color:var(--dim);text-transform:uppercase;letter-spacing:.5px}
.rlm-field select,.rlm-field input,.rlm-field textarea{background:var(--surf2);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:8px 10px;font-family:inherit;font-size:.85rem}
.rlm-field textarea{min-height:60px;resize:vertical}
.rlm-actions{display:flex;gap:10px;margin-top:14px}
.rlm-hint{color:var(--dim);font-size:.72rem}
.rlm-hint2{color:var(--dim);font-size:.72rem;margin-top:4px}
.rlm-seclist{display:flex;flex-direction:column;gap:6px;background:var(--surf2);border:1px solid var(--border);border-radius:8px;padding:10px;max-height:180px;overflow-y:auto}
.rlm-seclist label{display:flex;align-items:center;gap:8px;font-size:.82rem;font-weight:400;text-transform:none;letter-spacing:normal;color:var(--text)}
[data-theme="light"] .rlm-card{border-color:#c8c2d8;box-shadow:0 1px 4px rgba(0,0,0,.08)}
/* OWNER REQ #6 (2026-08-07) — group/sort/declutter layer on top of the
   card list above. Additions only, same .rlm- prefix. */
.rlm-toolbar{display:flex;align-items:center;justify-content:flex-end;gap:10px;flex-wrap:wrap;margin-bottom:14px}
.rlm-sort{display:flex;align-items:center;gap:8px;font-size:.76rem;color:var(--dim)}
.rlm-sort select{background:var(--surf2);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:6px 9px;font-family:inherit;font-size:.78rem}
.rlm-groups{display:flex;flex-direction:column;gap:4px}
.rlm-group{margin-bottom:10px}
.rlm-group>summary{display:flex;align-items:center;gap:8px;cursor:pointer;list-style:none;user-select:none;
  padding:9px 4px;font-weight:800;font-size:.88rem;color:var(--text)}
.rlm-group>summary::-webkit-details-marker{display:none}
.rlm-group-caret{display:inline-block;color:var(--dim);font-size:.78rem;transition:transform .15s;flex-shrink:0}
.rlm-group[open]>summary .rlm-group-caret{transform:rotate(90deg)}
.rlm-group-count{font-weight:400;color:var(--dim);font-size:.8rem}
.rlm-group-body{padding-top:2px}
.rlm-group-self>summary{color:var(--yellow)}
.rlm-stats-compact{background:var(--surf2);border:1px solid var(--border);border-radius:999px;padding:4px 11px;font-size:.72rem;color:var(--dim);white-space:nowrap;cursor:default}
@media(max-width:768px){
  .rlm-card-head{padding:14px}
  .rlm-card-body{padding:12px 14px 16px}
  .rlm-gradefield textarea{width:100%;max-width:none}
  .rlm-toolbar{justify-content:flex-start}
}

/* ══ Bảng xếp hạng khu Bảng điểm (vocab/teacher/rank-board.js) ══════════
   Cố tình bám sát layout hàng của leaderboard/index.css phía học sinh (hạng ·
   tên · điểm · caret, breakdown bung ra dưới) để giáo viên và học sinh nhìn
   thấy CÙNG MỘT hình dạng bảng — mismatch thị giác cũng gây cãi khi trao
   thưởng, không riêng gì mismatch số liệu. Prefix lbt- để không đụng .lb-*
   của app học sinh hay .shw-* của Speaking. */
.lbt-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.lbt-bar-scroll{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px}
.lbt-bar-scroll::-webkit-scrollbar{display:none}
.lbt-bar .cls-pill{flex-shrink:0}
.lbt-rows{background:var(--surf);border:1px solid var(--border);border-radius:12px;overflow:hidden;margin-top:4px}
.lbt-row{display:flex;align-items:center;gap:12px;padding:11px 14px;border-top:1px solid var(--border);cursor:pointer;transition:background .15s}
.lbt-rows>.lbt-row:first-child{border-top:none}
.lbt-row:hover{background:var(--surf2)}
.lbt-rank{font-family:'JetBrains Mono',monospace;font-weight:700;font-size:.9rem;min-width:34px;text-align:center;color:var(--dim);flex-shrink:0}
.lbt-rank.medal{font-size:1.25rem}
.lbt-name{flex:1;min-width:0}
.lbt-nm{font-weight:700;font-size:.9rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lbt-sub{font-size:.72rem;color:var(--dim);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lbt-meta{display:flex;align-items:center;gap:10px;flex-shrink:0;font-size:.8rem;color:var(--dim)}
.lbt-pts{font-weight:700;color:var(--text);white-space:nowrap}
.lbt-streak{color:var(--yellow);font-weight:600;white-space:nowrap}
.lbt-caret{color:var(--dim);font-size:.8rem;transition:transform .15s;display:inline-block}
.lbt-caret.open{transform:rotate(180deg)}
.lbt-bd{display:flex;flex-wrap:wrap;gap:6px;padding:0 14px 11px 48px;background:var(--surf)}
.lbt-bd[hidden]{display:none}
.lbt-chip{background:var(--surf2);border:1px solid var(--border);border-radius:999px;padding:3px 10px;font-size:.72rem;color:var(--dim);font-weight:600;white-space:nowrap}
.lbt-chip b{color:var(--text);font-weight:800}
.lbt-bd-empty{font-size:.75rem;color:var(--dim);font-style:italic}
.lbt-foot{margin-top:10px;font-size:.74rem;color:var(--dim);line-height:1.7}
.lbt-foot code{background:var(--surf2);border-radius:4px;padding:1px 5px;font-size:.9em}
[data-theme="light"] .lbt-rows{box-shadow:0 1px 4px rgba(0,0,0,.08),0 0 0 1px rgba(0,0,0,.04)}
[data-theme="light"] .lbt-nm,[data-theme="light"] .lbt-pts{color:#1a1a2e}
@media(max-width:600px){
  .lbt-row{padding:10px;gap:8px}
  .lbt-meta{gap:6px;font-size:.74rem}
  .lbt-bd{padding-left:14px}
}

@media(max-width:768px){
  .t2-sidebar{width:60px;padding:10px 6px}
  .t2-sidebar .t2-nav-lbl,.t2-classbox-lbl .t2-nav-lbl{display:none}
  .t2-nav-item{justify-content:center;padding:10px 6px;gap:0}
  .t2-classbox{padding:0 0 8px}
  .t2-classbox-lbl{text-align:center}
  .t2-class-sel{padding:7px 2px;font-size:.68rem;text-align:center;text-align-last:center}
  .t2-foot{align-items:center}
  .t2-foot #lastUpdate{display:none}
  .t2-foot .btn-refresh{padding:6px 8px}
}

/* ══ Speaking category grouping + "đã ra cho lớp này" badge (vocab/teacher/
   speaking-hw.js — shwRenderPickTopics/shwRenderPickQs/shwRenderProgress).
   Base .shw-* rules live in speaking-hw.js's own injected <style> (this
   file's established pattern); these additions go here per this task's
   file-touch constraint. Reuses the same tokens as the JS-injected rules
   (var(--border)/--dim/--accent/--surf2/--green) — no new palette. ══════ */
.shw-cat-group{margin-bottom:10px}
.shw-cat-hd{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;border:none;text-align:left;cursor:pointer;font-family:inherit;font-size:.68rem;text-transform:uppercase;letter-spacing:.6px;color:var(--dim);font-weight:700;padding:8px 10px;position:sticky;top:0;background:var(--surf);z-index:1}
.shw-cat-hd:hover{color:var(--text)}
.shw-cat-group.open>.shw-cat-hd{color:var(--accent)}
.shw-cat-hd .cnt{font-weight:600;text-transform:none;letter-spacing:0}
.shw-cat-hd .chev{font-size:.8rem}
.shw-cat-group:first-child .shw-cat-hd{padding-top:2px}
.shw-cat-hd-th{font-size:.68rem;text-transform:uppercase;letter-spacing:.5px;color:var(--dim);border-bottom:1px solid var(--border);background:var(--surf2)}
.shw-asg-badge{color:var(--dim)}
.shw-asg-badge.has{color:var(--accent);border-color:var(--accent)}
.shw-q-cat{font-size:.66rem;color:var(--dim);border:1px solid var(--border);border-radius:5px;padding:0 5px;margin-right:6px;white-space:nowrap}
.shw-q-asg{font-size:.66rem;font-weight:700;color:var(--green);border:1px solid var(--green);border-radius:5px;padding:0 5px;margin-right:6px;white-space:nowrap}
.shw-pick-note{font-size:.72rem;color:var(--yellow);background:rgba(245,158,11,.08);padding:8px 18px;border-bottom:1px solid var(--border)}

/* Nhãn "đã giao cho lớp này" trong picker bộ đề Writing — cùng ngôn ngữ thị
   giác với nhãn đã-ra của picker Speaking ở trên. */
.hw-given-badge{color:var(--green,#10B981);font-weight:700}

/* Nhóm task_type thu gọn được trong picker bộ đề Writing — cùng ngôn ngữ với
   .shw-cat-hd của picker Speaking. */
.hw-bank-grp{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;background:none;border:none;text-align:left;cursor:pointer;font-family:inherit;font-size:.78rem;font-weight:700;color:var(--accent);padding:7px 2px;margin:4px 0 2px}
.hw-bank-grp:hover{opacity:.8}
.hw-bank-grp .cnt{font-weight:600;color:var(--dim)}
.hw-bank-grp .chev{color:var(--dim);font-size:.8rem}

/* ═══════════════════════════════════════════════════════════════
   Sidebar group labels — "📚 Trung tâm bài tập" / "📊 Dashboard".
   ═══════════════════════════════════════════════════════════════ */
.t2-nav-group-lbl{font-size:.66rem;text-transform:uppercase;letter-spacing:1px;color:var(--dim);
  font-weight:700;padding:14px 12px 4px}
.t2-nav-group-lbl:first-child{padding-top:2px}

/* ═══════════════════════════════════════════════════════════════
   HOMEWORK HUB — ported panels (Inbox/Giao bài/Luyện tập/Builder,
   moved from homework/teacher/{assign,inbox,practice,builder}.js
   unchanged). Ported from homework/teacher/teacher-hub.css.

   CONFLICT RESOLUTION — Hub's original CSS defined .btn/.btn-sm/.card/
   .tbl-wrap/th/td with different values than this file already has:
     - .btn didn't exist here at all → added, but scoped to .hwhub so it
       can't leak onto the rest of the dashboard.
     - .btn-sm DOES already exist here (border-radius 8px/padding 6px
       14px/font-size .82rem, used throughout the existing dashboard
       toolbars) — Hub's version was smaller (7px/5px 11px/.76rem).
       Scoped under .hwhub so ported markup gets Hub's sizing and every
       pre-existing .btn-sm elsewhere keeps this file's original rule
       (last-defined-wins would otherwise have silently shrunk them).
     - .card padding differs (20px here vs Hub's 18px) → .hwhub .card
       override, scoped.
     - .tbl-wrap here adds a right-edge scroll-hint mask Hub's didn't
       have → keep this file's version globally (harmless superset);
       only reset overflow-y or here (Hub used overflow-x:auto only)
       under .hwhub, scoped.
     - th/td padding differs (10px 14px here vs Hub's 9px 12px) →
       .hwhub th/.hwhub td override, scoped.
     - .toast is NOT duplicated: HWShell.toast() delegates to this
       page's own global toast()/#toast element (index.html ~3049) —
       Hub's ported panels render into #toast via that same call, so
       they automatically get this file's existing .toast rule.
     - .modal-overlay / .modal (z-index 200 here vs Hub's 300, plus a
       cloneNode-based confirm click handler that would silently kill
       this page's own #modalConfirm.onclick if shared) are NOT reused
       at all — hw-shell-adapter.js's confirmModal() builds its OWN
       overlay (#hwaModalOverlay, distinct ids, see .hwa-modal-* below)
       instead. See hw-shell-adapter.js top comment for why.
   Everything below with no equivalent in this file (badge/empty-state/
   loading DO already match near-exactly and are left as this file's
   existing rules; .hh-modal-*, .bld-*, .ib-*, .pr-*, .chips/.chip,
   .hh-lbl/.hh-field/.hh-row are Hub-only class names with zero clash
   risk) is added unscoped, same as the rest of this file's per-tab
   sections above.
   ═══════════════════════════════════════════════════════════════ */
/* ⚠️ SCOPE: .hwhub alone is NOT enough. The 4 moved modules build their modal
   overlays with document.body.appendChild() (assign.js:450, inbox.js:237,
   builder.js:544 & :893), so that DOM sits OUTSIDE the .hwhub panel and any
   rule scoped only to .hwhub misses it — every "💾 Lưu"/"Huỷ"/"Trả bài" button
   and every field inside a modal would render as an unstyled browser default.
   `.btn`/`.btn-primary` exist NOWHERE else in this file, so there is no
   fallback to catch them. Hence each scoped rule below also lists the two
   body-level overlay classes. Adding a new body-level overlay? Add it here. */
.hwhub .btn,.hh-modal-overlay .btn,.hwa-modal-overlay .btn{border-radius:9px;padding:9px 16px;font-family:inherit;font-size:.83rem;font-weight:700;cursor:pointer;border:1px solid var(--border);background:var(--surf2);color:var(--text);transition:all .15s}
.hwhub .btn:hover,.hh-modal-overlay .btn:hover,.hwa-modal-overlay .btn:hover{border-color:var(--accent);color:var(--accent)}
.hwhub .btn-primary,.hh-modal-overlay .btn-primary,.hwa-modal-overlay .btn-primary{background:var(--grad);border:none;color:#fff}
.hwhub .btn-primary:hover,.hh-modal-overlay .btn-primary:hover,.hwa-modal-overlay .btn-primary:hover{opacity:.9;color:#fff}
.hwhub .btn-sm,.hh-modal-overlay .btn-sm,.hwa-modal-overlay .btn-sm{padding:5px 11px;font-size:.76rem;border-radius:7px}
.hwhub .btn:disabled,.hh-modal-overlay .btn:disabled,.hwa-modal-overlay .btn:disabled{opacity:.4;cursor:not-allowed}
.hwhub .card{padding:18px}
.hwhub .tbl-wrap{overflow-y:visible;-webkit-mask-image:none;mask-image:none}
.hwhub th{padding:9px 12px}
.hwhub td{padding:9px 12px}
/* Form controls. teacher-hub.css styled these GENERICALLY (bare
   input/select/textarea selectors); this file has no such base rule at all —
   it styles inputs per-class (.sbar-inp, .t2-class-sel, .rlm-field …). So the
   Hub's ported markup had NO input styling after the merge and rendered with
   browser defaults. Ported here, scoped to .hwhub so it cannot restyle the
   Dashboard's own inputs. input[type=search] + .asu-toggle come from the
   #asUnit picker (search + optgroup + "chỉ hiện chưa giao"). */
.hwhub input[type=text],.hwhub input[type=number],.hwhub input[type=datetime-local],
.hwhub input[type=file],.hwhub input[type=search],.hwhub select,.hwhub textarea,
.hh-modal-overlay input[type=text],.hh-modal-overlay input[type=number],
.hh-modal-overlay input[type=datetime-local],.hh-modal-overlay input[type=file],
.hh-modal-overlay input[type=search],.hh-modal-overlay select,.hh-modal-overlay textarea{
  width:100%;background:var(--surf2);border:1px solid var(--border);border-radius:8px;padding:9px 11px;
  font-family:inherit;font-size:.84rem;color:var(--text);outline:none}
.hwhub input:focus,.hwhub select:focus,.hwhub textarea:focus,
.hh-modal-overlay input:focus,.hh-modal-overlay select:focus,.hh-modal-overlay textarea:focus{border-color:var(--accent)}
.hwhub textarea,.hh-modal-overlay textarea{resize:vertical;min-height:64px;font-family:inherit}
.hwhub .asu-toggle{display:flex;align-items:center;gap:6px;font-size:.76rem;color:var(--dim);margin-top:6px;cursor:pointer}
.hwhub .asu-toggle input{width:auto;accent-color:var(--accent)}
label.hh-lbl{display:block;font-size:.72rem;color:var(--dim);font-weight:700;margin-bottom:5px;text-transform:uppercase;letter-spacing:.5px}
.hh-field{margin-bottom:12px}
.hh-row{display:flex;gap:12px;flex-wrap:wrap}
.hh-row>.hh-field{flex:1;min-width:160px}
.chips{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.chip{padding:6px 14px;border-radius:99px;border:1px solid var(--border);background:var(--surf2);font-size:.78rem;font-weight:600;color:var(--dim);cursor:pointer;transition:all .15s}
.chip.active{background:rgba(124,92,191,.15);border-color:var(--accent);color:var(--accent)}

/* ── HWShell's own confirm modal (hw-shell-adapter.js) — separate DOM from
   this page's #modalOverlay, z-index above it (200) and above the OLD Hub
   modal z-index (300) it replaced. ── */
.hwa-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:400;display:none;align-items:center;justify-content:center;padding:16px}
.hwa-modal-overlay.show{display:flex}
.hwa-modal{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:26px;max-width:380px;width:100%;text-align:center}
.hwa-modal h3{margin-bottom:8px}.hwa-modal p{color:var(--dim);font-size:.85rem;margin-bottom:20px}
.hwa-modal-btns{display:flex;gap:10px}
.hwa-modal-btns button{flex:1;padding:11px;border-radius:9px;font-family:inherit;font-size:.87rem;font-weight:700;cursor:pointer;border:none}
.hwa-modal-btns .hwa-m-cancel{background:var(--surf2);border:1px solid var(--border);color:var(--text)}
.hwa-modal-btns .hwa-m-confirm{background:var(--red);color:#fff}

/* ── big modal (item editor / submission detail) — builder.js/inbox.js
   build+append these to document.body themselves (className='hh-modal-overlay').
   Distinct names from this file's .modal-overlay/.modal — no clash. ── */
.hh-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:250;display:none;align-items:flex-start;justify-content:center;padding:24px 12px;overflow-y:auto}
.hh-modal-overlay.show{display:flex}
.hh-modal{background:var(--surf);border:1px solid var(--border);border-radius:var(--r);padding:22px;max-width:760px;width:100%;margin:0 auto}
.hh-modal-wide{max-width:1080px}
.hh-modal-hd{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}
.hh-modal-hd h3{font-size:1rem}
.hh-modal-x{background:var(--surf2);border:1px solid var(--border);color:var(--text);width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:.85rem;flex-shrink:0}

/* ── builder.js ── */
.bld-layout{display:grid;grid-template-columns:300px 1fr;gap:18px;align-items:start}
.bld-unit-list{display:flex;flex-direction:column;gap:8px}
.bld-unit-item{background:var(--surf);border:1px solid var(--border);border-radius:10px;padding:11px 13px;cursor:pointer;transition:border-color .15s}
.bld-unit-item:hover{border-color:var(--accent)}
.bld-unit-item.active{border-color:var(--accent);background:rgba(124,92,191,.08)}
.bld-unit-title{font-weight:700;font-size:.87rem;margin-bottom:4px}
.bld-unit-meta{display:flex;gap:6px;align-items:center;font-size:.72rem;color:var(--dim);flex-wrap:wrap}
.bld-section{border:1px solid var(--border);border-radius:10px;margin-bottom:14px;overflow:hidden}
.bld-section-hd{background:var(--surf2);padding:10px 14px;display:flex;align-items:center;gap:10px}
.bld-section-hd input{max-width:280px}
.bld-section-body{padding:12px 14px}
.bld-task{border:1px solid var(--border);border-radius:9px;margin-bottom:10px;overflow:hidden}
.bld-task-hd{background:var(--surf2);padding:9px 12px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.bld-task-hd input{max-width:220px}
.bld-task-body{padding:10px 12px}
.bld-item-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:.82rem}
.bld-item-row .bld-item-info{flex:1;min-width:0}
.bld-item-row .bld-item-prompt{color:var(--dim);font-size:.76rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bld-asset-row{display:flex;align-items:center;gap:8px;font-size:.78rem;padding:5px 8px;background:var(--surf2);border-radius:7px;margin-bottom:5px}
.bld-asset-row .bld-asset-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.opt-row{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.opt-row .opt-key{width:34px;flex-shrink:0;font-weight:700;text-align:center;color:var(--accent)}
.opt-row input[type=checkbox],.opt-row input[type=radio]{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}

/* ── inbox.js detail ── */
.ib-detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.ib-item-block{border:1px solid var(--border);border-radius:9px;padding:12px;margin-bottom:10px}
.ib-item-block .ib-item-hd{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
.ib-item-block .ib-item-prompt{font-size:.85rem;font-weight:600;margin-bottom:6px}
.ib-answer{background:var(--surf2);border-radius:7px;padding:8px 10px;font-size:.82rem;white-space:pre-wrap;word-break:break-word}
.ib-key{font-size:.76rem;color:var(--dim);margin-top:4px}
.ib-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

/* ── practice.js ── */
.pr-catalog{max-height:340px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--r2);padding:10px;background:var(--surf)}
.pr-unit{padding:8px 0;border-bottom:1px solid var(--border)}
.pr-unit:last-child{border-bottom:0}
.pr-unit-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px;font-size:.88rem}
.pr-lesson{display:flex;align-items:center;gap:8px;padding:4px 0 4px 6px;font-size:.84rem;color:var(--text2);cursor:pointer}
.pr-lesson:hover{color:var(--text)}

@media(max-width:860px){
  .bld-layout{grid-template-columns:1fr}
  .ib-detail-grid{grid-template-columns:1fr}
}

/* ── perf-pills.js — 📘 Unit BTVN / 📚 R/L (Tổng quan zone) ──────────────
   Two "pills" (subnav tabs) reading teacher_homework_unit_perf /
   teacher_rl_perf. Not scoped to .hwhub — these panels use only .btn-sm/
   .btn-refresh/.card/.kpi/.badge, all of which are unscoped globals (see
   teacher.css:7-13, :27-34, :53-58). No .btn/.btn-primary/form-control used
   here, so no .hwhub wrapper needed. */
.pp-err-banner{background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.3);color:var(--red);
  border-radius:9px;padding:10px 14px;margin-bottom:14px;font-size:.82rem;line-height:1.5}
.pp-warn-banner{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.3);color:var(--yellow);
  border-radius:9px;padding:10px 14px;margin-bottom:14px;font-size:.82rem;line-height:1.5}
.pp-note-box{background:var(--surf2);border:1px solid var(--border);border-radius:9px;padding:10px 14px;
  margin-bottom:14px;font-size:.79rem;color:var(--dim);line-height:1.6}
.pp-meta{font-size:.72rem;color:var(--dim);margin-left:auto}
.pp-sub{font-size:.78rem;color:var(--dim);margin-top:6px;line-height:1.5}

/* by-unit / by-skill table cells reuse table/.badge; only a couple of
   width/align tweaks needed */
.pp-tbl td,.pp-tbl th{white-space:nowrap}
.pp-tbl td.pp-tbl-wide{white-space:normal;min-width:160px}

/* prominent "Tự luyện vs Được giao" split bar — the signal the owner cares
   about most, so it gets its own full-width card, not a buried table row */
.pp-split-card{margin-bottom:20px}
.pp-split{display:flex;height:26px;border-radius:8px;overflow:hidden;background:var(--surf2);margin-bottom:10px}
.pp-split-seg{height:100%;min-width:0;transition:width .3s}
.pp-split-assigned{background:var(--accent)}
.pp-split-self{background:var(--teal)}
.pp-split-legend{display:flex;gap:18px;flex-wrap:wrap;font-size:.83rem}
.pp-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:6px;vertical-align:middle}
.pp-dot-assigned{background:var(--accent)}
.pp-dot-self{background:var(--teal)}

/* HTML/CSS bar-sparkline for trends — no canvas, no CDN dep (Chart.js is
   available on this page but trend arrays here are short; a plain bar row
   is simpler and doesn't fight the accordion-resize-on-open quirk that
   canvas charts have, see shell.js's `toggle` listener) */
.pp-bars{display:flex;align-items:flex-end;gap:6px;height:84px;padding-top:8px;overflow-x:auto}
.pp-bar{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;flex:1 0 26px;min-width:26px;height:100%}
.pp-bar-fill{width:100%;max-width:22px;border-radius:4px 4px 0 0;background:var(--accent);min-height:2px}
.pp-bar-fill.pp-bar-fill-2{background:var(--teal)}
.pp-bar-empty{background:var(--border)!important}
.pp-bar-lbl{font-size:.62rem;color:var(--dim);margin-top:5px;white-space:nowrap;max-width:34px;overflow:hidden;text-overflow:ellipsis}
.pp-trend-title{font-size:.78rem;font-weight:700;color:var(--text2);margin:14px 0 2px}

[data-theme="light"] .pp-note-box{border-color:#c8c2d8}
[data-theme="light"] .pp-split{background:#e3ddf0}

[data-theme="light"] .bld-unit-item,[data-theme="light"] .bld-section,[data-theme="light"] .bld-task,[data-theme="light"] .bld-item-row,[data-theme="light"] .ib-item-block,[data-theme="light"] .pr-catalog{border-color:#c8c2d8}
