:root{
  --ink:#22312d; --muted:#6b7a75; --teal:#0e7c72; --teal-dark:#0a5f57;
  --cream:#fff8ef; --card:#ffffff; --line:#eadfce; --soft:#eef6f3;
  --green:#2e9e62; --green-bg:#dff3e4; --amber:#e8930c; --red:#d64541;
  --shadow:0 2px 10px rgba(90,70,30,.08), 0 12px 32px rgba(90,70,30,.06);
}
*{box-sizing:border-box}
body{font-family:system-ui,-apple-system,"Segoe UI",sans-serif;margin:0;color:var(--ink);
  background:linear-gradient(180deg,#fff8ef 0%,#fdf3e3 240px,#fbf7ef 100%);min-height:100vh;display:flex;flex-direction:column}
header{display:flex;gap:16px;align-items:center;background:rgba(255,253,248,.88);color:var(--ink);padding:10px 20px;border-bottom:1px solid var(--line)}
header a{color:var(--teal-dark)}
.brandLogo{height:52px;width:auto;display:block}
.brandSys{font-weight:600;color:var(--muted);letter-spacing:.02em;white-space:nowrap}
.brandRight{margin-left:auto;display:flex;align-items:center;gap:16px}
.brandWho{text-align:right;line-height:1.25}
.brandName{font-weight:700}
.brandEmail{font-size:.82em;color:var(--muted)}
@media (max-width:640px){.brandLogo{height:40px}.brandSys{display:none}}
main{max-width:1180px;margin:26px auto;padding:0 16px 60px;flex:1;width:100%}
section{background:transparent}
#login,#preflight,#policy{background:var(--card);border:1px solid var(--line);border-radius:20px;padding:26px;box-shadow:var(--shadow)}
/* Login hero (2026-11-08 redesign): a centered, narrower sign-in card
   with a big welcome headline; scoped to #login so the preflight and
   policy cards keep their working layout. */
#login{max-width:700px;margin:14px auto;padding:58px 48px 52px}
.loginHero{text-align:center;margin-bottom:22px}
.loginTitle{font-size:1.9em;font-weight:800;line-height:1.28;color:var(--ink);white-space:nowrap}
.loginSub{margin:14px 0 0;letter-spacing:.16em;text-transform:uppercase;font-size:.78em;font-weight:700;color:var(--teal)}
#login .hint{text-align:center;line-height:1.75;margin:24px 0 10px}
#login label{display:flex;flex-direction:column;gap:5px;margin:24px 0 0;line-height:1.3}
#login input{width:100%;min-width:0;padding:13px 14px;font-size:1em;border-radius:12px}
#login #btnLogin{width:100%;margin:32px 0 4px;padding:14px;font-size:1.06em;border-radius:12px}
#login .msg{text-align:center}
#examList{margin-top:30px}
#examList h3{text-align:center}
@media (max-width:640px){#login{padding:32px 22px 28px}.loginTitle{font-size:1.3em;white-space:normal}}
#policy{line-height:1.65}
#policy h1{margin-top:0}
#policy li{margin:5px 0}
.hidden{display:none!important}
label{display:block;margin:12px 0;font-weight:600}
input,select,textarea{padding:10px 12px;border:1.5px solid #d8cfbc;border-radius:10px;min-width:260px;font:inherit;background:#fff}
input:focus,select:focus,textarea:focus{outline:3px solid rgba(14,124,114,.25);border-color:var(--teal)}
button{background:#e8f2ef;color:var(--teal-dark);border:1.5px solid #cfe3dc;border-radius:12px;
  padding:10px 18px;cursor:pointer;margin:6px 6px 6px 0;font:inherit;font-weight:600}
button:hover{filter:brightness(.97)}
button.primary{background:var(--teal);border-color:var(--teal);color:#fff}
button.ghost{background:#fff}
button:disabled{opacity:.45;cursor:not-allowed}
.hint{color:var(--muted);font-weight:400}
.msg{font-weight:600;min-height:1.2em}
.msg.ok{color:var(--green)} .msg.err{color:var(--red)}
.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.center{text-align:center}
.card{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:20px;box-shadow:var(--shadow);margin:16px 0}
.stepHead{display:flex;justify-content:space-between;align-items:center;gap:12px}
.pill{background:var(--soft);color:var(--teal-dark);border-radius:999px;padding:4px 12px;font-size:.85em;font-weight:700;white-space:nowrap}
.pill.done{background:var(--green-bg);color:var(--green)}
.bigShare{background:var(--teal);color:#fff;border:0;border-radius:16px;padding:18px 34px;font-size:1.15em;font-weight:800;
  box-shadow:0 8px 20px rgba(14,124,114,.35);margin:14px auto}
.bigStart{padding:16px 44px;font-size:1.1em;border-radius:16px}
.camPrev,.sharePrev{width:100%;max-width:520px;border-radius:14px;background:#111;display:block;margin:10px 0}
.prev{width:100%;border-radius:12px;margin-top:12px}
/* exam layout */
.examHead{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.examLayout{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:20px;align-items:start}
@media (max-width:900px){.examLayout{grid-template-columns:1fr}.sideCol{position:static;max-height:none;overflow:visible}}
.sideCol{position:sticky;top:16px;max-height:calc(100vh - 32px);overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;padding-right:4px}
.sideCol .card{margin-top:0}
.progressBar{background:#f1e7d3;border-radius:999px;height:12px;overflow:hidden;margin:8px 0}
#progressFill{background:linear-gradient(90deg,#37b58c,var(--teal));height:100%;width:0%;border-radius:999px;transition:width .4s ease}
.progressText{font-size:1.1em;font-weight:800}
.q{border:1.5px solid var(--line);border-radius:18px;padding:20px;margin:16px 0;background:#fff;box-shadow:var(--shadow)}
.q.current{border-color:var(--teal);box-shadow:0 0 0 3px rgba(14,124,114,.18), var(--shadow)}
.qHead{display:flex;justify-content:space-between;align-items:center;gap:10px}
.qHead h4{margin:0;font-size:1.02em}
.points{background:#fff3d6;color:#8a5a00;border-radius:999px;padding:3px 10px;font-size:.82em;font-weight:700}
.markBtn{margin:0;padding:6px 12px;font-size:.85em}
.markBtn.active{background:#ffe9c2;border-color:#e8b64c;color:#7a5200}
.qStem{font-size:1.06em;line-height:1.65;white-space:pre-wrap}
.qStem code,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.opt{display:flex;gap:12px;align-items:flex-start;border:1.5px solid #e4dccb;border-radius:14px;
  padding:13px 16px;margin:9px 0;cursor:pointer;font-weight:500;line-height:1.5;background:#fffdf8}
.opt:hover{border-color:var(--teal)}
/* flex:none + pinned size: as a flex item the input used to be
   shrinkable (flex-shrink:1 with min-width:0), so the longer an
   option's text, the more the browser squeezed the checkbox/radio -
   the longest option ended up as a tiny fully-rounded dot (the
   global input rule's border-radius). Pinning the box keeps every
   option's control at exactly 18x18. */
.opt input{flex:none;width:18px;height:18px;min-width:18px;margin:3px 0 0;padding:0;accent-color:var(--teal);vertical-align:top}
.opt.picked{background:#e7f4ec;border-color:var(--green)}
.opt .tick{margin-left:auto;color:var(--green);font-weight:900;visibility:hidden}
.opt.picked .tick{visibility:visible}
.fillRow{display:flex;gap:8px;flex-wrap:wrap}.fillRow input{min-width:150px}
textarea{width:100%}
/* sidebar widgets */
.timeCard{text-align:center}
.ringWrap{position:relative;width:176px;margin:6px auto}
.ringBg{fill:none;stroke:#f1e7d3;stroke-width:11}
.ringFg{fill:none;stroke:var(--teal);stroke-width:11;stroke-linecap:round;transform:rotate(-90deg);transform-origin:center;transition:stroke-dashoffset 1s linear, stroke .5s}
.timeCard.amber .ringFg{stroke:var(--amber)} .timeCard.red .ringFg{stroke:var(--red)}
.ringText{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:1.5em;font-weight:800;font-variant-numeric:tabular-nums}
.qStats{display:flex;flex-direction:column;gap:5px;margin-bottom:12px;font-size:.95em}
.dot{display:inline-block;width:11px;height:11px;border-radius:50%;margin-right:7px;border:2.5px solid}
.dotA{border-color:var(--green);background:var(--green-bg)} .dotU{border-color:#7d8bff;background:#e3e7ff}
/* the legend rows double as the question filter (Part 5): click a row
   to filter the question list, click it again to return to All */
.statRow{display:flex;align-items:center;width:100%;margin:0;padding:5px 8px;background:none;
  border:1.5px solid transparent;border-radius:9px;font:inherit;color:inherit;text-align:left;cursor:pointer}
.statRow:hover{background:#f6efe0}
/* the "Questions" title doubles as a reset-to-All shortcut: same
   hover tint as the legend rows, but it stays a plain heading */
.qTitle{cursor:pointer;width:fit-content;padding:2px 6px;margin-left:-6px;border-radius:8px}
.qTitle:hover{background:#f6efe0;text-decoration:underline}
.statRow.active{background:#e7f4ec;border-color:var(--green);font-weight:700}
.statRow .fxI{font-style:normal;width:16px;margin-right:7px;text-align:center;flex:none}
.qGrid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.qGrid button{margin:0;padding:8px 0;border-radius:10px;background:#eef0ff;border:1.5px solid #c3cbf5;color:#39448f;font-weight:700;position:relative}
.qGrid button.answered{background:var(--green-bg);border-color:#9ed3ae;color:#14532d}
.qGrid button.current{outline:3px solid rgba(14,124,114,.45);outline-offset:1px}
.qGrid button.marked::after{content:"🔖";position:absolute;top:-7px;right:-4px;font-size:.72em}
.submitBtn{width:100%;padding:14px;font-size:1.05em}
/* completion page */
.doneCard{text-align:center;padding:48px 30px;max-width:640px;margin:36px auto}
.doneEmoji{font-size:3.2em;line-height:1}
.doneCard h1{font-size:2.2em;margin:12px 0 6px;color:var(--teal-dark)}
.doneText{font-size:1.15em}
.doneWhen{font-weight:800;color:var(--teal-dark);font-size:1.12em;margin:14px 0 4px}
.doneAuto{color:var(--amber);font-weight:700;margin:4px 0}
.doneGuide{color:var(--muted);line-height:1.65;max-width:480px;margin:18px auto 0}
/* overlays */
.gate{position:fixed;inset:0;background:rgba(24,26,34,.78);z-index:999;display:flex;align-items:center;justify-content:center;padding:16px}
.gateBox{background:#fff;border-radius:20px;padding:30px;max-width:560px;width:100%;text-align:center;box-shadow:var(--shadow)}
.gateBox p{line-height:1.6}
/* admin */
table{border-collapse:collapse;width:100%;background:#fff}
td,th{border:1px solid #e7dfcd;padding:7px 9px;text-align:left;vertical-align:top}
th{background:#fdf6e7}
pre{background:#12312c;color:#d9f2e8;padding:14px;border-radius:12px;overflow:auto;max-height:340px;white-space:pre-wrap}
.snapBtns button,.photoBtns button{font-size:.85em;padding:6px 10px}
/* The shared-screen <video> on the exam page is an off-screen capture
   source only (Part H'): snapshots draw frames from it, but the
   preview itself is never displayed, whatever classes it carries. */
#screenPrev{display:none!important}
/* in-exam calculator (Part G): floating panel, warm card styling.
   Default spot is the viewport's bottom-right; the button that opens
   it sits in the Time Left card at the top of the sidebar, so the two
   never overlap; once dragged, inline left/top take over. */
.calcPanel{position:fixed;right:18px;bottom:86px;width:min(324px,calc(100vw - 24px));background:var(--card);
  border:1.5px solid var(--line);border-radius:18px;box-shadow:var(--shadow);z-index:900;padding:12px}
/* Calculator button (Part G follow-up 2): a plain in-card button at
   the bottom of the Time Left card, under the hint line. The card is
   inside the #exam section, so the button exists only in the exam
   view; no fixed positioning, no JS show/hide needed for the button
   itself (syncCalcFab now only closes the panel - see app.js). */
.calcBtn{display:flex;align-items:center;justify-content:center;gap:9px;margin:14px auto 0;padding:11px 22px;
  background:#fff;color:var(--teal-dark);border:1.5px solid var(--teal);border-radius:14px;
  font-size:1em;font-weight:700;box-shadow:0 2px 8px rgba(14,124,114,.12);cursor:pointer;
  transition:background .15s ease,box-shadow .15s ease,transform .15s ease}
.calcBtn:hover{background:#eef7f4;box-shadow:0 4px 12px rgba(14,124,114,.18);transform:translateY(-1px)}
.calcBtn:active{transform:translateY(0)}
.calcBtn svg{flex:none}
.calcHead{display:flex;justify-content:space-between;align-items:center;font-weight:800;color:var(--teal-dark);
  cursor:move;padding:2px 2px 10px;touch-action:none;user-select:none}
.calcX{margin:0;padding:2px 10px;line-height:1.2}
.calcDisplay{background:var(--soft);border:1.5px solid var(--line);border-radius:12px;padding:12px 14px;
  font-size:1.45em;font-weight:700;text-align:right;min-height:1.35em;overflow-x:auto;white-space:nowrap;font-variant-numeric:tabular-nums}
.calcDisplay.err{color:var(--red)}
.calcGrid{display:grid;grid-template-columns:repeat(5,1fr);gap:7px;margin-top:10px}
.calcGrid button{margin:0;padding:12px 0;font-size:1.05em;border-radius:10px}
.calcGrid button.fn{background:#fdf6e7}
.calcGrid button.eq{background:var(--teal);border-color:var(--teal);color:#fff;grid-column:span 3}
/* in-exam proctor chat: the student page's fixed button + panel sit
   in the bottom-right corner (button z 800, panel z 950 - above the
   calculator panel's 900, below the .gate overlays' 999, so a lock
   overlay still covers everything), and the same bubble styles are
   reused by the admin Proctor Chat card. Own messages align right in
   teal, the other side's align left on the soft background. The
   message list is the only scrolling region; the input row is a
   sibling, so a re-render never touches a half-typed draft. */
.chatFab{position:fixed;right:18px;bottom:18px;z-index:800;background:var(--teal);color:#fff;border:0;
  border-radius:999px;padding:13px 20px;font-size:1em;font-weight:800;cursor:pointer;
  box-shadow:0 8px 20px rgba(14,124,114,.35)}
.chatFab:hover{background:var(--teal-dark)}
.chatBadge{display:inline-block;min-width:21px;text-align:center;background:var(--red);color:#fff;
  border-radius:999px;padding:1px 6px;font-size:.8em;font-weight:800;margin-left:8px;vertical-align:2px}
.chatPanel{position:fixed;right:18px;bottom:18px;z-index:950;width:min(340px,calc(100vw - 24px));
  height:min(450px,calc(100vh - 36px));background:var(--card);border:1.5px solid var(--line);
  border-radius:18px;box-shadow:var(--shadow);padding:12px;display:flex;flex-direction:column}
.chatHead{display:flex;justify-content:space-between;align-items:center;font-weight:800;color:var(--teal-dark);padding:2px 2px 8px}
.chatMsgs{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:8px;padding:4px 2px}
.chatMsg{max-width:86%;padding:8px 12px;border-radius:14px;line-height:1.45;white-space:pre-wrap;overflow-wrap:break-word}
.chatMsg.mine{align-self:flex-end;background:var(--teal);color:#fff;border-bottom-right-radius:4px}
.chatMsg.theirs{align-self:flex-start;background:var(--soft);border:1.5px solid var(--line);border-bottom-left-radius:4px}
.chatTime{display:block;font-size:.72em;opacity:.7;margin-top:3px}
.chatHint{font-size:.82em;margin:8px 0 0}
.chatInputRow{display:flex;gap:8px;margin-top:10px}
.chatInputRow input{flex:1;min-width:0}
.chatInputRow button{margin:0;white-space:nowrap}
/* site footer (student page, admin page and the privacy policy page):
   one quiet bar in normal flow at the bottom of every view - the
   ZenoWise credit links to their site, the policy link stays in-app.
   Nothing fixed or floating, so the calculator / chat / lock overlays
   never interact with it. */
.siteFooter{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;
  border-top:1px solid var(--line);padding:11px 20px;color:var(--muted);font-size:.88em}
.siteFooter a{color:var(--teal-dark)}
.devCredit{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink);font-weight:600}
.devLogo{height:28px;width:auto;display:block}
.footRight{margin-left:auto}
/* ID-check privacy consent: a soft notice card inside Step 1. The
   checkbox row is a real flex label (the global label rule is block),
   with the same pinned 18px box as the answer options. */
.consentBox{background:var(--soft);border:1.5px solid var(--line);border-radius:14px;padding:14px 16px;margin:12px 0;line-height:1.55}
.consentBox p{margin:6px 0}
.consentCheck{display:flex;gap:10px;align-items:flex-start;font-weight:600;margin:10px 0 2px;cursor:pointer}
.consentCheck input{flex:none;width:18px;height:18px;min-width:18px;margin:2px 0 0;padding:0;accent-color:var(--teal)}
/* ID check, second path (live Zoom verification): one quiet box
   under the camera controls with three mutually exclusive states -
   the offer (#zoomAlt), the waiting state (#zoomWait) and the
   completed state (#zoomDone) - toggled by app.js from the server's
   zoom_check_status. Dashed border sets it apart from the photo
   path without shouting. */
.zoomBox{border:1.5px dashed #cbbd97;border-radius:14px;padding:14px 16px;margin:14px 0 4px;line-height:1.55;background:#fffdf8}
.zoomBox p{margin:6px 0}
.viewer{overflow:auto;border:1.5px solid var(--line);border-radius:14px;background:#222;max-height:70vh;margin-top:10px}
.viewer img{display:block}
.snapMetaRow{margin-top:10px;min-height:1em}
.idPhotoImg{max-width:420px;width:100%;border-radius:14px;border:1.5px solid var(--line)}
details.card{padding:14px 20px}
#examList .card>div{margin-top:12px}
.submittedChip{display:inline-block;padding:10px 18px;border-radius:999px;background:#e7f6ec;color:#1c7a3d;border:1px solid #bfe6cc;font-weight:700;font-size:.95em;box-shadow:0 2px 8px rgba(28,122,61,.12)}
.submittedChip.closed{background:#f1efe9;color:var(--muted);border-color:var(--line)}
