:root {
  --color-navy: #1b2a4a;
  --color-navy-light: #2c3f6b;
  --color-gold: #c9a84c;
  --color-gold-light: #f3e9d2;
  --color-green: #217a3c;
  --color-green-hover: #195f2e;
  --color-amber: #c47a1a;
  --color-amber-hover: #a06010;
  --color-amber-bg: #fff5e1;
  --color-amber-border: rgba(196, 122, 26, 0.4);
  --color-red: #b3261e;
  --color-red-hover: #8f1e18;
  --color-ink: #1b2a4a;
  --color-muted: #4a5568;
  --color-border: #d7dce6;

  --cat-officers: #add8e6;
  --cat-warrant-officers: #b6e6b6;
  --cat-associates: #ffec99;
  --cat-ncos: #d9d9d9;
  --cat-cadets: #ffffff;
  --cat-aal-staff: #d8bfd8;
  --cat-guests: #ffc896;
  --cat-default: #f5f7fa;
}

* {
  box-sizing: border-box;
}

body {
  font-family: system-ui, sans-serif;
  max-width: 40rem;
  margin: 0 auto;
  padding: 0 0 1.5rem;
  color: var(--color-ink);
  background: #f7f8fb;
}

body.kiosk-page {
  max-width: none;
  background: #f0f2f7;
}

body.admin-page {
  max-width: 95vw;
}

a {
  color: var(--color-navy);
}

h1,
h2 {
  padding: 0 1rem;
}

h3 {
  font-size: 1rem;
  color: var(--color-navy);
  margin: 1.5rem 0 0.5rem;
}

form h3:first-of-type {
  margin-top: 0;
}

main {
  padding: 0 1rem;
}

body.kiosk-page main {
  padding: 0;
}

/* Header / nav */

nav {
  background: var(--color-navy);
  padding: 1.1rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-bottom: 1rem;
}

/* Admin pages cap `body` (and so `main`) at 95vw, but the nav should still
   read as a full-width bar rather than floating with a gap down each side
   — a standard "full-bleed inside a centered container" trick: back out to
   100% of the viewport regardless of how narrow/offset the body itself is. */
body.admin-page nav {
  width: 100vw;
  margin-left: calc(-50vw + 50%);
}

nav .nav-logo {
  margin-right: auto;
  display: flex;
  align-items: center;
}

nav .nav-logo img {
  height: 3.5rem;
  display: block;
}

nav a {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
}

nav a:hover {
  color: #fff;
  text-decoration: underline;
}

.kiosk-header {
  background: var(--color-navy);
  color: #fff;
  padding: 1.25rem 1.5rem;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.kiosk-header h1 {
  margin: 0;
  padding: 0;
  font-size: 1.5rem;
}

.kiosk-header-right {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.kiosk-header .kiosk-session {
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.9rem;
  text-align: right;
}

.kiosk-header .kiosk-logo {
  height: 5rem;
  width: auto;
  display: block;
  flex-shrink: 0;
}

/* Buttons */

button,
.button {
  /* `font: inherit` (not just `font-family`) plus an explicit `box-sizing`
     resets the parts of a <button>'s and an <a>'s default UA styling that
     otherwise differ from each other (font metrics, box model) — without
     this, an <a class="button"> and a real <button> can render at visibly
     different heights/roundness even with identical padding. */
  font: inherit;
  font-weight: 600;
  line-height: 1.2;
  box-sizing: border-box;
  vertical-align: middle;
  border: none;
  border-radius: 0.4rem;
  padding: 0.55rem 1.1rem;
  cursor: pointer;
  background: var(--color-navy);
  color: #fff;
}

/* `a.button` (not just `.button`) is deliberately the more specific
   compound selector here — an <a> that should read as a button (e.g. the
   Sessions page's "Stats" link) rather than underlined text needs
   `display: inline-block` and `text-decoration: none` to override the
   browser's default link styling unambiguously. */
a.button {
  display: inline-block;
  text-decoration: none;
}

button:hover,
a.button:hover {
  background: var(--color-navy-light);
}

button:disabled {
  background: #c7cbd4;
  color: #8a8f9c;
  cursor: not-allowed;
}

/* Flashes */

.flashes {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}

.flash {
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
  margin-bottom: 0.5rem;
}

.flash-success {
  background: #d4edda;
  color: #155724;
}

.flash-error {
  background: #f8d7da;
  color: #721c24;
}

form label {
  display: block;
  margin-bottom: 0.5rem;
}

.field-hint {
  margin: -0.5rem 0 1rem;
  color: var(--color-muted);
  font-size: 0.85rem;
}

input[type="text"],
input[type="password"],
input[type="date"],
input[type="number"],
select {
  font-family: inherit;
  font-size: 1rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
}

/* Tables */

table {
  border-collapse: collapse;
  width: 100%;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  overflow: hidden;
}

th {
  background: var(--color-gold-light);
  color: var(--color-navy);
}

th,
td {
  text-align: left;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--color-border);
}

tr:last-child td {
  border-bottom: none;
}

.search-form {
  display: flex;
  gap: 0.5rem;
  margin: 0.75rem 0;
}

.search-form input[type="text"] {
  flex: 1;
}

.show-archived-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
  font-weight: normal;
}

