*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The responsive table rules below set display:block on tr/td, which would
   otherwise override the UA [hidden] rule and reveal elements meant to be hidden
   (e.g. the collapsed "Add recipient" row). Make the hidden attribute win. */
[hidden] {
  display: none !important;
}


body { font-family: Arial, sans-serif; margin: 1em; background: #f7f7f7; }
form {
  max-width: 480px;
  margin: auto;
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
label { display: block; margin-top: 12px; font-weight: bold; }
input[type="text"],
input[type="email"],
input[type="tel"] {
  width: 100%; padding: 10px; margin-top: 4px;
  border: 1px solid #ccc; border-radius: 4px;
}
.radio-group { margin-top: 12px; }
.radio-group label { font-weight: normal; }
button {
  margin-top: 20px;
  width: 100%;
  padding: 12px;
  background: #007BFF;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  cursor: pointer;
}
button:hover { background: #0056b3; }

table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 20px;
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
th, td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #ddd;
  font-size: 14px;
}
th a {
  text-decoration: none;
  color: #333;
}
/* Ensure rows stay styled correctly after sorting */
tr {
  display: table-row;
}

tr:hover { background-color: #f1f1f1; }
tr.pending { background-color: #fff3cd; }
tr.expired { background-color: #ffcc80; }
th::after {
  display: inline-block;
  width: 1ch;                /* Reserve space for arrow */
  content: " ";              /* Use a non-breaking space for consistent width */
  font-size: inherit;
  vertical-align: middle;
  font-weight: inherit;
  color: inherit;
  margin-left: 4px;
}

.sort-asc::after {
  content: "▲";
}

.sort-desc::after {
  content: "▼";
}

input::placeholder {
  color: #bbb;
}
.verification-form input[type="submit"] {
  margin-top: 10px;
  padding: 10px 20px;
  font-size: 1rem;
}
@media (max-width: 768px) {
  table, thead, tbody, th, td, tr {
    display: block;
  }
  tr {
    margin-bottom: 1rem;
    border-bottom: 2px solid #ccc;
  }
  td {
    padding-left: 50%;
    position: relative;
  }
  td::before {
    content: attr(data-label);
    position: absolute;
    left: 0;
    width: 45%;
    padding-left: 15px;
    font-weight: bold;
    white-space: nowrap;
  }
  th { display: none; }
}

th {
  background: #eee;
  cursor: pointer;
}
tr.pending {
  background-color: #ffffcc;
}

tr.registered {
  background-color: #eef8ee;
}

.admin-filter {
  max-width: none;
  display: flex;
  align-items: end;
  gap: 12px;
  margin: 0 0 16px;
}

.admin-filter label {
  margin-top: 0;
}

.admin-filter input {
  max-width: 100px;
}

.admin-filter button {
  width: auto;
  margin-top: 0;
  padding: 10px 18px;
}


.form-container {
  max-width: 600px;
  margin: 40px auto;
  padding: 20px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 0 15px rgba(0,0,0,0.1);
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.form-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 2px solid #ccc;
  margin-bottom: 20px;
  padding-bottom: 10px;
}
.form-header .header-text {
  flex-grow: 1;
}
.form-header h1 {
  margin: 0;
  font-size: 26px;
}
.form-header p {
  margin: 4px 0 0;
  font-size: 18px;
}
.form-header .header-logo {
  width: 80px;
  height: auto;
  margin-left: 20px;
}
.form-field{
    margin-top: 12px;
}
.form-wrapper {
    max-width: 480px;
    margin: 30px auto;
    background: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}

.form-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: #d0e2f0;
    padding: 16px;
    border-radius: 6px;
    margin-bottom: 20px;
    flex-wrap: wrap;
}

.form-header .header-text {
    flex: 1;
    font-family: Arial, sans-serif;
}

.form-header .header-text h1 {
    font-size: 26px;
    margin: 0 0 6px;
}

.form-header .header-text p {
    margin: 4px 0;
    font-size: 18px;
}

.form-header .header-spacer {
    visibility: hidden;
}

.form-header img {
    max-height: 100px;
    margin-left: 20px;
}

@media (max-width: 600px) {
    .form-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .form-header img {
        margin: 12px 0 0;
        align-self: center;
    }
}

/* Admin dashboard */
.admin-page {
    margin: 0;
    background: #eef4f7;
    color: #1f2933;
}

.admin-shell {
    width: min(1180px, calc(100% - 32px));
    margin: 0 auto;
    padding: 20px 0 32px;
}

.admin-login-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
}

.admin-login {
    width: min(420px, 100%);
    max-width: none;
    margin: 0;
    padding: 28px;
    text-align: left;
}

.admin-login img {
    display: block;
    max-width: 110px;
    margin: 0 auto 14px;
}

.admin-login h1 {
    margin: 0 0 18px;
    color: #1f4e79;
    text-align: center;
}

.admin-login label {
    color: #516577;
    font-size: 13px;
}

.admin-login input[type="password"] {
    width: 100%;
    padding: 13px 14px;
    margin-top: 6px;
    border: 1px solid #a9c7dc;
    border-radius: 6px;
    background: #f8fbfd;
    color: #102a43;
    font-size: 16px;
    box-shadow: inset 0 1px 2px rgba(31, 78, 121, 0.08);
}

.admin-login input[type="password"]:focus {
    outline: 3px solid rgba(31, 78, 121, 0.18);
    border-color: #1f4e79;
    background: #fff;
}

.admin-login button {
    background: #1f4e79;
    border-radius: 6px;
    font-weight: 700;
}

.login-error,
.setup-error {
    margin: 0 0 14px;
    padding: 10px 12px;
    color: #7a1f1f;
    background: #fde8e8;
    border: 1px solid #f7b8b8;
    border-radius: 6px;
}

.setup-message {
    margin: 0 0 14px;
    padding: 10px 12px;
    color: #1e6b32;
    background: #e7f5e9;
    border: 1px solid #b9e2c2;
    border-radius: 6px;
}

.admin-masthead {
    background: #1f4e79;
    color: #fff;
    border-bottom: 4px solid #16395a;
}

.admin-masthead-inner {
    width: min(1180px, calc(100% - 32px));
    margin: 0 auto;
    padding: 18px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.admin-masthead h1 {
    margin: 0;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: 0.2px;
}

.admin-masthead img {
    max-height: 56px;
    width: auto;
    display: block;
}

.admin-main {
    display: grid;
    gap: 18px;
}

/* UI-3: grid items default to min-width:auto, which lets the wide (10-column,
   nowrap) registration table force the whole page wider than the viewport —
   that horizontal overflow shifts the margin:0 auto masthead/shell off-center.
   min-width:0 lets .table-scroll's overflow-x:auto contain the table instead. */
.admin-main > * {
    min-width: 0;
}

.admin-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 18px;
}

.admin-tabs a {
    display: inline-flex;
    align-items: center;
    min-height: 42px;
    padding: 0 18px;
    background: #fff;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
    color: #1f4e79;
    font-weight: 700;
    text-decoration: none;
}

.admin-tabs a.active {
    background: #1f4e79;
    border-color: #1f4e79;
    color: #fff;
}

.admin-tabs a.admin-logout {
    margin-left: auto;
    color: #8a3a3a;
}

.admin-toolbar,
.admin-dashboard,
.admin-table-panel {
    background: #fff;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(31, 78, 121, 0.08);
}

.admin-toolbar {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    padding: 18px;
}

.admin-toolbar h2,
.dashboard-heading h3,
.table-heading h3 {
    margin: 0;
    color: #1f4e79;
}

.admin-toolbar p {
    margin: 6px 0 0;
    color: #516577;
}

/* Step directions: yellow highlight so the "what to do now" is unmistakable. */
.admin-toolbar p.step-hint {
    display: inline-block;
    padding: 6px 12px;
    background: #fff3cd;
    border: 1px solid #ffe69c;
    border-radius: 6px;
    color: #6b5800;
    font-weight: 600;
}

.admin-toolbar p.step-hint a {
    color: #1f4e79;
    font-weight: 600;
}

.admin-summary {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}

.admin-stat {
    display: block;
    background: #d0e2f0;
    border: 1px solid #a9c7dc;
    border-radius: 8px;
    padding: 16px;
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.admin-stat[href]:hover {
    background: #d0e2f0;
}

.admin-stat.active {
    background: #ffe8bd;
    border-color: #e4b15a;
}

.admin-stat span {
    display: block;
    color: #516577;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
}

/* The tile's leading emoji: keep it inline with the label (overrides the block above),
   a bit larger than the 13px label, and vertically centered so it doesn't sit low. */
.admin-stat span.stat-emoji {
    display: inline-block;
    font-size: 20px;
    line-height: 1;
    vertical-align: middle;
    margin-right: 4px;
    position: relative;
    top: -1px;
}

.admin-stat strong {
    display: block;
    margin-top: 8px;
    font-size: 34px;
    color: #173c5c;
}

.admin-stat[href]:hover strong {
    color: #9f6b00;
}

.admin-stat.active:hover {
    background: #ffe8bd;
}

/* Section F: invitation email editor — fixed (read-only) sections framing the
   one editable message body, so the admin sees the finished email. */
.invitation-email-editor .invite-fixed {
    margin-top: 14px;
    padding: 10px 12px;
    background: #eef4f9;
    border: 1px dashed #a9c7dc;
    border-radius: 6px;
}

.invitation-email-editor .invite-fixed-label {
    display: block;
    margin-bottom: 4px;
    color: #516577;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.invitation-email-editor .invite-fixed-value {
    color: #1f2937;
    font-size: 15px;
    line-height: 1.5;
}

.invitation-email-editor .invite-fixed-sub {
    display: block;
    margin-top: 6px;
    color: #516577;
    font-size: 12px;
}

.invitation-email-editor textarea {
    width: 100%;
    margin-top: 4px;
    padding: 10px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    background: #fff;
    font: inherit;
    line-height: 1.5;
    box-sizing: border-box;
    /* Fixed height with an internal scrollbar; sized so the default message fits
       without scrolling at typical admin widths. */
    height: 360px;
    resize: none;
    overflow-y: auto;
}

/* Chief Letter editor: same non-resizable, internal-scrollbar treatment as the
   invitation editor, but taller so the (much longer) letter body fits without a
   scrollbar. A small script auto-fits the height to the current text on load;
   this height is the fallback / minimum. */
.chief-letter-editor textarea {
    width: 100%;
    margin-top: 4px;
    padding: 10px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    background: #fff;
    font: inherit;
    line-height: 1.5;
    box-sizing: border-box;
    height: 600px;
    resize: none;
    overflow-y: auto;
}

/* Section F: the four invitation buttons share one row. */
.invitation-send-note {
    margin-top: 16px;
    color: #516577;
    font-size: 13px;
}

.invitation-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
}

.invitation-actions form {
    margin: 0;
}

.invitation-actions button {
    width: auto;
    margin-top: 0;
    background: #1f4e79;
}

.invitation-actions button:hover {
    background: #16395a;
}

.invitation-actions button.secondary {
    background: #e7eef4;
    color: #1f4e79;
    border: 1px solid #b8c8d4;
}

.invitation-actions button.secondary:hover {
    background: #d8e3ea;
}

.invitation-actions button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* The "Load campaign" button sits on its own line below the paragraph — a real
   button, but with no boxed form/frame around it (see the no-button-frames rule). */
.load-campaign-btn {
    display: inline-block;
    width: auto;
    margin-top: 14px;
    padding: 12px 20px;
    background: #1f4e79;
    color: #fff;
    border: none;
    border-radius: 6px;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
}

.load-campaign-btn:hover {
    background: #16395a;
    color: #fff;
}

/* When the button is an <a> (e.g. "Return to invitations"), beat the generic
   .admin-page a colour so the white label doesn't vanish on the blue background. */
.admin-page a.load-campaign-btn,
.admin-page a.load-campaign-btn:hover {
    color: #fff;
    text-decoration: none;
}

/* Landing "Load invitations" block — frameless (no card around the button). */
.load-block {
    margin: 0;
}

.load-block p {
    margin: 0;
    color: #516577;
}

/* Interactive-send progress (recipients step). */
.send-progress {
    margin: 12px 0;
    padding: 14px 16px;
    background: #f4f9fc;
    border: 1px solid #cfe0ec;
    border-radius: 8px;
}

.send-progress-track {
    height: 10px;
    background: #dce8f1;
    border-radius: 999px;
    overflow: hidden;
}

.send-progress-fill {
    height: 100%;
    width: 0;
    background: #1f4e79;
    transition: width 0.2s ease;
}

.send-progress-text {
    margin: 10px 0 0;
    font-weight: 700;
    color: #1f4e79;
}

/* A text link that sits in a button row (e.g. "Close without sending"). */
.action-link {
    align-self: center;
    color: #1f4e79;
    font-weight: 700;
}

/* Recipients step is frameless: the table fills the full width of the page, no
   card frame and no horizontal scrollbar. */
.recipients-block {
    margin: 0;
}

/* The recipients <form> wrappers must NOT pick up the global form card styling
   (max-width:480px + white box + shadow) — that boxed the table and squeezed it
   to ~480px, leaving dead space on both sides. */
#sendForm,
#addRecipientForm,
#unsubscribeForm,
.recipient-conflict form {
    max-width: none;
    width: 100%;
    margin: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
}

.admin-page table.recipients-table {
    table-layout: fixed;
    width: 100%;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
    overflow: hidden;
}

/* Fixed layout: Business/Name/Email share the remaining width; the rest are sized
   to their content so Status/Last sent aren't padded with dead space and the
   Unsubscribe header isn't truncated. */
.recipients-table .status-col { width: 120px; }
.recipients-table .lastsent-col { width: 168px; }
.recipients-table .unsub-col { width: 120px; }

.admin-page table.recipients-table td {
    overflow-wrap: anywhere;
}

/* Recipients step: action rows above/below the table, and the inline Add row. */
.recipient-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 12px 0;
}

.recipient-toolbar button {
    width: auto;
    margin-top: 0;
}

.recipient-toolbar .send-btn {
    background: #1f4e79;
}

.recipient-toolbar .send-btn:hover {
    background: #16395a;
}

.recipient-toolbar .add-btn,
.recipient-toolbar .cancel-btn {
    background: #e7eef4;
    color: #1f4e79;
    border: 1px solid #b8c8d4;
}

.recipient-toolbar .add-btn:hover,
.recipient-toolbar .cancel-btn:hover {
    background: #d8e3ea;
}

/* Live search box (with an inline clear ×) that filters the recipients table. */
.recipient-search {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: auto;
}

.recipient-search input {
    width: 520px;
    max-width: 100%;
    margin-top: 0;
    padding: 9px 32px 9px 36px;
    border: 1px solid #b8c8d4;
    border-radius: 6px;
    font: inherit;
    box-sizing: border-box;
}

.search-icon {
    position: absolute;
    left: 11px;
    width: 17px;
    height: 17px;
    color: #516577;
    pointer-events: none;
}

.search-clear {
    position: absolute;
    right: 4px;
    width: auto;
    margin-top: 0;
    padding: 0 6px;
    background: transparent;
    border: none;
    color: #516577;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

.search-clear:hover {
    background: transparent;
    color: #1f4e79;
}

.check-col {
    width: 38px;
    text-align: center;
}

.recipient-check {
    width: 16px;
    height: 16px;
}

.recipient-add-row td {
    background: #f4f9fc;
}

.recipient-add-row input {
    width: 100%;
    padding: 7px 8px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    font: inherit;
    box-sizing: border-box;
}

.recipient-add-row .name-inputs {
    display: flex;
    gap: 6px;
}

.recipient-add-row button {
    width: auto;
    margin-top: 0;
    padding: 8px 14px;
}

.recipient-add-row .add-actions {
    white-space: nowrap;
}

.recipient-add-row .cancel-add-btn {
    margin-left: 8px;
    background: #e7eef4;
    color: #1f4e79;
    border: 1px solid #b8c8d4;
}

.recipient-add-row .cancel-add-btn:hover {
    background: #d8e3ea;
}

.unsub-col {
    width: 96px;
    text-align: center;
}

.unsub-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto;
    margin-top: 0;
    padding: 5px 9px;
    background: #e7eef4;
    border: 1px solid #b8c8d4;
    border-radius: 6px;
    color: #1f4e79;
    line-height: 0;
    cursor: pointer;
}

.unsub-btn:hover {
    background: #d8e3ea;
    border-color: #9fb6c6;
}

.recipient-conflict {
    margin-bottom: 16px;
    padding: 12px 14px;
    background: #fff7e6;
    border: 1px solid #f0c36d;
    border-radius: 6px;
}

.recipient-conflict p {
    margin: 0 0 8px;
}

.recipient-conflict .invitation-actions {
    margin-top: 4px;
}

.campaign-status-line {
    font-size: 16px;
}

.campaign-message {
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
    padding: 10px;
    background: #f4f7fa;
    border: 1px solid #dbe6ee;
    border-radius: 4px;
    font: 14px/1.5 Arial, Helvetica, sans-serif;
}

.msg-dialog {
    max-width: 560px;
    width: 90%;
    border: 1px solid #a9c7dc;
    border-radius: 8px;
    padding: 18px;
}

.msg-dialog::backdrop {
    background: rgba(31, 78, 121, 0.35);
}

.msg-dialog button {
    margin-top: 12px;
    width: auto;
    padding: 8px 16px;
    background: #1f4e79;
}

.admin-filter {
    max-width: none;
    display: flex;
    align-items: end;
    gap: 10px;
    margin: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
}

.admin-filter label {
    margin-top: 0;
    color: #516577;
    font-size: 13px;
}

.admin-filter input {
    width: 92px;
    margin-top: 4px;
    border-color: #b8c8d4;
}

.admin-filter button {
    width: auto;
    margin-top: 0;
    padding: 10px 18px;
    background: #1f4e79;
}

.setup-form {
    max-width: none;
    margin: 0;
    padding: 0;
    background: transparent;
    box-shadow: none;
}

.setup-form label {
    color: #516577;
    font-size: 13px;
}

.setup-form input[type="text"],
.setup-form input[type="url"],
.setup-form input[type="email"],
.setup-form input[type="date"] {
    width: 100%;
    padding: 10px;
    margin-top: 4px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    background: #fff;
    box-sizing: border-box;
}

.field-hint {
    color: #7a8a99;
    font-weight: 400;
    font-size: 12px;
}

/* Setup-form checkbox row (e.g. "Allow registrants to request space for vehicles"):
   checkbox and its label share one line, spaced clear of the field above. */
.setup-form .setup-check {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    font-weight: 600;
    cursor: pointer;
}
.setup-form .setup-check input[type="checkbox"] {
    width: auto;
    margin: 0;
}

.setup-form input[readonly] {
    color: #31495e;
    background: #eef4f7;
    border-color: #d8e3ea;
    cursor: default;
}

.setup-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
}

.setup-fieldset {
    margin: 16px 0 4px;
    padding: 12px 16px;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
}

.setup-fieldset legend {
    padding: 0 6px;
    color: #1f4e79;
    font-weight: 700;
}

/* Scan-window override (CHG-9): a real native number spinner holds a 15-minute offset
   (0 … −4) from the event time. The offset digits are hidden (color: transparent) and
   the actual 12-hour time is painted in an overlay label on the left; the native arrows
   on the right stay visible and clickable. See the JS in passport.php. */
.kp-timespin {
    position: relative;
    display: inline-block;
    margin-top: 4px;
}
.kp-timespin-num {
    width: 108px;
    padding: 10px 12px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    background: #fff;
    font: inherit;
    color: transparent;        /* hide the raw offset digits */
    caret-color: transparent;  /* no blinking caret on focus */
    box-sizing: border-box;
}
.kp-timespin-label {
    position: absolute;
    left: 12px;
    top: 0;
    height: 100%;
    display: flex;
    align-items: center;
    font-weight: 600;
    color: #31495e;
    font-variant-numeric: tabular-nums;
    pointer-events: none;      /* clicks fall through to the input + its arrows */
}

.setup-form button {
    width: auto;
    padding: 11px 20px;
    background: #1f4e79;
}

.review-form {
    max-width: none;
    margin: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
}

.review-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 0 0 12px;
}

