/* CertPass — minimal clean stylesheet */

:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --muted: #6b7280;
  --border: #e5e7eb;
  --accent: #111827;
  --accent-hover: #000000;
  --error-bg: #fef2f2;
  --error-border: #fecaca;
  --error-text: #b91c1c;
  --tag-bg: #f3f4f6;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

h1,
h2 {
  margin: 0 0 0.5rem;
  font-weight: 600;
}

h1 {
  font-size: 1.6rem;
}

h2 {
  font-size: 1.15rem;
}

.brand {
  font-weight: 700;
  letter-spacing: -0.01em;
}

.muted {
  color: var(--muted);
  margin: 0.25rem 0 0;
}

.small {
  font-size: 0.875rem;
}

/* ---- Auth screen ---- */

.auth-shell {
  /* Fill the viewport (use dvh where supported so the iOS toolbar
     doesn't crop the gradient) and centre the card vertically. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  /* Subtle white → very pale teal gradient. The teal stop matches
     the brand and stays light enough for the white card to lift
     off via shadow without contrast issues. */
  background: linear-gradient(180deg, #ffffff 0%, #E8F7F2 100%);
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 12px;
  /* 40px desktop padding per spec; mobile override drops to 28px. */
  padding: 40px;
  /* Slightly more pronounced lift off the gradient background. */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 12px 32px rgba(15, 23, 42, 0.10);
}

/* Tagline directly under the wordmark — small, grey, 14px. */
.auth-tagline {
  margin: 0.25rem 0 0;
  color: var(--muted);
  font-size: 14px;
}

.auth-subhead {
  margin-top: 0.5rem;
}

/* Bottom links: extra 8px of breathing room above each, on top of
   the existing .hint margins. */
.auth-forgot {
  /* Previous inline margin was 14px; spec adds +8px → 22px. */
  margin: 22px 0 0;
  text-align: center;
  font-size: 14px;
}
.auth-forgot a {
  color: #64748B;
  text-decoration: none;
  font-size: 14px;
}
.auth-forgot a:hover { text-decoration: underline; }

.auth-signup {
  margin: calc(1.125rem + 8px) 0 0;
  font-size: 14px;
  color: var(--muted);
}
.auth-signup a {
  color: var(--brand-teal);
  font-weight: 600;
  text-decoration: none;
}
.auth-signup a:hover { text-decoration: underline; }

.auth-card .brand {
  font-size: 1.5rem;
  margin: 0;
}

.form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.form label {
  font-size: 0.875rem;
  color: var(--muted);
  margin-top: 0.5rem;
}

.form input {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.75rem;
  /* Hard 16px to defeat iOS Safari's auto-zoom-on-focus behaviour
     (any input <16px triggers a viewport zoom on iPhone). */
  font-size: 16px;
  font-family: inherit;
  outline: none;
}

.form input:focus {
  border-color: var(--accent);
}

.form button {
  margin-top: 1rem;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 6px;
  padding: 0.7rem 1rem;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
}

.form button:hover {
  background: var(--accent-hover);
}

.hint {
  margin-top: 1.25rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.hint code {
  background: var(--tag-bg);
  padding: 0.05rem 0.3rem;
  border-radius: 4px;
}

.error {
  margin-top: 1rem;
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  color: var(--error-text);
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  font-size: 0.9rem;
}

/* ---- Dashboard ---- */

.topbar {
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}

.topbar-inner {
  max-width: 1400px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 1.5rem;
}

.link-button {
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  padding: 0;
}

.link-button:hover {
  color: var(--text);
}

.page {
  /* All internal app pages (Dashboard, Sessions, Training records,
     Courses, People, Organisation) use the full available width up
     to 1400px so wide-screen monitors don't waste space on huge
     side gutters. The 1.5rem horizontal padding keeps content from
     touching the screen edges on narrower viewports. The auth/login
     pages use a separate .auth-shell class and are unaffected. */
  max-width: 1400px;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* Legacy alias, retained so existing `class="page page-wide"` markup
   keeps working. The base .page is now already 1400px wide, so this
   is a no-op but harmless. */
.page-wide {
  max-width: 1400px;
}

/* Comfortable-but-near-edge-to-edge variant for pages we want to fill
   a normal monitor without going so wide that text rivers form on
   ultrawide displays. Side gutters scale with viewport so it never
   touches the screen edges. Applied opt-in via `class="page page-stretch"`
   while we roll out the new look one page at a time. */
.page-stretch {
  max-width: min(96vw, 1600px);
  padding-left: 2rem;
  padding-right: 2rem;
}

/* When a page opts into page-stretch, also stretch the topbar so the
   nav links sit in line with the page content rather than clustering
   in the centre. Implemented as a body-level class set by the view. */
body.body-stretch .topbar-inner {
  max-width: min(96vw, 1600px);
}

/* ---- Organisation page per-section edit controls ----
   Each editable section in the org form has its OWN Edit / Save /
   Cancel trio in its card-header (see organisation.js). Sections
   start read-only on every page load, so accidental clicks on
   Remove location / Remove trainer can't fire from a locked card.
   Disabled inputs get a slightly muted look so locked fields are
   visually distinct without making the values hard to read. */
.section-edit-controls {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex: 0 0 auto;
}
[data-edit-section].is-readonly input:disabled,
[data-edit-section].is-readonly select:disabled,
[data-edit-section].is-readonly textarea:disabled {
  background: var(--surface-muted, #f6f7f8);
  color: var(--text);
  cursor: default;
  opacity: 1;
}
[data-edit-section].is-readonly button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* Subtle highlight on the section currently being edited so the
   operator can see which card is "live" — handy on a long page. */
[data-edit-section].is-editing {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.5rem;
}

.course-form {
  margin-top: 1rem;
}

.course-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.course-list li {
  border-top: 1px solid var(--border);
}

.course-list li:first-child {
  border-top: 0;
}

.course-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0.25rem;
  cursor: pointer;
}

.course-row input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

.course-row .code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
  color: var(--accent);
  min-width: 7rem;
  flex-shrink: 0;
}

.course-row .title {
  flex: 1;
  color: var(--text);
}

.course-row .tag {
  font-size: 0.75rem;
  background: var(--tag-bg);
  color: var(--muted);
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  flex-shrink: 0;
}

.course-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

.course-actions .muted {
  margin: 0;
}

.primary-button {
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 6px;
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
}

.primary-button:hover {
  background: var(--accent-hover);
}

.notice {
  margin-top: 1rem;
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  color: #166534;
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  font-size: 0.9rem;
}

/* ---- Shared layout helpers ---- */

.card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.card-header h1 {
  margin-bottom: 0.25rem;
}

.list-footer {
  margin-top: 1rem;
}

.error-card {
  padding: 0;
  border: 0;
}

.error-card .error {
  margin: 0;
}

/* Free-trial soft-cap banners on the dashboard. Yellow at >=75% of cap;
   red blocker at the cap unless billing is arranged. The hello@ link
   carries a pre-filled subject with the RTO number so the inbound
   email is easy to triage. */
.cap-banner {
  padding: 14px 18px;
  font-size: 14px;
  line-height: 1.55;
}
.cap-banner strong { font-weight: 700; }
.cap-banner a {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
}
.cap-banner-warn {
  background: #FFFBEB;
  color: #92400E;
  border: 1px solid #FDE68A;
}
.cap-banner-blocked {
  background: #FEF2F2;
  color: #991B1B;
  border: 1px solid #FECACA;
}

/* Disabled action button — used for the "+ New session" link when the
   free-trial cap has been reached. Renders as a non-interactive span
   that visually matches .primary-button but is desaturated and
   unclickable. */
.primary-button.is-disabled,
a.primary-button.is-disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
  text-decoration: none;
}

.course-row.static {
  cursor: default;
}

/* ---- Buttons ---- */

.secondary-button {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem 0.85rem;
  font-size: 0.9rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  margin-top: 0.75rem;
}

.secondary-button:hover {
  border-color: var(--accent);
}

a.primary-button {
  display: inline-block;
  text-decoration: none;
  text-align: center;
}

a.link-button {
  text-decoration: none;
}

/* ---- New session form ---- */

#new-session-form {
  display: contents;
}

.text-input {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.55rem 0.7rem;
  font-size: 0.95rem;
  font-family: inherit;
  outline: none;
  background: var(--bg);
  color: var(--text);
}

.text-input:focus {
  border-color: var(--accent);
}

.card h2 + .text-input,
.card .muted + .text-input {
  margin-top: 0.5rem;
}

.trainee-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.75rem 0;
  flex-wrap: wrap;
}

.file-input-label {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.875rem;
  background: var(--bg);
}

.file-input-label:hover {
  border-color: var(--accent);
}

.file-input-label input[type="file"] {
  display: none;
}

.error-text {
  color: var(--error-text);
}

#trainees {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* Legacy single-row trainee layout — kept for any other view that
   still uses it. The new-session form uses .trainee-card below. */
.trainee-row {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1.3fr 1fr auto;
  gap: 0.5rem;
  align-items: center;
}

@media (max-width: 900px) {
  .trainee-row {
    grid-template-columns: 1fr 1fr;
  }
  .trainee-row .remove-trainee {
    grid-column: 2;
    justify-self: end;
  }
}

.usi-input {
  text-transform: uppercase;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
}

.trainee-row .remove-trainee,
.trainee-card .remove-trainee {
  font-size: 0.85rem;
  white-space: nowrap;
}

.trainee-row .remove-trainee:disabled,
.trainee-card .remove-trainee:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---- Trainee table layout (used on /sessions/new) -----------------
   Wide screens (>=900px): one row per trainee with column headings at
   the top — header row + body rows share a single CSS grid track set,
   so columns stay aligned across rows. Narrow screens fall back to the
   stacked-card layout below for usability on phones / split panes. */
