/* ============================================================================
   DALIJAY E-Voting — modern SaaS design system
   Layered over AdminLTE 2 / Bootstrap 3. Same-origin (CSP-safe). WCAG-AA minded.
   Font (Inter) is loaded via <link> in the page <head>.
   Theme colour: pages may override --c-primary inline (System Settings).
   ============================================================================ */

/* ---- Theme tokens --------------------------------------------------------
   Colour is split into two layers:
     · brand + geometry live on :root and are shared by both themes
     · every surface / ink / line value is redefined per [data-theme]
   Nothing below this block should hardcode a colour — that is what made the
   old dashboard impossible to re-theme without editing every rule.

   The admin area boots in dark; the voter-facing pages stay light. The theme is
   written to <html data-theme> before first paint (see admin/includes/header.php)
   so there is no flash of the wrong theme. --------------------------------- */
:root {
  /* Brand — --c-primary may be overridden inline by System Settings. */
  --c-primary:      #2563EB;
  --c-primary-600:  color-mix(in srgb, var(--c-primary) 84%, black);
  --c-primary-050:  color-mix(in srgb, var(--c-primary) 8%, white);
  --c-primary-100:  color-mix(in srgb, var(--c-primary) 16%, white);
  /* Readable against dark surfaces whatever brand colour the school picked. */
  --c-primary-lift: color-mix(in srgb, var(--c-primary) 55%, white);
  --c-glow:         #22D3EE;

  --c-success:      #16A34A;
  --c-warning:      #F59E0B;
  --c-danger:       #DC2626;
  --c-info:         #0891B2;

  --r-sm: 8px; --r-md: 12px; --r-lg: 18px; --r-pill: 999px;
  --t-fast: .15s ease; --t: .25s ease;
  --e-out: cubic-bezier(.16,1,.3,1);
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-num: 'Inter', ui-monospace, 'Segoe UI', system-ui, sans-serif;
}

/* ---- Light ---- */
:root, [data-theme="light"] {
  --c-ink:          #0f172a;
  --c-ink-soft:     #64748b;
  --c-line:         #e5e7eb;
  --c-surface:      #ffffff;
  --c-surface-2:    #f1f5f9;
  --c-bg:           #f8fafc;
  --c-glass:        rgba(255,255,255,.72);
  --c-glass-line:   rgba(15,23,42,.08);
  --c-track:        #e9eef6;
  --sh-sm: 0 1px 2px rgba(15,23,42,.06), 0 1px 3px rgba(15,23,42,.08);
  --sh-md: 0 6px 18px rgba(15,23,42,.08);
  --sh-lg: 0 18px 40px rgba(15,23,42,.16);
  --c-accent:       var(--c-primary);
  --ambient-1: color-mix(in srgb, var(--c-primary) 12%, transparent);
  --ambient-2: rgba(34,211,238,.10);
}

/* ---- Dark (admin default) --------------------------------------------------
   Deep navy rather than pure black: #000 smears on OLED and crushes the
   elevation scale. Surfaces step up in lightness as they come forward. ------ */
[data-theme="dark"] {
  --c-ink:          #E8F0FA;
  --c-ink-soft:     #93A9C7;
  --c-line:         rgba(255,255,255,.10);
  --c-surface:      #10203A;
  --c-surface-2:    #16294a;
  --c-bg:           #0A1628;
  --c-glass:        rgba(20,38,66,.62);
  --c-glass-line:   rgba(255,255,255,.09);
  --c-track:        rgba(255,255,255,.09);
  --sh-sm: 0 1px 2px rgba(0,0,0,.34), 0 1px 3px rgba(0,0,0,.30);
  --sh-md: 0 8px 24px rgba(0,0,0,.40);
  --sh-lg: 0 22px 52px rgba(0,0,0,.55);
  /* Brand blues go muddy on navy — lift the accent for AA contrast. */
  --c-accent:       var(--c-primary-lift);
  --c-success:      #34D399;
  --c-warning:      #FBBF24;
  --c-danger:       #F87171;
  --ambient-1: color-mix(in srgb, var(--c-primary) 26%, transparent);
  --ambient-2: rgba(34,211,238,.16);
}

/* Fallback if color-mix is unsupported */
@supports not (color: color-mix(in srgb, red, blue)) {
  :root { --c-primary-600:#1d4ed8; --c-primary-050:#eff6ff; --c-primary-100:#dbeafe; --c-primary-lift:#7EA6FF; }
  [data-theme="dark"] { --ambient-1: rgba(37,99,235,.26); }
}

/* Colour changes are animated so the toggle reads as one deliberate switch
   rather than a jarring repaint. */
body, .content-wrapper, .box, .main-header, .main-sidebar, .metric, .panel-glass {
  transition: background-color var(--t), border-color var(--t), color var(--t);
}

/* ---- Base ---------------------------------------------------------------- */
body, .content-wrapper, .wrapper { font-family: var(--font); color: var(--c-ink); }
body { background: var(--c-bg); }
.content-wrapper { background: var(--c-bg); }
h1,h2,h3,h4,h5,.box-title,.page-header { font-family: var(--font); font-weight: 700; letter-spacing:-.01em; }
a { color: var(--c-primary); }
a:hover, a:focus { color: var(--c-primary-600); }

a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, .btn:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--c-primary) 45%, transparent);
  outline-offset: 2px;
}

