:root{--navy:#1d3d5c;--navy-deep:#14293e;--teal:#3db5a0;--teal-dark:#157a5a;--coral:#d85a30;--amber:#b7791f;--ink:#22272b;--dim:#5f676e;--line:#dfe4e8;--panel:#ffffff;--bg:#f4f6f8;--radius:14px;--shadow:0 1px 2px rgba(20,41,62,0.06),0 8px 24px rgba(20,41,62,0.07)}*{box-sizing:border-box}body,html{margin:0;padding:0;background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;-webkit-text-size-adjust:100%}h1,h2,h3{margin:0 0 8px;line-height:1.2;letter-spacing:-.01em}p{line-height:1.55}.wrap{max-width:940px}.wrap,.wrap-narrow{margin:0 auto;padding:24px 20px 64px}.wrap-narrow{max-width:480px}.topbar{background:var(--navy);color:#fff;padding:14px 20px;display:flex;align-items:center;justify-content:space-between;gap:12px}.topbar .brand{font-weight:700;font-size:17px;letter-spacing:-.01em}.topbar .brand span{color:var(--teal);font-weight:500}.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:20px;margin-bottom:18px}.label{display:block;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--teal-dark);margin-bottom:6px}input[type=number],input[type=password],input[type=text],select,textarea{width:100%;padding:12px;font-size:16px;font-family:inherit;color:var(--ink);background:#fff;border:1px solid var(--line);border-radius:10px}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid rgba(61,181,160,.55);outline-offset:2px}.row{display:flex;gap:14px;flex-wrap:wrap}.row>*{flex:1 1 200px}.field{margin-bottom:16px}.btn,button{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:12px 18px;font-size:15px;font-weight:600;font-family:inherit;border:1px solid transparent;border-radius:10px;background:var(--navy);color:#fff;cursor:pointer;text-decoration:none}.btn:hover,button:hover{background:var(--navy-deep)}button:disabled{opacity:.45;cursor:not-allowed}.btn.secondary,button.secondary{background:#fff;color:var(--navy);border-color:var(--line)}.btn.secondary:hover,button.secondary:hover{background:#f0f3f6}button.danger{background:var(--coral)}button.big{width:100%;padding:16px;font-size:17px}.toggle{display:flex;align-items:flex-start;gap:10px;padding:10px 0}.toggle input{width:18px;height:18px;margin-top:2px;flex:none}.toggle .t-title{font-weight:600;font-size:15px}.toggle .t-help{margin-top:2px}.note,.toggle .t-help{font-size:13px;color:var(--dim)}.note{margin:6px 0 0}.alert{border-radius:10px;padding:12px 14px;font-size:14px;line-height:1.5;margin-bottom:14px;border:1px solid}.alert.error{background:#fdf0eb;border-color:#f0c4b3;color:#8f3517}.alert.warn{background:#fdf7e7;border-color:#ecd9a5;color:#7a5a11}.alert.ok{border-color:#b6e2d6;color:#10604a}.alert.ok,.pill{background:#eaf7f3}.pill{display:inline-block;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:700;color:var(--teal-dark)}table{width:100%;border-collapse:collapse;font-size:14px}td,th{text-align:left;padding:9px 8px;border-bottom:1px solid var(--line)}th{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--dim)}td.mono,th.mono{font-feature-settings:"tnum";font-variant-numeric:tabular-nums;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.projector{min-height:100dvh;background:var(--navy);color:#fff;display:grid;grid-template-columns:1.35fr .65fr;grid-gap:28px;gap:28px;padding:28px}@media (max-width:900px){.projector{grid-template-columns:1fr}}.proj-main{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}.proj-title{font-size:clamp(22px,3vw,38px);font-weight:700}.proj-sub{color:var(--teal);font-size:clamp(14px,1.6vw,20px);margin-bottom:20px}.qr-frame{background:#fff;padding:18px;border-radius:20px;line-height:0;box-shadow:0 20px 60px rgba(0,0,0,.35)}.qr-frame img{width:min(52vh,100%);height:auto;image-rendering:pixelated}.qr-hint{margin-top:18px;font-size:clamp(14px,1.5vw,19px);opacity:.85}.ttl-bar{width:min(52vh,100%);height:6px;border-radius:999px;background:rgba(255,255,255,.2);margin-top:14px;overflow:hidden}.ttl-fill{height:100%;background:var(--teal);transition:width .12s linear}.proj-side{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:18px;padding:18px;display:flex;flex-direction:column;min-height:0}.count{font-size:clamp(40px,6vw,76px);font-weight:800;line-height:1;font-feature-settings:"tnum";font-variant-numeric:tabular-nums}.count small{display:block;font-size:13px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--teal);margin-top:6px}.roster-list{list-style:none;margin:14px 0 0;padding:0;overflow-y:auto;flex:1 1}.roster-list li{display:flex;justify-content:space-between;gap:10px;padding:9px 2px;border-bottom:1px solid rgba(255,255,255,.12);font-size:15px}.roster-list .t{opacity:.6;font-feature-settings:"tnum";font-variant-numeric:tabular-nums}.proj-actions{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap}.proj-actions .btn,.proj-actions button{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.25);color:#fff;font-size:14px;padding:9px 14px}.proj-actions .btn:hover,.proj-actions button:hover{background:rgba(255,255,255,.22)}.checkin-hero{text-align:center;padding:22px 0 8px}.checkin-hero .course{font-size:22px;font-weight:700}.checkin-hero .meta{color:var(--dim);font-size:15px;margin-top:4px}.cam-preview{object-fit:cover;background:#000;display:block;transform:scaleX(-1)}.cam-placeholder,.cam-preview{width:100%;max-width:260px;aspect-ratio:3/4;border-radius:14px;margin:0 auto 12px}.cam-placeholder{border:1px dashed var(--line);background:#f7f9fb;display:flex;align-items:center;justify-content:center;font-size:34px}.success{text-align:center;padding:28px 20px}.success .tick{width:72px;height:72px;border-radius:50%;background:var(--teal);color:#fff;display:flex;align-items:center;justify-content:center;font-size:38px;margin:0 auto 16px}.spinner{width:26px;height:26px;border-radius:50%;border:3px solid var(--line);border-top-color:var(--navy);animation:spin .8s linear infinite;margin:20px auto}@keyframes spin{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.spinner{animation-duration:3s}.ttl-fill{transition:none}}