.trainee-table {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Column track template, repeated by header AND each row so columns
   line up. 7 inputs + 1 row-number gutter + 1 remove-button column.
   minmax(0,…) prevents long emails from blowing out the row. */
.trainee-table-row {
  display: grid;
  grid-template-columns:
    2.5rem               /* row # */
    minmax(0, 1.1fr)     /* first name */
    minmax(0, 1.1fr)     /* last name */
    minmax(0, 1fr)       /* USI */
    minmax(0, 1.1fr)     /* phone */
    minmax(0, 1.6fr)     /* email */
    minmax(0, 1.2fr)     /* certificate # */
    minmax(0, 1fr)       /* student # */
    auto;                /* remove */
  gap: 0.5rem;
  align-items: center;
}

.trainee-table-head {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted, #6b7280);
  padding: 0 0.25rem 0.25rem;
  border-bottom: 1px solid var(--border, #e2e2e2);
}

.trainee-table-head > span {
  display: inline-flex;
  align-items: baseline;
  gap: 0.2rem;
}

.trainee-table-row .row-number {
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
  color: var(--muted, #6b7280);
  text-align: right;
  padding-right: 0.25rem;
}

.trainee-table-row .text-input {
  width: 100%;
}

.trainee-table-row .remove-trainee {
  font-size: 0.85rem;
  white-space: nowrap;
  padding: 0.4rem 0.6rem;
}

.trainee-table-row .remove-trainee:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* On narrow viewports the 8-column grid becomes unreadable; collapse
   each row back into a stacked card with inline labels so the form
   stays usable on a phone. We do this by overriding the grid into a
   single column and showing the per-row "mobile labels" that sit next
   to each input but are hidden on desktop via .visually-hidden-desktop. */
.trainee-table-mobile-label {
  display: none;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted, #6b7280);
  margin-bottom: 0.15rem;
}

@media (max-width: 900px) {
  .trainee-table-head {
    display: none;
  }
  .trainee-table-row {
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem 0.75rem;
    border: 1px solid var(--border, #e2e2e2);
    border-radius: 8px;
    padding: 0.75rem 1rem 1rem;
    background: var(--card-bg, #fafafa);
    align-items: stretch;
  }
  .trainee-table-row .row-number {
    grid-column: 1;
    text-align: left;
    font-weight: 600;
    color: var(--muted-strong, #555);
    font-size: 0.95rem;
  }
  .trainee-table-row .row-number::before {
    content: "Trainee ";
  }
  .trainee-table-row .remove-trainee {
    grid-column: 2;
    justify-self: end;
  }
  .trainee-table-row .field-cell {
    display: flex;
    flex-direction: column;
  }
  .trainee-table-mobile-label {
    display: block;
  }
}

@media (max-width: 600px) {
  .trainee-table-row {
    grid-template-columns: 1fr;
  }
  .trainee-table-row .row-number,
  .trainee-table-row .remove-trainee {
    grid-column: 1;
    justify-self: start;
  }
  .trainee-table-row .remove-trainee {
    justify-self: end;
    margin-top: -1.6rem;
  }
}

/* New 2-row card layout for trainees in the create-session form.
   Two columns on desktop, single column on narrow screens. The
   header row floats the Remove button to the right. */
.trainee-card {
  border: 1px solid var(--border, #e2e2e2);
  border-radius: 8px;
  padding: 0.75rem 1rem 1rem;
  background: var(--card-bg, #fafafa);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.trainee-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.trainee-card-title {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--muted-strong, #555);
}

.trainee-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.6rem 0.75rem;
}

@media (max-width: 900px) {
  .trainee-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 600px) {
  .trainee-grid {
    grid-template-columns: 1fr;
  }
}

/* Red asterisk on required fields. Aria-hidden via the surrounding
   label semantics + the native `required` attribute, so screen readers
   already announce the field as required. */
.req {
  color: #c0392b;
  margin-left: 0.15rem;
  font-weight: 700;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 1rem;
  padding: 0 0.25rem;
}

/* ---- Session-saved page ---- */

.plain-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.plain-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--border);
}

.plain-list li:first-child {
  border-top: 0;
}

/* ---- Topbar nav ---- */

.topbar-left {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.topnav {
  display: flex;
  gap: 1rem;
}

.topnav-link {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
}

.topnav-link:hover {
  color: var(--text);
}

.topnav-link.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}

/* ---- Register table ---- */

.table-scroll {
  overflow-x: auto;
  margin-top: 0.5rem;
}

.register-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.register-table th,
.register-table td {
  text-align: left;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.register-table th {
  font-weight: 600;
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-bottom: 1px solid var(--border);
}

.register-table tr.session-group-start td {
  border-top: 2px solid var(--border);
}

.register-table tr.session-group-start:first-child td {
  border-top: 0;
}

.register-table tbody tr:last-child td {
  border-bottom: 0;
}

.nowrap {
  white-space: nowrap;
}

.usi-cell code,
.delivery-trainee code {
  background: var(--tag-bg);
  padding: 0.05rem 0.35rem;
  border-radius: 4px;
  font-size: 0.85rem;
}

/* Course-codes cell on the sessions list. Intentionally NOT a flex
   container — flex on a <td> strips its `display: table-cell` which
   in turn defeats the table's `vertical-align: top` (so the other
   cells in the row would float to the middle whenever this cell
   wrapped to multiple lines). Whitespace text-nodes between chips
   also become flex items under flex, which renders as visible
   "divider" gaps between wrapped badge rows. Inline-block chips
   with their own margin avoid both problems and wrap naturally. */
.course-codes-cell .code-chip {
  display: inline-block;
  margin: 0 0.3rem 0.3rem 0;
  vertical-align: middle;
}
.course-codes-cell .code-chip:last-child { margin-right: 0; }

.code-chip {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  background: var(--tag-bg);
  color: var(--accent);
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
}

.plain-link {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px dotted var(--border);
}

.plain-link:hover {
  border-bottom-color: var(--accent);
}

/* ---- Status pills ---- */

.status-pill {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 500;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  white-space: nowrap;
}

.status-pending {
  background: var(--tag-bg);
  color: var(--muted);
}

.status-sent {
  background: #ecfdf5;
  color: #047857;
  border: 1px solid #a7f3d0;
}

/* ---- Delivery list (session-saved page) ---- */

.bulk-send-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  margin: 0.75rem 0 0.25rem;
}

.bulk-send-form .primary-button {
  margin-top: 0;
}

.bulk-sms-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  user-select: none;
}

.bulk-sms-toggle input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
}

.tag-coming-soon {
  display: inline-block;
  background: #1D9E75;
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 999px;
  margin-left: 0.25rem;
}

.delivery-list {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
}

.delivery-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.5rem 1rem;
  align-items: center;
  padding: 0.75rem 0;
  border-top: 1px solid var(--border);
}

/* Edit / Void toggles sit on a second grid row that spans the full
   width, so they don't compete for space with the wallet pills (which
   would otherwise stretch into giant ovals when the inline form is open
   inside the same flex container). */
.delivery-toggles {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: flex-start;
}

.delivery-row:first-child {
  border-top: 0;
}

.delivery-trainee {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.85rem;
  align-items: baseline;
}

.trainee-name {
  font-weight: 500;
}

.delivery-actions {
  display: flex;
  gap: 0.5rem;
  /* Centre items vertically so wallet pills don't get stretched when an
     adjacent element (e.g. the "Resend email" button or the cert-id chip
     that appears in the trainee column) makes the row taller. Without
     this, the default `align-items: stretch` on flex containers grows
     the wallet pills' height to match the tallest sibling, which made
     them look oversized after a delivery flipped to "Sent (email)". */
  align-items: center;
}

.delivery-actions form {
  margin: 0;
}

.delivery-actions .secondary-button {
  margin-top: 0;
}

/* Wallet pills must keep their intrinsic size in any flex container,
   regardless of what siblings appear after a delivery succeeds. */
.delivery-actions .gwallet-button,
.delivery-actions .awallet-button {
  flex: 0 0 auto;
  align-self: center;
}

@media (max-width: 640px) {
  .delivery-row {
    grid-template-columns: 1fr;
  }
}

/* ---- Notice variants ---- */

.info-notice {
  background: #eff6ff;
  border-color: #bfdbfe;
  color: #1d4ed8;
}

/* ---- Session details form grid ---- */

.session-details-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1rem;
  margin-top: 0.75rem;
}

@media (max-width: 640px) {
  .session-details-grid {
    grid-template-columns: 1fr;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.field-label {
  font-size: 0.85rem;
  color: var(--muted);
}

select.text-input {
  appearance: none;
  -webkit-appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    calc(100% - 18px) 50%,
    calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 2rem;
}

/* ---- Session-saved meta list ---- */

.meta-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  font-size: 0.9rem;
}

.meta-list li {
  display: inline-flex;
  gap: 0.4rem;
}

.meta-label {
  color: var(--muted);
}

/* ---- Register tabs ---- */

.tab-strip {
  display: flex;
  gap: 0.25rem;
  margin-top: 1.25rem;
  border-bottom: 1px solid var(--border);
  margin-left: -0.25rem;
  margin-right: -0.25rem;
}

.tab-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.85rem;
  font-size: 0.9rem;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.tab-link:hover {
  color: var(--text);
}

.tab-link.active {
  color: var(--text);
  border-bottom-color: var(--accent);
  font-weight: 500;
}

.tab-count {
  background: var(--tag-bg);
  color: var(--muted);
  font-size: 0.72rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-weight: 500;
}

.tab-link.active .tab-count {
  background: var(--accent);
  color: #fff;
}

/* ---- Tab toolbar (search + actions) ---- */

.tab-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.search-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex: 1;
  min-width: 240px;
}

.search-input {
  flex: 1;
  min-width: 0;
}

.tab-toolbar .secondary-button,
.tab-toolbar .link-button {
  margin-top: 0;
}

/* ---- Expandable rows (Sessions + People tabs) ---- */

.register-table th.num,
.register-table td.num {
  text-align: right;
  white-space: nowrap;
}

.expand-toggle-cell {
  width: 1.5rem;
  padding-right: 0 !important;
  color: var(--muted);
}

.expand-toggle {
  display: inline-block;
  transition: transform 120ms ease;
  font-size: 0.75rem;
  line-height: 1;
}

.expand-toggle.open {
  transform: rotate(90deg);
}

tr.expandable {
  cursor: pointer;
}

tr.expandable:hover td {
  background: #fafafa;
}

tr.expand-row > td {
  background: #fafafa;
  padding: 0.75rem 1rem 1rem;
  border-bottom: 1px solid var(--border);
}

.expand-inner {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.sub-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

.sub-table th,
.sub-table td {
  padding: 0.5rem 0.7rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.sub-table th {
  font-weight: 600;
  color: var(--muted);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: #fafafa;
}

.sub-table tbody tr:last-child td {
  border-bottom: 0;
}

/* ---- Dashboard metric tiles ---- */

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  margin: 1rem 0;
}

@media (max-width: 880px) {
  .metrics-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .metrics-grid { grid-template-columns: 1fr; }
}

.metric-tile {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  text-decoration: none;
  color: inherit;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.metric-tile:hover {
  border-color: var(--accent);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.metric-value {
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
}

.metric-label {
  font-size: 0.85rem;
  color: var(--muted);
}

.metric-tile.attention .metric-value {
  color: #b45309;
}

/* ---- Recent activity feed ---- */

.activity-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.activity-row {
  border-top: 1px solid var(--border);
}

.activity-row:first-child {
  border-top: 0;
}

.activity-link {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 1rem;
  align-items: center;
  padding: 0.75rem 0.25rem;
  text-decoration: none;
  color: inherit;
}

.activity-link:hover {
  background: #fafafa;
}

.activity-date {
  font-weight: 500;
  white-space: nowrap;
}

.activity-meta {
  color: var(--muted);
  font-size: 0.9rem;
}

.activity-arrow {
  color: var(--muted);
  font-size: 1.2rem;
}

/* ---- Topnav: tighter spacing for 5 items ---- */

.topnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
}

/* ---- Organisation page ---- */

.org-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1rem;
  margin-top: 0.75rem;
}

@media (max-width: 640px) {
  .org-grid { grid-template-columns: 1fr; }
}

.field-wide {
  grid-column: 1 / -1;
}

.row-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 0.75rem;
}

.row-item {
  display: grid;
  grid-template-columns: 1fr 2fr auto;
  gap: 0.75rem;
  align-items: end;
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fafafa;
}

@media (max-width: 640px) {
  .row-item { grid-template-columns: 1fr; }
}

.row-remove {
  align-self: end;
  margin-bottom: 0.55rem;
  color: var(--error-text);
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  margin: 1rem 0 2rem;
}

/* ---- Digital wallet card preview ---- */

.card-style-row {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  margin-top: 0.75rem;
}

.field-color {
  flex-direction: column;
}

.color-input {
  width: 80px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

.wallet-card {
  color: #fff;
  /* 16px radius + soft shadow makes the preview read as a physical
     wallet pass sitting on the page (matches the iPhone Apple Wallet
     pass corner radius). The shadow is intentionally subtle — strong
     enough to lift the card off the page background but not so heavy
     that it competes with the org-settings card chrome around it.

     min-height 460px gives the card the correct Apple Wallet aspect
     ratio at the 320px width we lock to (a real iPhone pass is
     roughly 320 × 500). The .wallet-card-bottom rule below uses
     margin-top:auto so the body sits at the top and the QR floats
     to the bottom edge, which produces the large empty zone between
     the units row and the QR that the real pass has. */
  border-radius: 16px;
  padding: 1.1rem 1.2rem 1.2rem;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  min-height: 460px;
}

.wallet-card-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.75rem;
}

.wallet-card-brand {
  font-weight: 700;
}

/* Top-left logo slot — fixed minimum height so the top row keeps a
   consistent baseline even when the RTO hasn't uploaded a logo yet
   (the right-hand "certpass / Valid" stack would otherwise jump
   around as RTOs add and remove their logo). */
.wallet-card-logo-slot {
  min-height: 44px;
  display: flex;
  align-items: center;
}

/* Top-right header stack — "certpass" wordmark above the green-dot
   "Valid" status indicator. Mirrors the Apple Wallet header field
   (label-above-value) but with per-line colours we control directly,
   which the live Apple pass can't do (Apple applies labelColor /
   foregroundColor globally). */
.wallet-card-header-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.18rem;
  text-align: right;
  line-height: 1.1;
}

.wallet-card-brand-mark {
  font-weight: 500;
  font-size: 0.95rem;
  color: #fff;
  letter-spacing: -0.005em;
  text-transform: lowercase;
}

.wallet-card-valid {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--brand-teal);
  letter-spacing: 0.01em;
}

/* "Training Certificate" sub-line under the certpass wordmark in the
   top-right header stack. Matches the Apple Wallet header field
   "value" treatment — slightly muted, smaller than the brand mark. */