.review-actions.bottom {
    margin: 12px 0 0;
}

.review-actions button {
    width: auto;
    margin-top: 0;
    padding: 10px 16px;
    background: #1f4e79;
}

.review-actions button.danger {
    background: #9f2f2f;
}

.review-actions button.danger:hover {
    background: #7a1f1f;
}

.admin-page input[type="checkbox"] {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: #1f4e79;
}

.admin-page input[type="checkbox"]:disabled {
    opacity: 0.3;
}

.admin-dashboard,
.admin-table-panel {
    padding: 18px;
}

.dashboard-heading,
.table-heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.table-heading-main {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}

.admin-page a.print-roster-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 34px;
    padding: 0 14px;
    background: #1f4e79;
    border: 1px solid #1f4e79;
    border-radius: 8px;
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
    text-decoration: none;
}

.admin-page a.print-roster-btn:hover {
    background: #173b5c;
    color: #fff;
}

.print-roster-btn .print-icon {
    flex-shrink: 0;
}

.record-count {
    color: #516577;
    font-weight: 400;
    font-size: 0.85em;
}

.review-filter {
    display: inline-flex;
    align-items: center;
    gap: 0;
    overflow: hidden;
    border: 1px solid #a9c7dc;
    border-radius: 7px;
}

.review-filter a {
    min-height: 30px;
    padding: 7px 11px;
    color: #1f4e79;
    background: #fff;
    border-right: 1px solid #d8e3ea;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
}