/* ---- Buttons (all variants + states) ------------------------------------ */
.btn {
  border-radius: var(--r-sm); font-weight: 600; border: 1px solid transparent;
  transition: transform var(--t-fast), box-shadow var(--t-fast), background var(--t-fast), border-color var(--t-fast);
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
}
.btn.btn-flat { border-radius: var(--r-sm); }
.btn:hover { transform: translateY(-1px); box-shadow: var(--sh-sm); }
.btn:active { transform: translateY(0); box-shadow: none; }
.btn:disabled, .btn.disabled { opacity:.6; transform:none; box-shadow:none; }
.btn-primary { background: var(--c-primary); border-color: var(--c-primary); }
.btn-primary:hover, .btn-primary:focus, .btn-primary:active { background: var(--c-primary-600); border-color: var(--c-primary-600); }
.btn-success { background: var(--c-success); border-color: var(--c-success); }
.btn-warning { background: var(--c-warning); border-color: var(--c-warning); color:#fff; }
.btn-danger  { background: var(--c-danger);  border-color: var(--c-danger); }
.btn-default { background:#fff; border-color: var(--c-line); color: var(--c-ink); }
.btn-default:hover { background:#f8fafc; border-color:#cbd5e1; }
.btn-outline { background:transparent; border-color: var(--c-primary); color: var(--c-primary); }
.btn-outline:hover { background: var(--c-primary-050); }
.btn-lg { border-radius: var(--r-md); }
/* loading spinner */
.btn.is-loading { color: transparent !important; pointer-events:none; position: relative; }
.btn.is-loading::after {
  content:""; position:absolute; width:16px; height:16px; top:calc(50% - 8px); left:calc(50% - 8px);
  border:2px solid rgba(255,255,255,.6); border-top-color:#fff; border-radius:50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Cards / boxes ------------------------------------------------------- */
.box { border:1px solid var(--c-line); border-radius: var(--r-md); box-shadow: var(--sh-sm); border-top-width:1px; }
.box:hover { box-shadow: var(--sh-md); }
.box > .box-header { border-radius: var(--r-md) var(--r-md) 0 0; }
.box-header .box-title { font-size:16px; }
.callout { border-radius: var(--r-md); box-shadow: var(--sh-sm); border-left-width:5px; }

/* Small stat boxes (dashboard) */
.small-box { border-radius: var(--r-md); box-shadow: var(--sh-sm); overflow: hidden; transition: transform var(--t-fast), box-shadow var(--t-fast); }
.small-box:hover { box-shadow: var(--sh-lg); transform: translateY(-3px); }
.small-box h3 { font-weight: 800; }
.small-box .icon { opacity:.28; transition: transform var(--t); }
.small-box:hover .icon { transform: scale(1.06) rotate(-4deg); }
.small-box > .small-box-footer { background: rgba(0,0,0,.10); }

/* ---- Tables -------------------------------------------------------------- */
.box .box-body > .table, .table { border-radius: var(--r-sm); overflow: hidden; }
.table > thead > tr > th {
  position: sticky; top: 0; z-index: 2;
  background:#f1f5f9; color: var(--c-ink); border-bottom:2px solid var(--c-line);
  text-transform: uppercase; font-size:11.5px; letter-spacing:.05em; font-weight:700;
}
.table > tbody > tr { transition: background var(--t-fast); }
.table-hover > tbody > tr:hover, .table > tbody > tr:hover { background: var(--c-primary-050); }
.table > tbody > tr > td { vertical-align: middle; }
code { background:#f1f5f9; color:#0f172a; border:1px solid var(--c-line); border-radius:var(--r-sm); padding:2px 8px; font-weight:700; }

/* DataTables controls */
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select { border:1px solid var(--c-line); border-radius: var(--r-sm); padding:4px 8px; }
.dataTables_wrapper .paginate_button.current { background: var(--c-primary) !important; border-color: var(--c-primary) !important; color:#fff !important; border-radius: var(--r-sm); }
.dataTables_wrapper .paginate_button { border-radius: var(--r-sm) !important; }

/* ---- Forms --------------------------------------------------------------- */
.form-control { border-radius: var(--r-sm); border-color: var(--c-line); box-shadow:none; transition: border-color var(--t-fast), box-shadow var(--t-fast); }
.form-control:focus { border-color: var(--c-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-primary) 15%, transparent); }
label { font-weight: 600; color:#334155; }
.help-block, .text-muted { color: var(--c-ink-soft); }
.label, .badge { border-radius: var(--r-pill); padding:.3em .7em; font-weight:600; }
.input-group-addon { border-radius: var(--r-sm) 0 0 var(--r-sm); background:#f1f5f9; border-color:var(--c-line); }
/* password toggle */
.pw-wrap { position: relative; }
.pw-wrap .pw-toggle { position:absolute; right:10px; top:50%; transform:translateY(-50%); border:0; background:transparent; color:var(--c-ink-soft); cursor:pointer; padding:4px; }
.pw-wrap .pw-toggle:hover { color: var(--c-primary); }
/* password strength meter */
.pw-meter { height:6px; border-radius: var(--r-pill); background:#e5e7eb; overflow:hidden; margin-top:8px; }
.pw-meter > span { display:block; height:100%; width:0; transition: width var(--t), background var(--t); }

/* ---- Modals -------------------------------------------------------------- */
.modal-content { border:0; border-radius: var(--r-lg); box-shadow: var(--sh-lg); overflow:hidden; }
.modal-header { border-bottom:1px solid var(--c-line); }
.modal-footer { border-top:1px solid var(--c-line); }
.modal.fade .modal-dialog { transform: translateY(-16px); transition: transform var(--t); }
.modal.in .modal-dialog { transform: translateY(0); }

/* ---- Alerts / notifications --------------------------------------------- */
.alert { border:0; border-radius: var(--r-md); box-shadow: var(--sh-sm); animation: slideIn var(--t); }
.alert-success { background:#ecfdf5; color:#065f46; }
.alert-danger  { background:#fef2f2; color:#991b1b; }
.alert-info    { background:#ecfeff; color:#155e75; }
.alert-warning { background:#fffbeb; color:#92400e; }
@keyframes slideIn { from { opacity:0; transform: translateY(-8px); } to { opacity:1; transform:none; } }

/* ---- Empty states -------------------------------------------------------- */
.empty-state { text-align:center; padding:48px 20px; color: var(--c-ink-soft); }
.empty-state i { font-size:56px; opacity:.35; margin-bottom:12px; display:block; }

/* ---- Header / Sidebar ---------------------------------------------------- */
.skin-blue .main-header .logo,
.skin-blue .main-header .navbar { background: var(--c-primary); }
.skin-blue .main-header .logo:hover { background: var(--c-primary-600); }
.skin-blue .sidebar-menu > li.active > a,
.skin-blue .sidebar-menu > li:hover > a { border-left:3px solid var(--c-primary); background:#1a2332; }
.skin-blue .sidebar-menu > li > a { transition: background var(--t-fast), border-color var(--t-fast); border-left:3px solid transparent; }
.sidebar-menu > li.header { letter-spacing:.08em; font-size:11px; color:#8aa4c8; }
.sidebar .user-panel { padding:14px 12px; }
.main-header .logo b, .main-header .logo { font-weight:800; }
.navbar-nav > .user-menu .user-image { border:2px solid rgba(255,255,255,.6); }
.brand-logo { height:30px; width:auto; vertical-align:middle; border-radius:6px; background:#fff; padding:2px; }

/* ---- Two-column auth layout --------------------------------------------- */
.auth-wrap { min-height:100vh; display:flex; }
/* The copy sits at the BOTTOM, not centred. Centred text landed directly over
   the ballot-box artwork and hid it; anchoring low keeps the upper two-thirds
   of the image clear while the text still has a dark base to sit on. */
.auth-visual {
  flex:1 1 52%; position:relative; color:#fff; display:flex;
  align-items:flex-end; justify-content:flex-start;
  background: #0b1220 center/cover no-repeat;
  overflow:hidden;
}
/* Scrim graded bottom-up: opaque where the words are, near-clear over the
   artwork. A flat overlay dimmed the whole image for no benefit. */
.auth-visual::before {
  content:""; position:absolute; inset:0;
  background:
    linear-gradient(to top,
      rgba(6,14,32,.94)  0%,
      rgba(6,14,32,.86) 26%,
      rgba(8,18,42,.52) 52%,
      rgba(10,22,52,.20) 78%,
      rgba(10,22,52,.10) 100%),
    linear-gradient(120deg, rgba(15,23,42,.34), rgba(37,99,235,.14));
}
.auth-visual .auth-visual-inner {
  position:relative; z-index:1; width:100%; max-width:560px;
  padding: 36px clamp(28px, 4vw, 48px);
}

/* Logo beside the name rather than above it — on a long school name the stacked
   version pushed the headline onto four lines and swallowed the panel. */
.auth-visual .auth-brandrow { display:flex; align-items:center; gap:14px; margin-bottom:14px; }
.auth-visual .auth-logo {
  flex:0 0 auto; height:56px; width:56px; margin:0; padding:5px;
  border-radius:13px; background:#fff; object-fit:contain;
  box-shadow: 0 6px 18px rgba(0,0,0,.34);
}
.auth-visual .auth-brandcopy { min-width:0; }
.auth-visual h1 {
  /* Scales down as the name gets longer instead of wrapping indefinitely. */
  font-size: clamp(19px, 2vw, 26px); font-weight:800; line-height:1.16;
  margin:0 0 3px; text-shadow:0 2px 12px rgba(0,0,0,.5); overflow-wrap:anywhere;
}
.auth-visual .auth-sub { font-size:14.5px; opacity:.92; }
.auth-visual .auth-desc { font-size:14px; line-height:1.6; opacity:.9; margin:0; max-width:46ch; }
.auth-visual .auth-tag {
  margin-top:16px; font-size:13.5px; opacity:.9;
  border-left:3px solid rgba(255,255,255,.6); padding-left:12px;
}

/* Sign-in panel reduced to a logo and one statement, so that statement has to
   carry the panel on its own — set at headline scale rather than as a caption.
   A separate class, so the small .auth-tag on other screens is unaffected. */
.auth-visual .auth-logo-solo { margin-bottom:22px; height:64px; width:64px; }
.auth-visual .auth-statement {
  margin:0; max-width:15ch;
  font-size: clamp(28px, 3.4vw, 44px);
  font-weight:800; line-height:1.14; letter-spacing:-.02em;
  text-shadow: 0 3px 18px rgba(0,0,0,.55);
}
/* Colour the last sentence so the line has a focal point rather than reading
   as one flat block. */
.auth-visual .auth-statement::after {
  content:""; display:block; width:64px; height:5px; border-radius:3px;
  margin-top:18px; background: linear-gradient(90deg,#60A5FA, rgba(96,165,250,0));
}

@media (max-width: 991px) {
  /* Below the split breakpoint the panel becomes a short banner — keep the
     brand row and drop the supporting copy so the box stays visible. */
  .auth-visual { min-height:210px; }
  .auth-visual .auth-desc, .auth-visual .auth-tag { display:none; }
  .auth-visual .auth-visual-inner { padding:22px 24px; }
}
.auth-form { flex:1 1 48%; display:flex; align-items:center; justify-content:center; padding:32px; background: var(--c-bg); }
.auth-card {
  width:100%; max-width:420px; background:#fff; border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); padding:34px 30px; animation: rise var(--t);
}
.auth-card .auth-brand { text-align:center; margin-bottom:18px; }
.auth-card .auth-brand img { height:52px; margin-bottom:8px; }
.auth-card .auth-brand .school { font-weight:800; font-size:20px; color:var(--c-ink); }
/* Centred to sit under the logo and school name above, which are already
   centred — left-aligned headings broke that axis. */
.auth-card h2 { font-size:22px; margin:0 0 4px; text-align:center; }
.auth-card h2 .fa { margin-right:4px; }
.auth-card .auth-lead { color:var(--c-ink-soft); margin-bottom:20px; text-align:center; }
.auth-card .form-control { padding:12px 14px; height:auto; font-size:15px; }
.auth-card .btn-block { padding:12px; font-size:16px; }
.auth-code { letter-spacing:3px; text-transform:uppercase; font-weight:800; text-align:center; font-size:22px; }
@keyframes rise { from { opacity:0; transform: translateY(14px); } to { opacity:1; transform:none; } }

@media (max-width: 900px) {
  .auth-visual { display:none; }
  .auth-form { flex-basis:100%; }
}

/* ---- Voter ballot polish -------------------------------------------------
   These rules were previously split between assets/app.css and an inline
   <style> block in includes/header.php, where the inline copy always won.
   They now live here only. */
.title { font-size:34px; letter-spacing:-.01em; }
.candidate-card {
  background:#fff; border:2px solid var(--c-line); border-radius: var(--r-md);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast), background var(--t-fast);
}
.candidate-card:hover { border-color: var(--c-primary); box-shadow: var(--sh-md); transform: translateY(-1px); background: var(--c-primary-050); }

.ballot-section { margin-bottom:24px; }
.ballot-section .box-header { background: var(--c-primary); border-radius: var(--r-md) var(--r-md) 0 0; }
.ballot-section .box-title, .ballot-section .box-title b { color:#fff; }
.ballot-section .ballot-position-number { background:#fff; color: var(--c-primary); }

.vote-instruction {
  color: var(--c-ink-soft); font-size:14px; margin-bottom:10px; padding:8px 12px;
  background: var(--c-bg); border-left:4px solid var(--c-primary); border-radius:0 var(--r-sm) var(--r-sm) 0;
}
.ballot-actions {
  text-align:center; padding:20px; margin-top:20px; background:#fff;
  border:1px solid var(--c-line); border-radius: var(--r-md);
}
.ballot-actions .btn { min-width:150px; margin:5px; font-size:16px; padding:10px 20px; }
.vote-state { padding:48px 16px; }
.vote-state h3 { margin-top:14px; font-weight:700; }

/* ---- Utilities ----------------------------------------------------------- */
.card-tile { background:#fff; border:1px solid var(--c-line); border-radius: var(--r-md); box-shadow: var(--sh-sm); padding:18px; }
.img-preview { max-height:90px; border-radius: var(--r-sm); border:1px solid var(--c-line); background:#f8fafc; padding:4px; }
.settings-nav .btn { text-align:left; }

@media (prefers-reduced-motion: reduce) {
  *, *::after { transition:none !important; animation:none !important; }
  .btn:hover, .candidate-card:hover, .small-box:hover { transform:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Ballot ordering & numbering
   Added 2026-07-30 alongside the ballot_order fix. The ballot number is the
   primary wayfinding device on every ballot surface (voter ballot, admin
   preview, candidate list, printed tally), so it gets a single consistent
   treatment everywhere.
   ═════════════════════════════════════════════════════════════════════════ */

.ballot-number {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:44px; padding:3px 9px;
  font-variant-numeric: tabular-nums; font-weight:700; font-size:13px;
  color: var(--c-primary); background: var(--c-primary-050);
  border:1px solid var(--c-primary-100); border-radius: var(--r-pill);
  letter-spacing:.02em;
}

.ballot-position-number {
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; margin-right:9px;
  font-size:13px; font-weight:800; font-variant-numeric: tabular-nums;
  color:#fff; background: var(--c-primary); border-radius:50%;
}

/* ---- Admin: ballot order screen ----------------------------------------- */
.ballot-help p { margin-bottom:0; }
.ballot-position { overflow:hidden; }
.ballot-position .box-title { display:flex; align-items:center; flex-wrap:wrap; gap:2px; }
.ballot-position-meta { margin-left:10px; color: var(--c-ink-soft); font-weight:500; }
.ballot-instruction {
  color: var(--c-ink-soft); font-size:13px; margin-bottom:14px;
  padding-left:10px; border-left:3px solid var(--c-primary);
}

.ballot-list { list-style:none; margin:0; padding:0; }
.ballot-row {
  display:flex; align-items:center; gap:14px;
  padding:10px 12px; border:1px solid var(--c-line); border-radius: var(--r-md);
  background:#fff; margin-bottom:8px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.ballot-row:last-child { margin-bottom:0; }
.ballot-row:hover { border-color: var(--c-primary); box-shadow: var(--sh-sm); }
.ballot-row-empty { justify-content:space-between; background: var(--c-bg); border-style:dashed; }
.ballot-avatar { width:56px; height:56px; border-radius: var(--r-sm); object-fit:cover; background:#f1f5f9; flex:0 0 auto; }
.ballot-name { font-weight:600; flex:1 1 auto; min-width:0; overflow-wrap:anywhere; }
.ballot-row-tools { flex:0 0 auto; white-space:nowrap; }
.ballot-row-tools .btn[disabled] { opacity:.35; }

.ballot-loading { padding:48px; text-align:center; color: var(--c-ink-soft); }
.ballot-loading .fa { font-size:22px; margin-right:8px; }

.ballot-empty {
  text-align:center; padding:52px 24px; background:#fff;
  border:1px dashed var(--c-line); border-radius: var(--r-lg);
}
.ballot-empty > .fa { font-size:44px; color:#cbd5e1; margin-bottom:14px; display:block; }
.ballot-empty h4 { font-weight:700; margin:0 0 6px; }
.ballot-empty p { color: var(--c-ink-soft); max-width:460px; margin:0 auto 18px; }

/* ---- Admin: candidate profile modal -------------------------------------- */
.candidate-profile { min-height:180px; }
.profile-state {
  display:flex; align-items:center; justify-content:center; gap:10px;
  min-height:180px; color: var(--c-ink-soft); text-align:center;
}
.profile-state-error { color: var(--c-danger); }
.profile-head { display:flex; align-items:center; gap:18px; margin-bottom:22px; }
.profile-photo {
  width:96px; height:96px; border-radius: var(--r-md); object-fit:cover;
  border:1px solid var(--c-line); background:#f1f5f9; flex:0 0 auto;
}
.profile-ident { min-width:0; }
.profile-name { font-size:21px; font-weight:800; margin:0 0 8px; overflow-wrap:anywhere; }
.profile-meta { display:flex; flex-wrap:wrap; gap:6px; }
.profile-chip {
  display:inline-flex; align-items:center; gap:5px;
  padding:3px 10px; border-radius: var(--r-pill); font-size:12px; font-weight:600;
  color:#fff; background: var(--c-primary);
}
.profile-chip-ghost {
  color: var(--c-ink-soft); background: var(--c-bg); border:1px solid var(--c-line);
}
.profile-section-label {
  text-transform:uppercase; letter-spacing:.07em; font-size:11px; font-weight:700;
  color: var(--c-ink-soft); margin:0 0 8px; padding-bottom:6px;
  border-bottom:1px solid var(--c-line);
}
.platform-text { white-space:pre-wrap; overflow-wrap:anywhere; line-height:1.65; margin:0; }
.platform-text.is-empty { color: var(--c-ink-soft); font-style:italic; }

.table-avatar { border-radius: var(--r-sm); object-fit:cover; background:#f1f5f9; }

/* ---- Voter ballot: numbered candidate cards ------------------------------ */
.candidate_list { margin-top:18px; }
.candidate_list ul { list-style:none; margin:0; padding:0; }

/* One candidate = one full-width row: [radio] [number] [photo] [name].
   The radio is a sibling of the label (iCheck wraps it in its own div), so the
   row itself is the flex container that keeps them on the same line. */
.candidate-item { display:flex; align-items:center; gap:14px; margin:0 0 12px; }
.candidate-item > .icheckbox_flat-green,
.candidate-item > .iradio_flat-green,
.candidate-item > input { flex:0 0 auto; margin:0 !important; }
.candidate-card { display:flex; align-items:center; gap:16px; padding:12px 16px; flex:1 1 auto; min-width:0; margin:0; cursor:pointer; font-weight:400; }
.candidate-number {
  flex:0 0 auto; min-width:46px; padding:4px 10px; text-align:center;
  font-weight:800; font-size:14px; font-variant-numeric: tabular-nums;
  color: var(--c-primary); background: var(--c-primary-050);
  border:1px solid var(--c-primary-100); border-radius: var(--r-pill);
}
.candidate-photo { border-radius: var(--r-sm); object-fit:cover; background:#f1f5f9; flex:0 0 auto; }
.candidate-info { display:flex; flex-direction:column; align-items:flex-start; gap:7px; min-width:0; }
.candidate-name { font-size:19px; font-weight:700; line-height:1.25; overflow-wrap:anywhere; }
.preview-number {
  display:inline-block; min-width:34px; padding:1px 7px; margin-right:6px;
  font-size:11px; font-weight:700; text-align:center; font-variant-numeric: tabular-nums;
  color: var(--c-primary); background: var(--c-primary-050);
  border:1px solid var(--c-primary-100); border-radius: var(--r-pill);
}
.votelist { padding:9px 0; border-bottom:1px solid var(--c-line); }
.votelist:last-child { border-bottom:0; }

/* Keyboard focus must stay obvious on every interactive ballot control. */
.ballot-row-tools .btn:focus-visible,
.candidate-card:focus-within,
.ballot-empty .btn:focus-visible {
  outline:3px solid var(--c-primary); outline-offset:2px;
}

@media (max-width: 767px) {
  .ballot-row { flex-wrap:wrap; gap:10px; }
  .ballot-name { flex-basis:100%; order:3; }
  .profile-head { flex-direction:column; text-align:center; }
  .profile-meta { justify-content:center; }
  .candidate-card { flex-wrap:wrap; }
  .candidate-info { flex-basis:100%; }
}

/* ---- Results tally bar ---------------------------------------------------- */
.tally-bar {
  height:8px; background: var(--c-line); border-radius: var(--r-pill);
  overflow:hidden; margin-bottom:3px;
}
.tally-bar > span {
  display:block; height:100%; background: var(--c-primary);
  border-radius: var(--r-pill); transition: width var(--t);
}

/* ---- Voters: roll summary strip ------------------------------------------ */
.voter-summary {
  display:flex; align-items:center; flex-wrap:wrap; gap:18px;
  padding:12px 16px; margin-bottom:16px;
  background: var(--c-bg); border:1px solid var(--c-line); border-radius: var(--r-md);
  font-size:13.5px; color: var(--c-ink-soft);
}
.voter-summary b { color: var(--c-ink); font-size:16px; font-variant-numeric: tabular-nums; }
.voter-summary .tally-bar { flex:1 1 140px; min-width:120px; margin-bottom:0; }

@media (max-width: 600px) {
  .voter-summary { gap:10px; font-size:12.5px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DARK MODE — AdminLTE surface overrides
   AdminLTE 2 hardcodes light colours throughout. Rather than fight it rule by
   rule, the handful of surfaces it paints are re-pointed at the theme tokens.
   ═════════════════════════════════════════════════════════════════════════ */
[data-theme="dark"] body,
[data-theme="dark"] .content-wrapper,
[data-theme="dark"] .wrapper          { background: var(--c-bg); color: var(--c-ink); }
[data-theme="dark"] .box,
[data-theme="dark"] .box-solid,
[data-theme="dark"] .modal-content,
[data-theme="dark"] .dropdown-menu    { background: var(--c-surface); border-color: var(--c-line); color: var(--c-ink); }
[data-theme="dark"] .box-header,
[data-theme="dark"] .box-footer,
[data-theme="dark"] .modal-header,
[data-theme="dark"] .modal-footer     { border-color: var(--c-line); }
[data-theme="dark"] .box-title,
[data-theme="dark"] h1, [data-theme="dark"] h2, [data-theme="dark"] h3,
[data-theme="dark"] h4, [data-theme="dark"] h5 { color: var(--c-ink); }
[data-theme="dark"] .content-header > h1 small { color: var(--c-ink-soft); }
[data-theme="dark"] .breadcrumb       { background: transparent; }
[data-theme="dark"] .breadcrumb > .active,
[data-theme="dark"] .text-muted,
[data-theme="dark"] .help-block       { color: var(--c-ink-soft); }
[data-theme="dark"] a                 { color: var(--c-accent); }
[data-theme="dark"] label             { color: #C7D6EA; }

[data-theme="dark"] .main-header .navbar,
[data-theme="dark"] .main-header .logo { background: #0C1D34; border-color: var(--c-line); }
[data-theme="dark"] .main-sidebar,
[data-theme="dark"] .left-side        { background: #081221; }
[data-theme="dark"] .sidebar-menu > li > a { color: #B9CBE4; }
[data-theme="dark"] .skin-blue .sidebar-menu > li.active > a,
[data-theme="dark"] .skin-blue .sidebar-menu > li:hover > a { background: #101f38; color: #fff; }
[data-theme="dark"] .main-footer      { background: var(--c-surface); border-color: var(--c-line); color: var(--c-ink-soft); }

[data-theme="dark"] .table            { color: var(--c-ink); }
[data-theme="dark"] .table > thead > tr > th { background: var(--c-surface-2); color: var(--c-ink); border-color: var(--c-line); }
[data-theme="dark"] .table > tbody > tr > td,
[data-theme="dark"] .table-bordered,
[data-theme="dark"] .table-bordered > tbody > tr > td,
[data-theme="dark"] .table-bordered > thead > tr > th { border-color: var(--c-line); }
[data-theme="dark"] .table-hover > tbody > tr:hover,
[data-theme="dark"] .table > tbody > tr:hover { background: rgba(255,255,255,.045); }

[data-theme="dark"] .form-control     { background: var(--c-surface-2); border-color: var(--c-line); color: var(--c-ink); }
[data-theme="dark"] .form-control::placeholder { color: #6F87A6; }
[data-theme="dark"] .input-group-addon { background: #0E1D33; border-color: var(--c-line); color: var(--c-ink-soft); }
[data-theme="dark"] .btn-default      { background: var(--c-surface-2); border-color: var(--c-line); color: var(--c-ink); }
[data-theme="dark"] .btn-default:hover { background: #1d3157; }
[data-theme="dark"] code              { background: var(--c-surface-2); border-color: var(--c-line); color: var(--c-accent); }
[data-theme="dark"] .dataTables_wrapper,
[data-theme="dark"] .dataTables_wrapper .dataTables_info,
[data-theme="dark"] .dataTables_wrapper label { color: var(--c-ink-soft); }
[data-theme="dark"] .dataTables_wrapper .paginate_button { background: var(--c-surface-2) !important; border-color: var(--c-line) !important; color: var(--c-ink) !important; }
[data-theme="dark"] .ballot-row,
[data-theme="dark"] .candidate-card,
[data-theme="dark"] .ballot-empty     { background: var(--c-surface); border-color: var(--c-line); }
[data-theme="dark"] .voter-summary,
[data-theme="dark"] .vote-instruction { background: var(--c-surface-2); border-color: var(--c-line); }
[data-theme="dark"] .ballot-number,
[data-theme="dark"] .candidate-number { background: rgba(34,211,238,.12); border-color: rgba(34,211,238,.28); color: var(--c-glow); }
[data-theme="dark"] .profile-chip-ghost { background: var(--c-surface-2); border-color: var(--c-line); color: var(--c-ink-soft); }

/* ---- Theme toggle --------------------------------------------------------- */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; min-width: 44px; padding: 0 12px; margin: 8px 6px;
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.20);
  border-radius: var(--r-pill); color: #fff; cursor: pointer;
  transition: background var(--t-fast), transform var(--t-fast);
}
.theme-toggle:hover  { background: rgba(255,255,255,.22); }
.theme-toggle:active { transform: scale(.95); }
.theme-toggle:focus-visible { outline: 3px solid var(--c-glow); outline-offset: 2px; }
.theme-toggle .fa { font-size: 15px; }
.theme-toggle .tt-label { font-size: 12.5px; font-weight: 600; letter-spacing: .02em; }
/* Only one icon shows per theme — the other is hidden, not merely faded. */
[data-theme="dark"]  .theme-toggle .i-light,
[data-theme="light"] .theme-toggle .i-dark { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   DASHBOARD
   ═════════════════════════════════════════════════════════════════════════ */

/* Ambient glow — echoes the constellation backdrop on the sign-in screen.
   Purely decorative, so it is aria-hidden and removed under reduced-motion. */
.dash-ambient {
  position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.dash-ambient span {
  position: absolute; border-radius: 50%; filter: blur(90px);
  animation: drift 24s ease-in-out infinite alternate;
}
.dash-ambient span:nth-child(1) { width: 480px; height: 480px; top: -140px; left: -100px;  background: var(--ambient-1); }
.dash-ambient span:nth-child(2) { width: 420px; height: 420px; top: 32%;   right: -150px; background: var(--ambient-2); animation-delay: -8s; }
.dash-ambient span:nth-child(3) { width: 380px; height: 380px; bottom: -160px; left: 34%;  background: var(--ambient-1); animation-delay: -16s; }
@keyframes drift {
  from { transform: translate3d(0,0,0)        scale(1); }
  to   { transform: translate3d(40px,-30px,0) scale(1.12); }
}
.content-wrapper > .content,
.content-wrapper > .content-header { position: relative; z-index: 1; }

/* ---- Status banner (replaces the .callout whose button was invisible) ----- */
.status-banner {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 16px 20px; margin-bottom: 20px;
  background: var(--c-glass); border: 1px solid var(--c-glass-line);
  border-left: 4px solid var(--tone, var(--c-primary));
  border-radius: var(--r-md); backdrop-filter: blur(10px); box-shadow: var(--sh-sm);
}
.status-banner .sb-icon {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 19px;
  background: color-mix(in srgb, var(--tone) 16%, transparent); color: var(--tone);
}
.status-banner .sb-body   { flex: 1 1 260px; min-width: 0; }
.status-banner .sb-title  { font-weight: 700; font-size: 15.5px; color: var(--c-ink); margin: 0 0 3px; }
.status-banner .sb-meta   { font-size: 13px; color: var(--c-ink-soft); margin: 0; }
.status-banner .sb-meta b { color: var(--c-ink); }
.status-banner .sb-action { flex: 0 0 auto; }
.status-tone-open          { --tone: var(--c-success); }
.status-tone-upcoming      { --tone: var(--c-info); }
.status-tone-closed        { --tone: var(--c-ink-soft); }
.status-tone-not_scheduled { --tone: var(--c-warning); }

/* ---- Metric cards --------------------------------------------------------- */
.metric-grid {
  display: grid; gap: 16px; margin-bottom: 20px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.metric {
  position: relative; overflow: hidden; display: block;
  padding: 20px; border-radius: var(--r-lg);
  background: var(--c-glass); border: 1px solid var(--c-glass-line);
  backdrop-filter: blur(12px); box-shadow: var(--sh-sm);
  text-decoration: none; color: inherit;
  transition: transform var(--t) var(--e-out), box-shadow var(--t), border-color var(--t);
  /* Entrance: staggered per card via --i, set inline. */
  animation: metric-in .5s var(--e-out) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
.metric:hover, .metric:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--sh-lg);
  border-color: color-mix(in srgb, var(--tone) 45%, transparent);
  color: inherit; text-decoration: none;
}
.metric:focus-visible { outline: 3px solid var(--tone); outline-offset: 2px; }
@keyframes metric-in { from { opacity:0; transform: translateY(14px); } to { opacity:1; transform:none; } }

/* Accent rule + wash pick up each card's own tone. */
.metric::before {
  content:""; position:absolute; inset:0 0 auto 0; height:3px; background: var(--tone);
}
.metric::after {
  content:""; position:absolute; width:150px; height:150px; right:-46px; top:-46px;
  border-radius:50%; background: color-mix(in srgb, var(--tone) 14%, transparent);
  transition: transform var(--t) var(--e-out);
}
.metric:hover::after { transform: scale(1.25); }

.metric-head  { display:flex; align-items:center; justify-content:space-between; gap:10px; position:relative; z-index:1; }
.metric-label { font-size:12px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color: var(--c-ink-soft); }
.metric-icon  {
  width:38px; height:38px; border-radius:11px; display:flex; align-items:center; justify-content:center;
  font-size:16px; background: color-mix(in srgb, var(--tone) 16%, transparent); color: var(--tone);
}
.metric-value {
  position:relative; z-index:1; margin:10px 0 2px;
  font-family: var(--font-num); font-size:40px; font-weight:800; line-height:1;
  font-variant-numeric: tabular-nums; color: var(--c-ink); letter-spacing:-.02em;
}
.metric-sub   { position:relative; z-index:1; font-size:12.5px; color: var(--c-ink-soft); display:flex; align-items:center; gap:5px; }
.metric-tone-a { --tone:#0EA5E9; }
.metric-tone-b { --tone:#10B981; }
.metric-tone-c { --tone:#F59E0B; }
.metric-tone-d { --tone:#8B5CF6; }

/* ---- Glass panels --------------------------------------------------------- */
.panel-glass {
  background: var(--c-glass); border:1px solid var(--c-glass-line); border-radius: var(--r-lg);
  backdrop-filter: blur(12px); box-shadow: var(--sh-sm); padding: 20px; height:100%;
}
.panel-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:16px; flex-wrap:wrap; }
.panel-title { font-size:15px; font-weight:700; margin:0; display:flex; align-items:center; gap:8px; color: var(--c-ink); }
.panel-title .fa { color: var(--c-accent); }
.panel-note { font-size:12.5px; color: var(--c-ink-soft); }
.dash-grid { display:grid; gap:16px; margin-bottom:20px; grid-template-columns: minmax(0,1fr) minmax(0,1.35fr); }
@media (max-width: 991px) { .dash-grid { grid-template-columns: 1fr; } }

/* ---- Donut (turnout) ------------------------------------------------------ */
.donut-wrap { display:flex; align-items:center; gap:22px; flex-wrap:wrap; justify-content:center; }
.donut { position:relative; flex:0 0 auto; width:172px; height:172px; }
.donut svg { transform: rotate(-90deg); width:100%; height:100%; display:block; }
.donut .track { fill:none; stroke: var(--c-track); stroke-width:14; }
.donut .value {
  fill:none; stroke: var(--c-accent); stroke-width:14; stroke-linecap:round;
  /* --dash/--gap are set inline from the real percentage. */
  stroke-dasharray: var(--dash) var(--gap);
  animation: donut-in 1.1s var(--e-out) both;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--c-accent) 45%, transparent));
}
@keyframes donut-in { from { stroke-dasharray: 0 999; } }
.donut-centre {
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center;
}
.donut-centre .pct { font-family: var(--font-num); font-size:34px; font-weight:800; line-height:1; color: var(--c-ink); font-variant-numeric: tabular-nums; }
.donut-centre .cap { font-size:11px; letter-spacing:.08em; text-transform:uppercase; color: var(--c-ink-soft); margin-top:3px; }
.donut-legend { list-style:none; margin:0; padding:0; min-width:150px; }
.donut-legend li { display:flex; align-items:center; gap:9px; padding:7px 0; font-size:13.5px; color: var(--c-ink-soft); }
.donut-legend .dot { width:10px; height:10px; border-radius:3px; flex:0 0 auto; }
.donut-legend b { margin-left:auto; color: var(--c-ink); font-variant-numeric: tabular-nums; }

/* ---- Horizontal bar chart ------------------------------------------------- */
.bars { list-style:none; margin:0; padding:0; }
.bars li { margin-bottom:13px; }
.bars li:last-child { margin-bottom:0; }
.bar-top { display:flex; align-items:baseline; gap:8px; margin-bottom:5px; font-size:13px; }
.bar-name { color: var(--c-ink); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bar-val  { margin-left:auto; color: var(--c-ink-soft); font-variant-numeric: tabular-nums; flex:0 0 auto; }
.bar-val b { color: var(--c-ink); }
.bar-track { height:9px; border-radius: var(--r-pill); background: var(--c-track); overflow:hidden; }
.bar-fill {
  display:block; height:100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--c-primary), var(--c-glow));
  width: var(--w, 0%);
  animation: bar-in 1s var(--e-out) both;
  animation-delay: calc(var(--i, 0) * 55ms);
}
@keyframes bar-in { from { width: 0; } }
.bar-lead .bar-fill { box-shadow: 0 0 12px color-mix(in srgb, var(--c-glow) 55%, transparent); }

/* ---- Per-position tally cards --------------------------------------------- */
.tally-grid { display:grid; gap:16px; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.tally-card { background: var(--c-glass); border:1px solid var(--c-glass-line); border-radius: var(--r-lg);
              backdrop-filter: blur(12px); box-shadow: var(--sh-sm); padding:18px; }
.tally-card h4 { display:flex; align-items:center; gap:9px; margin:0 0 4px; font-size:14.5px; font-weight:700; color: var(--c-ink); }
.tally-card .t-meta { font-size:12px; color: var(--c-ink-soft); margin:0 0 14px; }
.winner-tag {
  margin-left:auto; font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  padding:3px 9px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--c-success) 18%, transparent); color: var(--c-success);
  border:1px solid color-mix(in srgb, var(--c-success) 35%, transparent);
}

/* Screen-reader-only table paired with every chart (a chart alone is not
   accessible — WCAG). Visually hidden, fully readable to assistive tech. */
.sr-only-table { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

@media (max-width: 767px) {
  .metric-value { font-size:33px; }
  .status-banner { padding:14px; }
  .donut { width:142px; height:142px; }
}

/* Motion here is decorative — honour the OS setting. */
@media (prefers-reduced-motion: reduce) {
  .metric, .bar-fill, .donut .value, .dash-ambient span { animation: none !important; }
  .bar-fill { width: var(--w, 0%); }
  .dash-ambient { display: none; }
  .metric:hover { transform: none; }
}

/* Dark-mode semantic buttons: the lifted success/warning/danger tones are light
   colours, so white label text on them falls well below 4.5:1. Pair them with
   dark ink instead of dimming the button. */
[data-theme="dark"] .btn-success { color: #06231A; font-weight: 700; }
[data-theme="dark"] .btn-warning { color: #2B1C00; font-weight: 700; }
[data-theme="dark"] .btn-danger  { color: #2C0707; font-weight: 700; }
[data-theme="dark"] .btn-success:hover { background: color-mix(in srgb, var(--c-success) 85%, white); }
[data-theme="dark"] .btn-danger:hover  { background: color-mix(in srgb, var(--c-danger) 85%, white); }
[data-theme="dark"] .label-success { color: #06231A; }

/* An unopposed race is not a contest — say so rather than calling it a lead. */
.winner-tag.is-unopposed {
  background: color-mix(in srgb, var(--c-ink-soft) 16%, transparent);
  color: var(--c-ink-soft);
  border-color: color-mix(in srgb, var(--c-ink-soft) 30%, transparent);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ELECTION COUNTDOWN
   Urgency is carried by colour AND by the label wording, never colour alone.
   ═════════════════════════════════════════════════════════════════════════ */
.countdown {
  --cd-tone: var(--c-primary);
  border: 1px solid color-mix(in srgb, var(--cd-tone) 32%, transparent);
  background: color-mix(in srgb, var(--cd-tone) 8%, var(--c-surface));
  border-radius: var(--r-md);
  transition: border-color var(--t), background var(--t);
}
.countdown.is-warning  { --cd-tone: var(--c-warning); }
.countdown.is-critical { --cd-tone: var(--c-danger); }

.cd-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.cd-title {
  display:inline-flex; align-items:center; gap:7px;
  font-weight:700; color: var(--cd-tone);
  font-size:12px; letter-spacing:.09em; text-transform:uppercase;
}
.cd-note { font-size:11.5px; color: var(--c-ink-soft); }

.cd-clock { display:flex; align-items:flex-start; gap:6px; }
.cd-unit  { display:flex; flex-direction:column; align-items:center; min-width:44px; }
.cd-num {
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  font-weight:800; line-height:1; color: var(--c-ink);
  /* Tabular figures + a fixed min-width stop the row jittering as digits change. */
}
.cd-cap {
  font-size:9.5px; letter-spacing:.1em; text-transform:uppercase;
  color: var(--c-ink-soft); margin-top:5px;
}
.cd-sep {
  font-weight:800; line-height:1; color: color-mix(in srgb, var(--cd-tone) 55%, transparent);
  align-self:flex-start;
}
.cd-ended {
  margin:0; font-size:13px; font-weight:600; color: var(--cd-tone);
  display:flex; align-items:center; gap:8px;
}

/* ---- Hero variant: voter login + ballot ---------------------------------- */
.countdown-hero { padding:16px 18px; }
.countdown-hero .cd-head  { margin-bottom:12px; }
.countdown-hero .cd-clock { justify-content:center; gap:8px; }
.countdown-hero .cd-num   { font-size:30px; }
.countdown-hero .cd-sep   { font-size:26px; margin-top:1px; }

/* ---- Inline variant: admin status banner --------------------------------- */
.countdown-inline { padding:10px 14px; min-width:210px; }
.countdown-inline .cd-head  { margin-bottom:7px; }
.countdown-inline .cd-note  { display:none; }         /* the banner already states the window */
.countdown-inline .cd-num   { font-size:19px; }
.countdown-inline .cd-sep   { font-size:16px; }
.countdown-inline .cd-unit  { min-width:32px; }
.countdown-inline .cd-cap   { font-size:8.5px; margin-top:3px; }

/* The final five minutes pulse — motion is a redundant cue on top of the
   colour change and the "Voting closes in" label, never the only signal. */
.countdown.is-critical:not(.cd-no-motion) { animation: cd-pulse 1.6s ease-in-out infinite; }
@keyframes cd-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c-danger) 42%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--c-danger) 0%, transparent); }
}

/* On the voter sign-in card the countdown sits inside the glass panel. */
.auth-card .countdown { margin-bottom:18px; }

/* Admin status banner: countdown becomes its own column. */
.status-banner .countdown-inline { flex:0 0 auto; background: color-mix(in srgb, var(--cd-tone) 10%, var(--c-surface)); }

@media (max-width: 600px) {
  .countdown-hero .cd-num { font-size:25px; }
  .countdown-hero .cd-unit { min-width:38px; }
  .status-banner .countdown-inline { width:100%; }
}

@media (prefers-reduced-motion: reduce) {
  .countdown.is-critical { animation: none; }
}

/* The HTML `hidden` attribute is only display:none in the UA stylesheet, so any
   class rule setting display (flex/grid/block) silently defeats it. The
   countdown hides its "ended" message and the days column this way, and both
   stayed visible without this. Global reset — cheap, and prevents the same trap
   anywhere else. */
[hidden] { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   VOTER SIGN-IN
   Split layout: a cinematic visual panel beside a light, focused sign-in card.
   The visual panel plays the ballot-casting clip; all legibility comes from the
   scrim above it, never from the clip itself (which may be paused or missing).
   ═════════════════════════════════════════════════════════════════════════ */
body.voter-auth { background: #eef2f8; }

.voter-auth .auth-wrap { min-height: 100dvh; display: flex; }

/* ---- Visual panel --------------------------------------------------------- */
.voter-auth .auth-visual {
  flex: 1 1 58%;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  background: #041634;          /* shows through before the clip paints */
  color: #fff;
}

/* The clip is IN the flow now, not a background layer, so the quote can sit
   under it. `screen` still dissolves its dark letterbox into the panel, so no
   rectangular frame edge appears. */
.voter-auth .auth-stage {
  display: flex; align-items: center; justify-content: center;
  /* Hugs the clip. Letting it grow only stretched its own backdrop and left
     large empty bands above and below the ballot box. */
  flex: 0 0 auto;
  margin: clamp(10px, 1.8vh, 20px) auto;
  min-height: 0;               /* lets the clip shrink inside a flex column */
  /* mix-blend-mode blends with the nearest stacking context, and
     .auth-visual-inner creates one (z-index). Without a backdrop here the
     clip had nothing to blend into and its black frame stayed black. This
     background IS that backdrop: screen over it returns the same colour, so
     the clip's own frame disappears.
     It cannot match the panel's gradient exactly at every height, so rather
     than leave a faintly mismatched rectangle it is finished as a deliberate
     media panel — rounded, hairline border, soft depth. */
  background: #08183a;
  border-radius: 20px;
  border: 1px solid rgba(255,255,255,.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 18px 44px rgba(0,0,0,.38);
  padding: 6px;
  overflow: hidden;
  width: 100%;
  /* This cap — not the clip's own max-width — is what sets how large the
     ballot box can get, since the clip is sized to 100% of the stage. */
  max-width: 840px;
  align-self: center;
}
.voter-auth .auth-clip {
  display: block;
  width: 100%; max-width: 100%;
  /* The clip is 16:9 and `contain`, so width normally decides the rendered
     height. This ceiling only bites on short, wide windows, where it stops the
     box pushing the quote off-screen. */
  max-height: clamp(300px, 58vh, 620px);
  object-fit: contain;
  mix-blend-mode: screen;
}
.voter-auth .auth-clip-static {
  width: 100%; max-width: 100%; height: clamp(300px, 58vh, 620px);
  background-size: contain; background-position: center; background-repeat: no-repeat;
  mix-blend-mode: normal;
}

/* Gentle vignette only — with the clip in flow there is no longer text sitting
   on top of it, so the heavy left-to-right scrim is no longer needed. */
.voter-auth .auth-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(120% 80% at 50% 42%, rgba(37,99,235,.26), transparent 66%),
    linear-gradient(180deg, rgba(3,12,32,.55) 0%, rgba(3,12,32,.10) 38%, rgba(3,12,32,.62) 100%);
}

.voter-auth .auth-visual-inner {
  position: relative; z-index: 2;
  width: 100%; max-width: 820px;
  display: flex; flex-direction: column; justify-content: space-around;
  /* Centre the stack and let it use the full panel height, so the leftover
     space is shared evenly above and below instead of pooling at the bottom.
     Narrower side padding also keeps the three feature pills on one row. */
  height: 100%;
  padding: clamp(35px, 5.5vh, 70px) clamp(16px, 2vw, 30px);
}

/* Brand mark is still used by the sign-in card on the right. */
.voter-auth .auth-mark {
  flex: 0 0 auto; width: 54px; height: 54px; border-radius: 15px;
  background: #fff; color: var(--c-primary);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 22px rgba(0,0,0,.28); overflow: hidden;
}
.voter-auth .auth-mark img { width: 100%; height: 100%; object-fit: cover; }
.voter-auth .auth-mark .mark-svg { width: 32px; height: 32px; }

/* ---- Headline: one row ---------------------------------------------------
   The three phrases sit on a single line. They stay inline-block so a phrase
   wraps as a unit if the panel is ever too narrow — breaking mid-phrase
   ("Your / Voice.") would read worse than wrapping between them. */
.voter-auth .auth-headline {
  margin: 0 0 clamp(18px, 2.6vh, 30px);
  font-size: clamp(19px, 2.35vw, 34px);
  font-weight: 800; line-height: 1.2; letter-spacing: -.02em;
  text-align: center;
}
.voter-auth .auth-headline span { display: inline-block; margin-right: .34em; }
.voter-auth .auth-headline span:last-child { margin-right: 0; }
.voter-auth .auth-headline b { font-weight: 800; color: #fff; }
.voter-auth .auth-headline i { font-style: normal; color: #C3D2EA; }
.voter-auth .auth-headline em {
  font-style: normal; position: relative;
  color: #3B82F6;
  text-shadow: 0 0 26px rgba(59,130,246,.45);
}
.voter-auth .auth-headline em::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.16em;
  height: 4px; border-radius: 3px;
  background: linear-gradient(90deg, #3B82F6, rgba(59,130,246,0));
}

/* ---- Feature pills -------------------------------------------------------
   Entrance is staggered per pill via --i. On hover a sheen sweeps across and
   the icon lifts — motion that responds to the pointer rather than looping on
   its own, so it reads as polish instead of decoration. */
.voter-auth .auth-points {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
}
.voter-auth .auth-points li {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 18px 10px 10px; border-radius: 999px;
  background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: blur(6px);
  font-size: clamp(13px, .95vw, 15px); font-weight: 600; color: #EAF1FB;
  cursor: default;
  transition: transform .35s var(--e-out), background .35s var(--e-out),
              border-color .35s var(--e-out), box-shadow .35s var(--e-out);
  /* Two animations: the one-off entrance, then a looping zoom that travels
     along the row one pill at a time.
     The pulse deliberately occupies only the first ~22% of the cycle (≈0.7s of
     3.2s) and the offset between pills (0.75s) is slightly longer than that, so
     each pill has finished before the next begins — a clear 1 → 2 → 3 sequence
     rather than three pills breathing together. The remaining ~1s of the cycle
     is a rest before the wave repeats. */
  animation: pt-in .6s var(--e-out) both,
             pt-zoom-stagger 3.2s ease-in-out infinite;
  animation-delay: calc(.25s + var(--i, 0) * .13s), calc(1.1s + var(--i, 0) * .75s);
}
/* Hover cancels the loop so the pointer response is not fighting the keyframe
   for control of `transform`. */
.voter-auth .auth-points li:hover {
  animation: none;
  transform: translateY(-3px) scale(1.04);
  background: rgba(255,255,255,.15);
  border-color: rgba(96,165,250,.55);
  box-shadow: 0 10px 26px rgba(2,10,28,.5), 0 0 0 1px rgba(96,165,250,.18);
}
@keyframes pt-in {
  from { opacity: 0; transform: translateY(14px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes pt-zoom-stagger {
  0%        { transform: scale(1); }
  11%       { transform: scale(1.09); }   /* zoom in  */
  22%       { transform: scale(1); }      /* zoom out */
  100%      { transform: scale(1); }      /* rest, so the next pill is alone */
}

/* Sheen: a highlight that sweeps once across the pill on hover. */
.voter-auth .auth-points li::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.30), transparent);
  transform: skewX(-18deg); opacity: 0;
  transition: left .65s var(--e-out), opacity .2s ease;
}
.voter-auth .auth-points li:hover::before { left: 120%; opacity: 1; }

.voter-auth .auth-points .pt-ico {
  position: relative; z-index: 1; flex: 0 0 auto;
  width: 33px; height: 33px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(96,165,250,.20); color: #93C5FD; font-size: 14px;
  transition: transform .35s var(--e-out), background .35s var(--e-out), color .35s var(--e-out);
}
.voter-auth .auth-points li:hover .pt-ico {
  background: #3B82F6; color: #fff; transform: scale(1.12) rotate(-8deg);
}
/* Slow breathing glow so the row has life before anyone interacts with it. */
.voter-auth .auth-points .pt-ico::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(96,165,250,.45);
  animation: pt-pulse 3.4s ease-out infinite;
  animation-delay: calc(1s + var(--i, 0) * .5s);
}
@keyframes pt-pulse {
  0%       { box-shadow: 0 0 0 0 rgba(96,165,250,.40); }
  55%,100% { box-shadow: 0 0 0 10px rgba(96,165,250,0); }
}

/* ---- Quote: sits below the ballot animation ------------------------------ */
.voter-auth .auth-quote {
  display: flex; align-items: center; gap: 14px; margin: 0; align-self: center;
  padding: 15px 26px 15px 15px; border-radius: 999px;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.13);
  backdrop-filter: blur(6px);
  font-size: clamp(15px, 1.15vw, 18px); font-style: italic; color: #E3EBF7;
  animation: pt-in .6s var(--e-out) both; animation-delay: .75s;
}
.voter-auth .auth-quote .fa {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 50%; font-size: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(251,191,36,.18); color: #FBBF24; font-style: normal;
}

@media (prefers-reduced-motion: reduce) {
  /* All pills now share one keyframe, staggered only by delay, so a single
     selector switches the whole wave off. (The earlier alternating version
     needed :nth-child(even) repeated here to out-specify it — no longer.) */
  .voter-auth .auth-points li,
  .voter-auth .auth-quote { animation: none; transform: none; }
  .voter-auth .auth-points .pt-ico::after { animation: none; box-shadow: none; }
  .voter-auth .auth-points li::before { display: none; }
  .voter-auth .auth-points li:hover { transform: none; }
  .voter-auth .auth-points li:hover .pt-ico { transform: none; }
}

/* ---- Sign-in panel -------------------------------------------------------- */
.voter-auth .auth-form {
  flex: 1 1 46%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: 40px 24px; background: #eef2f8;
}
.voter-auth .auth-card {
  width: 100%; max-width: 430px;
  background: #fff; border-radius: 22px;
  box-shadow: 0 24px 60px rgba(15,23,42,.13), 0 2px 8px rgba(15,23,42,.06);
  padding: clamp(26px, 4vw, 38px);
  animation: auth-rise .5s var(--e-out) both;
}
@keyframes auth-rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

.voter-auth .auth-cardhead { text-align: center; margin-bottom: 22px; }
.voter-auth .auth-mark-lg {
  width: 62px; height: 62px; border-radius: 17px; margin: 0 auto 14px;
  box-shadow: 0 10px 26px rgba(37,99,235,.20);
}
.voter-auth .auth-mark-lg .mark-svg { width: 38px; height: 38px; }
.voter-auth .auth-school { font-size: clamp(22px, 3vw, 27px); font-weight: 800; color: #0f172a; margin: 0 0 4px; line-height: 1.2; overflow-wrap: anywhere; }
.voter-auth .auth-system { font-size: 14.5px; color: #64748b; margin: 0; }
.voter-auth .auth-rule { display: block; width: 54px; height: 4px; border-radius: 2px; margin: 16px auto 0;
               background: linear-gradient(90deg, var(--c-primary), #93b4fb); }

.voter-auth .auth-h2 { font-size: 23px; font-weight: 800; color: #0f172a; text-align: center; margin: 0 0 5px; }
.voter-auth .auth-lead { font-size: 14.5px; color: #64748b; text-align: center; margin: 0 0 20px; }

/* Input with a leading icon well. */
.voter-auth .auth-field { position: relative; display: flex; align-items: stretch; }
.voter-auth .auth-field-icon {
  position: absolute; left: 0; top: 0; bottom: 0; width: 52px;
  display: flex; align-items: center; justify-content: center;
  color: #94a3b8; font-size: 16px; pointer-events: none;
  border-right: 1px solid #e5e7eb;
}
.voter-auth .auth-field .form-control {
  height: 60px; padding: 0 18px 0 68px; width: 100%;
  border-radius: 13px; border: 1.5px solid #e2e8f0; background: #f8fafc;
  font-size: 20px; font-weight: 700; letter-spacing: .16em; text-align: center;
  color: #0f172a; text-transform: uppercase;
}
.voter-auth .auth-field .form-control::placeholder { color: #b6c2d2; font-weight: 600; letter-spacing: .16em; }
.voter-auth .auth-field .form-control:focus {
  border-color: var(--c-primary); background: #fff;
  box-shadow: 0 0 0 4px rgba(37,99,235,.14);
}
.voter-auth .auth-code { font-family: var(--font-num); }

.voter-auth .auth-submit {
  height: 58px; margin-top: 14px; border: 0; border-radius: 13px;
  font-size: 16.5px; font-weight: 700; gap: 10px;
  background: linear-gradient(100deg, #1D4ED8, #2F7BF6 55%, #1D4ED8);
  box-shadow: 0 12px 26px rgba(29,78,216,.30);
}
.voter-auth .auth-submit:hover, .voter-auth .auth-submit:focus {
  background: linear-gradient(100deg, #1A44BE, #2A6FE0 55%, #1A44BE);
  box-shadow: 0 16px 32px rgba(29,78,216,.38);
}
.voter-auth .auth-submit-go { margin-left: 4px; transition: transform var(--t-fast); }
.voter-auth .auth-submit:hover .auth-submit-go { transform: translateX(4px); }

.voter-auth .auth-hint {
  display: flex; align-items: flex-start; gap: 10px; margin: 18px 0 0;
  padding: 13px 15px; border-radius: 12px;
  background: #eff4ff; border: 1px solid #dbe6fe;
  font-size: 13px; line-height: 1.55; color: #3f5878;
}
.voter-auth .auth-hint .fa { color: var(--c-primary); margin-top: 2px; flex: 0 0 auto; }

.voter-auth .auth-trust {
  margin: 18px 0 0; padding-top: 16px; border-top: 1px solid #eef1f6;
  text-align: center; font-size: 13px; font-weight: 600; color: #64748b;
}
.voter-auth .auth-trust .fa { color: var(--c-primary); margin-right: 4px; }
.voter-auth .auth-trust span { margin: 0 7px; color: #cbd5e1; }

.voter-auth .auth-copy { margin: 0; font-size: 12.5px; color: #8496ad; text-align: center; }

/* Alerts inside the card stay compact and left-aligned for readability. */
.voter-auth .auth-card .alert { border-radius: 12px; font-size: 13.5px; padding: 12px 14px; margin-bottom: 16px; text-align: left; }

/* ---- Responsive ----------------------------------------------------------- */
@media (max-width: 991px) {
  .voter-auth .auth-wrap { flex-direction: column; }
  /* Keep the animation, just as a shorter banner above the card. */
  .voter-auth .auth-visual { flex: 0 0 auto; min-height: 44vh; }
  .voter-auth .auth-visual-inner { max-width: none; padding: 32px 24px; height: auto; justify-content: center; }
  .voter-auth .auth-brandbar { margin-bottom: 26px; }
  .voter-auth .auth-points { margin-bottom: 22px; }
  .voter-auth .auth-form { flex: 1 1 auto; padding: 28px 20px 34px; }
}
@media (max-width: 600px) {
  .voter-auth .auth-visual { min-height: 300px; }
  .voter-auth .auth-headline { font-size: 31px; }
  .voter-auth .auth-blurb { font-size: 15px; max-width: none; }
  /* Below this width the pills wrap awkwardly and push the card off-screen. */
  .voter-auth .auth-points li { font-size: 13px; padding: 7px 14px 7px 7px; }
  .voter-auth .auth-quote { font-size: 13px; }
  .voter-auth .auth-field .form-control { height: 56px; font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .voter-auth .auth-card { animation: none; }
  .voter-auth .auth-submit:hover .auth-submit-go { transform: none; }
}

/* ---- Admin auth screens in dark mode --------------------------------------
   admin/index.php and change_password.php use the original .auth-card, which
   hardcodes a white background. Once the admin area defaulted to dark, those
   cards kept the white surface while inheriting the dark theme's light ink —
   near-invisible text on white. The card follows the theme instead.
   Scoped to [data-theme="dark"], so the voter sign-in (always light) is
   untouched. --------------------------------------------------------------- */
[data-theme="dark"] .auth-form { background: var(--c-bg); }
[data-theme="dark"] .auth-card {
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  color: var(--c-ink);
}
[data-theme="dark"] .auth-card h2,
[data-theme="dark"] .auth-card .school { color: var(--c-ink); }
[data-theme="dark"] .auth-card .auth-lead,
[data-theme="dark"] .auth-card .text-muted { color: var(--c-ink-soft); }
[data-theme="dark"] .auth-card label { color: #C7D6EA; }
[data-theme="dark"] .auth-card .pw-toggle { color: var(--c-ink-soft); }
[data-theme="dark"] .auth-card .pw-toggle:hover { color: var(--c-accent); }