.wallet-card-kind {
  font-size: 0.72rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.78);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* Card body wrapper: trainee/rows column on the left, certpass
   thumbnail icon pinned to the right side of the body (mirrors the
   Apple Wallet `thumbnail.png` slot which sits on the right edge of
   the primary fields area on a real pass). */
.wallet-card-body {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 0.9rem;
}
.wallet-card-body-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
.wallet-card-thumb {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  object-fit: contain;
  /* SVG is now self-coloured (white certificate body, dark line
     details, green tick badge) so it reads correctly on any user-
     picked card colour. No CSS filter — the previous brightness/
     invert flattened the green tick to white and made the icon
     look like a chat bubble. */
}

/* Green status glyph — the 🟢 emoji is a colour glyph (renders green
   regardless of any inherited text-colour), so this is a sizing/
   alignment-only rule. Slightly smaller than the "Valid" word so the
   dot reads as a status indicator rather than competing for weight. */
.wallet-card-valid-dot {
  font-size: 0.7rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}

/* RTO logo as it appears in the top-left of preview wallet cards.
   Sized to match Apple Wallet's real logo slot (~50px tall on a real
   pass) so what the operator sees in the preview matches what
   trainees will see in their wallet. Cap width so an extra-wide
   wordmark doesn't push the "Training Certificate" label off-card.
   object-fit:contain keeps both square and wide logos undistorted.
   Rendered with NO background — Apple Wallet passes the logo bytes
   straight onto the card colour, so the preview must do the same.
   If a logo is hard to read against a particular card colour, the
   answer is for the RTO to upload a light/dark variant or change
   the card colour, not for us to silently overlay a pill. */
.wallet-card-logo {
  display: block;
  height: 44px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
}

/* Logo upload section on /organisation. Two-column layout: current
   logo on the left, upload form + remove on the right. Stacks on
   narrow viewports. */
/* Signature preview is wider+shorter than the logo (a horizontal
   scribble), so we override max-width on the thumbnail without
   changing any other shared org-logo styling. */
.org-signature-current {
  width: 240px;
  max-width: 100%;
}
.org-signature-thumb {
  max-width: 240px;
  max-height: 80px;
  object-fit: contain;
  background: #fff;
}