.review-filter a:last-child {
    border-right: none;
}

.review-filter a.active {
    color: #173c5c;
    background: #ffe8bd;
}

.dashboard-heading span,
.table-heading span {
    color: #516577;
    font-size: 13px;
}

/* ── Kids Passport dashboard stat tiles (§6.9) ── */
.kp-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
}

.kp-stat {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    background: #f3f8fc;
    border: 1px solid #d8e3ea;
    border-radius: 10px;
}

.kp-stat-num {
    font-size: 26px;
    font-weight: 800;
    color: #1f4e79;
    line-height: 1.1;
}

.kp-stat-label {
    color: #516577;
    font-size: 13px;
}

/* Kids Passport — Test mode panel (passport settings) */
/* Warning-emoji heading: flex row so the icon centers on the text with a tight gap. */
.kp-test-title {
    display: flex;
    align-items: center;
    gap: 0;
}
.kp-test-title .kp-warn {
    font-size: 0.85em;
    line-height: 1;
    color: inherit;
    margin-right: -2px;
    transform: translateY(-3px);
}
/* Neutralize the global boxed `form` frame (white bg + shadow) on the bare test forms. */
.kp-test-form,
.kp-test-actions form {
    max-width: none;
    margin: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
}
.kp-test-form {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px 16px;
    margin: 8px 0 4px;
}
.kp-test-check {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    margin: 0;
}
.kp-check-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    margin: 14px 0 4px;
}
.kp-check-row input {
    margin: 0;
    width: auto;
}
.kp-test-check input {
    margin: 0;
}
.kp-test-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 12px 0 8px;
}
.kp-test-actions button {
    margin-top: 0;
    width: auto;
    padding: 11px 20px;
    background: #1f4e79;
}
.kp-test-actions button:hover {
    background: #163a5c;
}
.kp-test-panel button.danger {
    background: #b3261e;
    color: #fff;
}
.kp-test-panel button.danger:hover {
    background: #8f1e17;
}

.bar-chart {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    gap: 10px;
    min-height: 250px;
}

.bar-y-axis {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 4px 0 28px;
    color: #516577;
    font-size: 12px;
    text-align: right;
}

.bar-plot {
    display: flex;
    align-items: end;
    gap: 2px;
    min-width: 0;
    border-left: 1px solid #d8e3ea;
    border-bottom: 1px solid #d8e3ea;
    padding: 8px 4px 24px;
    overflow-x: auto;
}

.bar-slot {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    flex: 0 0 16px;
    min-width: 0;
    height: 220px;
}