.sessions-toolbar {
  margin: 1rem 0;
}

.open-session-form {
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  padding: 1rem;
  margin: 1rem 0;
}

.danger-zone {
  background: #fff;
  border: 1px solid var(--color-red);
  border-radius: 0.4rem;
  padding: 1rem;
  margin: 1rem 0 2rem;
}

.danger-zone h2 {
  margin-top: 0;
  color: var(--color-red);
}

.btn-danger {
  background: var(--color-red);
}

.btn-danger:hover {
  background: var(--color-red-hover);
}

/* A smaller variant for buttons that sit inline in a table row (the
   Sessions page's Stats/Roll QR/Close session) — the default button size
   is tuned for standalone touch targets, which reads as too chunky packed
   into a table cell. */
.btn-sm {
  padding: 0.35rem 0.7rem;
  font-size: 0.85rem;
}

.row-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  white-space: nowrap;
}

.row-actions form {
  margin: 0;
}

.guest-add-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}

.guest-add-form label {
  flex: 1 1 14rem;
}

.guest-add-form input[type="text"] {
  width: 100%;
}

.guest-add-form button {
  align-self: flex-end;
}

.guests-import-textarea {
  display: block;
  width: 100%;
  font-family: ui-monospace, monospace;
  font-size: 0.9rem;
  padding: 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  margin-bottom: 0.75rem;
  resize: vertical;
}

/* Session Stats page header: name/opened/closed/opened-by at a glance —
   an auto-width key/value table rather than the full-width data tables
   below it, since a 2-column label/value layout stretched to 95vw would
   leave the value column mostly empty space. */
.session-header-table {
  width: auto;
  margin-bottom: 1rem;
}

/* Form 19 section on the Session Stats page — styled to mirror the real
   AirLeague Form 19 web form as closely as possible (see CHANGELOG), so
   staff can visually cross-reference/copy values across: title with the
   full weekday+date, two columns (all-Male fields, then all-Female fields)
   each in the real form's own category order. */
.form19 {
  margin: 1.5rem 0;
}

.form19-title {
  margin: 0 0 1rem;
}

.form19-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 3rem;
}

.form19-col {
  flex: 1 1 16rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.form19-field label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.form19-field input {
  width: 100%;
  background: #f7f8fb;
  color: var(--color-ink);
}

/* --- App Stats page --- */

.window-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0 0.5rem;
}

.window-filter-option {
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: #fff;
  color: var(--color-navy);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
}

.window-filter-option:hover {
  background: var(--color-gold-light);
}

.window-filter-option.is-selected {
  background: var(--color-navy);
  border-color: var(--color-navy);
  color: #fff;
}

.stat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.75rem;
  margin: 1rem 0 2rem;
}

.stat-tile {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.9rem 1rem;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
}

.stat-tile-label {
  font-size: 0.8rem;
  color: var(--color-muted);
  font-weight: 600;
}

.stat-tile-value {
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--color-navy);
  font-variant-numeric: normal;
}

.stat-tile-sub {
  font-size: 0.8rem;
  color: var(--color-muted);
}

