:root{
  --night:#141235; --blue-deep:#1e2a6b; --blue:#2f4bb5; --line:#e2e5f0;
  --ink:#1a1a2e; --ink2:#5a5f7a; --bg:#f6f7fb; --warn:#c81e2e;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
  font-family:-apple-system,"Segoe UI",Roboto,Arial,sans-serif;font-size:16px}
main{max-width:1100px;margin:0 auto;padding:18px 16px 48px}
a{color:var(--blue)}

header{background:var(--night);color:#fff}
.hwrap{max-width:1100px;margin:0 auto;padding:14px 16px;display:flex;
  justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap}
.brand{font-size:19px;font-weight:700}
.ver{color:#b9a24a;font-size:13px;font-weight:600;margin-left:6px}
.hlinks{font-size:14px;color:#c9cbe0}
.hlinks a{color:#fff;text-decoration:none;margin-left:14px}

h1{font-size:24px;margin:6px 0 2px}
.sub{color:var(--ink2);font-size:14px;margin:0 0 18px}
.sec{margin:22px 0 8px;color:var(--ink2);text-transform:uppercase;
  font-size:12px;letter-spacing:1px;font-weight:700}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}
.card{display:block;background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:18px 20px;text-decoration:none;color:var(--blue-deep);
  box-shadow:0 1px 3px rgba(20,18,53,.07)}
.card .t{font-size:17px;font-weight:700}
.card .m{color:var(--ink2);font-size:13px;font-weight:400;margin-top:4px}
.pill{display:inline-block;background:#eef1fb;color:var(--blue-deep);
  border-radius:20px;padding:3px 11px;font-size:12px;font-weight:700;margin-top:10px}

/* Forms and buttons */
.panel{background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:26px;max-width:400px;margin:56px auto;
  box-shadow:0 2px 10px rgba(20,18,53,.08)}
input[type=text],input[type=password]{width:100%;padding:11px 12px;font-size:16px;
  border:1px solid var(--line);border-radius:9px;margin-bottom:12px;
  background:#fff;color:var(--ink)}
input:focus{outline:2px solid var(--blue);outline-offset:1px;border-color:var(--blue)}
.btn{display:inline-block;background:var(--blue);color:#fff;border:0;border-radius:9px;
  padding:11px 20px;font-size:16px;font-weight:700;cursor:pointer;text-decoration:none}
.err{background:#fdecee;color:var(--warn);border:1px solid #f3c3c9;
  border-radius:9px;padding:10px 12px;margin-bottom:14px;font-size:14px}
.empty{background:#fff;border:1px dashed var(--line);border-radius:12px;
  padding:30px;text-align:center;color:var(--ink2)}

/* ---------------------------------------------------------------------------
   Pointer feedback (Ron, 2026-08-01): a control should visibly react when the
   mouse is over it.

   Wrapped in `hover: hover` so it applies ONLY to devices with a real pointer.
   Touch devices never match this query, which avoids the sticky-hover problem
   where a tapped element on a phone keeps its hover styling until you tap
   something else. This app has to work on phones, so the effect is opt-in by
   capability rather than guessed at by screen width.
   `prefers-reduced-motion` suppresses the movement for anyone who has asked
   their system for less animation; the colour change still happens.
--------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine){
  .card, .btn{transition:background-color .12s ease, box-shadow .12s ease,
              transform .12s ease, border-color .12s ease}
  .card:hover{background:#f4f6fe;border-color:#c3ccec;
    box-shadow:0 5px 14px rgba(20,18,53,.13);transform:translateY(-2px)}
  .btn:hover{background:var(--blue-deep);box-shadow:0 5px 14px rgba(20,18,53,.20)}
  .hlinks a:hover{text-decoration:underline}
}
@media (hover: hover) and (prefers-reduced-motion: reduce){
  .card, .btn{transition:background-color .12s ease}
  .card:hover{transform:none}
}
/* Keyboard users get the same affordance on every device. */
.card:focus-visible,.btn:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* Touch feedback: brief press state, which phones do support. */
.card:active,.btn:active{filter:brightness(.96)}

/* Settings forms */
.panel.wide{max-width:none;margin:0 0 6px;padding:20px 22px}
.panel.wide label{display:block;font-size:13px;font-weight:700;
  color:var(--ink2);margin-bottom:12px}
.panel.wide label input,.panel.wide label select{display:block;margin-top:5px;
  font-weight:400;color:var(--ink)}
select{width:100%;padding:11px 12px;font-size:16px;border:1px solid var(--line);
  border-radius:9px;background:#fff;color:var(--ink)}
.row{display:flex;gap:16px;flex-wrap:wrap}
.row > label{flex:1 1 220px}
.hint{color:var(--ink2);font-size:13px;margin:2px 0 14px;max-width:640px}
.ok{background:#eaf6ec;color:#1d6b30;border:1px solid #bfe2c6;border-radius:9px;
  padding:10px 12px;margin-bottom:14px;font-size:14px}
.btn.ghost{background:#fff;color:var(--blue-deep);border:1px solid var(--line)}

/* Module checkbox rows */
.modrow{border-bottom:1px solid var(--line);padding:12px 0}
.modrow:last-child{border-bottom:0}
.modlab{display:flex;align-items:flex-start;gap:12px;margin:0 !important;
  font-weight:400 !important;cursor:pointer}
.modrow.fixed .modlab{cursor:default;opacity:.72}
.modlab input[type=checkbox]{margin:2px 0 0 0 !important;width:18px;height:18px;
  flex:0 0 auto;accent-color:var(--blue);cursor:inherit}
.modlab b{color:var(--ink);font-size:16px}
.modlab em{color:var(--ink2);font-size:12px;font-style:normal;font-weight:700;
  text-transform:uppercase;letter-spacing:.5px}
.modlab .m{display:block;color:var(--ink2);font-size:13px;margin-top:3px;
  max-width:640px}
@media (hover: hover) and (pointer: fine){
  .modrow:not(.fixed) .modlab:hover b{color:var(--blue)}
}

/* People and Roles */
.person{padding:16px 18px;margin-bottom:10px}
.phead{display:flex;justify-content:space-between;align-items:flex-start;
  gap:14px;flex-wrap:wrap;margin-bottom:12px}
.phead b{font-size:16px;color:var(--ink)}
.phead .m{display:block;color:var(--ink2);font-size:13px;margin-top:2px}
.labelin{width:200px;padding:8px 10px !important;font-size:14px !important;
  border:1px solid var(--line);border-radius:8px;margin:0 !important}

/* Group chips: wrap on any width, so this works on a phone.
   A checkbox matrix with twelve columns would not. */
.chips{display:flex;flex-wrap:wrap;gap:7px}
.chip{display:inline-flex;align-items:center;gap:6px;margin:0 !important;
  padding:6px 12px 6px 9px;border:1px solid var(--line);border-radius:20px;
  background:#fff;cursor:pointer;font-size:13px !important;
  font-weight:600 !important;color:var(--ink2) !important}
.chip input{width:15px;height:15px;margin:0 !important;accent-color:var(--blue);
  cursor:pointer}
.chip.on{background:#eef1fb;border-color:#c3ccec;color:var(--blue-deep) !important}
@media (hover: hover) and (pointer: fine){
  .chip{transition:background-color .12s ease,border-color .12s ease}
  .chip:hover{border-color:var(--blue);background:#f4f6fe}
}

form.inline{display:flex;gap:10px;flex-wrap:wrap;align-items:center;
  margin-bottom:8px}
form.inline select{width:auto;min-width:200px;flex:0 1 auto}

code.pw{display:inline-block;background:#fff;border:1px solid #bfe2c6;
  border-radius:6px;padding:4px 10px;font-size:17px;letter-spacing:1px;
  font-family:Consolas,"Courier New",monospace;margin:4px 0}
.ok .m{display:block;color:var(--ink2);font-size:13px;margin-top:4px}

/* Attendee pages */
.stats{display:flex;gap:12px;flex-wrap:wrap;margin:0 0 18px}
.stat{background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:12px 18px;min-width:130px}
.stat b{display:block;font-size:24px;color:var(--blue-deep);line-height:1.1}
.stat span{color:var(--ink2);font-size:12px;text-transform:uppercase;
  letter-spacing:.5px;font-weight:700}
.stat.warn b{color:var(--warn)}

.panel.nopad{padding:0;overflow-x:auto}
table.grid-t{width:100%;border-collapse:collapse;font-size:14px}
table.grid-t th{text-align:left;padding:11px 14px;border-bottom:1px solid var(--line);
  color:var(--ink2);font-size:12px;text-transform:uppercase;letter-spacing:.5px}
table.grid-t td{padding:11px 14px;border-bottom:1px solid #f0f2f8;vertical-align:top}
table.grid-t tr:last-child td{border-bottom:0}
table.grid-t td .m{display:block;color:var(--ink2);font-size:12px;margin-top:2px}
@media (hover: hover) and (pointer: fine){
  table.grid-t tbody tr:hover{background:#f7f9ff}
}

.tag{display:inline-block;background:#eef1fb;color:var(--blue-deep);
  border-radius:12px;padding:1px 9px;font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.4px}
.tag.warn{background:#fdecee;color:var(--warn)}
.tag.ok{background:#eaf6ec;color:#1d6b30}

.pager{display:flex;gap:10px;margin:14px 0}
.crumb{margin:0 0 4px;font-size:13px}
.two{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}
dl.kv{margin:0}
dl.kv dt{color:var(--ink2);font-size:12px;text-transform:uppercase;
  letter-spacing:.5px;font-weight:700;margin-top:10px}
dl.kv dd{margin:2px 0 0}
ul.plain{list-style:none;padding:0;margin:6px 0}
ul.plain li{padding:5px 0;border-bottom:1px solid #f0f2f8}
ul.plain li:last-child{border-bottom:0}
ul.plain .m{color:var(--ink2);font-size:12px;margin-left:6px}
ul.small{font-size:14px}
.code-h{font-family:Consolas,"Courier New",monospace;font-size:19px;
  letter-spacing:1px;background:#f6f7fb;border:1px solid var(--line);
  border-radius:9px;padding:12px 14px;margin:4px 0 10px;word-break:break-all}
input[type=file]{font-size:14px;margin-top:5px}

/* ---------------------------------------------------------------------------
   Scanner. Designed at 380px first and allowed to grow -- not a desktop
   layout shrunk down. Big targets, high contrast, minimal chrome, because it
   is used one-handed in a queue.
--------------------------------------------------------------------------- */
.scanwrap{max-width:520px;margin:0 auto}
.scanhead{display:flex;justify-content:space-between;align-items:center;
  gap:12px;margin-bottom:10px}
.scanhead b{font-size:18px;display:block}
.scanhead .m{color:var(--ink2);font-size:13px}
.tally{text-align:right;line-height:1}
.tally b{font-size:30px;color:var(--blue-deep)}
.tally span{display:block;font-size:11px;color:var(--ink2);font-weight:700;
  text-transform:uppercase;letter-spacing:1px}

.result{border-radius:14px;padding:18px;text-align:center;margin-bottom:12px;
  border:2px solid var(--line);background:#fff;min-height:86px;
  display:flex;flex-direction:column;justify-content:center}
.result .rmsg{font-size:24px;font-weight:800;letter-spacing:-.3px}
.result .rname{font-size:16px;margin-top:3px;opacity:.85}
.result.idle{color:var(--ink2)}
.result.ok{background:#e7f7ea;border-color:#43a75c;color:#14682c}
.result.duplicate{background:#fff4e0;border-color:#d98b16;color:#8a5100}
.result.unknown,.result.invalid,.result.revoked{
  background:#fdecee;border-color:#d3495a;color:#a2101f}
.result.queued{background:#eef1fb;border-color:#7d8fce;color:var(--blue-deep)}

/* Every outcome flashes once (Ron, 2026-08-04). A green following a green
   otherwise looks like the same green, so the operator waits to be sure the
   banner belongs to the person in front of them -- and that wait, not the
   clear timer, is what slows a moving queue. Short and unmistakable, not
   decorative. Under reduced-motion the pulse drops the scale and keeps the
   brightness, because the cue is the point and only the movement is optional. */
@keyframes resultflash{
  0%{transform:scale(1);filter:brightness(1)}
  22%{transform:scale(1.035);filter:brightness(1.3)}
  100%{transform:scale(1);filter:brightness(1)}
}
@keyframes resultflashcalm{
  0%{filter:brightness(1.4)}
  100%{filter:brightness(1)}
}
.result.flash{animation:resultflash .34s ease-out}
@media (prefers-reduced-motion:reduce){
  .result.flash{animation:resultflashcalm .34s ease-out}
}

/* Name and email on a person's row (Ron, 2026-08-04). Sits between the header
   and the role chips: it is a correction, not a headline, so it stays quiet
   until somebody looks for it. */
.acctedit{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;
  margin:10px 0 4px}
.acctedit label{margin:0;font-size:12px;font-weight:700;color:var(--ink2);
  display:flex;flex-direction:column;gap:3px}
.acctedit input{font-size:14px;padding:6px 8px;min-width:200px}
.acctedit input:disabled{background:#f4f5f8;color:var(--ink2)}

.camerabox{position:relative;background:#0d0c22;border-radius:14px;
  overflow:hidden;aspect-ratio:4/3;margin-bottom:12px}
.camerabox video{width:100%;height:100%;object-fit:cover;display:block}
.camnote{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;text-align:center;color:#fff;padding:20px;
  font-size:14px;line-height:1.5}
.camnote code{background:rgba(255,255,255,.15);padding:2px 6px;border-radius:5px}

.manual{display:flex;gap:9px;align-items:flex-end}
.manual label{flex:1;margin:0;font-size:12px;font-weight:700;color:var(--ink2)}
.manual input{font-family:Consolas,"Courier New",monospace;font-size:17px;
  letter-spacing:.5px;text-transform:uppercase;margin:0 !important}
.manual .btn{padding:11px 16px}

.btn.small{padding:6px 12px;font-size:13px}
tr.undone td{opacity:.5;text-decoration:line-through}
tr.undone td .tag{text-decoration:none;opacity:1}
.qrbox{text-align:center;background:#fff;border:1px solid var(--line);
  border-radius:12px;padding:16px;margin:6px 0}
.qrbox img{width:100%;max-width:230px;height:auto;display:block;margin:0 auto}

.scanstatus{font-size:12px;color:var(--ink2);margin:-6px 0 12px;
  font-family:Consolas,"Courier New",monospace}
.scanstatus.bad{color:var(--warn);font-weight:700}

/* Breadcrumbs. Built centrally in views.render so no page can ship without
   a route back. Wraps on a phone rather than overflowing. */
nav.crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  margin:0 0 14px;font-size:13px;line-height:1.7}
nav.crumbs a{color:var(--blue);text-decoration:none}
nav.crumbs .sep{color:var(--ink2);opacity:.6}
nav.crumbs .here{color:var(--ink2);font-weight:700}
@media (hover: hover) and (pointer: fine){
  nav.crumbs a:hover{text-decoration:underline}
}

.chips.wide-chips .chip{font-size:14px !important;padding:8px 14px 8px 11px}
.chip em{font-style:normal;opacity:.65;font-weight:700}

.warnbox{background:#fff4e0;color:#8a5100;border:1px solid #f0cf9a;
  border-radius:9px;padding:11px 13px;margin-bottom:14px;font-size:14px}
.warnbox b{color:#6d3f00}

/* Type-ahead dropdown */
.ta-box{position:absolute;z-index:40;left:0;right:0;top:100%;margin-top:4px;
  background:#fff;border:1px solid var(--line);border-radius:10px;
  box-shadow:0 8px 22px rgba(20,18,53,.16);max-height:320px;overflow-y:auto}
.ta-item{display:block;width:100%;text-align:left;background:none;border:0;
  border-bottom:1px solid #f0f2f8;padding:9px 12px;cursor:pointer;font:inherit}
.ta-item:last-child{border-bottom:0}
.ta-item b{display:block;font-size:15px;color:var(--ink)}
.ta-item span{display:block;font-size:12px;color:var(--ink2);margin-top:1px}
.ta-item:hover,.ta-item:focus{background:#f0f3fd;outline:none}
.ta-none{padding:10px 12px;color:var(--ink2);font-size:13px}
.ta-wrap{position:relative}

/* ---------------------------------------------------------------------------
   Visual assets, carried across from GA2026 (Ron, meeting note 2026-08-03:
   "the visual assets were not there like they were for the GA2026").
   The photographic band behind the header and the badge beside the name are
   what make it recognisable as the same application.
   --------------------------------------------------------------------------- */
header { position: relative; overflow: hidden; }
header img.band {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 30%; opacity: .28;
}
header .hwrap { position: relative; z-index: 2; }
header .brand { display: flex; align-items: center; gap: 10px; }
img.hbadge {
  height: 34px; width: auto; border-radius: 10px; background: #fff;
  padding: 3px 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}

/* Hero band for the portal and event home. */
.hero {
  position: relative; overflow: hidden; border-radius: 14px;
  margin: 4px 0 20px; min-height: 132px; display: flex;
  align-items: flex-end; background: #1c2330;
}
.hero img.hbg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 26%; opacity: .92;
}
.hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(18, 11, 36, .10),
              rgba(18, 11, 36, .12) 45%, rgba(18, 11, 36, .78));
}
.hero .hcap {
  position: relative; z-index: 2; padding: 16px 18px; color: #fff;
}
.hero .hcap h1 { margin: 0; color: #fff; font-size: 1.55rem; }
.hero .hcap p { margin: 4px 0 0; color: rgba(255, 255, 255, .82); }
@media (max-width: 560px) {
  .hero { min-height: 104px; }
  .hero .hcap h1 { font-size: 1.25rem; }
}
/* Viewing as somebody else. Deliberately loud and always on screen: the one
   failure mode of impersonation is forgetting you are doing it, and a subtle
   indicator is the same as no indicator. */
.viewas {
  position: sticky; top: 0; z-index: 40;
  display: flex; gap: 14px; align-items: center; justify-content: space-between;
  flex-wrap: wrap;
  background: #7a2e12; color: #fff;
  padding: 9px 16px; font-size: .92rem; line-height: 1.35;
  border-bottom: 3px solid #f0a35e;
}
.viewas b { color: #ffe6cf; }
.viewas .btn { background: #fff; color: #7a2e12; border-color: #fff; }
.viewas .btn:hover { background: #ffe6cf; }