.bar-value {
    position: relative;
    justify-self: center;
    width: 11px;
    min-height: 2px;
    background: #1f4e79;
    border-radius: 4px 4px 0 0;
}

.bar-value:hover {
    background: #d49b00;
}

.bar-label {
    position: absolute;
    top: calc(100% + 3px);
    left: 50%;
    transform: translateX(-50%);
    color: #516577;
    font-size: 11px;
    text-align: center;
    white-space: nowrap;
    pointer-events: none;
}

/* Horizontal bar chart (dashboard per-booth kids, ranked most-visited first). */
.hbar-chart {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.hbar-row {
    display: grid;
    grid-template-columns: minmax(120px, 220px) minmax(0, 1fr);
    align-items: center;
    gap: 12px;
}

.hbar-name {
    color: #1f2d3a;
    font-size: 14px;
    text-align: right;
    overflow-wrap: anywhere;
}

.hbar-closed {
    display: inline-block;
    margin-left: 4px;
    padding: 1px 6px;
    border-radius: 10px;
    background: #eef2f5;
    color: #8a97a3;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.hbar-track {
    min-width: 0;
    background: #eef3f7;
    border-radius: 4px;
}

.hbar-fill {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-width: 30px;
    height: 26px;
    padding: 0 8px;
    box-sizing: border-box;
    background: #1f4e79;
    border-radius: 4px;
    transition: width 0.3s ease;
}

.hbar-count {
    color: #fff;
    font-size: 13px;
    font-weight: 700;
}

@media (max-width: 620px) {
    .hbar-row {
        grid-template-columns: minmax(90px, 40%) minmax(0, 1fr);
        gap: 8px;
    }
    .hbar-name {
        font-size: 13px;
    }
}

/* Descriptive/intro text above a table, chart, or action row. The bottom margin
   keeps it from smooshing against whatever follows (this is the shared intro
   class on every admin page). */
.chart-note {
    margin: 10px 0 18px;
    color: #516577;
    font-size: 13px;
}

.table-scroll {
    overflow-x: auto;
}

.admin-page table {
    margin-top: 0;
    box-shadow: none;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
    overflow: hidden;
}

.admin-page th {
    background: #d0e2f0;
    color: #173c5c;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0;
    vertical-align: middle;
    white-space: nowrap;
}

.admin-page td {
    vertical-align: middle;
}

.admin-page tr.registered {
    background: #fff;
}

.admin-page tr:hover {
    background: #f5fafc;
}

.admin-page a {
    color: #1f4e79;
    text-decoration: none;
}

.admin-page a:hover {
    text-decoration: underline;
}

.choice-pill,
.status-pill {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 4px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
}

.choice-pill {
    background: #eef4f7;
    color: #173c5c;
}

.status-pill {
    background: #e7f5e9;
    color: #1e6b32;
}

.status-pill.suspicious {
    background: #fde8e8;
    color: #9f2f2f;
}

.status-pill.booth-yes {
    background: #e7eefb;
    color: #1f4ea0;
}

.status-pill.booth-no {
    background: #f5f6f8;
    color: #9aa3af;
}

/* Invitation recipient statuses. ready/registered keep the default green. */
.status-pill.is-queued {
    background: #e7eefb;
    color: #1f4ea0;
}

.status-pill.is-failed {
    background: #fde8e8;
    color: #9f2f2f;
}

.status-pill.is-on-hold {
    background: #fff3df;
    color: #8a5a12;
}

.status-pill.is-unsubscribed {
    background: #f5f6f8;
    color: #6b7480;
}

.empty-state {
    margin: 0;
    padding: 20px;
    color: #516577;
    background: #eef4f7;
    border-radius: 8px;
}

@media (max-width: 820px) {
    .admin-shell {
        width: min(100% - 20px, 1180px);
        padding-top: 10px;
    }

    .admin-masthead-inner {
        width: min(100% - 20px, 1180px);
        flex-direction: column;
        text-align: center;
        gap: 10px;
    }

    .admin-masthead img {
        max-height: 56px;
    }

    .admin-toolbar {
        align-items: stretch;
        flex-direction: column;
    }

    .admin-summary {
        grid-template-columns: 1fr;
    }

    .admin-filter {
        align-items: end;
    }

    .setup-grid {
        grid-template-columns: 1fr;
    }

    .bar-chart {
        min-height: 220px;
    }

    .bar-slot {
        height: 190px;
    }

    .admin-page table,
    .admin-page thead,
    .admin-page tbody,
    .admin-page th,
    .admin-page td,
    .admin-page tr {
        display: block;
    }

    .admin-page table {
        border: none;
        background: transparent;
    }

    .admin-page thead {
        display: none;
    }

    .admin-page tr.registered {
        margin-bottom: 12px;
        padding: 12px;
        border: 1px solid #d8e3ea;
        border-radius: 8px;
        background: #fff;
        box-shadow: 0 4px 14px rgba(31, 78, 121, 0.08);
    }

    .admin-page td {
        display: grid;
        grid-template-columns: 112px minmax(0, 1fr);
        gap: 10px;
        padding: 8px 0;
        border-bottom: 1px solid #edf2f5;
        font-size: 14px;
        overflow-wrap: anywhere;
    }

    .admin-page td:last-child {
        border-bottom: none;
    }

    .admin-page td::before {
        content: attr(data-label);
        position: static;
        width: auto;
        padding-left: 0;
        color: #516577;
        font-weight: 700;
        white-space: normal;
    }
}

@media (max-width: 520px) {
    .admin-page {
        font-size: 15px;
    }

    .admin-dashboard,
    .admin-table-panel,
    .admin-toolbar {
        padding: 14px;
    }

    .dashboard-heading,
    .table-heading {
        align-items: flex-start;
        flex-direction: column;
        gap: 4px;
    }

    .admin-filter {
        display: grid;
        grid-template-columns: 1fr auto;
    }

    .admin-tabs {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }

    .admin-tabs a {
        justify-content: center;
    }

    .admin-filter label {
        grid-column: 1 / -1;
    }

    .admin-filter input {
        width: 100%;
        max-width: none;
    }

    .bar-plot {
        gap: 2px;
    }

    .bar-slot {
        flex-basis: 16px;
    }

    .admin-page td {
        grid-template-columns: 96px minmax(0, 1fr);
    }
}

/* ── Section J: RBAC / user management ──────────────────────────────────────
 * Per-user permissions: login hints, the Management module (user list + the
 * permission editor), and hiding the registrant "Select" column from users who
 * lack review_registrations. The column stays in the DOM (so the table's fixed
 * sort-column indices are unaffected) and is only hidden visually. */

.no-review .review-col {
    display: none;
}

.login-hint {
    margin: -4px 0 8px;
    font-size: 12px;
    color: #516577;
}

/* Management — user list */
.mgmt-table {
    width: 100%;
    border-collapse: collapse;
}

.mgmt-table th,
.mgmt-table td {
    text-align: left;
    padding: 10px 14px;
    border-bottom: 1px solid #e3edf3;
}

.mgmt-table th {
    color: #1f4e79;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.mgmt-tag {
    display: inline-block;
    padding: 1px 8px;
    margin-left: 4px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    background: #e7eef5;
    color: #1f4e79;
}

.mgmt-tag-super {
    background: #1f4e79;
    color: #fff;
}

.mgmt-tag-off {
    background: #f3dede;
    color: #9f2f2f;
}

.mgmt-tag-pending {
    background: #fbe8a6;
    color: #7a5d00;
}

.mgmt-table th.mgmt-type-col,
.mgmt-table td.mgmt-type-cell {
    text-align: center;
}

/* Kids Passport booths table: Organization ~half, Booth # a wider block, and the icon
   actions right-aligned so there is open space between Booth # and the actions. */
.kp-booths-table {
    table-layout: fixed;
}
.kp-booths-table .kp-booth-fr-col {
    width: 12%;
    white-space: nowrap;
    text-align: center;
}
.kp-booths-table .kp-booth-org-col {
    width: 40%;
}
.kp-booths-table .kp-booth-num-col {
    width: 16%;
}
.kp-booths-table .kp-booth-veh-col {
    width: 10%;
    white-space: nowrap;
    text-align: center;
}
.kp-booths-table .kp-booth-num-input {
    width: 110px;
    max-width: 100%;
}
.kp-booths-table th.mgmt-actions-col {
    width: auto;
}
.kp-booths-table td.mgmt-actions,
.kp-booths-table th.mgmt-actions-col {
    text-align: right;
}

.mgmt-type-cell .mgmt-tag {
    margin-left: 0;
}

.mgmt-crown {
    margin-left: 6px;
    font-size: 0.95em;
    cursor: default;
}

/* Management — permission editor + account actions */
.mgmt-check {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 8px 0;
    font-weight: 500;
    color: #2a3b49;
}

.mgmt-check input {
    flex: 0 0 auto;
    /* Optically center the box on the first line of the (possibly wrapping) label. */
    margin: 2px 0 0;
}

.mgmt-fieldset {
    margin: 0 0 16px;
    padding: 12px 16px;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
}

.mgmt-fieldset legend {
    padding: 0 6px;
    color: #1f4e79;
    font-weight: 700;
}

.mgmt-inline-form {
    border-bottom: 1px solid #e3edf3;
    padding-bottom: 16px;
    margin-bottom: 16px;
}

/* ── Shared masthead: Admin › Module breadcrumb + account dropdown ──────────── */
.admin-crumbs {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 18px;
    font-weight: 700;
    line-height: 1;
}

.admin-crumbs a {
    color: #fff;
    text-decoration: none;
}

.admin-crumbs a:hover {
    text-decoration: underline;
}

.crumb-sep {
    opacity: 0.7;
}

.crumb-current {
    font-weight: 600;
    opacity: 0.95;
}

.admin-masthead-right {
    display: flex;
    align-items: center;
    gap: 14px;
}

.admin-user-menu {
    position: relative;
    display: flex;
    align-items: center;
}

.admin-user-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin: 0;
    padding: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.35);
    color: #fff;
    cursor: pointer;
}