.stat-tile-delta-up {
  color: var(--color-green);
}

.stat-tile-delta-down {
  color: var(--color-red);
}

.chart-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin: 1rem 0 2rem;
}

.chart-card {
  flex: 1 1 20rem;
  margin: 0;
  padding: 1rem;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
}

.chart-card figcaption {
  font-weight: 600;
  color: var(--color-navy);
  margin-bottom: 0.5rem;
}

.chart-card details {
  margin-top: 0.75rem;
  font-size: 0.85rem;
}

.chart-card summary {
  cursor: pointer;
  color: var(--color-muted);
}

.chart-card table {
  margin-top: 0.5rem;
}

.chart-svg {
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart-baseline {
  stroke: var(--color-border);
  stroke-width: 1;
}

.chart-bar {
  transition: opacity 0.1s;
}

.chart-bar:hover {
  opacity: 0.85;
}

.chart-value-label {
  font-size: 11px;
  fill: var(--color-ink);
  font-weight: 600;
}

.chart-axis-label {
  font-size: 10px;
  fill: var(--color-muted);
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.9rem;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  color: var(--color-muted);
}

.chart-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.chart-legend-swatch {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 0.2rem;
}

/* --- Kiosk page --- */

body.kiosk-page {
  padding-bottom: 6.5rem;
}

/* Welcome/goodbye/guest confirmations (.flash-success) and errors
   (.flash-error) auto-dismiss (flashes.js) — routine, not worth blocking on.
   Check-in alerts (.flash-alert) are the one exception: they require a tap
   to dismiss instead of fading, since a "please see staff about..." message
   is exactly the one thing that must not be missed. */
body.kiosk-page .flashes {
  position: fixed;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  max-width: 40rem;
  margin: 0 auto;
  padding: 0 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  z-index: 20;
}

body.kiosk-page .flash {
  padding: 1.5rem 2rem;
  border-radius: 0.5rem;
  font-size: 2rem;
  font-weight: 600;
  text-align: center;
  color: #fff;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  margin: 0;
  white-space: pre-line;
}

body.kiosk-page .flash::before {
  content: "\2713  ";
}

body.kiosk-page .flash-success {
  background: var(--color-green);
}

body.kiosk-page .flash-error {
  background: var(--color-red);
}

body.kiosk-page .flash-error::before {
  content: "\26A0  ";
}

body.kiosk-page .flash-alert {
  background: var(--color-amber);
  cursor: pointer;
}

body.kiosk-page .flash-alert::before {
  content: none;
}

body.kiosk-page .flash-alert::after {
  content: "tap to dismiss";
  display: block;
  font-weight: normal;
  font-size: 0.85rem;
  margin-top: 0.5rem;
  opacity: 0.85;
}

.summary-counts {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: 0.5rem;
  list-style: none;
  padding: 0.75rem 1.5rem;
  background: #fff;
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
  z-index: 10;
}

.summary-count {
  flex: 0 0 auto;
  min-width: 5.5rem;
  text-align: center;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  background: #f9fafc;
}

.summary-count .count {
  display: block;
  font-size: 1.75rem;
  font-weight: bold;
  color: var(--color-navy);
}

.summary-count .label {
  color: var(--color-muted);
  font-size: 0.8rem;
}

.roll-selected-panel {
  margin: 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  background: #fff;
}

.roll-selected-hint {
  margin: 0 0 0.5rem;
  color: var(--color-muted);
  font-size: 0.9rem;
}

.roll-selected-list {
  list-style: none;
  padding: 0;
  margin: 0 0 0.75rem;
}

.roll-selected-entry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.6rem;
  border-radius: 0.4rem;
  background: var(--color-gold-light);
  margin-bottom: 0.35rem;
}

.roll-selected-remove {
  border: none;
  background: none;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  color: var(--color-red);
  padding: 0 0.5rem;
}

.roll-selected-count {
  margin: 0 0 0.6rem;
  font-weight: 600;
  color: var(--color-navy);
}

.roll-selected-actions {
  display: flex;
  gap: 0.75rem;
}

.roll-selected-actions button {
  flex: 1;
  padding: 1rem;
  font-size: 1.1rem;
  border-radius: 0.5rem;
}

