*{box-sizing:border-box;margin:0;padding:0;border-radius:0!important} :root{--bg:#0b0b0b;--panel:#111111;--card:#141414;--input:#0e0e0e;--border:#2e2e2e;--border2:#3d3d3d;--edge:#626262;--txt:#e5e5e5;--body:#cccccc;--muted:#9a9a9a;--dim:#7d7d7d;--ok:#10b981;--cyan:#38bdf8;--amber:#f59e0b;--bad:#ff5555;--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace} html{background:var(--bg)} body{background:var(--bg);color:var(--body);font-family:var(--mono);font-size:14px;line-height:1.55;max-width:1180px;margin:0 auto;padding:0 16px 64px} a{color:var(--cyan);text-decoration:none} a:hover{text-decoration:underline} h1{font-size:2.1rem;font-weight:600;letter-spacing:-.04em;color:#fff;line-height:1.15;margin:18px 0 10px} h2{font-size:.76rem;font-weight:500;text-transform:uppercase;letter-spacing:.12em;color:var(--muted);margin:28px 0 12px;border-bottom:1px solid var(--border);padding-bottom:8px} h3{color:#fff;font-size:1rem;margin:0 0 6px} .topbar{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--border);padding:12px 0;position:sticky;top:0;background:rgba(11,11,11,.92);z-index:5} .brand{color:#fff;font-weight:600;font-size:1rem;letter-spacing:-.02em} .brand span{color:var(--dim);font-weight:400;font-size:.78rem;margin-left:10px} .nav{display:flex;gap:14px;align-items:center;font-size:.8rem} .btn{display:inline-flex;align-items:center;justify-content:center;padding:8px 18px;background:#161616;color:#ddd;border:1px solid var(--edge);font-size:.8rem;font-family:inherit;cursor:pointer;letter-spacing:.02em;transition:all .15s ease;text-decoration:none} .btn:hover:not(:disabled){background:#242424;border-color:#555;color:#fff;text-decoration:none} .btn:active:not(:disabled){background:#fff;color:#000;border-color:#fff} .btn:disabled{opacity:.3;cursor:not-allowed} .btn.primary{background:var(--cyan);border-color:var(--cyan);color:#001018;font-weight:600} .btn.primary:hover{background:#7cd4fc;color:#000} .btn.ok{border-color:var(--ok);color:var(--ok)} .btn.danger{border-color:var(--bad);color:var(--bad)} .grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px} .grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px} .card{background:var(--card);border:1px solid var(--border);padding:16px} .card:hover{border-color:var(--border2)} .meta{color:var(--muted);font-size:.78rem} .dim{color:var(--dim);font-size:.78rem} table{width:100%;border-collapse:collapse;font-size:.82rem} th{color:var(--dim);text-transform:uppercase;letter-spacing:.1em;font-size:.68rem;text-align:left;padding:8px;border-bottom:1px solid var(--border)} td{padding:8px;border-bottom:1px solid #1c1c1c;font-variant-numeric:tabular-nums} input[type=text],input[type=email],input[type=number],select,textarea{background:var(--input);color:#e5e5e5;border:1px solid var(--edge);padding:9px 12px;font-family:inherit;font-size:.82rem;outline:none;width:100%} input:focus,textarea:focus,select:focus{border-color:var(--cyan)} input::placeholder{color:var(--dim)} label{display:block;font-size:.75rem;color:var(--muted);margin:10px 0 4px;text-transform:uppercase;letter-spacing:.08em} .chk{display:flex;gap:10px;align-items:flex-start;border:1px solid var(--edge);padding:10px 12px;margin:6px 0;background:var(--panel);cursor:pointer;font-size:.85rem} .chk:hover{border-color:var(--border2)} .chk input{width:auto;margin-top:3px;accent-color:var(--cyan)} .palette{display:grid;grid-template-columns:repeat(5,1fr);gap:6px} .pal{aspect-ratio:1;display:grid;place-items:center;border:1px solid var(--edge);background:var(--panel);color:var(--muted);font-size:.75rem;cursor:pointer;min-height:44px} .pal.cur{border-color:var(--cyan);color:#fff} .pal.ans{background:#12301f;border-color:var(--ok);color:var(--ok)} .pal.rev{background:#2a1f05;border-color:var(--amber);color:var(--amber)} .pal.skip{background:var(--panel)} .opt{display:flex;gap:10px;align-items:flex-start;border:1px solid var(--edge);padding:10px 12px;margin:8px 0;background:var(--panel);cursor:pointer} .opt:hover{border-color:var(--border2)} .opt.sel{border-color:var(--cyan);background:#0d1b24} .status-dot{width:6px;height:6px;background:#444;display:inline-block;flex:none} .ok-t{color:var(--ok)}.bad-t{color:var(--bad)}.warn-t{color:var(--amber)}.cyan-t{color:var(--cyan)} .bar{height:2px;background:#1c1c1c;overflow:hidden;margin-top:8px} .bar i{display:block;height:100%;background:var(--ok)} .seg{display:flex;height:10px;background:#1c1c1c;overflow:hidden} .seg i{display:block;height:100%} :focus-visible{outline:2px solid var(--cyan);outline-offset:2px} .cbt{display:grid;grid-template-columns:1fr 220px;gap:14px} .timer{font-variant-numeric:tabular-nums;color:var(--amber);font-weight:600} .kv{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:14px 0} .kv .card b{display:block;font-size:1.5rem;color:#fff;font-variant-numeric:tabular-nums} footer{margin-top:48px;border-top:1px solid var(--border);padding-top:16px;color:var(--dim);font-size:.75rem;display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px} /* Tablet: the CBT palette drops under the question instead of squeezing it. */ @media(max-width:1024px){.cbt{grid-template-columns:1fr}.palette{grid-template-columns:repeat(8,1fr)}} /* Phone: one column throughout, a 2x2 metric grid and full-width palette taps. */ @media(max-width:700px){.grid2,.grid3{grid-template-columns:1fr}.kv{grid-template-columns:1fr 1fr}h1{font-size:1.6rem}.nav a.hidem{display:none}.palette{grid-template-columns:repeat(5,1fr)}.cbt{gap:10px}.topbar{padding:10px 0}.brand span{display:none}} @media(max-width:420px){.kv{grid-template-columns:1fr}.palette{grid-template-columns:repeat(4,1fr)}.brand{font-size:.9rem}.btn{padding:10px 14px;min-height:44px}} @media(hover:none){.pal{min-height:48px}} /* ===== exam screen ===== The clock and the palette are the two things a candidate must never lose, so both are pinned rather than left to scroll. */ .exam-bar{position:sticky;top:0;z-index:6;background:var(--bg);border-bottom:1px solid var(--border);padding:8px 0 0;margin:0 0 12px} .exam-bar-inner{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:44px} .exam-title{display:flex;flex-direction:column;min-width:0} .exam-title b{color:#fff;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} .exam-clock{text-align:right;flex:none} .exam-progress{height:3px;background:#1c1c1c;margin-top:8px} .exam-progress i{display:block;height:100%;background:var(--cyan);width:0;transition:width .2s ease} .exam-bar.complete .exam-progress i{background:var(--ok)} .exam-bar .timer{font-size:1.15rem;line-height:1.1} .timer.urgent{color:var(--amber)} .timer.critical{color:var(--bad)} .cbt-side h2{margin-top:0} .legend{list-style:none;display:flex;flex-wrap:wrap;gap:10px;margin:10px 0;font-size:.7rem;color:var(--dim)} .legend li{display:flex;align-items:center;gap:5px} .legend .sw{width:9px;height:9px;display:inline-block;border:1px solid var(--edge)} .legend .sw.ans{background:#12301f;border-color:var(--ok)} .legend .sw.rev{background:#2a1f05;border-color:var(--amber)} .legend .sw.skip{background:var(--panel)} .cbt-count{margin:0 0 10px;font-variant-numeric:tabular-nums} .btn.block{display:block;width:100%;margin-top:8px} .cbt-side [data-close-palette]{display:none} button.pal-fab{display:none} .pane-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:.78rem} .stem{margin:10px 0 6px;color:#fff;font-size:1rem;line-height:1.5} .meta-line{margin-bottom:10px} .opt-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px} .opt-actions .btn{flex:1 1 auto;min-width:120px} /* The palette is a drawer under the question: it was a wall of tiles that pushed the submit button off a phone screen. */ @media(max-width:1024px){ /* A translated-off drawer is still in the tab order, so it is also hidden from assistive tech and hit testing while closed. */ .cbt-side{position:fixed;left:0;right:0;bottom:0;background:var(--panel);border-top:1px solid var(--edge);padding:14px 16px calc(68px + env(safe-area-inset-bottom));max-height:78vh;overflow-y:auto;transform:translateY(100%);visibility:hidden;transition:transform .2s ease,visibility .2s;z-index:31} .cbt-side.open{transform:translateY(0);visibility:visible} .cbt-side h2{margin-top:0} /* The button that opens the drawer cannot live inside the drawer, so it floats above the tab bar where a thumb reaches it while reading a question. */ /* It sits above the tab bar, so the page reserves that strip; without it the button lands on top of the last line of text. */ button.pal-fab{ display:flex;position:fixed;right:14px;z-index:25; bottom:calc(60px + env(safe-area-inset-bottom)); margin:0;min-height:48px;padding:12px 16px; background:var(--panel);border:1px solid var(--cyan);color:var(--cyan); } button.pal-fab[aria-expanded=true]{ /* While the drawer is open the button is redundant, so it leaves the submit row entirely rather than covering it. */ display:none; } /* The drawer keeps its own close control at the top. */ .cbt-side [data-close-palette]{display:block} .palette{grid-template-columns:repeat(6,1fr)} /* Room for the drawer so the last option row is never hidden behind it. */ .cbt{padding-bottom:76px} } /* Phone: a smaller type step, tighter gaps, and touch-sized controls throughout. */ @media(max-width:700px){ body{font-size:15px;padding:0 14px 72px} h1{font-size:1.55rem} h2{font-size:.7rem;margin:22px 0 10px} .exam-bar{padding-top:6px} .exam-title b{font-size:.85rem} .exam-bar .timer{font-size:1.35rem} .pane-head{font-size:.75rem} .stem{font-size:1.02rem;line-height:1.55} .opt-actions .btn{min-width:0;flex:1 1 44%;padding:12px 10px;min-height:48px} .palette{grid-template-columns:repeat(5,1fr);gap:8px} .pal{min-height:48px;font-size:.8rem} .kv .card b{font-size:1.3rem} /* Every control on the exam screen gets a thumb-sized target. */ .btn{padding:11px 14px;min-height:44px} .opt{padding:12px 12px;min-height:48px} table{font-size:.78rem} /* A data table cannot shrink to a phone, so it scrolls inside its own box instead of pushing the whole page sideways. */ .table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -14px;padding:0 14px} } @media(max-width:420px){ .palette{grid-template-columns:repeat(4,1fr)} .opt-actions .btn{flex:1 1 100%} } /* Tablet: the palette drops under the question, so it needs the same drawer treatment as a phone but with room for a wider grid. */ @media(max-width:1024px) and (min-width:701px){ .cbt{padding-bottom:0} .cbt-side{max-height:70vh} } /* ===== phone navigation ===== The desktop link row has nowhere to go under 700px. Rather than hiding it, the primary destinations move to a fixed bottom bar within thumb reach. */ .tabbar{display:none} @media(max-width:700px){ .tabbar{ display:grid;grid-auto-flow:column;grid-auto-columns:1fr; position:fixed;left:0;right:0;bottom:0;z-index:30; background:var(--panel);border-top:1px solid var(--edge); padding-bottom:env(safe-area-inset-bottom); } .tabbar a{ display:flex;align-items:center;justify-content:center;text-align:center; min-height:52px;padding:6px 4px;font-size:.72rem;color:var(--muted); border-right:1px solid var(--border);text-decoration:none;line-height:1.3; } .tabbar a:last-child{border-right:0} .tabbar a:active{background:#1c1c1c;color:#fff} .tabbar a:hover{text-decoration:none;color:#fff} /* The bar is fixed, so the page reserves its height or the last row sits under it. */ body{padding-bottom:calc(72px + env(safe-area-inset-bottom))} /* Clear the floating palette button in the exam view only. */ body.exam{padding-bottom:calc(122px + env(safe-area-inset-bottom))} footer{margin-top:32px} } @media(min-width:701px){body{padding-bottom:64px}} /* ===== tap targets ===== Measured at 35px on a pointer device and 13px on the chapter checkboxes, both below the 44px minimum. Padding fixes the hit area without making the control look heavy. */ .btn,a.btn{min-height:44px;padding:12px 18px;display:inline-flex;align-items:center;justify-content:center} button.btn{line-height:1.2} input[type=text],input[type=email],input[type=number],select{min-height:44px;padding:12px} /* The native checkbox is small by design, so the label around it carries the target. */ .chk{min-height:44px} .chk input[type=checkbox]{width:20px;height:20px;margin-top:2px;flex:none} .opt{min-height:44px} .opt input[type=radio]{width:20px;height:20px;flex:none} /* ===== builder: subtopic picker ===== Chapters are the primary unit; subtopics expand inside them. */ .subject-section{margin-bottom:20px} .subject-label{font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;margin:0 0 8px} .chapter-group{margin-bottom:8px} .chapter-hd{display:flex;align-items:center;min-height:44px;background:var(--panel);padding:10px 12px;border:1px solid var(--border)} .chapter-hd b{color:#fff} .subtopic-list{padding:4px 12px 4px 32px;border:1px solid var(--border);border-top:0;display:none} .chapter-group.expanded .subtopic-list{display:block} .sub-chk{min-height:38px;padding:4px 0} .settings-sticky{position:sticky;top:72px} .picker-col,.settings-col{min-width:0} .build-note{font-variant-numeric:tabular-nums} .all-subj input[type=checkbox]{accent-color:var(--cyan)} @media(max-width:700px){ .settings-sticky{position:static} .chapter-hd{background:none;padding:10px 0} .subtopic-list{padding:4px 0 4px 20px} } /* ===== per-subject timers on exam screen ===== Each strip shows for its subject window and hides when that window closes. */ .subj-timer-bar{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:8px} .subj-timer{display:flex;align-items:center;gap:8px;padding:6px 12px;background:var(--panel);border:1px solid var(--border);font-size:.8rem} .subj-timer b{color:#fff;min-width:5ch;font-variant-numeric:tabular-nums} .subj-timer.active{border-color:var(--cyan)} .subj-timer.warn{border-color:var(--amber)} .subj-timer.done{opacity:.4;text-decoration:line-through}