.admin-user-btn:hover {
    background: rgba(255, 255, 255, 0.28);
}

.admin-user-dropdown {
    position: absolute;
    right: 0;
    top: 48px;
    min-width: 230px;
    background: #fff;
    border: 1px solid #d8e3ea;
    border-radius: 10px;
    box-shadow: 0 12px 30px rgba(31, 78, 121, 0.18);
    padding: 12px;
    z-index: 50;
}

.admin-user-name {
    margin: 0;
    font-weight: 700;
    color: #1f2937;
}

.admin-user-email {
    margin: 2px 0 10px;
    font-size: 13px;
    color: #516577;
    word-break: break-all;
}

.admin-user-link {
    display: block;
    padding: 8px 6px;
    color: #1f4e79;
    text-decoration: none;
    border-top: 1px solid #eef3f7;
    font-weight: 600;
}

.admin-user-link:hover {
    background: #f4f9fc;
}

.admin-user-logout {
    color: #8a3a3a;
}

/* ── Launcher: module cards (3x3 grid, ≤ 9 modules) ────────────────────────── */
.admin-cards {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
}

.admin-card {
    position: relative;
    display: flex;
    flex-direction: column;
    /* Tall enough to hold the 200px corner image (10px top + 200 + 10px bottom). */
    min-height: 220px;
    /* Reserve the right gutter so card text never runs under the corner image. */
    padding: 22px 220px 22px 24px;
    background: #fff;
    border: 1px solid #d8e3ea;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(31, 78, 121, 0.08);
    color: #1f2937;
    text-decoration: none;
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}

/* Decorative module artwork, pinned ~10px off the card's top-right corner. */
.admin-card-img {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 200px;
    height: 200px;
    object-fit: contain;
    pointer-events: none;
}

a.admin-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 32px rgba(31, 78, 121, 0.16);
    border-color: #1f4e79;
}

.admin-card h2 {
    margin: 0 0 10px;
    color: #1f4e79;
    font-size: 20px;
}

.admin-card p {
    margin: 0;
    color: #51697b;
    font-size: 14px;
    line-height: 1.5;
}

.admin-card-disabled {
    opacity: 0.65;
    cursor: default;
}

.admin-card-soon {
    align-self: flex-start;
    margin-top: auto;
    padding: 2px 10px;
    background: #eef3f7;
    color: #51697b;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
}

@media (max-width: 880px) {
    .admin-cards {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 560px) {
    .admin-cards {
        grid-template-columns: 1fr;
    }
}

/* ── Management: add button, row action icons, inline add/edit rows ─────────── */
/* CHG-21: normalize so the <button> and <a> variants render identically. A bare
   <button> doesn't inherit the page font (it uses the UA's smaller default) and can
   carry a UA margin, so `font: inherit; margin: 0` is what actually makes a
   <button class="add-btn"> line up pixel-for-pixel with the <a class="add-btn">
   links; inline-flex + min-height + box-sizing keep the box identical. */
.admin-page .add-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: auto;
    min-height: 36px;
    margin: 0;
    padding: 0 16px;
    background: #1f4e79;
    border: 1px solid #1f4e79;
    border-radius: 8px;
    color: #fff;
    font: inherit;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
}

.admin-page .add-btn:hover {
    background: #16395a;
}

/* CHG-21: the "Assign winning tickets" button doubles as the editor toggle — while
   the open-all editor is active it turns red and reads "Close assignment editor". */
.admin-page .add-btn.is-closing {
    background: #b02a2a;
    border-color: #b02a2a;
}
.admin-page .add-btn.is-closing:hover {
    background: #8f2020;
}

/* ── STYLE GUIDE: table action columns ──────────────────────────────────────
   Every table's action column (Edit / Decision / row tools) uses the classes
   .mgmt-actions-col (th) + .mgmt-actions (td), and is RIGHT-ALIGNED so the
   button group sits flush under its header. The buttons inside are always
   .icon-btn (the framed rounded box, below) — never bare icons and never
   wrapped in an extra card/box. This is the one place these rules live. */
.mgmt-actions-col {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.mgmt-actions {
    white-space: nowrap;
    text-align: right;
}

/* STYLE GUIDE: the standard table action button — a framed, rounded box around
   a single icon (pencil, check, ✕, toggle, …). Use this for ALL row/table
   actions across admin so they look identical; disable (not hide) when an
   action is unavailable. Do not strip the border/background or add an outer
   frame around it. */
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    margin: 0 2px;
    background: #fff;
    border: 1px solid #cdd9e3;
    border-radius: 7px;
    color: #1f4e79;
    cursor: pointer;
    vertical-align: middle;
}

a.icon-btn {
    text-decoration: none;
}

.icon-btn:hover {
    background: #eef4f9;
}

.icon-btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

.icon-btn.is-on {
    color: #2f8a4f;
}

.icon-btn.is-off {
    color: #9f2f2f;
}

.icon-btn.danger {
    color: #b3261e;
}
.icon-btn.danger:hover:not([disabled]) {
    background: #fbeaea;
}

.icon-btn.approve {
    color: #2f8a4f;
}
.icon-btn.approve:hover:not([disabled]) {
    background: #eaf6ee;
}

/* CHG-21: the prize pickup toggle has three clearly distinct states:
     - disabled   → faint grey check (not yet drawable / "No match").
     - not picked → bold green check on a white background.
     - picked up  → bold white check on a solid green background.
   A slightly heavier checkmark stroke reads as "bold" at 34px. */
.icon-btn.kp-pickup-btn {
    color: #1f7a3d;
    border-color: #9fd0af;
}
.icon-btn.kp-pickup-btn svg path {
    stroke-width: 2.6;
}
.icon-btn.kp-pickup-btn:hover:not([disabled]) {
    background: #eaf6ee;
}
.icon-btn.kp-pickup-btn.is-on {
    color: #fff;
    background: #1f7a3d;
    border-color: #1f7a3d;
}
.icon-btn.kp-pickup-btn.is-on:hover:not([disabled]) {
    background: #196a34;
}
.icon-btn.kp-pickup-btn[disabled] {
    color: #8a94a0;
    background: #fff;
    border-color: #cdd9e3;
    opacity: 0.5;
}