.roll-selected-actions .btn-checkin {
  background: var(--color-green);
}

.roll-selected-actions .btn-checkin:hover {
  background: var(--color-green-hover);
}

.roll-selected-actions .btn-checkout {
  background: var(--color-amber);
}

.roll-selected-actions .btn-checkout:hover {
  background: var(--color-amber-hover);
}

.search-wrapper {
  padding: 0 1rem;
}

.search-wrapper input[type="text"] {
  font-size: 1.25rem;
  padding: 0.65rem 0.75rem;
  width: 100%;
  border-radius: 0.5rem;
}

.roll-suggestions {
  /* Deliberately in normal flow, not an absolutely-positioned overlay — it
     pushes the rest of the page down instead of floating over whatever
     comes next (the multi-select panel, the guest form), which is what
     made both previous arrangements look broken. */
  margin: 0.5rem 1rem 0;
  padding: 0;
  list-style: none;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  max-height: 18rem;
  overflow-y: auto;
  overflow-x: hidden;
}

.roll-suggestion {
  padding: 0;
  margin-bottom: 0.35rem;
  border-radius: 0.4rem;
  background: var(--cat-default);
}

.roll-suggestion:last-child {
  margin-bottom: 0;
}

.roll-suggestion[data-category="Officers"] {
  background: var(--cat-officers);
}

.roll-suggestion[data-category="Warrant Officers"] {
  background: var(--cat-warrant-officers);
}

.roll-suggestion[data-category="Associates"] {
  background: var(--cat-associates);
}

.roll-suggestion[data-category="NCOs"] {
  background: var(--cat-ncos);
}

.roll-suggestion[data-category="Cadets"] {
  background: var(--cat-cadets);
}

.roll-suggestion[data-category="AAL Staff"] {
  background: var(--cat-aal-staff);
}

.roll-suggestion[data-category="Guests"] {
  background: var(--cat-guests);
}

.roll-suggestion.is-selected {
  background: var(--color-gold);
}

.roll-suggestion label {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
  min-height: 4.2rem;
  padding: 0.6rem 0.9rem;
}

/* The checkbox stays in the DOM (and keyboard-focusable) for accessibility,
   but the visual indicator is the right-aligned tick below — matching the
   PowerApp reference gallery, which shows a checkmark rather than a box. */
.roll-suggestion input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  padding: 0;
}

.roll-suggestion input[type="checkbox"]:focus-visible ~ .roll-suggestion-tick {
  outline: 2px solid var(--color-navy);
  outline-offset: 2px;
}

.roll-suggestion-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1;
}

.roll-suggestion-name {
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--color-navy);
}

.roll-suggestion-subtitle {
  font-style: italic;
  font-size: 0.9rem;
  color: var(--color-muted);
}

.roll-suggestion-tick {
  flex-shrink: 0;
  width: 1.5rem;
  text-align: center;
  font-size: 1.3rem;
  font-weight: bold;
  color: var(--color-navy);
  opacity: 0;
}

.roll-suggestion input[type="checkbox"]:checked ~ .roll-suggestion-tick {
  opacity: 1;
}

.roll-suggestion.is-selected .roll-suggestion-name,
.roll-suggestion.is-selected .roll-suggestion-subtitle {
  color: var(--color-navy);
}

h2 {
  font-size: 1.1rem;
}

.btn-guest-trigger {
  display: block;
  margin: 1.25rem 1rem 0;
  background: var(--color-amber);
  padding: 0.75rem 1.1rem;
  font-size: 1rem;
}

.btn-guest-trigger:hover {
  background: var(--color-amber-hover);
}

/* Guest-add dialog — an authorised-person-only overlay, orange to match the
   rest of the app's amber "needs staff attention" language (check-in
   alerts, the old inline guest panel this replaced). */
.dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 42, 74, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  z-index: 30;
}

/* Author styles win over the browser's built-in [hidden] { display: none }
   regardless of rule order, so without this the overlay above stays
   display:flex (visible) no matter what the `hidden` attribute says. */
.dialog-overlay[hidden] {
  display: none;
}