.org-logo-row {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  flex-wrap: wrap;
  margin-top: 0.75rem;
}
.org-logo-current {
  flex: 0 0 auto;
}
.org-logo-thumb {
  display: block;
  max-width: 160px;
  max-height: 100px;
  width: auto;
  height: auto;
  object-fit: contain;
  background: #f4f4f5;
  border: 1px solid #e4e4e7;
  border-radius: 8px;
  padding: 8px;
}
.org-logo-placeholder {
  width: 160px;
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fafafa;
  border: 1px dashed #d4d4d8;
  border-radius: 8px;
  color: #71717a;
  font-size: 0.85rem;
}
.org-logo-actions {
  flex: 1 1 320px;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.org-logo-upload {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.org-logo-upload .field {
  flex: 1 1 220px;
  margin-bottom: 0;
}
.org-logo-remove {
  margin-top: 0.25rem;
}

/* Trainee-name "hero" block on the front of every preview card.
   Mirrors Apple Wallet's primaryField: small teal label + large white
   value. The label sits above the value (column flex) so visually it
   matches a real generic pass. */
.wallet-card-hero {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.wallet-card-name {
  font-size: 1.4rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.wallet-card-rows {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem 1rem;
  /* No margin-top:auto — the new taller card pushes the QR to the
     bottom (see .wallet-card-bottom-qr below), so the body content
     stays stacked at the top instead of being centred awkwardly. */
}

.wallet-card-rows > div {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

/* Some rows (e.g. UNITS) need to span the whole width, not share the
   2-column grid with another field. Used for the multi-line unit
   list so each course code can sit on its own line without being
   crammed into half a column. */
.wallet-card-rows-fullwidth {
  grid-column: 1 / -1;
}

/* Auxiliary row that mirrors the Apple Wallet aux-field layout —
   dynamic column count based on unit count:
     -aux-1 → single full-width column (code — title)
     -aux-2 → two columns
     -aux-3 → three columns
     -aux-4 → four columns (used for both 4 units and the 5+ "& X more" tail)
   Sits below .wallet-card-rows; same vertical rhythm. */
.wallet-card-aux-row {
  display: grid;
  gap: 0.6rem 0.8rem;
  margin-top: 0.6rem;
}
.wallet-card-aux-row > div {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.wallet-card-aux-1 { grid-template-columns: 1fr; }
.wallet-card-aux-2 { grid-template-columns: repeat(2, 1fr); }
.wallet-card-aux-3 { grid-template-columns: repeat(3, 1fr); }
.wallet-card-aux-4 { grid-template-columns: repeat(4, 1fr); }

/* "Issued by" value carries the RTO name + RTO number, e.g.
   "InPipe Training Pty Ltd (RTO 46456)". Single line only —
   truncate with an ellipsis if it overflows, never wrap onto a
   second line (matches Apple Wallet's secondary-field rendering
   which clips at one line). */
.wallet-card-issuer {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  min-width: 0;
}

.wallet-card-bottom {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

.wallet-card-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.7;
}

.wallet-card-value {
  font-size: 0.9rem;
  font-weight: 500;
  word-break: break-all;
}

/* Avoid ugly default margin on h2 inside card-header */
.card-header h2 {
  margin: 0;
}

/* ============================================================
 * certpass brand styling
 * Dark charcoal nav + teal accents, layered as overrides so the
 * underlying page/card baseline (white bg, light borders) stays put.
 * ============================================================ */

:root {
  --brand-charcoal: #1c1c1e;
  --brand-teal: #1d9e75;
  --brand-teal-hover: #178661;
  --teal-light-bg: #e1f5ee;
  --teal-dark-text: #085041;
}

/* ---- Top navigation: dark charcoal with teal accents ---- */

.topbar {
  background: var(--brand-charcoal);
  border-bottom-color: transparent;
}

.topbar-inner {
  color: #fff;
}

.topbar .brand {
  color: #fff;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
}

/* Inline SVG mark — the rect/circle/tick combo. Sized in the SVG itself
   (22x22). The class is here mostly so flex alignment in .brand stays
   consistent and the mark can't shrink under tight nav widths. */
.brand-mark {
  display: inline-block;
  flex-shrink: 0;
  vertical-align: middle;
}

/* Two-tone wordmark: "cert" white, "pass" teal, weight 500, all lowercase. */
.brand-wordmark {
  font-weight: 500;
  letter-spacing: -0.01em;
  font-size: 1.05rem;
  text-transform: lowercase;
  display: inline-flex;
  align-items: baseline;
}

.brand-wordmark-cert { color: #fff; }
.brand-wordmark-pass { color: var(--brand-teal); }

/* Trademark superscript shown next to the wordmark. Used while the
   CertPass mark is registered with IP Australia but not yet granted
   — switch to ® once the registration certificate is issued. Sized
   small and given a faint colour so it reads as a legal mark
   without competing with the brand name itself. */
.brand-tm {
  font-size: 0.5em;
  font-weight: 600;
  vertical-align: super;
  line-height: 1;
  margin-left: 2px;
  opacity: 0.75;
  letter-spacing: 0;
}

/* On the login screen the brand sits on a light card, so "cert" needs a
   readable colour — use the dark charcoal there instead of white. */
.auth-brand .brand-wordmark-cert { color: var(--brand-charcoal); }

/* ---- Add to Google Wallet button ----
   Sits next to Send SMS / Send email in the delivery actions row. Google's
   public guidance for the "Add to Google Wallet" button is a black pill
   with white text and 18px icon — close enough to that without pulling
   in the official PNG asset. Anchor (not a form button) because it's a
   plain GET to pay.google.com with the JWT in the path. */
.gwallet-button,
.awallet-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: #000;
  color: #fff;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  line-height: 1;
  white-space: nowrap;
  transition: background 0.12s ease;
}
.gwallet-button:hover,
.gwallet-button:focus-visible,
.awallet-button:hover,
.awallet-button:focus-visible {
  background: #1a1a1a;
  color: #fff;
  text-decoration: none;
}
.gwallet-button:focus-visible,
.awallet-button:focus-visible {
  outline: 2px solid var(--brand-teal);
  outline-offset: 2px;
}
.gwallet-icon,
.awallet-icon { display: block; }

.topnav {
  margin-left: 0.25rem;
}

.topbar .topnav-link {
  color: rgba(255, 255, 255, 0.72);
  text-decoration: none;
  position: relative;
  padding-bottom: 0.15rem;
}

.topbar .topnav-link:hover {
  color: #fff;
  background: transparent;
}

.topbar .topnav-link.active {
  color: var(--brand-teal);
  font-weight: 600;
  background: transparent;
}

.topbar .topnav-link.active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -16px;
  height: 2px;
  background: var(--brand-teal);
  border-radius: 2px;
}

.topbar form .link-button {
  color: rgba(255, 255, 255, 0.85);
}

.topbar form .link-button:hover {
  color: #fff;
}

/* ---- Login screen: brand mark sits inline with the wordmark ---- */

.auth-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.25rem;
}

.auth-card .brand .brand-wordmark {
  font-size: 1.6rem;
}

/* ---- Primary buttons → teal ---- */

.primary-button,
a.primary-button {
  background: var(--brand-teal);
  border-radius: 8px;
}

.primary-button:hover,
a.primary-button:hover {
  background: var(--brand-teal-hover);
}

.form button {
  background: var(--brand-teal);
  border-radius: 8px;
}

.form button:hover {
  background: var(--brand-teal-hover);
}

.form input:focus {
  border-color: var(--brand-teal);
}

/* Course-row checkboxes pick up the teal accent so picking units feels
   on-brand on the new-session form. */
.course-row input[type="checkbox"] {
  accent-color: var(--brand-teal);
}

/* ---- Verified / sent / success states ---- */

.status-pill.status-sent {
  background: var(--teal-light-bg);
  color: var(--teal-dark-text);
  border-color: transparent;
}

.notice {
  background: var(--teal-light-bg);
  border-color: var(--teal-light-bg);
  color: var(--teal-dark-text);
}

.info-notice {
  background: var(--teal-light-bg);
  border-color: var(--teal-light-bg);
  color: var(--teal-dark-text);
}

/* Red error notice for inline form-section errors (used by the
   logo upload section so the user sees rejection right next to the
   file picker). */
.error-notice {
  background: #fef2f2;
  border-color: #fecaca;
  color: #991b1b;
}

.notice strong,
.info-notice strong {
  color: var(--teal-dark-text);
}

/* ---- Subtle teal border on metric tile hover ---- */

.metric-tile:hover {
  border-color: var(--brand-teal);
  box-shadow: 0 1px 3px rgba(29, 158, 117, 0.12);
}

/* ---- Wallet card: QR footer ----
   The redesign moves the "Powered by certpass" footer and the verify
   URL text row to the BACK of the pass, so the front bottom is just
   the QR code centred under the units-completed row. */

.wallet-card-bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
}

/* Centred-QR variant used by every front mock — overrides the
   space-between layout when there's no verify-text sibling.
   margin-top:auto pushes the QR to the bottom edge of the card
   regardless of how short the units row above is, producing the
   large empty zone between the units row and the QR that the
   real Apple Wallet pass shows. */
.wallet-card-bottom-qr {
  justify-content: center;
  margin-top: auto;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

/* Brand-teal value used by the "Units completed" full-width row on the
   front of the pass. The teal comes straight from the brand palette
   (#1d9e75) — same colour the live Apple pass renders for values, so
   the preview matches what the trainee will see. Slight overlay over
   the brand teal keeps the codes readable on lighter user-picked card
   colours. */
.wallet-card-units-teal {
  color: var(--brand-teal);
  font-weight: 600;
  letter-spacing: 0.01em;
  /* Single line only — truncate with an ellipsis instead of
     wrapping or breaking mid-word. The full code list is always
     available on the back of the live pass. */
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  min-width: 0;
}

.wallet-card-verify {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

.wallet-card-qr {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  background: #fff;
  border-radius: 6px;
  padding: 4px;
  box-sizing: border-box;
  display: flex;
}

.wallet-card-qr svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---- Two-card preview grid + multi-course variant ---- */

.wallet-cards-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  align-items: flex-start;
  width: 100%;
}

.wallet-card-mockup {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 0 0 320px;
}

.wallet-card-mockup .wallet-card {
  width: 100%;
}

@media (max-width: 720px) {
  .wallet-card-mockup { flex: 1 1 100%; }
}

/* Single-card preview wrapper (replaces the old quad grid). The card
   itself is locked to 320px — the physical width of an Apple Wallet
   pass on an iPhone — and never grows wider regardless of screen
   size. On viewports narrower than ~340px we let the card shrink to
   100% of its column so it doesn't overflow horizontally; the
   internal flex layout reflows down proportionally. We deliberately
   do NOT use `transform: scale(...)` for the down-scale because that
   leaves a phantom box at the original 320px and breaks the centered
   margin — natural reflow looks identical at sane viewport sizes. */
.wallet-cards-single {
  display: flex;
  justify-content: center;
  width: 100%;
}
.wallet-cards-single .wallet-card-mockup {
  flex: 0 0 auto;
  width: 320px;
  max-width: 100%;
}
@media (max-width: 340px) {
  .wallet-cards-single .wallet-card-mockup { width: 100%; }
}

.wallet-card-caption {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-weight: 600;
}

/* The multi-course variant is taller and uses a vertical-stack layout
   instead of the 2x2 metadata grid the single card uses. */
.wallet-card-multi {
  min-height: 420px;
}

.wallet-card-holder {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.wallet-card-courses {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.wallet-card-course-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
}

.wallet-card-course-list li {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  font-size: 0.78rem;
  line-height: 1.3;
}

.wallet-card-course-list .course-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  flex-shrink: 0;
  min-width: 5.4rem;
  text-align: center;
  letter-spacing: 0.02em;
}

.wallet-card-course-list .course-name {
  flex: 1;
  opacity: 0.95;
}

.wallet-card-meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem 1rem;
  margin-top: auto;
}

.wallet-card-meta > div {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

/* ---- People page: stats grid, filter pills, status badges, notes ---- */

.people-stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin: 1rem 0 1.25rem;
}

@media (max-width: 720px) {
  .people-stats-grid { grid-template-columns: 1fr; }
}

.people-stat {
  background: var(--surface, #fff);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  border-left: 4px solid var(--border);
}

.people-stat-value {
  font-size: 1.65rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.people-stat-label {
  font-size: 0.78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

.people-stat-recorded { border-left-color: #1D9E75; }
.people-stat-missing  { border-left-color: #b91c1c; }

.people-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: #fff;
  color: var(--text, #1f2937);
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.filter-pill:hover {
  border-color: #1D9E75;
  color: #085041;
}

.filter-pill.is-active {
  background: #1D9E75;
  border-color: #1D9E75;
  color: #fff;
}

.filter-pill-count {
  font-size: 0.72rem;
  font-weight: 600;
  background: rgba(0, 0, 0, 0.06);
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  min-width: 1.4rem;
  text-align: center;
}

.filter-pill.is-active .filter-pill-count {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}

/* USI compliance status badges (extends the existing .status-pill base
   style). "Recorded" means the RTO captured the trainee's USI against
   their record — this is NOT a claim of national-register verification,
   which certpass cannot perform. */
.status-pill.status-usi-recorded {
  background: #ecfdf5;
  color: #047857;
  border: 1px solid #a7f3d0;
}

.status-pill.status-usi-missing {
  background: #fee2e2;
  color: #b91c1c;
  border: 1px solid #fca5a5;
}

/* Explanatory note shown above the sub-table when a person's USI is
   missing from the RTO's records. */
.status-note {
  border-radius: 8px;
  padding: 0.55rem 0.85rem;
  margin-bottom: 0.85rem;
  font-size: 0.85rem;
  border: 1px solid transparent;
}

.status-note-missing {
  background: #fef2f2;
  color: #991b1b;
  border-color: #fca5a5;
}

/* ---- Notice variants (warn) ---- */
.notice.warn-notice,
.warn-notice {
  background: #fffbeb;
  border-color: #fcd34d;
  color: #92400e;
}
.warn-notice code { color: inherit; }
.warn-notice.small { font-size: 0.85rem; padding: 0.5rem 0.65rem; }

/* ---- Inline edit / void forms inside trainee row ---- */
.trainee-edit,
.trainee-void {
  margin-top: 0.25rem;
}
.trainee-edit > summary,
.trainee-void > summary {
  cursor: pointer;
  font-size: 0.85rem;
  list-style: none;
  display: inline-block;
}
.trainee-edit > summary::-webkit-details-marker,
.trainee-void > summary::-webkit-details-marker { display: none; }
.link-button.danger { color: #b91c1c; }

/* PDF certificate preview (organisation page, last section). The iframe
   uses an aspect-ratio wrapper so the embedded PDF keeps A4 portrait
   proportions (1 : √2) at any container width. Border + soft shadow
   match the wallet-card mockup styling above so the preview reads as a
   sibling to the wallet previews. */
.pdf-preview-wrap {
  margin-top: 16px;
  width: 100%;
  max-width: 720px;
  aspect-ratio: 1 / 1.414;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #f8fafc;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 12px rgba(15, 23, 42, 0.04);
}

.pdf-preview-frame {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #fff;
}

/* Shown by the <object> element when the browser refuses to render
   the embedded PDF (most commonly: Chrome's block on PDFs inside
   nested cross-origin iframes such as the Replit workspace preview).
   On a normal top-level page load the PDF renders and this fallback
   is never shown. */
.pdf-preview-fallback {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 32px;
  text-align: center;
  box-sizing: border-box;
  background: #fff;
}
.pdf-preview-fallback p { margin: 0; }

.pdf-preview-actions {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
}

.pdf-preview-actions-sep {
  color: #cbd5e1;
  user-select: none;
}

/* Organisation page tab strip + tab panels. Three role="tab" buttons
   sit at the top of the page and toggle which <section
   class="org-group" role="tabpanel"> is visible. We use the native
   `hidden` attribute on inactive panels (so the form fields inside
   are also removed from the tab order); JS just flips that attribute
   on click. */
.org-tabs {
  display: flex;
  gap: 4px;
  margin: 20px 0 16px;
  padding: 0;
  background: #ffffff;
  border-bottom: 2px solid #e2e8f0;
  flex-wrap: wrap;
  width: 100%;
}
.org-tab {
  appearance: none;
  background: transparent;
  border: 0;
  /* The 3px transparent bottom border becomes the teal active
     underline. We pull the bar down by -2px so its underline
     overlaps the strip's own 2px bottom border for a clean
     "selected" look. */
  border-bottom: 3px solid transparent;
  padding: 14px 22px;
  margin-bottom: -2px;
  font: inherit;
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.01em;
  color: #64748b;
  cursor: pointer;
  border-radius: 0;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.org-tab:hover {
  color: #0f172a;
  /* Light teal hover hint that previews the active underline. */
  border-bottom-color: rgba(29, 158, 117, 0.35);
  background: transparent;
}
.org-tab:focus-visible {
  outline: 2px solid #1D9E75;
  outline-offset: -2px;
}
.org-tab.is-active {
  color: #1D9E75;
  border-bottom-color: #1D9E75;
  background: transparent;
}
.org-tab.is-active:hover {
  /* Don't dim the active underline on hover. */
  border-bottom-color: #1D9E75;
}

@media (max-width: 640px) {
  .org-tab {
    padding: 12px 14px;
    font-size: 15px;
  }
}
.org-group {
  margin-top: 8px;
  padding: 0;
  border: none;
  background: transparent;
}
.org-group:focus { outline: none; }
.secondary-button.danger {
  border-color: #fca5a5;
  color: #b91c1c;
}
.secondary-button.danger:hover {
  background: #fef2f2;
}
.inline-edit-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding: 0.75rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  background: #fafafa;
  max-width: 28rem;
}
.inline-edit-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.inline-edit-form input,
.inline-edit-form textarea {
  padding: 0.4rem 0.5rem;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  font: inherit;
}
.inline-edit-form button { align-self: flex-start; }
.void-history-summary code { font-size: 0.78rem; }

/* ---- Public verify page ---- */
.verify-page {
  max-width: 42rem;
  margin: 2rem auto;
  padding: 0 1rem;
}
.verify-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
}
.verify-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  font-size: 1.05rem;
  color: #1C1C1E;
  text-decoration: none;
}
.verify-card { padding: 1.5rem; }
.verify-status {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1rem;
}
.verify-status h1 {
  font-size: 1.35rem;
  margin: 0 0 0.15rem;
}
.verify-fields {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: 0.4rem 1rem;
  margin: 1rem 0;
}
.verify-fields div { display: contents; }
.verify-fields dt { color: var(--muted); font-size: 0.85rem; }
.verify-fields dd { margin: 0; font-weight: 500; }
.verify-courses { margin-top: 1.25rem; }
.verify-courses h2 { font-size: 1rem; margin: 0 0 0.5rem; }
.verify-footer {
  text-align: center;
  margin-top: 1.5rem;
}
.verify-valid { border-top: 4px solid #1D9E75; }
.verify-voided { border-top: 4px solid #B45309; }
.verify-notfound { border-top: 4px solid #9ca3af; }
@media (max-width: 540px) {
  .verify-fields { grid-template-columns: 1fr; gap: 0.1rem 0; }
  .verify-fields div { display: block; margin-bottom: 0.5rem; }
}

/* ---- Quad preview grid (1-3 front+back, 4+ front+back) ---- */

.wallet-cards-grid-quad {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
  align-items: stretch;
}
.wallet-cards-grid-quad .wallet-card-mockup { flex: 1 1 auto; }
@media (max-width: 720px) {
  .wallet-cards-grid-quad { grid-template-columns: 1fr; }
}

/* ---- Mock of Apple Wallet "Pass Details" (back of pass) ----
   Pale background, charcoal text. dt is a small uppercase label,
   dd sits below it. Uses <pre> for the full course list so newlines
   render correctly while keeping the same font as the rest. */

.wallet-card-back {
  background: #f6f6f7;
  color: #1c1c1e;
  border: 1px solid #e1e1e3;
  border-radius: 14px;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.06);
  min-height: 240px;
  max-width: 360px;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.wallet-card-back-header {
  background: #ececee;
  border-bottom: 1px solid #d8d8db;
  padding: 0.65rem 1rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #3a3a3c;
}

.wallet-card-back-list {
  margin: 0;
  padding: 0.4rem 1rem 1rem;
  display: flex;
  flex-direction: column;
}

.wallet-card-back-list > div {
  padding: 0.7rem 0;
  border-bottom: 1px solid #e8e8eb;
}
.wallet-card-back-list > div:last-child { border-bottom: 0; }

.wallet-card-back-list dt {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #6e6e73;
  font-weight: 500;
  margin: 0 0 0.2rem;
}

.wallet-card-back-list dd {
  margin: 0;
  font-size: 0.88rem;
  color: #1c1c1e;
  line-height: 1.35;
  word-break: break-word;
}

.wallet-card-back-list dd a {
  color: #1d9e75;
  text-decoration: none;
}

.wallet-card-back-list dd pre {
  margin: 0;
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1.4;
  white-space: pre-wrap;
  color: #1c1c1e;
}

/* Back-of-card "Powered by certpass · certpass.com.au" footer row.
   The blank dt on the row would otherwise leave a visible gap above
   the link; collapse it so the footer reads as a single tight line. */
.wallet-card-back-list .wallet-card-back-footer dt {
  display: none;
}
.wallet-card-back-list .wallet-card-back-footer dd {
  font-size: 0.78rem;
  color: #6e6e73;
  text-align: center;
}
.wallet-card-back-list .wallet-card-back-footer dd a {
  color: #6e6e73;
  text-decoration: none;
}

/* ---- Void & reissue (audit trail visuals) ----------------------------
 *
 * A row representing a voided certificate stays in every list — session
 * page, training records, people expand panel — for compliance, but
 * needs to be obviously inactive at a glance. The treatment is two
 * layers: line-through + dim text (so the data is still legible but
 * clearly historical), and an amber "Voided" pill in the status column
 * (matches the verify page's amber Superseded badge).
 *
 * The strikethrough is scoped to specific elements rather than `tr`
 * itself because some browsers won't strike-through td contents when
 * the rule lives on the row. .delivery-row uses display: grid so we
 * can target it directly there.
 */

.delivery-row.is-voided {
  opacity: 0.62;
}
.delivery-row.is-voided .trainee-name,
.delivery-row.is-voided .delivery-trainee code {
  text-decoration: line-through;
  text-decoration-color: rgba(146, 64, 14, 0.55); /* same hue as pill */
}

tr.is-voided td {
  opacity: 0.62;
}
tr.is-voided td:first-child,
tr.is-voided td .trainee-name,
tr.is-voided td .code-chip,
tr.is-voided td code {
  text-decoration: line-through;
  text-decoration-color: rgba(146, 64, 14, 0.55);
}

/* Voided status pill — amber, same palette as verify.ejs's superseded
 * badge so the visual language is consistent across surfaces. */
.status-pill.status-voided {
  background: #FEF3C7;
  color: #92400E;
  border: 1px solid #FCD34D;
}

/* "Reissued from <oldCert>" / "Superseded by <newCert>" inline chips.
 * Block on its own line under the cert id / status pill so long IDs
 * don't push the surrounding fields around. Uses the same monospace
 * code-chip treatment for the cert id itself. */
.reissue-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.2rem;
  font-size: 0.75rem;
}
.reissue-chip code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: var(--tag-bg);
  color: var(--accent);
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  text-decoration: none !important; /* survive the .is-voided strikethrough */
}

.void-reason-line {
  display: block;
  margin-top: 0.25rem;
  /* Reason text itself stays readable — only the cert id / name on the
   * voided row gets the strikethrough; the reason is the *new* info. */
  text-decoration: none !important;
  opacity: 1;
}
.void-reason-line em {
  color: var(--text);
  font-style: italic;
}

/* ---- Void & reissue form ----
 * The form lives inside <details> in the Edit toggles strip. It's a
 * destructive action so the surrounding notice + danger button already
 * carry the warning weight; the form itself just needs comfortable
 * spacing and the course checklist to feel like a checklist (not a
 * dense block of checkboxes). */
.void-form fieldset.course-checklist {
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 0.6rem 0.85rem 0.75rem;
  margin: 0.25rem 0 0;
}
.void-form fieldset.course-checklist legend {
  padding: 0 0.35rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.course-check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0;
  cursor: pointer;
  user-select: none;
}
.course-check input[type="checkbox"] {
  margin: 0;
}

/* ----------------------------------------------------------
 * Organisation page — independent per-section UX
 * ----------------------------------------------------------*/

/* Setup-incomplete banner. Sits between the page title and the first
 * editable section. The notice element inside carries the colour. */
.setup-incomplete-card {
  border-color: #fde68a;
}

/* Read-only definition list used by the "view" mode of the
 * organisation-details and card-style sections. Two columns on
 * desktop, single column on mobile. */
.org-details-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem 1.5rem;
  margin: 0.5rem 0 0;
}
.org-details-list > div {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.org-details-list dt {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #64748b;
  margin: 0;
}
.org-details-list dd {
  margin: 0;
  font-size: 0.95rem;
  color: #0f172a;
  word-break: break-word;
}
.org-details-list .org-details-wide {
  grid-column: 1 / -1;
}
@media (max-width: 720px) {
  .org-details-list { grid-template-columns: 1fr; }
}

/* A single trainer / location is a card with a read-only "view"
 * (info + Edit/Remove buttons) and a hidden inline edit form. */
.row-item-card {
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  padding: 0.75rem 1rem;
  background: #fff;
  margin-bottom: 0.6rem;
}
.row-item-card:last-child {
  margin-bottom: 0;
}
.row-item-view {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.row-item-info {
  min-width: 0;
  flex: 1 1 auto;
}
.row-item-title {
  font-weight: 600;
  color: #0f172a;
}
.row-item-sub {
  margin-top: 0.15rem;
}
.row-item-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  flex: 0 0 auto;
}
.row-item-actions .inline-form {
  display: inline;
  margin: 0;
}
.row-item-form {
  margin-top: 0.5rem;
}

/* The "+ Add ..." form is a card with a slightly distinct background
 * so it reads as "this is new, not editing an existing row". */
.row-item-new {
  background: #f8fafc;
  border-style: dashed;
  margin-top: 0.6rem;
}

.empty-row-hint {
  margin: 0.5rem 0 0.6rem;
  font-style: italic;
}

/* Logo upload spinner — shown inline next to the current logo while
 * the file is being uploaded after auto-submit.
 *
 * NOTE: the `:not([hidden])` selector is load-bearing. A bare
 * `.org-logo-spinner { display: flex }` would override the browser's
 * UA `[hidden] { display: none }` rule (same specificity, author wins),
 * so the spinner would render permanently — even on initial page load
 * and after the upload completes. Scoping `display: flex` to the
 * not-hidden state lets the `hidden` attribute on the element behave
 * the way the rest of the upload JS assumes (toggling `hidden` on/off
 * actually shows/hides the spinner). */
.org-logo-spinner:not([hidden]) {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid #cbd5e1;
  border-top-color: #0f172a;
  border-radius: 50%;
  animation: spinner-rotate 0.8s linear infinite;
}
@keyframes spinner-rotate {
  to { transform: rotate(360deg); }
}

/* Small colour swatch used in the card-style read-only view. */
.color-swatch {
  display: inline-block;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 4px;
  border: 1px solid rgba(15, 23, 42, 0.15);
  vertical-align: middle;
  margin-right: 0.4rem;
}

/* ---------------- TGA pre-fill ----------------
 * Small green badge that appears next to fields on the Organisation page
 * whose value either came from training.gov.au (suggestion) or whose
 * saved value matches the live register exactly. Uses the same green
 * family as .info-notice so it reads as "verified / friendly" rather
 * than "warning". `.tga-badge-inline` is a slightly smaller variant for
 * use inside a form-field label.
 */
.tga-badge {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.45rem;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.4;
  color: #14532d;
  background: #dcfce7;
  border: 1px solid #86efac;
  border-radius: 999px;
  vertical-align: middle;
  white-space: nowrap;
}
.tga-badge-inline {
  font-size: 0.65rem;
  padding: 0.05rem 0.35rem;
  margin-left: 0.4rem;
  font-weight: 500;
  text-transform: none;
}
/* Pre-filled values render in italic + slightly muted so the user can
 * see at a glance that those bits aren't yet "saved" (vs the badged
 * already-saved values, which use the page's normal text colour). */
.tga-suggested-value {
  font-style: italic;
  color: #475569;
}
.tga-sites-picker-field {
  margin-bottom: 0.75rem;
}

/* ============================================================== *
 * Multi-location TGA suggestions + state pill                    *
 *                                                                *
 * Used by the Organisation page's "Training locations" section   *
 * (Suggested-from-TGA panel, per-row state pills, sort dropdown, *
 * count in the header) and by the new-session location dropdown. *
 * ============================================================== */

/* Header bits ------------------------------------------------------------- */

.location-count {
  font-size: 0.85em;
  font-weight: 400;
  margin-left: 0.5rem;
}

/* Sort control sits beside the "+ Add location" button in the section
   header. Inline form so it doesn't break onto its own row at common
   breakpoints; the select itself stays small to avoid out-shouting
   the primary action. */
.sort-control {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-right: 0.5rem;
}
.sort-control select {
  padding: 0.25rem 0.5rem;
  font-size: 0.85rem;
  width: auto;
  min-width: 7rem;
}

/* "Suggested from training.gov.au" panel ---------------------------------- */

/* Tinted background so the panel reads as a distinct "import area"
   above the saved list, without needing a heavy border. Reuses the
   existing TGA badge palette (green) for visual continuity with the
   per-field "From training.gov.au" badges elsewhere on the page. */
.tga-suggestions {
  margin: 0 0 1.25rem 0;
  padding: 0.85rem 1rem;
  border: 1px solid #bbf7d0;
  background: #f0fdf4;
  border-radius: 0.5rem;
}
.tga-suggestions-header {
  margin-bottom: 0.5rem;
}
.tga-suggestions-title {
  font-size: 1rem;
  margin: 0 0 0.15rem 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Each suggested-site card on a slightly lighter ground than the
   panel so it looks "click-to-add"-able. */
.tga-suggested-card {
  background: #ffffff;
  border-color: #bbf7d0;
}
.tga-suggested-card .row-item-actions .secondary-button.small {
  padding: 0.35rem 0.75rem;
  font-size: 0.85rem;
}

/* State pill on each saved-location card ---------------------------------- */

/* Subtle, monochrome by default — different colour per state so a
   long list still scans visually. Kept small and inline so it doesn't
   compete with the location name. */
.state-pill {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.05rem 0.45rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  border-radius: 999px;
  vertical-align: middle;
  background: #e2e8f0;
  color: #334155;
  border: 1px solid #cbd5e1;
}
.state-pill-nsw { background: #dbeafe; color: #1e40af; border-color: #bfdbfe; }
.state-pill-vic { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
.state-pill-qld { background: #fee2e2; color: #991b1b; border-color: #fecaca; }
.state-pill-wa  { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.state-pill-sa  { background: #fce7f3; color: #9d174d; border-color: #fbcfe8; }
.state-pill-tas { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
.state-pill-act { background: #ccfbf1; color: #115e59; border-color: #99f6e4; }
.state-pill-nt  { background: #ffedd5; color: #9a3412; border-color: #fed7aa; }

/* ============================================================
   Courses tab — table, toggle switch, status pill
   ============================================================ */

.courses-table-wrap {
  margin-top: 12px;
  overflow-x: auto;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
}
.courses-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.courses-table th,
.courses-table td {
  padding: 4px 12px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid #f1f5f9;
  line-height: 1.3;
}
.courses-table thead th {
  padding-top: 8px;
  padding-bottom: 8px;
  background: #f8fafc;
  color: #475569;
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid #e2e8f0;
}
.courses-table tbody tr:last-child td { border-bottom: none; }
.courses-table tbody tr.is-disabled td.col-code,
.courses-table tbody tr.is-disabled td.col-title {
  opacity: 0.55;
}
.courses-table .col-code  { width: 130px; white-space: nowrap; }
.courses-table .col-type  { width: 110px; }
.courses-table .col-toggle { width: 90px; text-align: center; }
.courses-table .col-note  { width: 32%; }
.courses-table .col-note .text-input {
  width: 100%;
  max-width: none;
  padding: 4px 8px;
  font-size: 13px;
  border-radius: 5px;
}
/* Compact the iOS-style toggle inside the courses table so the row
   height is driven by the text rather than the switch chrome. */
.courses-table .switch { height: 20px; width: 34px; }
.courses-table .switch-track { height: 20px; width: 34px; border-radius: 10px; }
.courses-table .switch-thumb { height: 16px; width: 16px; top: 2px; left: 2px; }
.courses-table .switch input:checked + .switch-track .switch-thumb {
  transform: translateX(14px);
}
.courses-table .course-status {
  display: inline-block;
  margin-left: 6px;
  font-size: 12px;
}
.course-status.status-ok      { color: #166534; }
.course-status.status-err     { color: #b91c1c; }
.course-status.status-pending { color: #475569; }

/* ============================================================
   Floating save bar — pinned to the bottom of the viewport on
   the Courses page whenever any row differs from its snapshot.
   White surface, soft top shadow so it lifts off the page,
   full viewport width. Slide-up transition on first appearance
   via the .is-open class (toggled by /courses.js a frame after
   `hidden` is unset, so the transition has both states to
   interpolate between).
   ============================================================ */
.save-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80;
  background: #ffffff;
  border-top: 1px solid #e5e7eb;
  box-shadow: 0 -8px 24px -10px rgba(15, 23, 42, 0.18);
  transform: translateY(100%);
  transition: transform 180ms ease-out;
}
.save-bar.is-open {
  transform: translateY(0);
}
.save-bar-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 14px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.save-bar-msg {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 0.95rem;
  font-weight: 500;
  color: #0f172a;
}
.save-bar-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #1D9E75;
  display: inline-block;
}
.save-bar-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.save-bar-btn {
  appearance: none;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1;
  padding: 10px 18px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.save-bar-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.save-bar-btn-ghost {
  background: #ffffff;
  color: #334155;
  border: 1px solid #cbd5e1;
}
.save-bar-btn-ghost:hover:not(:disabled) {
  border-color: #94a3b8;
  color: #0f172a;
}
.save-bar-btn-primary {
  background: #1D9E75;
  color: #ffffff;
  border: 1px solid #1D9E75;
}
.save-bar-btn-primary:hover:not(:disabled) {
  background: #178862;
  border-color: #178862;
}

@media (max-width: 640px) {
  .save-bar-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 12px 16px;
  }
  .save-bar-actions {
    justify-content: flex-end;
  }
}

/* Transient toast — used by the Courses save bar to confirm a
   successful save. Pinned just above the save bar so the two
   don't overlap during the bar's slide-out animation. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 84px;
  transform: translate(-50%, 12px);
  z-index: 90;
  background: #0f172a;
  color: #ffffff;
  font-size: 0.9rem;
  font-weight: 500;
  padding: 10px 16px;
  border-radius: 999px;
  box-shadow: 0 10px 24px -8px rgba(15, 23, 42, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease;
}
.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Toggle switch — label.switch wraps a hidden checkbox + the visible
   track/thumb. Same pattern as a typical iOS-style toggle. */
.switch {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 24px;
  cursor: pointer;
  vertical-align: middle;
}
.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}
.switch-track {
  position: absolute;
  inset: 0;
  background: #cbd5e1;
  border-radius: 999px;
  transition: background 120ms ease;
}
.switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.3);
  transition: transform 120ms ease;
}
.switch input:checked + .switch-track {
  background: #15803d;
}
.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(18px);
}
.switch input:focus-visible + .switch-track {
  box-shadow: 0 0 0 3px #bbf7d0;
}

/* ============================================================
   Course picker (chip-style multi-select on /sessions/new)
   ============================================================ */

.course-picker {
  position: relative;
  margin-top: 8px;
}
.course-picker-field {
  min-height: 44px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 36px 8px 10px;
  border: 1px solid #cbd5e1;
  border-radius: 10px;
  background: #fff;
  cursor: text;
  align-items: center;
}
.course-picker-field:focus-within {
  border-color: #15803d;
  box-shadow: 0 0 0 3px #bbf7d0;
}
.course-picker-placeholder {
  color: #94a3b8;
  font-size: 14px;
  padding: 4px 2px;
}
.course-picker-caret {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid #64748b;
  pointer-events: none;
}
.course-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px 3px 8px;
  background: #ecfdf5;
  border: 1px solid #a7f3d0;
  border-radius: 999px;
  font-size: 13px;
  color: #065f46;
  max-width: 100%;
}
.course-chip-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
}
.course-chip-remove {
  appearance: none;
  background: transparent;
  border: none;
  color: #047857;
  font-size: 16px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  border-radius: 999px;
}
.course-chip-remove:hover { background: #d1fae5; color: #064e3b; }

.course-picker-panel {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.14);
  padding: 8px;
  display: none;
}
.course-picker.is-open .course-picker-panel { display: block; }
.course-picker-search {
  width: 100%;
  margin: 0 0 8px 0;
  padding: 8px 10px;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  font-size: 14px;
  box-sizing: border-box;
}
.course-picker-list {
  max-height: 260px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 2px;
}
.course-picker-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
}
.course-picker-option:hover { background: #f1f5f9; }
.course-picker-option input { margin: 0; }
.course-picker-option-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  color: #0f172a;
  min-width: 92px;
}
.course-picker-option-title {
  flex: 1 1 auto;
  color: #334155;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.course-picker-option-tag {
  font-size: 11px;
  padding: 1px 7px;
  border-radius: 999px;
  background: #e2e8f0;
  color: #334155;
}
.course-picker-empty {
  padding: 12px 8px;
  color: #64748b;
  font-size: 13px;
  text-align: center;
}

/* ============================================================
   Mobile responsiveness baseline (target: iPhone 14, 390px wide)
   ----------------------------------------------------------------
   One global block of mobile-only overrides covering every
   screen in the app. Layout / spacing / sizing only — no
   functional, colour, or copy changes. Sits at the END of the
   stylesheet on purpose so it wins the cascade against every
   other rule, including the older 480/720/880 breakpoints.

   Breakpoint chosen at 640px (slightly above 600/620) so that
   small tablets in portrait also pick up the friendlier layout.
   ============================================================ */

/* Belt-and-braces: no view should ever overflow the viewport
   horizontally on mobile. Pages that *do* need horizontal scroll
   (the data tables) own that scroll inside a .table-scroll
   wrapper, never on the document. */
html, body {
  max-width: 100vw;
}

/* The dark topbar is the parent of the absolute hamburger panel
   on mobile (when applicable) and houses the relative coordinate
   space for any children that need it. Harmless on desktop. */
.topbar { position: relative; }

/* Desktop layout for the right-hand account + sign-out cluster.
   Used to be three inline style="" attributes on topbar.ejs; moved
   here so the mobile @media block can hide/show .topbar-right via
   the hamburger toggle (inline display:flex used to win the
   cascade against display:none). The mobile block then overrides
   these for the dropdown row. */
.topbar-right {
  display: flex;
  align-items: center;
  gap: 18px;
}
.topbar-account-link {
  font-size: 13px;
  color: #64748B;
  text-decoration: none;
}
.topbar-signout-form { margin: 0; }

/* Hamburger toggle button — base styles. Hidden on desktop, only
   becomes visible inside the @media block below. Sized to a 44px
   tap target. Lives on the dark topbar so colours match the
   white-on-charcoal scheme. */
.topbar-mobile-toggle {
  display: none;
  background: transparent;
  border: 0;
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
  padding: 0;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  margin-left: auto;
}
.topbar-mobile-toggle:hover,
.topbar-mobile-toggle:focus-visible {
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}
.topbar-mobile-toggle svg { display: block; }
/* Two icons inside the toggle — menu (☰) by default, close (✕) when
   the menu is open. Driven by the data-mobile-open attribute on the
   parent .topbar via the inline JS in topbar.ejs. */
.topbar-mobile-toggle .icon-close { display: none; }
.topbar[data-mobile-open="true"] .topbar-mobile-toggle .icon-menu { display: none; }
.topbar[data-mobile-open="true"] .topbar-mobile-toggle .icon-close { display: block; }

@media (max-width: 640px) {
  /* ---- iOS auto-zoom prevention ----
     Safari zooms the page when a focused input is below 16px.
     Enforce 16px on every text-entry control so forms stay still
     when the keyboard pops. */
  input, textarea, select {
    font-size: 16px;
  }

  /* ---- 44px minimum tap targets ----
     Apple HIG / WCAG 2.5.5 baseline. Buttons and text inputs all
     get a hard min-height; checkbox / radio are intentionally
     excluded so they keep their native sizes. */
  .primary-button,
  .secondary-button,
  .link-button,
  .form button,
  button[type="submit"],
  button[type="button"],
  .landing-cta,
  .landing-link-button,
  input[type="text"],
  input[type="email"],
  input[type="tel"],
  input[type="password"],
  input[type="search"],
  input[type="number"],
  input[type="date"],
  textarea,
  select {
    min-height: 44px;
  }
  /* Inline link-style buttons inside text shouldn't get the 44px
     stretch — only standalone ones do. .link-button used inside a
     .topbar form (Sign out) and inside .form-actions counts as
     standalone; inline ones inside paragraphs get exempted via
     a stricter selector if needed later. */

  /* ---- Side gutters ----
     The desktop default of 1.5rem padding on .page becomes 16px on
     mobile so the content has room to breathe without touching the
     screen edges. */
  .page,
  .page-stretch {
    padding-left: 16px;
    padding-right: 16px;
    padding-top: 1rem;
    gap: 1rem;
  }

  /* Cards on mobile: less wasted internal padding so the actual
     content has room. */
  .card {
    padding: 1rem;
  }

  /* ---- Headings ---- */
  h1 { font-size: 1.35rem; }
  h2 { font-size: 1.05rem; }

  /* ---- Card headers ----
     Title block on top, action button stretched full-width below
     for a comfortable thumb tap. */
  .card-header {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }
  .card-header > div {
    width: 100%;
  }
  .card-header .primary-button,
  .card-header .secondary-button,
  .card-header a.primary-button,
  .card-header a.secondary-button,
  .card-header .link-button {
    width: 100%;
    text-align: center;
    justify-content: center;
  }

  /* ---- Form actions (Save / Cancel rows) ----
     Stack vertically with primary action on top so the user can
     hit Save without thumb travel. */
  .form-actions {
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 0.5rem;
    padding: 0;
  }
  .form-actions .primary-button,
  .form-actions .secondary-button,
  .form-actions .link-button,
  .form-actions button {
    width: 100%;
    text-align: center;
  }

  /* ---- Tab toolbars (search bar + export button + filter pills) ---- */
  .tab-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }
  .tab-toolbar > * { width: 100%; }
  .search-form {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-width: 0;
    width: 100%;
  }
  .search-form .text-input,
  .search-form .search-input {
    flex: 1 1 100%;
    min-width: 0;
    width: 100%;
  }
  .search-form .secondary-button,
  .search-form .primary-button {
    flex: 1 1 auto;
  }
  .search-form .link-button {
    flex: 0 0 auto;
  }

  /* Filter pills on the People page wrap and breathe so they stack
     neatly over two rows at 390px. Each pill keeps its hit target. */
  .filter-bar {
    flex-wrap: wrap;
    gap: 0.4rem;
  }
  .filter-pill {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* Export-CSV button on the records page sits below the search
     row at full width — easy thumb target. */
  .tab-toolbar > a.secondary-button {
    text-align: center;
  }

  /* ---- Table scroll wrappers ----
     Tables are deliberately wide on desktop. On phones we let the
     table scroll horizontally inside the .table-scroll container
     with iOS momentum, so the page itself never overflows. We do
     NOT mask-image the container — masking the content layer
     interferes with sticky headers and clips real text on the
     right edge. The visible right column itself is enough of an
     affordance that there's more to scroll. */
  .table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Topbar mobile drawer styles live in their own 768px breakpoint
     block below this one — see "Topbar / nav: full-width drawer". */

  /* ---- Dashboard metric tiles ----
     Force 2x2 even at 390px. The earlier rule at 480px collapsed
     to a single column which wasted vertical real estate; the user
     spec is "stack to 2x2 grid on mobile not 4 across". This block
     is later in source order than the 480px rule so it wins
     without !important. */
  .metrics-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
  .metric-tile { padding: 0.85rem 0.9rem; }
  .metric-value { font-size: 1.45rem; }
  .metric-label { font-size: 0.78rem; }

  /* People stats — 3 stat tiles. At 390px stack 2 + 1 (the third
     tile spans the full row). */
  .people-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
  }
  .people-stats-grid > :nth-child(3) {
    grid-column: 1 / -1;
  }

  /* ---- Org settings / generic forms ----
     Make every input/select/textarea fill its container and ensure
     the section-edit-controls (Edit / Save / Cancel) wrap when
     they don't fit. */
  .field input,
  .field select,
  .field textarea {
    width: 100%;
    max-width: 100%;
  }
  .section-edit-controls {
    flex-wrap: wrap;
    gap: 0.4rem;
  }

  /* ---- Auth (login/signup/etc) ---- */
  .auth-shell { padding: 1rem; }
  /* 28px all-around card padding on mobile per spec. */
  .auth-card { padding: 28px; }
  .auth-card .form button { width: 100%; }

  /* ---- Trainee table on /sessions/new ----
     Existing stack rules at 600/900px are good. Just make sure the
     row wrappers stay on screen and the remove button is reachable. */
  .trainee-card { padding: 0.85rem; }
  .trainee-grid { grid-template-columns: 1fr; }

  /* ---- Wallet preview card (Org settings) ----
     Already capped at 320px via .wallet-card-mockup; keep wrapper
     padding-light so the card actually centres. */
  .wallet-cards-single { padding: 0; }

  /* ---- Delivery actions row on /sessions/:id ----
     Buttons sit edge-to-edge instead of cramped. */
  .delivery-actions {
    flex-wrap: wrap;
    gap: 0.5rem;
  }
  .delivery-actions > * {
    flex: 1 1 auto;
  }
}

/* ============================================================
   Topbar / nav: full-width drawer (mobile, ≤768px).

   Replaces the old in-flow dropdown. When the hamburger is tapped
   (data-mobile-open="true"), the entire .topbar becomes a fixed
   full-width sheet pinned to the top of the viewport, with a
   semi-transparent backdrop covering the page below it.

   Anatomy when open:
     ┌────────────────────────────────┐
     │ [logo]                  [×]    │  ← .topbar-left brand row
     ├────────────────────────────────┤
     │  Dashboard                     │  ← .topnav links (52px each)
     │ │Sessions                      │  ← active = teal left border
     │  Training records              │
     │  …                             │
     ├────────────────────────────────┤
     │  Account                       │  ← .topbar-right (bottom)
     │  Sign out                      │
     └────────────────────────────────┘
        (backdrop fills the rest)

   Desktop (>768px) is untouched — those rules live above in the
   non-media-query block.
   ============================================================ */
@media (max-width: 768px) {
  .topbar-mobile-toggle { display: inline-flex; }

  /* Hidden by default; revealed below when data-mobile-open="true". */
  .topnav,
  .topbar-right {
    display: none;
  }

  /* ---- Backdrop ----
     Pseudo-element on the topbar so we don't need any extra DOM.
     Sits behind the drawer (drawer = z 100, backdrop = z 90) and
     covers everything else on the page. */
  .topbar[data-mobile-open="true"]::before {
    content: "";
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 90;
  }

  /* ---- Drawer ----
     The .topbar itself becomes the drawer. Full screen width,
     auto height (sized by content), pinned to the top of the
     viewport. Scrolls internally if it ever runs taller than the
     viewport (e.g. landscape phones). */
  .topbar[data-mobile-open="true"] {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Avoid 100vw — on browsers that show a vertical scrollbar this
       overflows by the scrollbar width and pushes the drawer to the
       right. left:0 + right:0 already give a true full width. */
    max-height: 100vh;
    overflow-y: auto;
    z-index: 100;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  }
  .topbar[data-mobile-open="true"] .topbar-inner {
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    gap: 0;
  }

  /* ---- Drawer content stacking ----
     The drawer's ::before backdrop sits at z:90 *inside* the topbar's
     stacking context. Lift .topbar-inner well above it so the menu
     content paints on top of the dim layer (otherwise the white text
     reads as washed-out grey because the backdrop covers it). */
  .topbar[data-mobile-open="true"] .topbar-inner {
    position: relative;
    z-index: 100;
    /* Match the topbar's dark surface — without an explicit background
       the .topbar-inner is transparent, so the drawer would render on
       whatever the page background is (white on most app pages),
       turning the white-on-charcoal nav text invisible. */
    background: var(--brand-charcoal);
  }

  /* ---- Header row (logo + close button) ----
     .topbar-left holds both the brand and (because of the existing
     DOM) the .topnav list. We make it a wrapping flex container so
     the brand sits on its own header row and .topnav drops to a
     full-width row below it. The mobile toggle (× when open) is
     pinned to the top-right of the drawer. */
  .topbar[data-mobile-open="true"] .topbar-left {
    width: 100%;
    padding: 0;
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0;
  }
  .topbar[data-mobile-open="true"] .topbar-left .brand {
    flex: 1 1 auto;
    padding: 10px 60px 10px 24px;
    min-height: 64px;
    display: inline-flex;
    align-items: center;
  }
  .topbar[data-mobile-open="true"] .topbar-mobile-toggle {
    margin: 0;
    align-self: flex-start;
    margin-top: 10px;
    margin-right: 10px;
    /* Anchored to the top-right of the drawer regardless of where
       it falls in DOM order (it's a sibling of .topbar-left, not
       a child). */
    position: absolute;
    top: 0;
    right: 0;
    width: 44px;
    height: 44px;
  }

  /* ---- Nav links column ----
     Full-width column, 4px gap between items, no dividing lines.
     Each link is a 52px tall, 16px text row with 24px left padding
     and a 3px transparent left border that turns teal on .active. */
  .topbar[data-mobile-open="true"] .topnav {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
    /* Force a wrap to a new row inside .topbar-left's flex-wrap
       container so the brand stays on its own header row above. */
    flex-basis: 100%;
    padding: 8px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
  }
  .topbar[data-mobile-open="true"] .topnav-link {
    min-height: 52px;
    display: flex;
    align-items: center;
    padding: 0 24px;
    font-size: 16px;
    line-height: 1.2;
    color: rgba(255, 255, 255, 0.85);
    background: transparent;
    border: 0;
    border-left: 3px solid transparent;
    border-radius: 0;
    text-decoration: none;
  }
  .topbar[data-mobile-open="true"] .topnav-link.active {
    color: #1D9E75;
    border-left-color: #1D9E75;
    background: transparent;
  }
  /* Kill the desktop underline indicator on mobile. */
  .topbar[data-mobile-open="true"] .topnav-link.active::after {
    display: none;
  }

  /* ---- Bottom row (Account + Sign out) ----
     Two stacked tappable rows, separated from the main nav by a
     subtle top divider, sharing the same 52px / 24px sizing. */
  .topbar[data-mobile-open="true"] .topbar-right {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    width: 100%;
    padding: 8px 0 12px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
  }
  /* Subtle divider between Account and Sign out. The form is the
     second child so a top-border on it draws the line between the
     two rows without affecting the outer top-border above. */
  .topbar[data-mobile-open="true"] .topbar-right .topbar-signout-form {
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    margin-top: 4px;
    padding-top: 4px;
  }
  .topbar[data-mobile-open="true"] .topbar-right .topbar-account-link,
  .topbar[data-mobile-open="true"] .topbar-signout-form .link-button {
    min-height: 52px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    padding: 0 24px;
    font-size: 16px;
    line-height: 1.2;
    color: rgba(255, 255, 255, 0.85);
    background: transparent;
    border: 0;
    border-left: 3px solid transparent;
    border-radius: 0;
    text-align: left;
    text-decoration: none;
  }
  .topbar[data-mobile-open="true"] .topbar-signout-form {
    margin: 0;
    width: 100%;
  }
}


/* ============================================================
   Digital certificate preview (Organisation settings).

   New .cert-preview-* namespace — none of the legacy
   .wallet-card-* rules apply here. Both faces (front + back)
   render side-by-side at the same time, mirroring the iOS
   pass + pass-back-panel layout the trainee actually sees.

   Front: locked-down 320px-wide Apple Wallet pass mock.
   Back:  iOS settings-style dark-grey card with hairline-
          divided rows, full course list, meta + action links.

   Every value field on the FRONT is single-line ellipsis
   truncated; no wrapping under any circumstance. The BACK
   intentionally allows wrapping for course titles and
   action URLs, matching the live iOS rendering.
   ============================================================ */

.cert-preview-wrap {
  /* Side-by-side at any width that fits two 320px cards
     plus a gap; stacks below that. flex-wrap handles the
     fallback automatically. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: 24px;
  width: 100%;
}

/* --- Card shell (shared by front + back). Width hard-locked
       to 320px so the layout never reflows under either face. --- */
.cert-preview-card {
  width: 320px;
  min-width: 320px;
  max-width: 320px;
  border-radius: 16px;
  padding: 16px;
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  position: relative;
}
.cert-preview-front { min-height: 480px; }

/* ---------- FRONT ---------- */

.cert-preview-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 40px;
}
.cert-preview-logo-slot {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
}
.cert-preview-logo {
  max-width: 140px;
  max-height: 40px;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}
.cert-preview-logo-default {
  /* The CertPass white logo is wider than most RTO uploads — cap it
     a little tighter so it doesn't crowd the "CERTIFICATE / Training"
     stack on the left. RTO-uploaded logos use the looser 140px cap
     above so existing brand assets aren't shrunk. */
  max-width: 110px;
  max-height: 28px;
}
.cert-preview-brand-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  flex-shrink: 0;
  line-height: 1.1;
}
.cert-preview-brand {
  /* "CERTIFICATE" label — small white uppercase, mirrors the
     Apple Wallet header-field label style on the live pass. */
  font-size: 9px;
  color: #fff;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.9;
}
.cert-preview-kind {
  /* "Training" header value — teal, slightly larger, matches the
     header-field value style on the live pass. */
  font-size: 14px;
  color: var(--brand-teal);
  font-weight: 600;
  margin-top: 2px;
  line-height: 1.1;
}

.cert-preview-primary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
}
.cert-preview-primary-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.cert-preview-trainee {
  font-size: 22px;
  font-weight: 700;
  color: var(--brand-teal);
  line-height: 1.1;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}
.cert-preview-thumb {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
}

.cert-preview-row-2 {
  /* Date column shrinks to fit "3 May 2026" exactly, then the
     issued-by column fills the rest of the row. This packs the
     two cells against each other instead of leaving a wide gap
     between them, matching the live pass layout. */
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  margin-top: 16px;
}
.cert-preview-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.cert-preview-row-3 {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 14px;
  min-width: 0;
}

.cert-preview-label {
  font-size: 9px;
  font-weight: 600;
  color: #fff;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.85;
  display: block;
}

.cert-preview-value {
  font-size: 13px;
  font-weight: 500;
  color: var(--brand-teal);
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  min-width: 0;
}
.cert-preview-value-tight {
  font-size: 11px;
}

.cert-preview-spacer {
  height: 80px;
  flex: 0 0 80px;
}

.cert-preview-qr {
  margin-top: auto;
  align-self: center;
  width: 80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  border-radius: 6px;
  padding: 4px;
  box-sizing: border-box;
}
.cert-preview-qr svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---------- BACK ----------
   Mirrors the iOS pass-back panel: a dark-grey iOS settings
   card with hairline-divided rows. Background is fixed dark
   grey (#1c1c1e) regardless of the org's chosen card colour
   — this is iOS chrome, not the pass surface, so the colour
   is a system-defined constant and is intentionally NOT
   driven by the colour picker. */
.cert-preview-back {
  background: #1c1c1e;
  padding: 0;
  /* Match the front's typical rendered height so the two
     cards line up at the top edge with similar visual weight. */
  min-height: 480px;
}

.cert-preview-back-row {
  /* Rows are full-width with a 16px inset, separated by a
     hairline divider that stops short of the card edges
     (matching iOS group-style table rows). */
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  flex-direction: row;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  min-width: 0;
}
.cert-preview-back-row:last-child { border-bottom: 0; }

.cert-preview-back-label {
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  flex: 0 0 auto;
}
.cert-preview-back-val {
  color: rgba(235, 235, 245, 0.6);
  font-size: 13px;
  font-weight: 400;
  text-align: right;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
}

/* Courses block — full width, vertical layout, course titles
   wrap naturally across multiple lines (no ellipsis). */
.cert-preview-back-courses-row {
  flex-direction: column;
  align-items: stretch;
}
.cert-preview-back-title {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.01em;
}
.cert-preview-back-courses {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.cert-preview-back-courses li {
  font-size: 13px;
  line-height: 1.4;
  color: rgba(235, 235, 245, 0.6);
  /* Allow wrapping — long course titles should flow onto a
     second visible line, exactly like the iOS screenshot. */
  white-space: normal;
  word-break: normal;
  overflow-wrap: break-word;
}

/* Action rows — stack the URL underneath the label so the
   long verify/download/share URLs have room to wrap. */
.cert-preview-back-action {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}
.cert-preview-back-url {
  text-align: left;
  white-space: normal;
  overflow-wrap: anywhere;
  font-size: 13px;
  /* iOS system tint (#007AFF) — Apple Wallet renders all
     back-of-pass links in the system blue regardless of the
     pass's foreground/label colours. We can't override it on
     the live pass, so the preview must match. */
  color: #0a84ff;
  font-weight: 500;
  text-decoration: none;
}

.cert-preview-back-link {
  /* Same iOS system blue as .cert-preview-back-url — see note
     above. Used for the inline USI link and the footer link. */
  color: #0a84ff;
  text-decoration: none;
}
.cert-preview-back-link:hover { text-decoration: underline; }

.cert-preview-back-footer {
  margin: 0;
  padding: 14px 16px 16px;
  text-align: left;
  font-size: 13px;
  color: #0a84ff;
}
.cert-preview-back-footer .cert-preview-back-link { font-weight: 500; }


/* ============================================================
   Mobile list/table refinements (≤768px). Desktop layouts are
   completely unchanged — every rule below lives inside the
   media query.

   Sessions list   → table hides, vertical card list shows
   Training records→ slim down to Trainee + Course + chevron
   Courses         → 3-column row (Code · Title · Toggle) with
                     the optional reason field stacked below when
                     a course is disabled
   ============================================================ */

/* Sessions cards — base styles (always defined; visibility flipped
   by the @media block below). Hidden on desktop. */
.sessions-mobile-list { display: none; }

/* Mobile-only chevron column on the training-records table. The TH/TD
   exist in markup at all viewport widths; this rule keeps them hidden
   on desktop so the desktop column count is unchanged. The ≤768px
   block below flips them back to table-cell. */
.register-table .tr-col-chevron { display: none; }

@media (max-width: 768px) {
  /* ---- Sessions: swap table for cards ---- */
  .sessions-desktop-table { display: none; }
  .sessions-mobile-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .session-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
  }
  .session-card-link {
    display: block;
    padding: 14px 16px;
    color: inherit;
    text-decoration: none;
    min-height: 52px;
  }
  .session-card-link:hover,
  .session-card-link:focus-visible {
    background: rgba(29, 158, 117, 0.04);
    outline: none;
  }
  .session-card-row1 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 6px;
  }
  .session-card-date {
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
  }
  .session-card-status {
    flex-shrink: 0;
  }
  .session-card-location {
    font-size: 14px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 2px;
  }
  .session-card-meta {
    margin-bottom: 8px;
  }
  .session-card-courses {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
  }
  /* The page footer count and the "+ New session" button were
     already styled by earlier mobile rules — nothing to add. */

  /* ---- Training records: hide non-essential columns ---- */
  .register-table .tr-col-mobile-hidden { display: none; }
  /* Mobile chevron column — hidden on desktop, visible here. */
  .register-table .tr-col-chevron {
    display: table-cell;
    width: 24px;
    padding-left: 0;
    padding-right: 8px;
    text-align: right;
    color: var(--muted);
    font-size: 18px;
    line-height: 1;
    vertical-align: middle;
  }
  /* Course title clamped to 2 lines under the code chip. */
  .register-table .tr-col-course .tr-course-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 2px;
  }
  .register-table .tr-col-trainee {
    font-weight: 500;
  }

  /* ---- Courses: 3-column compact row + inline note when disabled ---- */
  .courses-table thead .col-type,
  .courses-table thead .col-note,
  .courses-table tbody .col-type,
  /* Hide the note cell by default on mobile — the .is-disabled
     override below re-shows it as a full-width row beneath the
     row's other cells when (and only when) the course is off. */
  .courses-table tbody td.col-note {
    display: none;
  }
  /* Tighten the visible columns. */
  .courses-table .col-code  { width: 80px; padding-right: 6px; }
  .courses-table .col-title {
    /* Single-line truncation for long course names. */
    max-width: 0; /* lets text-overflow ellipsis kick in inside a table cell */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .courses-table .col-toggle { width: 60px; }

  /* The note input lives in the same TD as col-note (which is hidden
     above). Move it out of that cell visually by un-hiding only the
     input portion and absolutely-positioning a row beneath the main
     row… simpler: instead reveal the note cell as a full-width block
     below the row when the row is .is-disabled. We achieve that by
     turning .is-disabled rows into block-display containers so
     col-note can render full-width below the others. */
  .courses-table tbody tr.is-disabled {
    display: block;
    border-bottom: 1px solid var(--border);
    padding: 6px 0 10px;
  }
  .courses-table tbody tr.is-disabled td.col-code,
  .courses-table tbody tr.is-disabled td.col-title,
  .courses-table tbody tr.is-disabled td.col-toggle {
    display: inline-block;
    border-bottom: 0;
    vertical-align: middle;
    padding-top: 8px;
    padding-bottom: 8px;
  }
  .courses-table tbody tr.is-disabled td.col-code  { width: 80px; }
  .courses-table tbody tr.is-disabled td.col-title {
    width: calc(100% - 80px - 60px - 12px);
    max-width: none;
  }
  .courses-table tbody tr.is-disabled td.col-toggle { width: 60px; text-align: right; }
  .courses-table tbody tr.is-disabled td.col-note {
    display: block;
    width: 100%;
    padding: 4px 12px 4px 80px;
    border-bottom: 0;
  }
  .courses-table tbody tr.is-disabled td.col-note .text-input {
    width: 100%;
    font-size: 14px;
  }

  /* The .tab-toolbar mobile block (search bar stacked, full width)
     already exists in the ≤640px media block. Mirror it here at the
     ≤768px breakpoint so tablets in the 641–768px band also stack
     properly on the records and courses pages. */
  .tab-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }
  .tab-toolbar > * { width: 100%; }
  .tab-toolbar > a.secondary-button { text-align: center; }
}


/* ============================================================
   Dashboard mobile refinements (≤768px). Desktop unchanged.
   ============================================================ */

/* Default (desktop) visibility for the new mobile-only elements
   on the dashboard. These rules live OUTSIDE the media query so
   the mobile-only spans never bleed into the desktop layout. */
.metric-label-mobile,
.metric-usi-mobile,
.activity-date-pill,
.activity-location-mobile {
  display: none;
}

/* Desktop layout for the USI tile's wrapper span. Without this the
   .metric-value and .metric-label inside would render inline and
   collapse the original two-line treatment. */
.metric-usi-desktop {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

/* On desktop the trainee/course counts render inline as part of
   the meta string ("2 trainees · 4 courses · Location · Trainer").
   The mobile media query overrides this to stack on its own line. */
.activity-counts { display: inline; }

/* "See all sessions →" link below the recent-activity list. Teal,
   left-aligned (the previous "View all sessions →" lived in the
   card header on the right). */
.activity-see-all {
  display: inline-block;
  margin-top: 0.75rem;
  color: var(--brand-teal);
  font-weight: 500;
  text-decoration: none;
  font-size: 0.95rem;
}
.activity-see-all:hover { text-decoration: underline; }

@media (max-width: 768px) {
  /* ---- Metric labels: swap long for short ---- */
  .metric-label-desktop { display: none; }
  .metric-label-mobile  { display: inline; font-size: 0.85rem; color: var(--muted); }

  /* ---- USI tile: swap to mobile-friendly states ---- */
  .metric-usi-desktop { display: none; }
  .metric-usi-mobile {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
  }
  .metric-usi-ok {
    color: var(--brand-teal);
    font-size: 1rem;
    font-weight: 600;
  }
  .metric-tile-usi.attention .metric-usi-warn-value {
    /* Override the desktop attention amber → red on mobile so the
       warning reads more strongly on a phone glance. */
    color: #b91c1c;
  }
  .metric-tile-usi.attention .metric-usi-warn-label {
    color: #b91c1c;
    font-weight: 500;
  }

  /* ---- Recent activity rows ----
     Two-column grid: left = teal date pill, middle = stacked
     counts + location, right = chevron. */
  .activity-link {
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    padding: 12px 4px;
    align-items: center;
  }
  /* Hide the long date and the desktop meta tail (location +
     trainer in one string) on mobile. */
  .activity-date-long,
  .activity-meta-desktop {
    display: none;
  }
  .activity-date-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(29, 158, 117, 0.12);
    color: var(--brand-teal);
    font-weight: 600;
    font-size: 13px;
    padding: 4px 10px;
    border-radius: 999px;
    white-space: nowrap;
    line-height: 1.2;
  }
  .activity-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 14px;
    min-width: 0;
  }
  .activity-counts {
    display: block;
    color: var(--text);
    font-weight: 500;
  }
  .activity-location-mobile {
    display: block;
    color: var(--muted);
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .activity-arrow {
    color: var(--muted);
    font-size: 18px;
  }

  /* "See all sessions →" sits left-aligned and teal — the rules
     above already do that; nothing more needed in the mobile block. */
}


/* ============================================================
   Login page — split layout (scoped). Desktop: dark left
   marketing panel + white right sign-in column. Mobile (≤768px):
   left panel is hidden, right column fills the viewport with a
   pale teal gradient. Scoped under .login-split / .login-body
   so the signup page (still .auth-shell / .auth-card) is
   completely unaffected.
   ============================================================ */

.login-body { margin: 0; }

.login-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---- Left panel (dark marketing) ---- */

.login-left {
  position: relative;
  background: #0D3D2E; /* dark teal per spec */
  color: #ffffff;
  padding: 24px 48px 32px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Subtle diagonal-line texture. Two layered repeating gradients
   produce a faint cross-hatch that adds depth without busy-ness. */
.login-left::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.025) 0,
      rgba(255, 255, 255, 0.025) 1px,
      transparent 1px,
      transparent 14px
    ),
    repeating-linear-gradient(
      -45deg,
      rgba(255, 255, 255, 0.018) 0,
      rgba(255, 255, 255, 0.018) 1px,
      transparent 1px,
      transparent 22px
    );
}

/* Push everything above the texture layer. */
.login-left > * { position: relative; z-index: 1; }

.login-left-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
}
.login-left-brand .brand-wordmark { font-size: 1.6rem; }
/* Override the .brand-wordmark-cert default (white) — it's already
   white, but the auth-brand override would otherwise force charcoal
   if these classes were ever combined. Explicit + scoped is safer. */
.login-left .login-left-cert { color: #ffffff; }

.login-left-body {
  /* Vertically centre the headline / subline / bullets in the
     remaining space between the brand mark and the footnote. */
  margin: auto 0;
  max-width: 460px;
}

.login-left-headline {
  font-size: 32px;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
  color: #ffffff;
}

.login-left-subline {
  font-size: 16px;
  line-height: 1.55;
  margin: 0 0 28px;
  color: rgba(255, 255, 255, 0.72);
}

.login-left-bullets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.login-left-bullets li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 15px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.92);
}
.login-left-tick {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: rgba(29, 158, 117, 0.18);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 1px;
}

.login-left-footnote {
  margin: 24px 0 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.5;
}

/* ---- Right panel (sign-in form) ---- */

.login-right {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 32px;
  background: #ffffff;
}

/* Sign-in card on the right column. On desktop this is a visible
   white card with a subtle border + soft shadow so the form reads
   as a discrete object even though its background already matches
   the column. On mobile (overridden below) the card chrome is
   stripped so the form sits flat on the pale teal gradient. */
.login-right-inner {
  width: 100%;
  max-width: 380px;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 40px;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 8px 24px rgba(15, 23, 42, 0.06);
}

.login-right-brand {
  /* Larger, centred brand mark above the form. The .auth-brand
     base class uses inline-flex; we wrap it in a flex container
     so it horizontally centres regardless of column width.
     Negative top margin pulls the mark up closer to the card edge. */
  display: flex;
  justify-content: center;
  font-size: 2.25rem;
  margin: -8px 0 28px;
}
.login-right-brand .brand-wordmark { font-size: 2.6rem; }
.login-right-brand .brand-mark { width: 40px; height: 40px; }

.login-right-heading {
  font-size: 18px;
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--text);
  /* Centred to match the centred brand mark above. Form labels
     stay left-aligned with their inputs. */
  text-align: center;
}

/* Mobile-only tagline above the form. */
.login-mobile-tagline { display: none; text-align: center; }

/* Sign-up link below the form — centred to match the heading. */
.login-right-inner .auth-signup {
  text-align: center;
}

/* Tighter top spacing on the form since the right column already
   gives generous breathing room. */
.login-form { margin-top: 18px; }

/* ---- Mobile (≤768px): single-column form view ---- */

@media (max-width: 768px) {
  .login-split {
    grid-template-columns: 1fr;
    /* Plain white background on mobile. */
    background: #ffffff;
    /* Anchor for the 4px teal accent bar pinned to the top edge. */
    position: relative;
  }

  /* Top accent bar — a 4px solid teal stripe pinned to the very
     top of the screen so the login page has a visual identity
     without any background pattern or gradient. */
  .login-split::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--brand-teal);
    z-index: 1;
  }

  /* Hide the dark marketing panel entirely on mobile per spec. */
  .login-left { display: none; }

  .login-right {
    background: transparent;
    padding: 24px;
    /* Form vertically centred in the full viewport. */
    min-height: 100vh;
    min-height: 100dvh;
  }

  .login-right-inner {
    max-width: 420px;
    /* Strip the desktop card chrome so the form sits flat on the
       pale teal gradient. */
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 28px 4px;
  }

  /* Show the mobile-only tagline; the desktop heading still
     reads "Sign in to your RTO dashboard" below it. */
  .login-mobile-tagline {
    display: block;
    margin: 6px 0 0;
    color: var(--muted);
    font-size: 14px;
  }
}


/* ---- Inline brand wordmark for body copy ----
   The default .brand-wordmark-cert is white (designed for the dark
   topbar). When the wordmark appears mid-prose on a light page,
   wrap it in .brand-inline so "cert" reads in charcoal and "pass"
   keeps its teal. Inherits surrounding font-size so it sits flush
   with the line. */
.brand-inline { font-size: inherit; font-weight: inherit; }
.brand-inline .brand-wordmark-cert { color: var(--brand-charcoal); }
.brand-inline .brand-wordmark-pass { color: var(--brand-teal); }