/* NightOut roster: the two Yes/No columns (1st RSP, Booth) stay compact and centered
   so their headers no longer force the table into a horizontal scroll. */
.admin-page th.bool-col,
.admin-page td.bool-col {
    text-align: center;
    width: 1%;
    white-space: nowrap;
}

/* CHG-25: compact emoji columns (Choice / 1st RSP / Booth / Vehicle) replace the text
   headers + Yes/No pills so the roster reclaims width and never needs a horizontal scroll.
   The emoji is the visible value; a .visually-hidden word keeps it readable + sortable. */
#regTable th.emoji-col,
#regTable td.emoji-col {
    width: 1%;
    white-space: nowrap;
    text-align: center;
    padding-left: 6px;
    padding-right: 6px;
    font-size: 18px;
    line-height: 1;
}
#regTable th.emoji-col {
    cursor: pointer;
}
/* The global `th::after` reserves 1ch of arrow space on every header; on the emoji
   headers that pushed the glyph left of center and widened the column. Drop it so the
   emoji sits truly centered and the four flag/choice columns stay tight. */
#regTable th.emoji-col::after {
    content: none;
}

/* Screen-reader-only text: keeps Yes/No + Sponsorship/Raffle Basket audible on the emoji
   cells (including the blank "No" cells) without occupying any visual space. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* CHG-25 hard requirement — the roster must never scroll horizontally. On the desktop
   table layout, clamp a long email so it ellipsizes (full address in the anchor's title
   tooltip) instead of widening the table. The <=820px stacked-card layout shows the full
   email, so this only applies above that breakpoint. */
@media (min-width: 821px) {
    #regTable .reg-email-cell a {
        display: inline-block;
        max-width: 240px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        vertical-align: bottom;
    }
}

/* Review screen: the flag reason sits in a full-width, light-red row directly under
   its entry (no hover, instant decision). Kept visually joined to the row above. */
.admin-page tr.review-reason-row td {
    background: #fdecec;
    color: #7c2b2b;
    font-size: 12px;
    padding-top: 5px;
    padding-bottom: 9px;
    padding-left: 32px; /* ~20px indent past the normal 12px cell padding */
    border-top: 0;
}

.admin-page tr.review-reason-row:hover td {
    background: #fdecec;
}

.review-reason-icon {
    display: inline-flex;
    vertical-align: middle;
    margin-right: 5px;
    position: relative;
    top: -1px;
}

/* Review decision cell: the inline <form> must not inherit the global card
   frame (white bg / shadow / 20px padding) — that box is what pushed the
   Approve/Reject icons down (taller row) and to the right of the header. The
   buttons themselves stay standard framed .icon-btn (see the action-icon rule
   above) so they match the Edit pencil everywhere. */
.review-decision-form {
    display: inline;
    max-width: none;
    margin: 0;
    padding: 0;
    background: none;
    border-radius: 0;
    box-shadow: none;
}

/* STYLE GUIDE: the one confirmation/alert dialog used everywhere in /admin —
   always shown, no browser "stop prompting" escape hatch. Rendered once by
   admin_masthead() and driven by adminConfirm()/adminAlert(); never build a
   per-page popup or use the native confirm()/alert(). */
.admin-dialog-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(23, 60, 92, 0.45);
}

.admin-dialog-overlay[hidden] {
    display: none;
}

.admin-dialog-box {
    width: 100%;
    max-width: 430px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 18px 48px rgba(15, 40, 66, 0.28);
    padding: 24px 26px 18px;
}

.admin-dialog-msg {
    margin: 0 0 20px;
    font-size: 15px;
    line-height: 1.5;
    color: #1f3a57;
    white-space: pre-line; /* keep \n line breaks passed in the message */
}

.admin-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
}

.mgmt-add-row td,
.mgmt-edit-row td {
    background: #f4f9fc;
}

.mgmt-add-row input,
.mgmt-edit-row input {
    width: 100%;
    padding: 7px 8px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    font: inherit;
    box-sizing: border-box;
}

.mgmt-add-row .name-inputs,
.mgmt-edit-row .name-inputs {
    display: flex;
    gap: 6px;
}

.mgmt-add-row .mgmt-check,
.mgmt-edit-row .mgmt-check {
    margin: 0;
    white-space: nowrap;
}

.mgmt-add-row .mgmt-check input,
.mgmt-edit-row .mgmt-check input {
    width: auto;
}

/* Registration inline edit: tighter cells reclaim the dead space beside each
   input, the choice <select> matches the text inputs, the Yes/No checkboxes
   sit under a small caption, and Save/Cancel get their own full-width right-
   aligned row so the action column never widens the table (no h-scroll). */
.mgmt-edit-row td {
    padding-left: 5px;
    padding-right: 5px;
    border-bottom: 0;
}

.mgmt-edit-row td:first-child {
    padding-left: 12px;
}

.mgmt-edit-row select {
    width: 100%;
    padding: 7px 8px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    font: inherit;
    box-sizing: border-box;
}

.mgmt-check-stack {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    margin: 0;
}

.mgmt-check-stack .mgmt-check-label {
    font-size: 10px;
    font-weight: 400;
    color: #516577;
    text-transform: uppercase;
    letter-spacing: .02em;
    line-height: 1;
}

.mgmt-edit-row .mgmt-check-stack input {
    width: auto;
    margin: 0;
}

.mgmt-edit-actions td {
    background: #f4f9fc;
    text-align: right;
    padding: 4px 12px 10px;
    border-top: 0;
}

.mgmt-save,
.mgmt-cancel {
    width: auto;
    margin: 0 4px 0 0;
    padding: 8px 14px;
    border-radius: 6px;
    cursor: pointer;
}

.mgmt-save {
    background: #1f4e79;
    border: 1px solid #1f4e79;
    color: #fff;
}

.mgmt-save:hover {
    background: #16395a;
}

.mgmt-cancel {
    background: #e7eef4;
    border: 1px solid #b8c8d4;
    color: #1f4e79;
}

/* Without this, the global button:hover (#0056b3 fill) leaves the dark-blue
   label unreadable. Darken the fill and flip the text white on hover. */
.mgmt-cancel:hover {
    background: #1f4e79;
    border-color: #1f4e79;
    color: #fff;
}

.mgmt-super-toggle {
    padding: 12px 14px;
    background: #f4f9fc;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
}

.mgmt-perms-sub {
    margin: -6px 0 14px;
    color: #516577;
    font-size: 14px;
}

.mgmt-perms-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
}

.mgmt-perms-actions button {
    width: auto;
    margin-top: 0;
}