.dialog {
  background: #fff;
  border-radius: 0.6rem;
  padding: 1.5rem;
  width: 100%;
  max-width: 24rem;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}

.guest-dialog {
  border-top: 4px solid var(--color-amber);
}

.guest-dialog h2 {
  margin: 0 0 0.5rem;
  padding: 0;
  color: var(--color-amber);
  font-size: 1.1rem;
}

.dialog-hint {
  margin: 0 0 1rem;
  color: var(--color-muted);
  font-size: 0.85rem;
}

.guest-form input[type="text"],
.guest-form input[type="password"] {
  width: 100%;
  border-color: var(--color-amber-border);
}

.dialog-actions {
  display: flex;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

/* A <form> wrapping one action button (e.g. the roll QR dialog's
   "Regenerate code") would otherwise become the flex item instead of the
   button inside it — `display: contents` makes the form transparent to
   the flex layout so its button sizes like a direct sibling. */
.dialog-actions form {
  display: contents;
}

.dialog-actions button {
  flex: 1;
}

.dialog-actions button[type="submit"] {
  background: var(--color-amber);
}

.dialog-actions button[type="submit"]:hover {
  background: var(--color-amber-hover);
}

.btn-secondary {
  background: #fff;
  color: var(--color-navy);
  border: 1px solid var(--color-border);
}

.btn-secondary:hover {
  background: #f0f2f7;
}

/* Nav logout — a form (not a plain link) since it POSTs, styled to sit
   inline with the other nav items instead of looking like a form. */
.nav-logout {
  margin: 0;
}

.nav-logout button {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
}

.nav-logout button:hover {
  background: none;
  color: #fff;
  text-decoration: underline;
}

/* Admin login page */
.login-box {
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  padding: 1.5rem;
  margin: 3rem auto;
  max-width: 22rem;
  text-align: center;
}

.login-box h1 {
  padding: 0;
  margin: 0 0 1.25rem;
  font-size: 1.3rem;
}

.login-box form label {
  text-align: left;
}

/* Landing page */
.landing-meta {
  color: var(--color-muted);
  padding: 0 1rem;
  margin-top: -0.5rem;
}

.landing-docs h2 {
  font-size: 1.1rem;
}

/* Kiosk PIN entry — large/touch-friendly, matching the rest of the kiosk. */
.kiosk-pin-box {
  max-width: 22rem;
  margin: 3rem auto;
  padding: 0 1rem;
  text-align: center;
}

.kiosk-pin-box h2 {
  padding: 0;
}

.kiosk-pin-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 1rem;
}

.kiosk-pin-form input {
  font-size: 1.75rem;
  text-align: center;
  letter-spacing: 0.3rem;
  padding: 0.75rem;
}

.kiosk-pin-form button {
  font-size: 1.1rem;
  padding: 0.75rem;
}

/* Full-width, no-nav mobile utility page — used by both the mobile roll
   call (routes/roll.py) and the kiosk's dynamic-link landing/invalid pages
   (routes/kiosk.py). */
body.mobile-page {
  max-width: none;
  background: #f0f2f7;
}

.mobile-message-box {
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 0.4rem;
  padding: 1.5rem;
  margin: 3rem auto;
  max-width: 22rem;
  text-align: center;
}

.roll-enter-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 1rem;
}

.roll-enter-form input {
  font-size: 1.5rem;
  text-align: center;
  padding: 0.75rem;
}

.roll-enter-form button {
  font-size: 1.1rem;
  padding: 0.75rem;
}

.roll-checklist-header {
  padding: 0.75rem 1rem 0.5rem;
}

.roll-checklist-header h1 {
  margin: 0;
  padding: 0;
  font-size: 1.3rem;
}

.roll-officer-line {
  margin: 0.25rem 0 0;
  color: var(--color-muted);
  font-size: 0.85rem;
}

.roll-switch-officer-form {
  display: inline;
}

/* A <button> styled to read as a plain link — for JS-triggered actions
   (opening a dialog, in-place state changes) that aren't a real navigation
   and so shouldn't be an <a href>. */
.link-button {
  background: none;
  border: none;
  padding: 0;
  color: var(--color-navy);
  text-decoration: underline;
  font: inherit;
  cursor: pointer;
}