.mgmt-perms-actions button[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

a.mgmt-cancel {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    text-decoration: none;
}

/* ── Kids Passport (Phase 2): QR cards + inline booth actions ──────────────── */

/* A non-clickable card used to present a QR code (the .admin-card chrome without
   the hover/link affordance). */
.admin-card-static {
    cursor: default;
}

.qr-preview {
    display: block;
    width: 180px;
    height: 180px;
    margin: 12px 0;
    background: #fff;
    border: 1px solid #d8e3ea;
    border-radius: 8px;
    padding: 8px;
}

.qr-url {
    margin: 0 0 12px;
    color: #516577;
    font-size: 12px;
    word-break: break-all;
}

/* CHG-26 — a booth QR whose entry has no booth number yet: prominent warning to the
   right of the code (big emoji, "Missing Booth #" underneath). */
.qr-preview-row {
    display: flex;
    align-items: center;
    gap: 18px;
}
.qr-preview-row .qr-preview {
    flex: 0 0 auto;
}
.qr-missing-number {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
}
.qr-missing-emoji {
    font-size: 44px;
    line-height: 1;
}
.qr-missing-text {
    font-size: 13px;
    font-weight: 700;
    color: #b3261e;
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* CHG-10 — consolidated QR codes page: the Download / Regenerate action row. */
.kp-qr-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin: 0 0 18px;
}

.kp-qr-actions .action-button {
    display: inline-block;
    width: auto;
    margin: 0;
    padding: 10px 18px;
    background: #1f4e79;
    color: #fff;
    border: none;
    border-radius: 6px;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
}

.kp-qr-actions .action-button:hover {
    background: #16395a;
}

.kp-qr-actions .action-button:disabled,
.kp-qr-actions .action-button:disabled:hover {
    background: #9aa9b6;
    cursor: not-allowed;
}

.kp-qr-actions form {
    max-width: none;
    margin: 0;
}

/* Canonical reset for a <form> that exists only to POST a button (with CSRF) —
   e.g. the QR generate/regenerate actions and booth row Close/Restore. It must
   NOT inherit the global form card (background / padding / shadow / radius),
   which is the "frame around the buttons" we never want. See UI_STYLE_GUIDE.md. */
.inline-action {
    display: inline;
    max-width: none;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

button.linklike {
    width: auto;
    margin: 0 0 0 10px;
    padding: 0;
    background: none;
    border: none;
    color: #1f4e79;
    font: inherit;
    font-size: inherit;
    cursor: pointer;
}

button.linklike:hover {
    background: none;
    text-decoration: underline;
}

button.linklike.danger {
    color: #9f2f2f;
}

button.linklike[disabled] {
    color: #9aa9b6;
    cursor: not-allowed;
    text-decoration: none;
}
button.linklike[disabled]:hover {
    text-decoration: none;
}

/* Anchor styled to read as an inline row action (e.g. "View QR" on the booths
   page), matching button.linklike so the two sit together cleanly. */
a.linklike {
    margin: 0 0 0 10px;
    color: #1f4e79;
    text-decoration: none;
    font: inherit;
    cursor: pointer;
}

/* ── Management — audit log viewer (SEC-5) ──────────────────────────────────
   Read-only viewer over logs/admin_audit.log. Reuses .admin-table-panel /
   .table-heading / .admin-filter / .mgmt-table / .mgmt-tag; below are only the
   audit-specific bits: grouped heading buttons, filter-bar sizing, category
   chip colors, the sensitive-row warning tint, and the pager. */

/* Two heading controls (Audit + Add admin) grouped on the right. */
.table-heading-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

.audit-filter {
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.audit-filter input[type="date"] {
    width: 140px;
}

.audit-filter input[type="text"] {
    width: 190px;
}

.audit-filter select {
    display: block;
    width: auto;
    margin-top: 4px;
    padding: 10px;
    border: 1px solid #b8c8d4;
    border-radius: 4px;
    font: inherit;
    background: #fff;
    box-sizing: border-box;
}

/* "Security events" preset + "Reset" — quiet pill links beside Apply. */
.audit-preset,
.audit-reset {
    align-self: end;
    padding: 9px 14px;
    border: 1px solid #b8c8d4;
    border-radius: 6px;
    color: #1f4e79;
    font-size: 14px;
    text-decoration: none;
    white-space: nowrap;
}

.audit-preset:hover,
.audit-reset:hover {
    background: #e7eef5;
}

.audit-preset.is-active {
    background: #9f2f2f;
    border-color: #9f2f2f;
    color: #fff;
}

.audit-preset.is-active:hover {
    background: #872626;
}

.audit-note,
.audit-empty {
    color: #516577;
    font-size: 14px;
}

.audit-table td {
    vertical-align: top;
}

.audit-time {
    white-space: nowrap;
    font-size: 13px;
}

.audit-action {
    white-space: nowrap;
}

.audit-action .mgmt-tag {
    margin-left: 6px;
}

.audit-ip {
    white-space: nowrap;
    font-size: 13px;
}

.audit-detail {
    word-break: break-word;
    font-size: 13px;
    color: #384855;
}

.audit-anon {
    color: #8a97a3;
    font-style: italic;
}

/* Unparseable log line: shown raw so the viewer never hides or crashes on it. */
.audit-raw-row td {
    font-family: Consolas, Menlo, monospace;
    font-size: 12px;
    color: #516577;
    word-break: break-all;
}

/* Sensitive events (shared-key login, failed login, lockout, 403) — warning tint. */
.audit-row-warn td {
    background: #fdf3d9;
}

/* Category chips (Auth reuses the default .mgmt-tag blue). */
.audit-tag-users {
    background: #e2f0e2;
    color: #2f6b2f;
}

.audit-tag-nightout {
    background: #ece4f3;
    color: #5b2f7a;
}

.audit-tag-kids {
    background: #fdebd7;
    color: #8a4b0f;
}

.audit-tag-other {
    background: #ececec;
    color: #555f68;
}

.audit-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 12px;
    color: #516577;
    font-size: 13px;
}

.audit-pager a {
    color: #1f4e79;
    text-decoration: none;
    font-weight: 600;
}

.audit-pager a:hover {
    text-decoration: underline;
}

.audit-pager-off {
    color: #9aa9b6;
}

a.linklike:hover {
    text-decoration: underline;
}

/* Resume-QR card on the redeem page — constrain its width. */
.kp-qr-card {
    max-width: 320px;
}

/* Final-booth recovery code: a big, unmistakable 3-digit number to read aloud. */
.kp-code-card {
    max-width: 320px;
    text-align: center;
}

.kp-bigcode {
    margin: 0.25rem 0 0.5rem;
    font-size: 3.25rem;
    font-weight: 800;
    letter-spacing: 0.35em;
    /* the letter-spacing pushes the block right; nudge it back so it reads centered */
    text-indent: 0.35em;
    color: #1f4e79;
    font-variant-numeric: tabular-nums;
}

/* Inline pickup search form on the prizes page (no top/bottom margin). */
.kp-inline-search {
    margin: 0;
}

/* Final booth (CHG-15): paper-booklet stamp-count confirmation before redeeming. */
.kp-stamp-confirm {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0.75rem 0 1rem;
    font-weight: 600;
}

/* Final booth (CHG-15): the result panel that appears under a Redeem / Recover lookup. */
.table-subpanel {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid #e2e8f0;
}
.table-subpanel h3 {
    margin: 0 0 0.5rem;
    color: #1f4e79;
}
/* Recover: colour-code the roster so the volunteer reads it at a glance — the main
   registrant on a light-green row, the kids indented on amber rows. Cell backgrounds
   (not row) so they win over the table's zebra/hover striping. */
.kp-roster .kp-registrant-row td { font-weight: 700; background: #e3f4e6; }
.kp-roster .kp-kid-row td { background: #fdf1d6; }
.kp-roster .kp-kid-row td:first-child { padding-left: 2.25rem; }
.kp-muted { color: #6b7684; font-weight: 400; font-size: 0.9em; }

/* Recover: "Show recovery code" — a plain, left-aligned, normal-width dark-blue button.
   Kill the global form card (white box + shadow + auto-centering) — NO button frames. */
.kp-reveal-form {
    max-width: none;
    margin: 0;
    padding: 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
}
.kp-reveal-btn {
    width: auto;
    margin-top: 1rem;
    padding: 11px 20px;
    background: #1f4e79;
}
/* Recover: the revealed code — plain paragraph, big bold number, no card/frame. */
.kp-recover-reveal {
    margin: 1rem 0 0;
    font-size: 1.05rem;
    line-height: 1.6;
}
.kp-recover-code {
    font-size: 2rem;
    font-weight: 800;
    color: #1f4e79;
    letter-spacing: 0.12em;
}

.kp-search-input {
    min-width: 220px;
}

/* ── CHG-21: prize "#" column, open-all ticket editor, single-writer lock banner ── */

/* Organizer-assigned prize number: narrow numeric input + tight table column. */
.kp-prizeno-input { max-width: 70px; }
.mgmt-table th.kp-prizeno-col,
.mgmt-table td.kp-prizeno-cell {
    width: 56px;
    white-space: nowrap;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* The read-only banner shown to a second admin while someone holds the draw lock. */
.kp-lockbanner {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
    padding: 10px 14px;
    border: 1px solid #d9a441;
    background: #fbf3df;
    border-radius: 8px;
    color: #6b4e12;
    font-weight: 600;
}
.kp-lockbanner::before { content: "\1F512"; } /* lock emoji */

/* Open-all editor: the per-row ticket input + its inline save status. */
.kp-ticket-input {
    max-width: 110px;
    font-variant-numeric: tabular-nums;
}
.kp-cell-status {
    display: inline-block;
    margin-left: 6px;
    font-size: 0.8rem;
    font-weight: 700;
    vertical-align: middle;
}
.kp-cell-status.is-saving { color: #7a7a7a; }
.kp-cell-status.is-saved  { color: #1f7a3d; }
.kp-cell-status.is-warn   { color: #b3541e; }
.kp-cell-status.is-error  { color: #b02a2a; }

/* The editor toolbar (Close) that sits below the table while editing is open. */
.kp-editor-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 12px;
}

/* Open-all editor toggle: only when the table carries .editing do the per-row ticket
   inputs replace the read-only value, and the per-row action buttons hide (the editor
   is the only writer while open). */
.kp-editcell { display: none; align-items: center; gap: 6px; }
.mgmt-table.editing .kp-ticketview { display: none; }
.mgmt-table.editing .kp-editcell { display: inline-flex; }
.mgmt-table.editing td.mgmt-actions { visibility: hidden; }

/* ── CHG-17: Final-booth three-tab console + staggered redeem + Search ── */

/* Connected tabs for the Final booth strip (Redeem / Recover / Search). Inactive tabs are
   brand navy; the SELECTED tab is white and merges into the panel below — its bottom border
   opens into the card so it reads as a real tab, not a floating button. Top corners only are
   rounded; the strip sits flush on the panel (no gap, no shadow line). The wrapper takes the
   pair out of the .admin-main grid gap. Tabs stay plain links → a fresh ?tab= page. */
.kp-tabwrap { position: relative; }
.kp-subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0 0 0 10px;
    position: relative;
}
.kp-subtabs a {
    display: inline-flex;
    align-items: center;
    min-height: 42px;
    padding: 0 24px;
    margin-bottom: -1px;                 /* overlap the panel's top border */
    background: #1f4e79;                  /* brand navy — the inactive tabs */
    border: 1px solid #1f4e79;
    border-bottom: none;
    border-radius: 8px 8px 0 0;          /* top corners only — no bottom rounding */
    color: #fff;
    font-weight: 700;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 1px;
    text-decoration: none;
    cursor: pointer;
    position: relative;
    transition: background-color 0.2s linear;
}
.kp-subtabs a:hover { background: #2f6ba5; }
.kp-subtabs a.active {
    border-color: #d8e3ea;               /* match the panel's border */
    color: #1f4e79;
    z-index: 2;                          /* paint over the panel's top border seam */
    background: #fff;                     /* fallback for the gradient below */
    background: linear-gradient(to bottom, #d1d1d1, #ffffff 50%);  /* demo's grey sheen:
        a grey top edge fading to pure white by the midpoint, then white down to the panel */
}
/* A white bridge along the active tab's base, drawn over the panel's top border so the tab
   flows seamlessly into the (white) card. The -1px overlap alone leaves a subpixel sliver of
   that border showing at fractional browser-zoom levels; this covers it for good. */
.kp-subtabs a.active::after {
    content: "";
    position: absolute;
    left: -1px;
    right: -1px;
    bottom: -2px;
    height: 3px;
    background: #fff;
    z-index: 1;
}

/* Only the active panel shows; it sits flush under the tabs and the active tab merges in.
   z-index:1 runs the panel's top border in front of the (recessed) inactive tabs. */
.kp-tabpanel { display: none; }
.kp-tabpanel.is-active {
    display: block;
    position: relative;
    z-index: 1;
}

/* A sheet number flagged as a duplicate or already-issued (JS pre-check + server report). */
.kp-sheet-input.kp-sheet-bad {
    background: #fdeaea;
    border-color: #c0392b;
    outline: 2px solid #c0392b;
    outline-offset: -2px;
}
.kp-roster .kp-sheet-bad-row td { background: #fdeaea; }

/* Staggered redeem: the "present" toggle sits above its kid's sheet input. */
.kp-present {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: 8px;
    font-weight: 600;
    white-space: nowrap;
}
.kp-sheet-input { max-width: 130px; }

/* Search results: one card per registrant group, action on the right of the head. */
.kp-search-group { margin-top: 1.25rem; }
.kp-search-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.kp-search-head h3 { margin: 0; }
/* The matched kid(s) in a name search, highlighted so the eye lands on them. */
.kp-roster .kp-search-hit td { outline: 2px solid #1f4e79; outline-offset: -2px; }

/* A row of heading buttons (Print roster / Print winners / Add prize). */
.kp-heading-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}

/* ── CHG-27: Dashboard tabs (Summary / Participants / Latest activity) ─────────
   The Summary tab is a STACK of panels, not one panel, so it gets a wrapper that
   restores the .admin-main grid gap between them (the tab strip sits on the first). */
.kp-tabstack.is-active {
    display: grid;
    gap: 18px;
}
/* Same UI-3 guard as .admin-main > * — grid items default to min-width:auto, which
   would let a wide table push the page wider than the viewport instead of scrolling
   inside its own .table-scroll. */
.kp-tabstack > * { min-width: 0; }

/* The two superuser tabs are deliberately red: they list every kid's details, can
   delete them, and show live visitor activity. The tab reads danger even when it isn't
   active, and the panel it opens into carries the same red so you always know which tab
   you're standing in. Reuses the existing danger tokens (#b3261e) — no new colors. */
.kp-subtabs a.is-danger {
    background: #b3261e;
    border-color: #b3261e;
}
.kp-subtabs a.is-danger:hover { background: #8f1e17; }
/* The active red tab still merges into its panel, but tinted rather than white. */
.kp-subtabs a.is-danger.active {
    border-color: #e8b9b5;
    color: #8f1e17;
    background: #fdf3f2;
    background: linear-gradient(to bottom, #f0cfcc, #fdf3f2 50%);
}
.kp-subtabs a.is-danger.active::after { background: #fdf3f2; }

.kp-roster-panel {
    background: #fdf3f2;
    border-color: #e8b9b5;
    border-left: 4px solid #b3261e;
}
/* The red panels hold one standard table each (Participants / Latest activity), so the
   table keeps its normal white card look sitting on the red-tinted section. */

/* Standalone red action button (e.g. "Delete all") — auto width, not the global
   full-width blue button. The form around it uses .inline-action to drop the form card. */
.kp-danger-btn {
    margin: 0;
    width: auto;
    padding: 9px 18px;
    background: #b3261e;
    color: #fff;
}
.kp-danger-btn:hover { background: #8f1e17; }

/* ── Latest activity: a standard admin table (one row per phone). The Progress cell
   holds a small bar + count; a row whose id wasn't in the previous 15-second render
   flashes so the eye lands on whoever just acted. ── */
.kp-act-table .kp-act-time {
    color: #6b7684;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.kp-act-empty td { color: #6b7684; }
.kp-act-prog {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.kp-act-bar {
    display: block;
    width: 110px;
    height: 8px;
    border-radius: 4px;
    background: #e6ecf1;
    overflow: hidden;
}
.kp-act-fill {
    display: block;
    height: 100%;
    background: #1f4e79;
    border-radius: 4px;
    transition: width 0.3s linear;
}
.kp-act-count {
    font-variant-numeric: tabular-nums;
    font-size: 13px;
    font-weight: 700;
    color: #1f4e79;
    white-space: nowrap;
}
/* "This just happened" — a one-shot flash on the row's cells, then settle to normal.
   Animated on the <td>s (not the <tr>) so it wins over the table background reliably. */
.kp-act-row.is-new td {
    animation: kpActFlash 2.4s ease-out 1;
}
@keyframes kpActFlash {
    0%   { background: #fff4cc; }
    60%  { background: #fffaeb; }
    100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .kp-act-row.is-new td { animation: none; background: #fffaeb; }
    .kp-act-fill { transition: none; }
}

/* The Kids Passport reconciliation print pages (prizes.php ?print=roster / ?print=winners)
   are now self-contained — they carry their own inline <style> and PD-seal letterhead, the
   same as the NightOut registrations roster — so they no longer depend on this shared
   stylesheet (whose responsive rules were collapsing the print tables into cards). No
   .kp-print-* rules live here anymore. */

/* Inline "Booth" checkbox in the registration edit row. */
.kp-inline-check {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
}