.roll-switch-officer {
  font-size: 0.9rem;
}

/* Same per-category tally as the kiosk's .summary-counts (reuses its
   .summary-count item styling, but as small pill-shaped chips rather than
   the kiosk's big stacked-number cards — the checklist below needs the
   vertical space more than the kiosk's mostly-empty search screen does).
   Sticky at the top rather than fixed to the bottom — the bottom is
   already claimed by .roll-checklist-submit. Wraps onto a second line
   rather than scrolling horizontally, so every category stays visible at
   a glance instead of some being hidden off-screen. */
.roll-summary-counts {
  position: sticky;
  top: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0.5rem 0.75rem;
  background: #f0f2f7;
  border-bottom: 1px solid var(--color-border);
  z-index: 10;
}

.roll-summary-counts .summary-count {
  flex: 0 0 auto;
  min-width: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  padding: 0.2rem 0.55rem;
  border-radius: 1rem;
  background: #fff;
}

.roll-summary-counts .summary-count .count {
  display: inline;
  font-size: 0.95rem;
}

.roll-summary-counts .summary-count .label {
  font-size: 0.75rem;
}

.roll-checklist {
  list-style: none;
  margin: 0 1rem 5rem;
  padding: 0;
}

.roll-checklist-row {
  background: #fff;
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--cat-default);
  border-radius: 0.5rem;
  margin-bottom: 0.5rem;
}

/* A left-edge colour stripe by category (Officers/NCOs/Cadets/Guests/...),
   reusing the same `--cat-*` variables as the kiosk's roll-suggestion rows
   — a left border rather than a full background fill so it doesn't fight
   with the "present" gold highlight below. */
.roll-checklist-row[data-category="Officers"] {
  border-left-color: var(--cat-officers);
}

.roll-checklist-row[data-category="Warrant Officers"] {
  border-left-color: var(--cat-warrant-officers);
}

.roll-checklist-row[data-category="Associates"] {
  border-left-color: var(--cat-associates);
}

.roll-checklist-row[data-category="NCOs"] {
  border-left-color: var(--cat-ncos);
}

.roll-checklist-row[data-category="AAL Staff"] {
  border-left-color: var(--cat-aal-staff);
}

.roll-checklist-row[data-category="Guests"] {
  border-left-color: var(--cat-guests);
}

.roll-checklist-row-present {
  background: var(--color-gold-light);
  border-color: var(--color-gold);
  border-left-color: var(--color-gold);
}

.roll-checklist-row label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3.5rem;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
}

.roll-checklist-row input[type="checkbox"] {
  width: 1.5rem;
  height: 1.5rem;
  flex-shrink: 0;
}

.roll-checklist-name {
  font-weight: 600;
  flex: 1;
}

.roll-checklist-subtitle {
  font-style: italic;
  font-size: 0.9rem;
  color: var(--color-muted);
}

.roll-checklist-submit {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  font-size: 1.2rem;
  padding: 1rem;
  border-radius: 0;
}

/* Dynamic-access QR dialog on the Sessions page (opened via a button,
   matching the guest-add/open-session dialog pattern) — shared by both the
   mobile roll call and the kiosk's dynamic entry link, since both are the
   same "QR + plain link + regenerate" shape. */
.access-dialog {
  text-align: center;
  max-width: 28rem;
}

.access-qr-image {
  margin: 0.75rem auto;
  max-width: 14rem;
}

.access-qr-image svg {
  width: 100%;
  height: auto;
  /* segno draws each module as a stroked path segment; scaling that up via
     CSS lets the browser anti-alias the seams between adjacent modules,
     which reads as faint/jagged lines across the code. Crisp (unantialiased)
     edges make it render as solid blocks at any display size. */
  shape-rendering: crispEdges;
}

.access-link {
  /* A single scrollable line rather than guessing a width that fits every
     possible domain/token combination — wrapping mid-URL is harder to read
     and copy than a line that scrolls. */
  overflow-x: auto;
  white-space: nowrap;
  font-size: 0.65rem;
  padding-bottom: 0.25rem;
}

.access-pin {
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.15rem;
  margin: 0.5rem 0 0;
}
