:root {
  color-scheme: dark;
}

/* ── GLOBAL THEME ── */
body {
  background: #0a1628 !important;
  background-image:
    radial-gradient(ellipse 1000px 600px at 20% 10%, rgba(56, 100, 180, 0.35) 0%, transparent 60%),
    radial-gradient(ellipse 800px 500px at 80% 90%, rgba(30, 60, 140, 0.25) 0%, transparent 60%),
    radial-gradient(ellipse 600px 400px at 60% 40%, rgba(20, 80, 120, 0.15) 0%, transparent 55%) !important;
  background-attachment: fixed !important;
  color: white;
  font-family: 'Inter', sans-serif;
  margin: 0;
  -webkit-font-smoothing: antialiased;
}

/* ── PAGE LAYOUT ── */
.bv-page {
  padding: 40px;
  min-height: 100vh;
  box-sizing: border-box;
}

.bv-auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

.bv-dashboard-layout {
  display: flex;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  position: relative;
  z-index: 10;
}

.bv-main-content {
  flex-grow: 1;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  background: transparent;
}

.bv-page-header {
  margin-bottom: 32px;
}

.bv-page-header h1 {
  color: white;
  font-size: 2rem;
  font-weight: 900;
  margin: 0 0 8px 0;
  letter-spacing: -0.02em;
}

.bv-page-header p {
  color: rgba(255,255,255,0.4);
  margin: 0;
  font-size: 14px;
}

/* ── GRID LAYOUTS ── */
.bv-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.bv-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 24px; }
.bv-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.bv-grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }

.bv-hamburger { display: block; }
@media (min-width: 1024px) {
  .bv-hamburger { display: none !important; }
}

/* ── TRUE FROSTED GLASS CARDS ── */
.bv-card, .glass-card, .glass-panel, .bv-card--lg {
  background: rgba(255, 255, 255, 0.085) !important;
  /* No backdrop-filter: this cost one compositor layer PER CARD, and the
     backdrop is an 80px-blurred gradient with no detail left to frost. */
  border: 1px solid rgba(255, 255, 255, 0.10) !important;
  border-top: 1px solid rgba(255, 255, 255, 0.18) !important;
  border-radius: 16px !important;
  box-shadow: 0 8px 32px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.08) !important;
  transition: transform 0.2s, border-color 0.2s;
}

.bv-card--accent {
  border-top: 2px solid rgba(255, 180, 0, 0.4) !important;
}

.bv-minimal-card {
  width: 400px;
  padding: 48px 40px;
  background: rgba(255, 255, 255, 0.03) !important;
  backdrop-filter: blur(32px) saturate(200%) !important;
  -webkit-backdrop-filter: blur(32px) saturate(200%) !important;
  border: 1px solid rgba(255, 255, 255, 0.06) !important;
  border-top: 1px solid rgba(255, 255, 255, 0.12) !important;
  border-radius: 20px !important;
  box-shadow: 0 32px 64px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.08) !important;
  box-sizing: border-box;
}

.bv-login-logo-container {
  text-align: center;
  margin-bottom: 20px;
}

.bv-login-logo {
  height: 44px;
  width: auto;
  display: inline-block;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

.bv-login-title {
  font-size: 22px;
  font-weight: 700;
  color: white;
  text-align: center;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
  margin-top: 20px;
}

.bv-login-subtitle {
  font-size: 10px;
  letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.3);
  text-align: center;
  margin-bottom: 32px;
  text-transform: uppercase;
  font-weight: 700;
}

.bv-login-form-group {
  margin-bottom: 16px;
}

.bv-login-form-group--password {
  margin-bottom: 20px;
}

.bv-card__body {
  padding: 2rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.bv-card__header {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.bv-card__icon {
  width: 52px;
  height: 52px;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.2);
  color: rgba(255, 180, 0, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  border-radius: 8px;
  flex-shrink: 0;
}

/* ── Inline Icon Helpers ──────────────────────────────────────────
   Tailwind emits no utilities in this build (v3 directives in app.css
   under the v4 vite plugin), so mr-2 / text-xs / text-4xl are inert.
   Icons that sit inline with text use these instead. Colour helpers
   exist because the CSP has no style-src-attr, which drops style="".
   Flex containers (.bv-nav-item, .bv-btn) already space their icons
   with `gap` — do not add --lead there.                            */
.bv-icon--lead   { margin-right: 0.5rem; }
.bv-icon--trail  { margin-left: 0.5rem; }
.bv-icon--sm     { font-size: 0.75rem; }
.bv-icon--lg     { font-size: 1.25rem; }
.bv-icon--xl     { font-size: 2rem; }
.bv-icon--2xl    { font-size: 3rem; }
.bv-icon--muted  { opacity: 0.35; }
.bv-icon--gold   { color: #FFB400; }
.bv-icon--green  { color: #22c55e; }
.bv-icon--red    { color: #ef4444; }
.bv-icon--blue   { color: #3b82f6; }
.bv-icon--indigo { color: #6366f1; }
.bv-icon--amber  { color: #f59e0b; }

/* Card icon size + colour variants (were inline styles the CSP now drops). */
.bv-card__icon--sm { width: 32px; height: 32px; font-size: 0.75rem; border: none; }
.bv-card__icon--blue  { background: rgba(59,130,246,0.15);  border-color: rgba(59,130,246,0.3);  color: #3b82f6; }
.bv-card__icon--green { background: rgba(34,197,94,0.15);   border-color: rgba(34,197,94,0.3);   color: #22c55e; }
.bv-card__icon--red   { background: rgba(239,68,68,0.15);   border-color: rgba(239,68,68,0.3);   color: #ef4444; }
.bv-card__icon--amber { background: rgba(245,158,11,0.15); border-color: rgba(245,158,11,0.3); color: #f59e0b; }
.bv-card__icon--crimson { background: rgba(153,27,27,0.18);  border-color: rgba(153,27,27,0.4);   color: #dc2626; }

.bv-card__meta {
  font-size: 11px;
  font-weight: 800;
  color: rgba(255,255,255,0.3);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  margin: 0 0 4px 0;
}

.bv-card__title {
  font-size: 18px;
  font-weight: 700;
  color: rgba(255,255,255,0.9);
  margin: 0;
}

.bv-card__stat {
  font-size: 1.1rem;
  font-weight: 600;
  color: white;
  margin-bottom: 8px;
}

.bv-card__desc {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.7;
  margin: 0;
}

.bv-card__actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── BUTTONS ── */
.bv-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 14px 20px;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  transition: all 0.2s;
  width: 100%;
  text-align: center;
}

.bv-btn--primary, .primary-yellow-btn {
  width: 100% !important;
  padding: 13px 20px !important;
  background: rgba(59, 130, 246, 0.2) !important;
  border: 1px solid rgba(100, 150, 255, 0.3) !important;
  color: white !important;
  backdrop-filter: blur(8px) !important;
  border-radius: 10px !important;
  font-weight: 700 !important;
  letter-spacing: 0.12em !important;
  text-transform: uppercase !important;
  text-align: center !important;
  cursor: pointer !important;
  /* flex, not block. `.bv-btn` sets `gap: 8px` to space an icon from its
     label, and gap only applies to a flex or grid container — `display: block`
     made it inert, so the icon sat flush against the first letter on all 16
     icon-bearing primary buttons ("VERIFY CHAIN INTEGRITY", "Execute Batch
     Import", "Add Candidate", …). align-items/justify-content are repeated
     here rather than inherited from `.bv-btn` so the rule does not depend on
     that class also being present. Width is untouched: ~20 views rely on
     `width: 100%`. */
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  margin-bottom: 12px !important;
}

.bv-btn--primary:hover, .primary-yellow-btn:hover {
  background: rgba(59, 130, 246, 0.4) !important;
  border-color: rgba(100, 150, 255, 0.5) !important;
}

.bv-btn--google {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 13px;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
  box-sizing: border-box;
}

.bv-btn--google:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.15);
}

.bv-btn--logout {
  background: transparent !important;
  border: none !important;
  color: rgba(255, 255, 255, 0.25) !important;
  padding: 10px 16px !important;
  font-size: 12px !important;
  font-weight: 600 !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
  display: flex !important;
  align-items: center !important;
  gap: 8px !important;
  cursor: pointer !important;
  transition: color 0.2s !important;
  text-decoration: none !important;
  width: 100% !important;
  justify-content: center !important;
}

.bv-btn--logout:hover {
  background: transparent !important;
  color: #ef4444 !important;
}

.bv-btn--secondary {
  background: transparent;
  color: rgba(255,255,255,0.4);
  padding: 10px;
}

.bv-btn--secondary:hover {
  color: white;
}

.bv-btn--danger {
  background: rgba(239, 68, 68, 0.1);
  border: 1px solid rgba(239, 68, 68, 0.3);
  color: #ef4444;
}

.bv-btn--danger:hover {
  background: rgba(239, 68, 68, 0.2);
}

.bv-btn--signout {
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.2);
  color: rgba(239, 68, 68, 0.6);
  border-radius: 8px;
  padding: 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  cursor: pointer;
  transition: all 0.2s;
  text-decoration: none;
}
.bv-btn--signout:hover {
  background: rgba(239, 68, 68, 0.15);
  border-color: rgba(239, 68, 68, 0.4);
  color: #ef4444;
}

.bv-btn--ghost {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
  color: rgba(255,255,255,0.7);
}

/* ── BADGES ── */
.bv-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.bv-badge--green {
  background: rgba(34, 197, 94, 0.2) !important;
  border: 1px solid rgba(34, 197, 94, 0.4) !important;
  color: #22c55e !important;
}

.bv-badge--gold {
  background: rgba(255, 180, 0, 0.2) !important;
  border: 1px solid rgba(255, 180, 0, 0.4) !important;
  color: #FFB400 !important;
}

.bv-badge--red {
  background: rgba(239, 68, 68, 0.15) !important;
  border: 1px solid rgba(239, 68, 68, 0.3) !important;
  color: #ef4444 !important;
}

/* Full-width alert banner (login / dashboard flash messages) */
.bv-alert {
  width: 100%;
  padding: 14px 16px;
  border-radius: 8px;
  text-align: left;
  box-sizing: border-box;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
}

.bv-alert--green {
  background: rgba(34, 197, 94, 0.15);
  border: 1px solid rgba(34, 197, 94, 0.35);
  color: #22c55e;
}

.bv-alert--red {
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.3);
  color: #ef4444;
}

.bv-badge--amber {
  background: rgba(245, 158, 11, 0.15);
  border: 1px solid rgba(245, 158, 11, 0.4);
  color: #F59E0B;
}

.bv-badge--outline {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.4);
}

.bv-badge--vote-cast {
  background: rgba(34, 197, 94, 0.12) !important;
  border: 1px solid rgba(34, 197, 94, 0.3) !important;
  color: #22c55e !important;
  padding: 4px 14px !important;
  border-radius: 999px !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  white-space: nowrap !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 5px !important;
  width: auto !important;
  max-width: fit-content !important;
}

.bv-badge--ballot-cast {
  white-space: nowrap !important;
  padding: 4px 12px !important;
  border-radius: 999px !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  background: rgba(255, 180, 0, 0.12) !important;
  border: 1px solid rgba(255, 180, 0, 0.3) !important;
  color: #FFB400 !important;
  display: inline-block !important;
  width: auto !important;
}

.bv-badge--active {
  background: rgba(34, 197, 94, 0.15) !important;
  border: 1px solid rgba(34, 197, 94, 0.4) !important;
  color: #22c55e !important;
  padding: 4px 12px !important;
  border-radius: 999px !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  display: inline-block !important;
  width: auto !important;
}

/* ── CANDIDATE BALLOT CARDS ── */
.bv-candidate-card {
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.10) !important;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.15s !important;
}

.bv-candidate-card:hover {
  border-color: rgba(255, 180, 0, 0.3) !important;
}

/* Selection ring indicator */
.bv-candidate-card__selector {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid rgba(255, 180, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: border-color 0.2s;
}

/* Hide native inputs robustly */
input.peer.hidden {
  opacity: 0 !important;
  position: absolute !important;
  width: 0 !important;
  height: 0 !important;
  pointer-events: none !important;
}


.bv-candidate-card__selector-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #FFB400;
  opacity: 0;
  transform: scale(0);
  transition: opacity 0.2s, transform 0.2s;
}

/* Gold bottom bar — hidden by default */
.bv-candidate-card__bar {
  height: 3px;
  background: #FFB400;
  border-radius: 99px;
  margin-top: 16px;
  width: 0%;
  transition: width 0.3s ease-in-out;
  box-shadow: 0 0 8px rgba(255, 180, 0, 0.4);
}

/* Selected state — driven by peer checkbox */
label:has(input:checked) .bv-candidate-card {
  border-color: #FFB400 !important;
  background: rgba(255, 180, 0, 0.05) !important;
  box-shadow: 0 0 24px rgba(255, 180, 0, 0.12) !important;
}

label:has(input:checked) .bv-candidate-card__selector {
  border-color: #FFB400;
}

label:has(input:checked) .bv-candidate-card__selector-dot {
  opacity: 1;
  transform: scale(1);
}

label:has(input:checked) .bv-candidate-card__bar {
  width: 100%;
}

/* ── AVATAR ── */
.bv-avatar {
  width: 36px !important;
  height: 36px !important;
  min-width: 36px !important;
  min-height: 36px !important;
  border-radius: 50% !important;
  aspect-ratio: 1 / 1 !important;
  background: rgba(255, 180, 0, 0.05);
  border: 1px solid rgba(255, 180, 0, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 180, 0, 0.6);
  flex-shrink: 0;
}

.bv-avatar--lg {
  width: 52px;
  height: 52px;
  font-size: 16px;
}

/* ── INPUTS ── */
input, textarea, select, .bv-input {
  width: 100%;
  background: rgba(255, 255, 255, 0.03) !important;
  border: 1px solid rgba(255, 255, 255, 0.07) !important;
  border-radius: 10px !important;
  color: white !important;
  padding: 12px 16px !important;
  font-size: 14px;
  color-scheme: dark !important;
  transition: border-color 0.2s, box-shadow 0.2s !important;
  box-sizing: border-box;
}

input:focus, textarea:focus, select:focus, .bv-input:focus {
  outline: none !important;
  border-color: rgba(100, 150, 255, 0.4) !important;
  box-shadow: 0 0 0 3px rgba(100, 150, 255, 0.08) !important;
}

.bv-input::placeholder {
  color: rgba(255, 255, 255, 0.2);
}

.bv-label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.35);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  margin-bottom: 6px;
}

/* ── TABLE ── */
.bv-table {
  width: 100%;
  border-collapse: collapse;
}

.bv-table th {
  color: rgba(255, 255, 255, 0.25) !important;
  font-size: 10px !important;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.15em !important;
  padding: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  text-align: left;
}

.bv-table td {
  padding: 16px;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  border-bottom: 1px solid rgba(255, 255, 255, 0.03);
}

.bv-table tr:hover td {
  background: rgba(255, 255, 255, 0.01);
}

/* ── STATUS DOT ── */
.bv-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}

.bv-dot--green {
  background: #22c55e;
  animation: bv-pulse 2s infinite;
}

.bv-dot--gold {
  background: #FFB400;
  animation: bv-pulse 2s infinite;
}

/* ── SECTION ── */
.bv-audit-section {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.bv-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

.bv-profile-header {
  margin-bottom: 24px;
}

.bv-profile-avatar-label {
    display: block;
    cursor: pointer;
    overflow: hidden;
    border-radius: 50%;
    transition: transform 0.3s;
    border: 2px solid #FFB400;
    box-shadow: 0 10px 30px rgba(0,0,0,0.4);
    width: 80px;
    height: 80px;
    margin: 0;
    position: relative;
    outline: none !important;
}

.bv-profile-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 50%;
}

.bv-profile-avatar-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 2rem;
    color: #FFB400;
    background: rgba(255, 180, 0, 0.1);
}

.bv-avatar-trigger {
    position: absolute;
    bottom: 0;
    right: 0;
    background: #FFB400;
    color: #0a1628;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    border: 2px solid #0a1628;
    box-shadow: 0 2px 10px rgba(0,0,0,0.4);
    z-index: 5;
}

@media (max-width: 1023px) {
    .bv-profile-avatar-label {
        width: 64px;
        height: 64px;
    }
    .bv-profile-avatar-placeholder {
        font-size: 1.5rem;
    }
    .bv-avatar-trigger {
        width: 20px;
        height: 20px;
        font-size: 8px;
    }
}

.bv-profile-grid {
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 20px;
  align-items: start;
}

.bv-section {
  margin-bottom: 40px;
}

.bv-section__heading, .bv-section-heading {
  color: rgba(255, 255, 255, 0.5) !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  text-transform: uppercase;
  letter-spacing: 0.15em !important;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.bv-page-title {
  color: #FFB400 !important;
  font-size: 1.4rem !important;
  font-weight: 800 !important;
  letter-spacing: 0.05em !important;
  text-transform: uppercase !important;
  margin: 0 0 8px 0;
}

.bv-page-heading {
  font-size: 1.8rem;
  font-weight: 800;
  color: white;
  letter-spacing: -0.02em;
  margin: 0 0 6px 0;
}

.bv-page-subheading {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.4);
  margin: 0 0 24px 0;
  font-weight: 400;
}

.bv-btn--verify {
  background: rgba(59, 130, 246, 0.2);
  border: 1px solid rgba(100, 150, 255, 0.3);
  color: white;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 12px 24px;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.bv-btn--verify:hover {
  background: rgba(59, 130, 246, 0.35);
  border-color: rgba(100, 150, 255, 0.5);
  box-shadow: 0 0 16px rgba(59, 130, 246, 0.2);
}

.bv-divider {
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  margin: 24px 0;
}

.bv-login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 24px 0;
}

.bv-login-divider-line {
  flex: 1;
  height: 1px;
  background: rgba(255, 255, 255, 0.06);
}

.bv-login-divider-text {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.25);
  letter-spacing: 0.1em;
  font-weight: 700;
}

.bv-login-footer {
  text-align: center;
  font-size: 9px;
  letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.2);
  margin-top: 32px;
  text-transform: uppercase;
  font-weight: 700;
}

/* ── HASH / MONO ── */
.bv-hash {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.3);
}

/* ── BRANDING ── */
.bv-logo-container {
  background: transparent !important;
  border: none !important;
  padding: 0;
  margin-bottom: 24px;
  display: inline-block;
}

.bv-logo, .login-logo {
  height: 40px !important;
  width: auto !important;
  display: block !important;
  margin: 0 auto !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
}

/* ── DASHBOARD UI ── */
.bv-sidebar {
  width: 268px;
  flex-shrink: 0;
  background: rgba(7, 14, 38, 0.92) !important;
  /* No backdrop-filter: at 82% opaque it frosted only ~18% of each pixel,
     yet every hover repaint inside re-blurred this whole 268px column. */
  border-right: 1px solid rgba(255, 255, 255, 0.06) !important;
  display: flex;
  flex-direction: column;
  height: 100%;
  z-index: 50;
}

/* Header */
.bv-sidebar__header {
  padding: 1.5rem 1.5rem 1.25rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.bv-sidebar__brand {
  font-size: 1.15rem;
  font-weight: 800;
  color: #ffffff;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  letter-spacing: -0.01em;
  transition: opacity 0.2s;
}

.bv-sidebar__brand:hover { opacity: 0.85; }

.bv-sidebar__brand-icon {
  font-size: 1.3rem;
  line-height: 1;
}

/* Wordmark: one flex item, so "Bee" and "ote" are not pushed apart by the
   parent's gap. The V is gold and tilted; inline-block is required because
   transforms do not apply to inline boxes. */
.bv-sidebar__wordmark {
  display: inline-block;
  white-space: nowrap;
}

.bv-sidebar__brand-v {
  display: inline-block;
  color: #FFB400;
  font-weight: 900;
  transform: rotate(-8deg);
  transform-origin: 50% 65%;
}

/* User Card */
.bv-sidebar__user {
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  background: rgba(255, 255, 255, 0.02);
}

.bv-sidebar__avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 180, 0, 0.6);
  flex-shrink: 0;
}

.bv-sidebar__avatar-placeholder {
  width: 38px !important;
  height: 38px !important;
  flex-shrink: 0;
}

.bv-sidebar__user-info {
  flex: 1;
  min-width: 0;
}

.bv-sidebar__user-name {
  font-size: 0.85rem;
  font-weight: 700;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}

.bv-sidebar__user-role {
  margin-top: 4px;
}

.bv-sidebar__role-badge {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 20px;
}

.bv-sidebar__role-badge--admin    { background: rgba(255,80,80,0.15);  color: #ff6b6b; border: 1px solid rgba(255,80,80,0.25); }
.bv-sidebar__role-badge--comelec  { background: rgba(255,180,0,0.15);  color: #FFB400; border: 1px solid rgba(255,180,0,0.25); }
.bv-sidebar__role-badge--voter    { background: rgba(80,160,255,0.15); color: #64a8ff; border: 1px solid rgba(80,160,255,0.25); }
.bv-sidebar__role-badge--judge    { background: rgba(150,80,255,0.15); color: #b87eff; border: 1px solid rgba(150,80,255,0.25); }
.bv-sidebar__role-badge--organizer { background: rgba(0,200,150,0.15); color: #2dd4a8; border: 1px solid rgba(0,200,150,0.25); }

/* Nav */
.bv-sidebar__nav {
  padding: 0.5rem 0 1rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.08) transparent;
}

.bv-sidebar__nav::-webkit-scrollbar { width: 4px; }
.bv-sidebar__nav::-webkit-scrollbar-track { background: transparent; }
.bv-sidebar__nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 4px; }

/* Section Labels */
.bv-sidebar__section-label {
  padding: 1.1rem 1.5rem 0.35rem;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.22);
}

/* Nav Items */
.bv-nav-item {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.65rem 1.25rem 0.65rem 1.5rem;
  color: rgba(255, 255, 255, 0.45);
  text-decoration: none;
  transition: background-color 0.18s ease, color 0.18s ease, border-left-color 0.18s ease;
  font-weight: 500;
  font-size: 0.875rem;
  border-left: 3px solid transparent;
  border-radius: 0 8px 8px 0;
  margin: 1px 0.75rem 1px 0;
  position: relative;
}

.bv-nav-item__icon {
  font-size: 1rem;
  width: 22px;
  text-align: center;
  flex-shrink: 0;
  opacity: 0.55;
  transition: opacity 0.18s ease;
}

.bv-nav-item:hover {
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.05);
  border-left-color: rgba(255, 255, 255, 0.15);
}

.bv-nav-item:hover .bv-nav-item__icon {
  opacity: 0.85;
}

.bv-nav-item--active {
  background: rgba(255, 180, 0, 0.1) !important;
  color: #FFB400 !important;
  border-left: 3px solid #FFB400 !important;
  font-weight: 600;
}

.bv-nav-item--active .bv-nav-item__icon {
  opacity: 1;
}

/* Footer / Logout */
.bv-sidebar__footer {
  padding: 1rem 0.75rem 1.25rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  padding-left: 0;
}

.bv-sidebar__logout {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.65rem 1.25rem 0.65rem 1.5rem;
  width: 100%;
  background: none;
  border: none;
  border-left: 3px solid transparent;
  border-radius: 0 8px 8px 0;
  color: rgba(255, 255, 255, 0.4);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease, border-left-color 0.18s ease;
  text-align: left;
  margin-right: 0.75rem;
}

.bv-sidebar__logout:hover {
  color: #ff6b6b;
  background: rgba(255, 80, 80, 0.08);
  border-left-color: rgba(255, 80, 80, 0.4);
}

/* ── PUBLIC ANCHORS ── */
.bv-public-anchors {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 12px;
  padding: 24px 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 80px;
}

.bv-public-anchors__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #FFB400;
  flex-shrink: 0;
  animation: bv-pulse 1.5s infinite;
}

.bv-public-anchors__text {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.35);
  text-transform: uppercase;
}

.bv-section-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.3);
  text-transform: uppercase;
  margin-bottom: 10px;
}

.bv-topbar {
  min-height: 70px;
  padding: 20px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(6, 13, 26, 0.78) !important;
  /* No backdrop-filter: same trap as the sidebar - a hover repaint inside a
     blurred surface re-blurs the entire surface, every frame of it. */
  border-bottom: 1px solid rgba(255, 255, 255, 0.05) !important;
  position: sticky;
  top: 0;
  z-index: 100;
}

.bv-topbar__title {
  font-size: 1.1rem;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.8);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.bv-topbar-title {
  font-size: 1.5rem;
  font-weight: 800;
  color: #FFB400;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 0;
  line-height: 1;
}

/* The drawer used to be declared twice: once here at max-width:1024px (280px,
   no !important) and again at max-width:1023px (80%/300px, !important). At
   exactly 1024px this block AND the min-width:1024px desktop block both
   matched, so the sidebar became a fixed overlay that was simultaneously
   forced visible — it covered the page. The 1023px block is the authoritative
   one; this duplicate is removed rather than left to fight with it. */

@keyframes bv-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.8); }
}

@keyframes bv-simulation-pulse {
  0% { transform: scale(1); opacity: 0.5; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ── ANIMATIONS ── */
.animate-slide-up {
  animation: slideUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── CUSTOM SCROLLBAR ── */
::-webkit-scrollbar {
  width: 4px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.2);
}

/* ── SELECT DROPDOWNS ── */
select.bv-input,
select.form-control,
select {
    background: rgba(15, 25, 50, 0.9) !important;
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    color: white !important;
    border-radius: 8px !important;
    padding: 10px 14px !important;
    color-scheme: dark !important;
    appearance: auto !important;
    cursor: pointer !important;
}

select.bv-input:focus,
select.form-control:focus,
select:focus {
    border-color: rgba(100, 150, 255, 0.4) !important;
    outline: none !important;
}

/* Force dark dropdown options */
select option {
    background: #0f1932 !important;
    color: white !important;
    padding: 8px !important;
}

select option:hover,
select option:checked {
    background: rgba(59, 130, 246, 0.3) !important;
    color: white !important;
}

/* ── GLOBALLY ADDED FIXES ── */
.bv-empty-state {
    text-align: center;
    margin-top: 40px;
    padding: 40px;
    background: rgba(255, 255, 255, 0.02);
    border-radius: 12px;
    border: 1px dashed rgba(255, 255, 255, 0.1);
}

.bv-empty-state p {
    color: rgba(255, 255, 255, 0.4);
    margin-bottom: 16px;
}

.bv-btn--create {
    width: auto;
    align-self: flex-start;
    padding: 12px 24px;
    background: rgba(59, 130, 246, 0.2);
    border: 1px solid rgba(100, 150, 255, 0.3);
    color: white;
    border-radius: 8px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.08em;
}

.bv-stat--critical { color: #ef4444; }
.bv-stat--warning  { color: #f59e0b; }
.bv-stat--normal   { color: white; }

.bv-error-context {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 600px;
}

/* ── MOBILE RESPONSIVENESS ── */
@media (max-width: 1023px) {
    .bv-page {
        padding: 20px !important;
    }

    .bv-page-header h1 {
        font-size: 1.5rem !important;
    }

    /* Grid Fixes */
    .bv-grid-2, .bv-grid-3, .bv-grid-4, .bv-stat-grid, .bv-profile-grid {
        grid-template-columns: 1fr !important;
        gap: 16px !important;
    }

    /* Small Stats can keep 2 columns if specifically needed, but default to 1 for safety */
    .bv-stat-grid {
        grid-template-columns: repeat(2, 1fr) !important;
    }

    /* Sidebar Drawer Fix */
    .bv-sidebar {
        position: fixed !important;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 10000 !important;
        height: 100vh !important;
        width: 80% !important;
        max-width: 300px !important;
        box-shadow: 20px 0 60px rgba(0,0,0,0.8) !important;
        transform: translateX(-100%);
        transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important;
        display: flex !important;
    }

    .bv-sidebar.open {
        transform: translateX(0) !important;
    }

    /* Table Responsiveness */
    .bv-table-container {
        width: 100%;
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
        margin-bottom: 1rem;
        background: rgba(255, 255, 255, 0.02);
        border-radius: 8px;
        position: relative;
    }

    .bv-table {
        min-width: 600px !important; /* Force scroll on small screens */
    }

    .bv-table th, .bv-table td {
        padding: 12px 10px !important;
        font-size: 11px !important;
    }

    /* Ellipsis for long names */
    .truncate-mobile {
        max-width: 120px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
    }

    /* Badge scaling */
    .bv-badge {
        font-size: 9px !important;
        padding: 2px 6px !important;
    }

    /* Card Padding */
    .bv-card__body {
        padding: 1rem !important;
    }

    .bv-hash {
        word-break: break-all;
        white-space: normal;
        font-size: 9px;
        color: rgba(255,255,255,0.4);
    }
    
    .mobile-hidden {
        display: none !important;
    }
}

@media (min-width: 1024px) {
    .bv-hamburger {
        display: none !important;
    }
    
    .bv-sidebar {
        transform: translateX(0) !important;
        position: relative !important;
        display: flex !important;
    }
}

/* ── PAGINATION STYLING ── */
.pagination, [role="navigation"] nav {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 16px;
}

.pagination .page-item, [role="navigation"] nav a, [role="navigation"] nav span {
    background: rgba(255, 255, 255, 0.05) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: rgba(255, 255, 255, 0.6) !important;
    padding: 8px 14px !important;
    border-radius: 8px !important;
    font-size: 13px !important;
    font-weight: 700 !important;
    text-decoration: none !important;
    transition: all 0.2s !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    min-width: 40px !important;
}

.pagination .page-item:hover, [role="navigation"] nav a:hover {
    background: rgba(255, 255, 255, 0.1) !important;
    border-color: rgba(255, 255, 255, 0.2) !important;
    color: white !important;
}

.pagination .page-item.active, [role="navigation"] nav span[aria-current="page"], [role="navigation"] nav .bg-blue-600 {
    background: #FFB400 !important;
    border-color: #FFB400 !important;
    color: #0D1117 !important;
    box-shadow: 0 0 15px rgba(255, 180, 0, 0.3) !important;
}

.pagination .page-item.disabled, [role="navigation"] nav span[aria-disabled="true"] {
    opacity: 0.3 !important;
    cursor: not-allowed !important;
}

[role="navigation"] nav svg {
    width: 16px !important;
    height: 16px !important;
}

/* ── ADDITIONAL PAGINATION SELECTORS ── */
nav[role="navigation"] a, 
nav[role="navigation"] span,
.pagination li a, 
.pagination li span {
    background: rgba(255, 255, 255, 0.05) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: rgba(255, 255, 255, 0.6) !important;
    padding: 8px 14px !important;
    border-radius: 8px !important;
    font-size: 13px !important;
    font-weight: 700 !important;
    text-decoration: none !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    min-width: 40px !important;
    margin: 0 4px !important;
}

nav[role="navigation"] a:hover {
    background: rgba(255, 255, 255, 0.1) !important;
    color: white !important;
}

nav[role="navigation"] .active span,
nav[role="navigation"] span[aria-current="page"],
nav[role="navigation"] .bg-blue-600 {
    background: #FFB400 !important;
    border-color: #FFB400 !important;
    color: #0D1117 !important;
}

/* Secondary Button Styling (Used in Errors Pagination) */
.bv-btn--secondary {
    background: rgba(255, 255, 255, 0.05) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: rgba(255, 255, 255, 0.8) !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.1em !important;
    font-size: 11px !important;
    transition: all 0.3s !important;
}

.bv-btn--secondary:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.1) !important;
    border-color: rgba(255, 255, 255, 0.2) !important;
    color: white !important;
    transform: translateY(-1px) !important;
}

[role="navigation"] div p, 
.bv-table-pagination-meta {
    color: rgba(255, 255, 255, 0.4) !important;
    font-size: 11px !important;
    font-weight: 500 !important;
    letter-spacing: 0.05em !important;
    margin: 8px 0 !important;
}

[role="navigation"] div p span,
.bv-table-pagination-meta span {
    color: white !important;
    font-weight: 700 !important;
}

/* ── PROFILE PAGE COMPONENTS ──────────────────────────────────────
   Class-based on purpose. This CSP sets style-src with a nonce and
   no style-src-attr, so inline style="" attributes are dropped by
   the browser — overlays, modals and "hidden" inputs cannot rely on
   them. Anything positional or state-bearing lives here instead.   */

/* Verified banner under the profile header */
.bv-verified-banner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.25rem;
  margin-bottom: 24px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(255, 255, 255, 0.03);
  border-radius: 12px;
}
.bv-verified-banner > i { color: #FFB400; font-size: 0.95rem; }
.bv-verified-banner__label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}

/* Avatar with an always-visible upload affordance */
.bv-avatar-upload {
  position: relative;
  display: inline-block;
  line-height: 0;
  cursor: pointer;
}
.bv-avatar-upload__img,
.bv-avatar-upload__initials {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  border: 2px solid rgba(255, 180, 0, 0.5);
  object-fit: cover;
}
.bv-avatar-upload__initials {
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 180, 0, 0.15);
  color: #FFB400;
  font-size: 22px;
  font-weight: 800;
  line-height: 1;
}
.bv-avatar-upload__overlay {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: rgba(7, 14, 38, 0.66);
  color: #FFB400;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
  opacity: 0.92;
  transition: opacity 0.2s ease, background 0.2s ease;
}
.bv-avatar-upload:hover .bv-avatar-upload__overlay {
  opacity: 1;
  background: rgba(7, 14, 38, 0.82);
}

/* The file input must be hidden by a class: style="display:none" is
   dropped by the CSP, which leaves a raw file picker on the page. */
.bv-visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* Card heading with a trailing action button */
.bv-card__title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 2rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.bv-card__title-row .bv-card__title {
  margin: 0;
  font-size: 18px;
  color: #ffffff;
}

/* Round icon button used to reveal the voter hash */
.bv-reveal-btn {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  cursor: pointer;
  background: transparent;
  border: 1px solid rgba(255, 180, 0, 0.4);
  color: #FFB400;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.bv-reveal-btn:hover {
  background: rgba(255, 180, 0, 0.1);
  border-color: #FFB400;
}

/* Modal shell — toggled with .is-open, never with an inline style */
.bv-modal {
  position: fixed;
  inset: 0;
  z-index: 99999;
  padding: 24px;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(7, 14, 38, 0.9);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
}
.bv-modal.is-open { display: flex; }
.bv-modal__card {
  position: relative;
  width: 100%;
  max-width: 520px;
  padding: 40px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(15, 23, 42, 0.97);
  box-shadow: 0 32px 64px rgba(0, 0, 0, 0.5);
}
.bv-modal__close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #ffffff;
  cursor: pointer;
  transition: background 0.2s ease;
}
.bv-modal__close:hover { background: rgba(255, 255, 255, 0.12); }
.bv-modal__title {
  font-size: 20px;
  font-weight: 800;
  color: #ffffff;
  margin: 0 0 24px;
}
.bv-modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 28px;
}
.bv-form-group { margin-bottom: 18px; }
.bv-field-error {
  margin: 6px 0 0;
  font-size: 11px;
  font-weight: 700;
  color: #ef4444;
}

/* Utility hide class — replaces style="display:none" which the CSP drops. */
.bv-hidden { display: none !important; }

/* Compact gold action button (card headers) */
.bv-btn--gold-sm {
  width: auto;
  padding: 8px 16px;
  font-size: 10px;
  border-radius: 8px;
  background: rgba(255, 180, 0, 0.12);
  border: 1px solid rgba(255, 180, 0, 0.45);
  color: #FFB400;
}
.bv-btn--gold-sm:hover {
  background: rgba(255, 180, 0, 0.22);
  border-color: #FFB400;
}

/* Auto-width button for action rows (.bv-btn is 100% wide by default) */
.bv-btn--auto { width: auto; padding: 12px 22px; }

/* ══════════════════════════════════════════════════════════════════
   DEVICE BREAKPOINTS
   Added because the interface had no phone breakpoint: every media
   query sat at the 1023/1024px boundary, so a 375px phone was styled
   exactly like a 1023px tablet. The 67 sm:/md:/lg: classes in the
   markup are Tailwind and emit nothing in this build, so any layout
   that must adapt has to be declared here.

   Boundaries are deliberately non-overlapping:
     phone   <= 640px
     tablet  641px - 1023.98px
     desktop >= 1024px
   ══════════════════════════════════════════════════════════════════ */

/* ── Stop the page sliding sideways ───────────────────────────────
   The decorative .blob elements are 450-578px wide and sit outside
   the viewport on a phone. With overflow visible they gave every
   dashboard page a few pixels of horizontal drag, which reads as a
   broken layout under the thumb. */
@media (max-width: 1023.98px) {
  html, body {
    overflow-x: hidden;
    max-width: 100%;
  }

  .blob, .blob-1, .blob-2, .blob-3 {
    pointer-events: none;
  }
}

/* ── Viewport height on mobile browsers ───────────────────────────
   100vh excludes the retracting address bar on iOS and Android, so a
   full-height shell is taller than the visible area and the bottom of
   the sidebar (including Sign Out) sits below the fold. dvh tracks the
   visible viewport; the vh line stays as the fallback. */
@media (max-width: 1023.98px) {
  .bv-dashboard-layout { height: 100vh; height: 100dvh; }
  .bv-sidebar { height: 100vh !important; height: 100dvh !important; }
}

/* ── Drawer backdrop ──────────────────────────────────────────────
   Without it there is no way to dismiss the menu except the hamburger,
   and nothing signals that the page behind is inert. */
.bv-sidebar-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(3, 7, 20, 0.6);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.bv-sidebar-backdrop.is-visible {
  opacity: 1;
  visibility: visible;
}

@media (min-width: 1024px) {
  .bv-sidebar-backdrop { display: none !important; }
}

/* ── Tablet: 641px - 1023.98px ────────────────────────────────────
   Enough width for two columns; the forced single column at this size
   left half the screen empty. */
@media (min-width: 641px) and (max-width: 1023.98px) {
  .bv-page { padding: 24px !important; }

  .bv-grid-2,
  .bv-grid-3,
  .bv-grid-4,
  .bv-stat-grid,
  .bv-profile-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 20px !important;
  }

  .bv-sidebar { width: 320px !important; }
}

/* ── Phone: <= 640px ──────────────────────────────────────────────── */
@media (max-width: 640px) {
  .bv-page { padding: 14px !important; }

  .bv-page-heading, .bv-page-header h1 { font-size: 1.25rem !important; }
  .bv-page-subheading { font-size: 12px !important; }

  /* One column everywhere, including the stat grid that stayed at two */
  .bv-grid-2,
  .bv-grid-3,
  .bv-grid-4,
  .bv-grid-auto,
  .bv-stat-grid,
  .bv-profile-grid {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  .bv-card__body { padding: 0.875rem !important; }
  .bv-card__icon { width: 42px; height: 42px; font-size: 1.15rem; }

  /* Touch targets: 42-43px measured, below the 44px minimum */
  .bv-btn,
  .bv-btn--verify,
  .bv-input,
  .bv-reveal-btn,
  select.bv-input,
  .bv-nav-item,
  .bv-sidebar__logout {
    min-height: 44px;
  }

  /* Actions stack instead of crowding onto one line */
  .bv-card__actions,
  .bv-modal__actions {
    flex-direction: column;
    align-items: stretch;
  }

  .bv-modal__actions .bv-btn,
  .bv-modal__actions .bv-btn--gold-sm { width: 100%; }

  .bv-modal { padding: 12px; }
  .bv-modal__card { padding: 24px 20px; }

  /* The login card is a fixed 400px; phones are narrower than that */
  .bv-minimal-card {
    width: 100% !important;
    max-width: 400px;
    padding: 32px 22px !important;
  }

  /* Topbar: the status pills crowd out the page title */
  .bv-topbar { padding: 0 14px !important; }
  .bv-topbar-title { font-size: 13px !important; }
  .bv-topbar .bv-card__meta { display: none; }

  .bv-sidebar { width: 86% !important; max-width: 320px !important; }

  /* Tables keep scrolling horizontally, but say so rather than
     looking truncated. */
  .bv-table-container { position: relative; }
  .bv-table-container::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 24px;
    pointer-events: none;
    background: linear-gradient(to right, rgba(10, 22, 40, 0), rgba(10, 22, 40, 0.85));
  }

  .bv-hash { font-size: 8px; }
  .bv-verified-banner { padding: 0.75rem 0.9rem; }
  .bv-avatar-upload__img,
  .bv-avatar-upload__initials { width: 68px; height: 68px; }
}

/* Very small phones (<=360px): stop the receipt/hash blocks overflowing */
@media (max-width: 360px) {
  .bv-page { padding: 10px !important; }
  .bv-card__body { padding: 0.75rem !important; }
  .bv-btn { font-size: 11px; letter-spacing: 0.06em; }
}

/* ── IDENTITY ROWS ────────────────────────────────────────────────
   Label/value pairs fronted by a tinted icon tile, as used on the
   profile's Verified Identity card. The tile carries the meaning at a
   glance; the label is secondary and the value leads.                */
.bv-id-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.bv-id-row:last-child { border-bottom: none; }

.bv-id-row__icon {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  font-size: 0.95rem;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.2);
  color: #FFB400;
}
.bv-id-row__icon--indigo { background: rgba(99,102,241,0.12); border-color: rgba(99,102,241,0.25); color: #818cf8; }
.bv-id-row__icon--green  { background: rgba(34,197,94,0.12);  border-color: rgba(34,197,94,0.25);  color: #22c55e; }

/* min-width:0 lets a long email wrap instead of forcing the row wider. */
.bv-id-row__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.bv-id-row__label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}
.bv-id-row__value {
  font-size: 15px;
  font-weight: 700;
  color: #ffffff;
  overflow-wrap: anywhere;
}

/* Status strip: the same idiom, boxed, for a single standout fact. */
.bv-id-status {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.9rem 1rem;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 180, 0, 0.18);
}
.bv-id-status > i { color: #FFB400; font-size: 1rem; flex-shrink: 0; }
.bv-id-status__label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #FFB400;
}
.bv-id-status__value {
  font-size: 13px;
  font-weight: 700;
  color: #ffffff;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ── AVATAR SIZING ────────────────────────────────────────────────
   .bv-avatar already fixes a 36px circle with !important, which is what
   makes it safe on an <img>: an unconstrained avatar renders at its
   natural size, so an uploaded photo blew up to several hundred pixels
   and wrecked the user table. The Tailwind classes previously used for
   this (w-9 h-9 rounded-full object-cover) emit nothing in this build.
   object-fit applies to the <img> case and is inert on the initials div. */
.bv-avatar { object-fit: cover; }

.bv-avatar--xl {
  width: 80px !important;
  height: 80px !important;
  min-width: 80px !important;
  min-height: 80px !important;
  font-size: 24px;
}

/* ── BORDER COLOURS ───────────────────────────────────────────────
   The built Tailwind bundle emits `.border` (a 1px WIDTH) but none of
   the paired colour utilities — `.border-white/5`, `.border-red-500/30`
   and friends are absent, though views use them ~56 times. A width with
   no colour falls back to `currentColor`, so every bordered panel drew a
   hard white line. (Tailwind v3's preflight defaulted borders to grey;
   v4 defaults to currentColor, which is exactly this trap.)

   Two parts: a subtle default so anything missed can never be white
   again, then the specific colours the views actually ask for, so an
   emergency panel still reads red rather than flattening to grey. */
*,
::before,
::after { border-color: rgba(255, 255, 255, 0.08); }

/* Neutrals — the dark theme wants a faint light line, not literal grey. */
.border-white\/5    { border-color: rgba(255, 255, 255, 0.05) !important; }
.border-white\/10   { border-color: rgba(255, 255, 255, 0.10) !important; }
.border-white\/20   { border-color: rgba(255, 255, 255, 0.20) !important; }
.border-gray-100,
.border-gray-200,
.border-gray-300    { border-color: rgba(255, 255, 255, 0.12) !important; }
.border-gray-700,
.border-gray-800    { border-color: rgba(255, 255, 255, 0.09) !important; }

/* Semantic — these carry meaning and must survive. */
.border-red-500     { border-color: rgba(239, 68, 68, 0.35) !important; }
.border-red-500\/20 { border-color: rgba(239, 68, 68, 0.20) !important; }
.border-red-500\/30 { border-color: rgba(239, 68, 68, 0.30) !important; }
.border-green-500   { border-color: rgba(34, 197, 94, 0.35) !important; }
.border-green-500\/30 { border-color: rgba(34, 197, 94, 0.30) !important; }
.border-green-600   { border-color: rgba(22, 163, 74, 0.40) !important; }
.border-blue-500    { border-color: rgba(59, 130, 246, 0.35) !important; }
.border-yellow-500  { border-color: rgba(255, 180, 0, 0.40) !important; }
.border-yellow-500\/50 { border-color: rgba(255, 180, 0, 0.50) !important; }
.border-indigo-400,
.border-indigo-500,
.border-indigo-700  { border-color: rgba(99, 102, 241, 0.35) !important; }

/* ── DIGITAL BALLOT ───────────────────────────────────────────────
   The ballot gets its own grid and card rather than reusing
   .bv-grid-3 / .bv-candidate-card, for two reasons:

   1. .bv-grid-3 is three fixed 1fr tracks, so a position with two
      candidates rendered two cards each a third of the viewport wide
      with a dead column beside them. auto-fill keeps every candidate
      card the same size no matter how many contest the seat, which is
      also the fairer presentation.
   2. .bv-grid-3 is shared by ~30 other views. Tuning the ballot on it
      would move all of them.

   The photo is deliberately NOT .bv-avatar: that class pins a 36px
   circle with !important (see AVATAR SIZING above) and a 36px face
   does not help a voter who does not know the names.                */

.bv-ballot-form {
  padding-bottom: 96px;   /* Tailwind pb-24 emits nothing in this build */
}

.bv-ballot-section + .bv-ballot-section {
  margin-top: 48px;       /* replaces the inert space-y-12 */
}

.bv-ballot-headline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

/* Two separate faults were fixed here; both showed up as dead space.

   1. auto-FILL keeps its empty tracks. At 1600px it laid out seven
      213px columns, put four candidates in the first four, and left
      three phantom columns on the right with every portrait shrunk to
      fit a track count nobody needed. auto-FIT collapses the empties.
 
   2. The replacement, minmax(210px, 300px), was worse in a quieter
      way: when the MAX of a minmax() is a definite length, that is what
      auto-fit counts tracks with -- not the min. 300px + 20px gap into
      932px of content is two columns, so a four-candidate ballot came
      out two-up with half the row empty. The max has to stay 1fr; the
      MIN is what actually sets how big a card gets, because auto-fit
      packs as many min-width tracks as fit and then grows them.
 
   260px min => three ~300px cards on a 932px content column, five on a
   wide desktop, two on a small laptop. The card size is the point: a
   ballot is chosen from faces. */
.bv-ballot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  align-items: stretch;
}

/* The <label> is the whole hit area. Content model is phrasing only,
   so everything inside is a span made block. */
.bv-ballot-option {
  display: block;
  position: relative;
  cursor: pointer;
  height: 100%;
  -webkit-tap-highlight-color: transparent;
}

/* The global `input { width: 100% !important }` rule further up would
   otherwise give this a box, so every property is forced. */
.bv-ballot-input {
  position: absolute !important;
  opacity: 0 !important;
  width: 1px !important;
  height: 1px !important;
  min-height: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  border: 0 !important;
  pointer-events: none !important;
}

.bv-ballot-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  height: 100%;
  padding: 14px;
  position: relative;
  overflow: hidden;
  transition: border-color 0.18s, box-shadow 0.18s, transform 0.15s;
}

.bv-ballot-option:hover .bv-ballot-card {
  border: 1px solid rgba(255, 180, 0, 0.35) !important;
  border-top: 1px solid rgba(255, 180, 0, 0.35) !important;
  transform: translateY(-2px);
}

/* Keyboard users get a visible target — the input itself is off-screen. */
.bv-ballot-input:focus-visible + .bv-ballot-card {
  outline: 2px solid #FFB400;
  outline-offset: 2px;
}

/* ── Photo ──
   4:5 portrait. object-fit: cover means an uploaded photo of any
   dimension crops to frame rather than stretching. */
.bv-ballot-photo {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: 12px;
  overflow: hidden;
  background: var(--bv-ballot-tint, rgba(255, 180, 0, 0.06));
  border: 1px solid rgba(255, 255, 255, 0.08);
  flex-shrink: 0;
}

.bv-ballot-photo__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No photo at all: a large initials tile. This is the production
   fallback — real recognition comes from COMELEC uploading real
   photos, and this keeps the ballot legible until they do. */
.bv-ballot-photo__initials {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  font-weight: 800;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.72);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.bv-ballot-body {
  display: block;
  min-width: 0;
}

.bv-ballot-name {
  display: block;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.35;
  color: #ffffff;
  overflow-wrap: anywhere;
}

.bv-ballot-party {
  display: block;
  margin-top: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
}

/* ── Selection check ──
   The previous card rendered an empty ring whose fill dot had been
   deleted from the markup, so clicking a candidate gave no positive
   confirmation. Driven by the adjacent-sibling selector rather than
   :has() so it does not depend on Safari 15.4+. */
.bv-ballot-check {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.45);
  background: rgba(6, 16, 30, 0.65);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #06101e;
  transition: background 0.18s, border-color 0.18s;
}

.bv-ballot-check i {
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 0.18s, transform 0.18s;
}

.bv-ballot-input:checked + .bv-ballot-card {
  /* .bv-card sets `border` AND `border-top` as !important shorthands, so the
     selected state restates both longhands rather than relying on a
     border-color shorthand outranking them. */
  border: 1px solid #FFB400 !important;
  border-top: 1px solid #FFB400 !important;
  background: rgba(255, 180, 0, 0.07) !important;
  box-shadow: 0 0 24px rgba(255, 180, 0, 0.18) !important;
}

.bv-ballot-input:checked + .bv-ballot-card .bv-ballot-check {
  background: #FFB400;
  border-color: #FFB400;
}

.bv-ballot-input:checked + .bv-ballot-card .bv-ballot-check i {
  opacity: 1;
  transform: scale(1);
}

.bv-ballot-input:checked + .bv-ballot-card .bv-ballot-photo {
  border-color: rgba(255, 180, 0, 0.45);
}

/* ── Tint palette for the initials fallback ──
   Assigned per candidate from a hash of the name, so a ballot of
   initials tiles is varied rather than 65 identical amber squares.
   A class, not a style attribute: the CSP drops inline styles. */
.bv-hue-0 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #1e3a5f, #16293f); }
.bv-hue-1 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #14494a, #0e3233); }
.bv-hue-2 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #3d2a4d, #291c34); }
.bv-hue-3 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #4a3a1c, #322612); }
.bv-hue-4 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #4a2530, #331920); }
.bv-hue-5 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #23422b, #17301d); }
.bv-hue-6 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #2a2f5c, #1c2040); }
.bv-hue-7 .bv-ballot-photo { --bv-ballot-tint: linear-gradient(180deg, #4a3326, #33221a); }

/* ── Tablet ── slightly wider tracks so names stop wrapping to 3 lines */
@media (min-width: 641px) and (max-width: 1023.98px) {
  .bv-ballot-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
  .bv-ballot-section + .bv-ballot-section { margin-top: 36px; }
}

/* ── Phone ──
   A 4:5 portrait per candidate would make a 65-candidate ballot an
   enormous scroll, so the card flips to a row: circular photo left,
   name right, check far right. Whole row stays one tap target. */
@media (max-width: 640px) {
  .bv-ballot-grid { grid-template-columns: 1fr; gap: 10px; }

  .bv-ballot-section + .bv-ballot-section { margin-top: 28px; }
  .bv-ballot-form { padding-bottom: 64px; }

  .bv-ballot-card {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 10px 12px;
    min-height: 76px;     /* comfortably over the 44px touch minimum */
  }

  .bv-ballot-photo {
    width: 56px;
    height: 56px;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
  }

  .bv-ballot-photo__initials { font-size: 1.05rem; }

  .bv-ballot-body { flex: 1 1 auto; }
  .bv-ballot-name { font-size: 0.9rem; }

  .bv-ballot-check {
    position: static;
    flex-shrink: 0;
  }

  .bv-ballot-headline { gap: 10px; }
}

/* The section heading previously leaned on Tailwind's `m-0`, which emits
   nothing in this build, so the h2 kept its UA margin and its 1.5em size
   (relative to the 11px the container forces). Made explicit. */
.bv-section__heading.bv-ballot-headline h2 {
  margin: 0;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.15em;
  color: rgba(255, 255, 255, 0.72);
}

/* ── ELECTION RESULTS ─────────────────────────────────────────────
   results/index.blade.php was the only view in the app that skipped
   .bv-page, so it rendered flush against the sidebar with no padding
   on any edge, and the fixed footer sat directly on its last row. It
   also carried Tailwind spacing classes (mb-8, p-6, mt-6) that this
   build emits nothing for — only gap-* utilities exist in the
   hand-rolled sheets — so none of its intended rhythm ever applied.

   Wrapping the page in .bv-page restores both. The classes below
   replace the inline styles it used for everything else, following
   the same reasoning as .bv-ballot-grid above: a named class rather
   than tuning .bv-grid-3, which ~30 other views share.             */

.bv-results-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 32px;
}

/* The select ran the full width of the card — a 1600px dropdown for a
   handful of short titles. Cap it and let the row breathe. */
.bv-results-toolbar__field {
  flex: 1 1 320px;
  max-width: 520px;
}

.bv-results-section + .bv-results-section {
  margin-top: 40px;
}

/* The heading row carries the denominator. A bare "71.4%" on a card
   answers nothing without the number it is a share of, and this page
   showed percentages with no total anywhere on it. */
.bv-results-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  max-width: 1180px;
  margin: 0 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-results-heading__title {
  margin: 0;
  color: rgba(255, 255, 255, 0.55);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.bv-results-heading__total {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-results-heading__total strong {
  color: #FFB400;
  font-weight: 800;
}

/* Was repeat(auto-fill, minmax(300px, 1fr)) — the only auto-fill in the
   app outside the ballot. auto-fill keeps every track that fits, so two
   candidates on a 1650px canvas built five tracks, filled two and
   reserved the other three: the cards huddled left under two thirds of
   dead space. auto-fit collapses the empty tracks instead, and the
   max-width stops a head-to-head from stretching two cards across the
   entire viewport. */
.bv-results-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  align-items: stretch;
  max-width: 1180px;
}

.bv-results-college {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 32px 0 16px;
}

.bv-results-college::before {
  content: "";
  width: 2px;
  height: 14px;
  background: #FFB400;
  border-radius: 2px;
  opacity: 0.8;
  box-shadow: 0 0 8px rgba(251, 191, 36, 0.4);
}

.bv-results-college__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #94a3b8;
}

.bv-results-college + .bv-results-grid {
  margin-bottom: 24px;
}

.bv-results-footer {
  max-width: 1180px;
  margin-top: 56px;
  padding-top: 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  text-align: center;
}

/* py-20 / py-32 / text-center / opacity-50 all emit nothing here. */
.bv-results-empty {
  max-width: 1180px;
  padding: 72px 32px;
  text-align: center;
}

.bv-results-empty p {
  margin: 16px 0 0;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

/* The share and the count are the two numbers a reader compares, but
   the share was rendered in .bv-card__meta — the same muted grey as the
   partylist label two lines above it. Lift it clear of the labels
   without letting it compete with the amber count. */
.bv-card__share {
  font-size: 15px;
  font-weight: 800;
  line-height: 1;
  color: rgba(255, 255, 255, 0.75);
}

/* `truncate` emits nothing in this build, so a long name overflowed its
   card instead of ellipsing. */
.bv-card__title--clip {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bv-results-college__total {
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-results-college__total strong {
  color: #FFB400;
  font-weight: 800;
}

.bv-results-college {
  max-width: 1180px;
}

/* An unopposed seat is a single card in the row. With 1fr tracks that card
   took the full 1180px band, which looked broken next to the contested rows
   above it. The cap only bites at one card — a two-up row computes to 581px
   and is untouched — so a lone candidate now matches its neighbours. */
.bv-results-grid > * {
  max-width: 600px;
}

/* ── RESULT CARD PORTRAIT ─────────────────────────────────────────
   partials/candidate-card-results.blade.php drew a .bv-avatar with
   initials and never read $candidate->photo_url, even though every
   seeded candidate has a photo (images/candidates/*.svg, served by
   nginx) and three other views already use that accessor.

   .bv-avatar cannot carry the image: it pins 36px with !important
   (see AVATAR SIZING above), which is a token rather than a face on a
   card this wide. Same reasoning as the ballot photo.               */

.bv-result-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;   /* mb-4 emits nothing in this build */
}

.bv-result-avatar {
  width: 56px;
  height: 56px;
  min-width: 56px;
  border-radius: 50%;
  object-fit: cover;
  /* Portrait sources are 4:5 with the head around 40% down; centring the
     crop would clip foreheads on real uploads. */
  object-position: 50% 40%;
  display: block;
  background: rgba(255, 180, 0, 0.05);
  border: 2px solid rgba(255, 180, 0, 0.35);
}

/* Same box as the photo, so a candidate without one does not shift the
   row next to a candidate who has one. */
.bv-result-avatar--text {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 800;
  color: rgba(255, 180, 0, 0.7);
}

/* mt-6 / mb-2 on the figures row emit nothing either, so the count sat
   flush against the partylist label. */
.bv-result-card__figures {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin: 24px 0 8px;
}

/* ══════════════════════════════════════════════════════════════════
   ADMIN IDENTITY DETAIL + SOC DASHBOARD
   Added 2026-08-23. Both screens were written almost entirely in
   Tailwind scale utilities, and this build emits none of them. Measured
   in the browser against the CSS the container actually serves, 50
   classes across the two views resolved to nothing: every `mb-*`,
   `mt-*`, `p-*`, `py-*`, `space-y-*`, every named colour
   (`text-green-400`, `bg-white/5`, `text-white/60` …), `font-bold`,
   `text-xs`, `text-2xl`, `tracking-widest`, `rounded-lg`, `rounded-xl`,
   `shadow-2xl`, `w-2`, `h-2`, `top-0`, `left-0` and `animate-pulse`.
   Arbitrary-value classes (`text-[10px]`, `min-w-[200px]`) DO survive
   the build, which is what made the wreckage look partial rather than
   total.

   Everything below is additive. No existing rule is edited, so no other
   view moves.                                                         */

/* ── MISSING BADGE MODIFIERS ──────────────────────────────────────
   `.bv-badge--blue` (COMELEC role, used here and in the user registry)
   and `.bv-badge--yellow` (login_failed in the audit trail) were
   referenced by four views and defined by none. Measured: transparent
   background, 0px border — the pill rendered as bare text. */
.bv-badge--blue {
  background: rgba(59, 130, 246, 0.18) !important;
  border: 1px solid rgba(59, 130, 246, 0.4) !important;
  color: #60a5fa !important;
}

.bv-badge--yellow {
  background: rgba(245, 158, 11, 0.15) !important;
  border: 1px solid rgba(245, 158, 11, 0.4) !important;
  color: #fbbf24 !important;
}

/* ── CONTROL + SUBMIT ROW ─────────────────────────────────────────
   The reason both role dropdowns collapsed to 30px. `.bv-btn--primary`
   carries `width: 100% !important; display: block !important`, so in a
   flex row the button's flex-basis is the whole container while
   `.flex-1` gives the select a basis of 0. There is no free space left
   and the select shrinks to its arrow. Measured in a 700px row:
   select 30px, button 654px.

   Fixed here rather than on `.bv-btn--primary`, which ~20 other views
   depend on being full width. `> .bv-btn` is two classes deep, so it
   outranks the single-class !important it has to beat. */
.bv-form-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 12px;
}

/* A 200px basis rather than auto so the control wraps onto its own full
   width line when the CARD is narrow, not just when the viewport is.
   The tablet breakpoint keeps .bv-grid-2 at two columns down to 641px,
   which leaves this row about 266px wide — a viewport media query would
   not catch that. */
.bv-form-row > .bv-input,
.bv-form-row > select.bv-input {
  flex: 1 1 200px;
  min-width: 0;
}

.bv-form-row > .bv-btn {
  flex: 0 0 auto;
  width: auto !important;
  margin-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .bv-form-row { flex-direction: column; }
  .bv-form-row > .bv-btn { width: 100% !important; }
}

/* ── FIELD LABEL + HELPER NOTE ────────────────────────────────────
   The helper text under each control used `.bv-card__meta`, which
   forces uppercase. A full sentence set in 10px capitals is close to
   unreadable — "PROMOTING TO COMELEC ALLOWS MANAGEMENT OF ELECTIONS
   AND CANDIDATES." Labels stay capitalised; prose does not. */
.bv-field-label {
  display: block;
  margin: 0 0 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
}

.bv-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 10px 0 0;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(255, 255, 255, 0.4);
}

.bv-note i {
  margin-top: 2px;
  color: rgba(255, 255, 255, 0.25);
  flex-shrink: 0;
}

.bv-note--error { color: #ff8080; }
.bv-note--error i { color: #ff8080; }

/* ── IDENTITY HEADER ──────────────────────────────────────────────
   `text-2xl` is dead, so the name measured 18px — the same size as the
   card title above it. The email used `.bv-card__meta`, which rendered
   an address in capitals. */
.bv-identity {
  display: flex;
  align-items: center;
  gap: 20px;
}

.bv-identity__name {
  margin: 0 0 5px;
  font-size: 22px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: #ffffff;
}

.bv-identity__email {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(255, 255, 255, 0.42);
  word-break: break-all;
}

/* ── DETAIL LIST ──────────────────────────────────────────────────
   Was `space-y-4` + `py-3` + `border-b`. Only the border survived, so
   the four rows measured 0px of padding and stacked flush against each
   other. The status value also lost `text-green-400` / `text-red-400`
   and computed to pure white — "Operational" and "Suspended" rendered
   identically, which is the one distinction on this card that carries
   meaning. */
.bv-detail-list {
  display: flex;
  flex-direction: column;
}

.bv-detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.bv-detail-row:first-child { padding-top: 0; }

.bv-detail-row:last-child {
  padding-bottom: 0;
  border-bottom: none;
}

.bv-detail-row__label {
  margin: 0;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-detail-row__value {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-align: right;
  color: rgba(255, 255, 255, 0.92);
}

.bv-detail-row__value--ok,
.bv-detail-row__value--warn {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.bv-detail-row__value--ok   { color: #22c55e; }
.bv-detail-row__value--warn { color: #ef4444; }

/* ── SECURITY EVENT LIST ──────────────────────────────────────────
   `p-3 bg-white/5 rounded-lg` all resolved to nothing, so each event
   measured padding 0, transparent background, radius 0 — a bare 2px
   stripe with text jammed against it. */
.bv-event-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.bv-event {
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-left: 2px solid rgba(59, 130, 246, 0.65);
  border-radius: 10px;
}

.bv-event--warning {
  border-left-color: rgba(245, 158, 11, 0.75);
}

.bv-event--critical {
  background: rgba(239, 68, 68, 0.06);
  border-left-color: rgba(239, 68, 68, 0.8);
}

.bv-event__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.bv-event__action {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

.bv-event__time {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.3);
}

.bv-event__detail {
  margin: 6px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, 0.5);
}

.bv-event-empty {
  margin: 0;
  padding: 20px 0;
  text-align: center;
  font-size: 12px;
  font-style: italic;
  text-transform: none;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.28);
}

.bv-event-empty i {
  display: block;
  margin-bottom: 10px;
  font-size: 22px;
  font-style: normal;
  color: rgba(255, 255, 255, 0.15);
}

/* Vertical rhythm between top-level blocks on a page. `mb-12` / `mb-8`
   emit nothing, so the metric grid, the filter bar and the audit trail
   were stacked flush against each other. */
.bv-stack-lg { margin-bottom: 32px; }
.bv-stack-md { margin-bottom: 24px; }

/* ── CALLOUT ──────────────────────────────────────────────────────
   The "this is your own session" panel: `p-6 bg-blue-500/10
   rounded-xl text-blue-300` — every one of those is dead. */
.bv-callout {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 20px;
  border-radius: 14px;
}

.bv-callout--blue {
  background: rgba(59, 130, 246, 0.08);
  border: 1px solid rgba(59, 130, 246, 0.2);
}

.bv-callout__icon {
  flex-shrink: 0;
  font-size: 20px;
  line-height: 1.3;
  color: #60a5fa;
}

.bv-callout__text {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.65;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(147, 197, 253, 0.85);
}

/* ── WALLET HASH CARD ─────────────────────────────────────────────
   `bg-[#6366f1]/10` does survive the build (arbitrary values do), but
   `bg-black/20 p-4 rounded-xl` on the code block do not, so the hash
   sat naked on the card. */
.bv-card-heading {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  color: #ffffff;
}

.bv-hash-block {
  padding: 14px 16px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12px;
}

.bv-hash-block code {
  display: block;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.02em;
  color: #a5b4fc;
  word-break: break-all;
}

/* ── DESTRUCTIVE / RESTORATIVE BUTTONS ────────────────────────────
   Replaces the inline style attribute on Suspend and the dead
   `bg-green-600` on Re-activate. Both inherit the full-width default
   from `.bv-btn`, which is what these two want. */
.bv-btn--danger-ghost {
  background: rgba(239, 68, 68, 0.06) !important;
  border: 1px solid rgba(239, 68, 68, 0.25) !important;
  color: #f87171 !important;
}

.bv-btn--danger-ghost:hover {
  background: rgba(239, 68, 68, 0.14) !important;
  border-color: rgba(239, 68, 68, 0.45) !important;
  color: #fca5a5 !important;
}

.bv-btn--success {
  background: rgba(34, 197, 94, 0.14) !important;
  border: 1px solid rgba(34, 197, 94, 0.35) !important;
  color: #4ade80 !important;
}

.bv-btn--success:hover {
  background: rgba(34, 197, 94, 0.24) !important;
  border-color: rgba(34, 197, 94, 0.55) !important;
  color: #86efac !important;
}

/* ── SOC: LIVE FEED INDICATOR ─────────────────────────────────────
   The status dot was `w-2 h-2 rounded-full bg-emerald-500
   animate-pulse`. Only `rounded-full` exists, so the element measured
   0×0 — there has never been a dot on this page. `text-emerald-500` is
   dead too, so the label was not green either. */
.bv-live {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 6px;
}

.bv-live__dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.6);
  animation: bv-live-pulse 2.2s infinite;
}

@keyframes bv-live-pulse {
  70%  { box-shadow: 0 0 0 7px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .bv-live__dot { animation: none; }
}

.bv-live__label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #22c55e;
}

.bv-live__stamp {
  display: block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: right;
  color: rgba(255, 255, 255, 0.3);
}

/* ── SOC: KPI NUMBER ──────────────────────────────────────────────
   `.bv-card__stat` is 1.1rem, so the four headline counts rendered
   SMALLER than the card titles above them. Scoped to a modifier —
   `.bv-card__stat` itself is shared by a dozen other cards. */
.bv-card__stat--kpi {
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 0;
}

/* ── SOC: FILTER BAR ──────────────────────────────────────────────
   Was `flex-wrap gap-6` with `border-r pr-6` dividers. `pr-6` is dead,
   so each label sat flush against the rule beside it. Dropped the
   rules; the gap already separates the fields, and the row now wraps
   into real columns instead of squeezing. */
.bv-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 18px;
}

.bv-filter-bar__field {
  flex: 1 1 200px;
  min-width: 170px;
}

.bv-filter-bar__actions {
  display: flex;
  flex: 0 0 auto;
  gap: 10px;
}

.bv-filter-bar__actions .bv-btn {
  width: auto !important;
  margin-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
}

/* ── SOC: AUDIT TRAIL ─────────────────────────────────────────────
   `max-h-[400px] overflow-y-auto` DOES apply (arbitrary values
   survive), so the log is a 400px scroll box nested inside the page's
   own scroll — and the header did not stick, so scrolling the log lost
   the column names. Sticky header, a slightly taller box, and an
   opaque header fill (a translucent one lets rows show through). */
.bv-log-scroll {
  max-height: 460px;
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12px;
}

.bv-log-scroll .bv-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #192435;
}

.bv-log-scroll .bv-table td { vertical-align: top; }

.bv-log-time {
  display: block;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10.5px;
  line-height: 1.5;
  white-space: nowrap;
  color: #60a5fa;
}

.bv-log-time span {
  color: rgba(255, 255, 255, 0.4);
}

.bv-log-ip {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10.5px;
  color: #818cf8;
}

.bv-log-actor {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.bv-log-actor__name {
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.88);
}

.bv-log-actor__id {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.28);
}

.bv-log-actor__anon {
  font-size: 12px;
  font-style: italic;
  color: rgba(255, 255, 255, 0.3);
}

/* Two lines, then ellipsis. The full text is on the cell's title
   attribute — the old hover panel used `bg-slate-900 shadow-2xl p-4
   rounded-lg top-0 left-0`, all dead, so it opened as a transparent
   unpositioned block on top of the row it was explaining. */
.bv-log-details {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  max-width: 460px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  color: rgba(255, 255, 255, 0.6);
}

.bv-log-badge {
  font-size: 9px;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

/* ── FIXED FOOTER CLEARANCE ───────────────────────────────────────
   layouts/dashboard.blade.php pins the footer with `position: fixed`,
   but `.bv-page` has no bottom padding to match, so the last ~40px of
   every page sits behind it — most visibly the final row of the audit
   trail. Applied to <main> rather than `.bv-page` because the layout
   renders flash messages in their own `.bv-page` with
   `padding-bottom: 0`, which this must not fight. */
.bv-main-content > main {
  padding-bottom: 48px;
}

/* ── SYSTEM SETTINGS: STATUS ROWS ─────────────────────────────────
   Added 2026-08-23. The two protocol rows were
   `p-4 bg-white/5 rounded-lg border border-white/5`. Only the two border
   classes exist in this build, so each row measured **padding 0,
   transparent background, radius 0** — a bare 1px hairline with the text
   pressed into it. The emergency block was the same shape: a 520px red
   box containing a 518px button, flush on every side. */
.bv-status-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.bv-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 12px;
}

.bv-status-row__body { min-width: 0; }

.bv-status-row__title {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.92);
}

/* Sentence case on purpose. `.bv-card__meta` forces uppercase, and these
   lines are prose — "MANDATORY FOR ALL ADMIN/COMELEC ROLES" set in 9px
   capitals is not something anyone reads. */
.bv-status-row__desc {
  margin: 4px 0 0;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(255, 255, 255, 0.42);
}

.bv-status-row__desc code {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10.5px;
  color: #a5b4fc;
}

.bv-status-row .bv-badge { flex-shrink: 0; }

/* A settings screen states policy. Where that policy is read from live
   configuration rather than typed in, say so — it is the difference
   between a panel that stays true and one that goes quietly stale. */
.bv-status-source {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(255, 255, 255, 0.3);
}

.bv-status-source i {
  margin-top: 2px;
  flex-shrink: 0;
  color: rgba(255, 255, 255, 0.22);
}

/* ══════════════════════════════════════════════════════════════════
   PAGEANT STRUCTURE BUILDER
   Added 2026-08-23. The builder injected its markup from JavaScript in
   Tailwind classes, almost none of which this build emits: `p-5`,
   `rounded-lg`, `bg-white/[0.03]`, `ml-6`, `pl-4`, `space-y-3`, `mb-3`,
   `!py-2`, `text-[9px]`, `w-24` and `flex-[2]` all resolved to nothing.
   That is why "ADD SEGMENT" collided with the next row's label, why no
   card ever appeared behind a group, and why the validation strip was a
   red line with unreadable text inside zero padding.

   The overlay also never set `overflow`, so once the structure grew past
   the viewport the dialog's own title became unreachable — which is what
   the reported screenshot shows.                                       */

/* ── Overlay ────────────────────────────────────────────────────── */
.bv-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  padding: 24px;
  background: rgba(15, 23, 42, 0.9);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  overflow-y: auto;              /* the fix for the unreachable header */
  -webkit-overflow-scrolling: touch;
}

.bv-modal-overlay.is-open {
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

/* Never taller than the viewport; the body scrolls, the header stays. */
.bv-modal-panel {
  position: relative;
  width: 100%;
  max-width: 780px;
  margin: auto;
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
}

/* The <form> wraps the body and the footer, so IT is the panel's flex item --
   not the body. Capping the panel and telling the body to scroll achieved
   nothing while the form in between was free to grow to its content. Every link
   in the chain has to be allowed to shrink. */
.bv-modal-panel > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.bv-modal-panel__head {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 26px 30px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-modal-panel__title {
  margin: 0;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #ffffff;
}

.bv-modal-panel__body {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 24px 30px;
  overflow-y: auto;

  /* A flex item defaults to min-height:auto, which refuses to shrink below its
     content -- so overflow-y never engaged and a tall structure pushed straight
     out through the bottom of the dialog. */
  flex: 1 1 auto;
  min-height: 0;
}

.bv-modal-panel__foot {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 18px 30px 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-modal-panel__foot .bv-btn {
  width: auto !important;
  margin-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
}

.bv-modal-close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.55);
  font-size: 13px;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}

.bv-modal-close:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}

/* ── Structure builder ────────────────────────────── */
/* Revised 2026-08-24. The first version gave every node a full card: its own
   background, border, padding, two label rows and a full-width gold button.
   That reads fine with three items and becomes a wall at seventeen — a pageant
   with two rounds of three categories of three criteria. Nesting a card inside a
   card inside a card also flattens the hierarchy, because depth 3 looks exactly
   like depth 1.

   It is a compact row tree instead: one line per item, chrome removed from the
   node itself and carried by an indent guide, and the controls reduced to icons.
   A node went from ~145px tall to ~38px. */

.bv-builder__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.bv-builder__title {
  margin: 0;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.bv-builder__hint {
  margin: 8px 0 0;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.6;
  text-transform: none;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.38);
}

.bv-builder__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 12px;
}

/* The node itself is now just a container. All the visual weight moved to the
   row, so nesting no longer stacks borders inside borders. */
.bv-node { display: block; }

.bv-node__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border-radius: 8px;
  border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s;
}

.bv-node__row:hover { background: rgba(255, 255, 255, 0.03); }

.bv-node__row:focus-within {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(100, 150, 255, 0.25);
}

/* A parent is the thing that carries a weight budget, so it gets the only
   emphasis in the tree — everything else stays quiet. */
.bv-node--parent > .bv-node__row {
  background: rgba(255, 255, 255, 0.035);
  border-color: rgba(255, 255, 255, 0.06);
}

.bv-node__grip {
  flex: 0 0 auto;
  width: 14px;
  text-align: center;
  font-size: 9px;
  color: rgba(255, 255, 255, 0.18);
}

.bv-node--parent > .bv-node__row .bv-node__grip { color: rgba(255, 180, 0, 0.5); }

/* Fields carry no visible label. Seventeen rows of "NAME / WEIGHT %" is the
   noise this layout exists to remove; the inputs keep aria-labels and
   placeholders instead. */
.bv-node__row .bv-input {
  padding: 6px 9px !important;
  font-size: 12px !important;
  border-radius: 7px !important;
  min-height: 0 !important;
}

.bv-node__name { flex: 1 1 150px; min-width: 110px; }

.bv-node__weight { flex: 0 0 64px; text-align: right; }

.bv-node__rule { flex: 0 0 156px; }

.bv-node__max { flex: 0 0 62px; text-align: right; }

/* Suffix so a bare number is not ambiguous once the labels are gone. */
.bv-node__unit {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.25);
}

.bv-node__btn {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 7px;
  font-size: 10px;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.5);
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}

.bv-node__btn:hover {
  background: rgba(255, 255, 255, 0.09);
  color: #ffffff;
}

.bv-node__btn--add:hover {
  background: rgba(255, 180, 0, 0.16);
  border-color: rgba(255, 180, 0, 0.4);
  color: #FFB400;
}

.bv-node__btn--remove:hover {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(239, 68, 68, 0.4);
  color: #f87171;
}

/* Indent guide. One line per level rather than a nested box, so depth is
   readable at a glance and costs 13px instead of a full card inset. */
.bv-node__children {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 2px 0 4px 13px;
  padding-left: 11px;
  border-left: 1px solid rgba(255, 180, 0, 0.18);
}

.bv-node__children:empty {
  display: none;
}

/* Running total for one sibling group, inline on the parent's own row. The
   first version put it on a separate line under a full-width button, which is
   most of why a three-level tree ran off the screen. */
.bv-node__tally {
  flex: 0 0 auto;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  white-space: nowrap;
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.35);
}

.bv-node__tally--ok {
  background: rgba(34, 197, 94, 0.14);
  color: #4ade80;
}

.bv-node__tally--over {
  background: rgba(239, 68, 68, 0.14);
  color: #f87171;
}

.bv-node__tally:empty { display: none; }

.bv-builder__summary {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding: 10px 13px;
  border-radius: 10px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.01em;
}

.bv-builder__summary--ok {
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.25);
  color: #4ade80;
}

.bv-builder__summary--warn {
  background: rgba(239, 68, 68, 0.07);
  border: 1px solid rgba(239, 68, 68, 0.22);
  color: #f87171;
}

.bv-builder__empty {
  margin: 12px 0 0;
  padding: 20px;
  text-align: center;
  font-size: 12px;
  font-style: italic;
  border: 1px dashed rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  color: rgba(255, 255, 255, 0.3);
}

/* The old full-width gold pill, kept only for the one "Add item" at the top of
   the builder. Inside the tree it is an icon. */
.bv-node__add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.3);
  border-radius: 7px;
  padding: 5px 11px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #FFB400;
  cursor: pointer;
  transition: background 0.15s;
}

.bv-node__add:hover { background: rgba(255, 180, 0, 0.2); }

/* Narrow screens: the scoring pair drops to its own line rather than squeezing
   the name field to nothing. */
@media (max-width: 620px) {
  .bv-node__rule { flex: 1 1 140px; }
  .bv-node__name { flex: 1 1 100%; }
}

.bv-form-error {
  margin: 0;
  padding: 12px 14px;
  border-radius: 10px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.25);
  color: #f87171;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.55;
}

/* Sub-label inside a tabulation header cell and for absent values. */
.bv-tab-sub {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.28);
}

/* The pager wrapper on the candidate registry. mt-8 emits nothing in this
   build, so without this the pager sat flush against the table card. */
.bv-candidates-pager {
  margin-top: 24px;
}

/* ── PAGER (resources/views/pagination/bv.blade.php) ──────────────
   Own markup, own styles. The [role="navigation"] nav rules above target
   the built-in Tailwind pager's nested structure and do not reach this
   one, which is why the five screens still on the default pager are
   unaffected by anything here. */

.bv-pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.bv-pager__meta {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-pager__meta span {
  color: rgba(255, 255, 255, 0.85);
  font-weight: 800;
}

.bv-pager__links {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

.bv-pager__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 10px;
  border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.65);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

a.bv-pager__link:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
  color: #ffffff;
}

.bv-pager__link--on {
  background: #FFB400;
  border-color: #FFB400;
  color: #0b1220;
}

.bv-pager__link--off {
  opacity: 0.3;
  cursor: default;
}

.bv-pager__gap {
  padding: 0 2px;
  color: rgba(255, 255, 255, 0.3);
  font-weight: 700;
}

@media (max-width: 640px) {
  .bv-pager { justify-content: center; }
  .bv-pager__links { margin-left: 0; }
}

/* ══════════════════════════════════════════════════════════════════
   BATCH VOTER IMPORT
   admin/users/import.blade.php was styled almost entirely with the
   dead half of the Tailwind build: mb-6 / p-4 / text-sm / font-semibold
   / text-gray-400 / bg-blue-900/20 / border-blue-500/30 / rounded-lg
   all emit nothing, so the page rendered as unpadded, single-weight
   white text with a 1px hairline where the drop target should be.
   Rebuilt here on real rules. Every selector below is a new name — no
   existing component is touched, so no other view can move.
   ══════════════════════════════════════════════════════════════════ */

/* .bv-card__body is `flex column; gap: 1.5rem`, but the form is a
   single child of it, so its own children need their own rhythm. */
.bv-import-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* ── DROP TARGET ──────────────────────────────────────────────────
   A <label for="file"> wrapping a .bv-visually-hidden input: the whole
   panel is the click target and the input stays keyboard-reachable,
   which `class="hidden"` (display:none) would have destroyed. */
.bv-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 44px 24px;
  text-align: center;
  cursor: pointer;
  border: 2px dashed rgba(255, 180, 0, 0.22);
  border-radius: 16px;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 180, 0, 0.05) 0%, rgba(255, 180, 0, 0) 60%),
    rgba(0, 0, 0, 0.18);
  transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s;
}

.bv-dropzone:hover,
.bv-dropzone:focus-within,
.bv-dropzone.is-dragging {
  border-color: rgba(255, 180, 0, 0.6);
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 180, 0, 0.10) 0%, rgba(255, 180, 0, 0) 62%),
    rgba(0, 0, 0, 0.28);
  box-shadow: 0 0 0 4px rgba(255, 180, 0, 0.07);
}

.bv-dropzone.is-dragging .bv-dropzone__icon {
  transform: translateY(-3px);
  border-color: rgba(255, 180, 0, 0.65);
}

.bv-dropzone__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  font-size: 26px;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.10);
  border: 1px solid rgba(255, 180, 0, 0.28);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10);
  transition: transform 0.2s, border-color 0.2s;
}

.bv-dropzone__title {
  font-size: 15px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.92);
  letter-spacing: 0.01em;
}

.bv-dropzone__link {
  color: #FFB400;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.bv-dropzone__hint {
  max-width: 460px;
  font-size: 12.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.42);
}

.bv-dropzone__chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
}

.bv-chip {
  padding: 4px 11px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* ── SELECTED FILE ────────────────────────────────────────────────
   The old page gave no confirmation at all: you picked a file, the
   dialog closed, and the panel still read "Click to upload". */
.bv-filecard {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 14px;
  background: rgba(34, 197, 94, 0.06);
  border: 1px solid rgba(34, 197, 94, 0.22);
}

.bv-filecard__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 10px;
  font-size: 16px;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.12);
  border: 1px solid rgba(34, 197, 94, 0.28);
}

.bv-filecard__body {
  flex: 1;
  min-width: 0;
}

.bv-filecard__name {
  display: block;
  font-size: 13.5px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.92);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bv-filecard__meta {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-filecard__remove {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.5);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: color 0.2s, border-color 0.2s, background-color 0.2s;
}

/* The card doubles as a drop target once a file is chosen — the empty
   drop panel is hidden by then. */
.bv-filecard.is-dragging {
  border-color: rgba(34, 197, 94, 0.55);
  background: rgba(34, 197, 94, 0.12);
  box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.07);
}

.bv-filecard__remove:hover {
  color: #f87171;
  border-color: rgba(239, 68, 68, 0.45);
  background: rgba(239, 68, 68, 0.08);
}

/* ── FORMAT SPEC TABLE ────────────────────────────────────────────
   Frames a .bv-table so it reads as a panel rather than four naked
   columns. Scoped padding: the default 16px is tuned for the log
   tables, which carry far more text per cell than this one. */
.bv-spec {
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 12px;
  overflow: hidden;
}

.bv-spec .bv-table th { padding: 12px 16px; }
.bv-spec .bv-table td { padding: 12px 16px; font-size: 13px; vertical-align: middle; }
.bv-spec .bv-table tr:last-child td { border-bottom: none; }

.bv-spec code {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 12px;
  font-weight: 600;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.08);
  border: 1px solid rgba(255, 180, 0, 0.16);
  border-radius: 6px;
  padding: 2px 7px;
  white-space: nowrap;
}

.bv-spec__example {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.55);
}

.bv-spec__rules {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Scoped to this form so no other view's disabled button changes. */
.bv-import-form .bv-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

@media (max-width: 640px) {
  .bv-dropzone { padding: 32px 18px; }
  .bv-dropzone__icon { width: 60px; height: 60px; font-size: 22px; }
  .bv-filecard { flex-wrap: wrap; }
  .bv-filecard__remove { width: 100%; }
}

/* ══════════════════════════════════════════════════════════════════
   JUDGING SHEET (judge/score-sheet.blade.php)
   Audited in the browser against the three stylesheets the container
   actually serves. The view was written almost entirely in Tailwind,
   and the measurements came back:
     - the criteria grid computed `display: flex`, not grid; `grid-cols-1`
       is emitted but `md:grid-cols-2` is not, so the second column never
       existed and the panels sized themselves to their content
     - every criterion panel: padding 0px, border-radius 0px (`p-8`,
       `rounded-xl` dead) — text flush to the edge of a grey rectangle
     - the criterion NAME rendered at rgba(255,255,255,0.35), because
       `.bv-label` won and `text-white` is dead, while its sub-label sat
       at full gold: the hierarchy was upside down
     - the section total — meant to be `text-6xl font-black text-gold` —
       computed 16px, weight 400, plain white, on a panel with no
       background, no padding and no radius (`bg-white/[0.02]` is dead
       despite the brackets), and its glow layer measured 0x0 (`inset-0`)
     - `mt-10`, `mt-8`, `mt-2`, `mb-2`, `gap-10`, `gap-5`, `text-sm`,
       `text-xs`, `text-2xl`, `text-3xl`, `font-black`, `font-bold`,
       `tracking-wider`, `tracking-widest`, `rounded-lg`, `rounded-xl`
       and every `md:` variant: all dead in this build
   Rebuilt below on real rules. New selectors only — nothing existing is
   touched, so no other screen can move.
   ══════════════════════════════════════════════════════════════════ */

/* ── STICKY SHEET HEADER ──────────────────────────────────────────
   Replaces a style="position:sticky;…" attribute on .bv-page-header. */
.bv-judge-head {
  position: sticky;
  top: 0;
  z-index: 20;
  margin-top: -20px;
  padding: 18px 0;
  background: #0a1628;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-judge-head__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.bv-judge-head__left {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

.bv-judge-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  text-decoration: none;
  transition: color 0.2s, border-color 0.2s, background-color 0.2s;
}

.bv-judge-back:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.16);
}

/* ── ROUND TABS ───────────────────────────────────────────────────
   These were `px-5 py-2.5 rounded-lg text-sm font-black … bg-gold
   text-slate-900` — every one of those is dead, so the tabs rendered as
   bare underlined anchors. */
.bv-seg {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.06);
  overflow-x: auto;
  max-width: 100%;
}

.bv-seg__item {
  padding: 9px 18px;
  border-radius: 8px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.45);
  transition: color 0.2s, background-color 0.2s;
}

.bv-seg__item:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
}

.bv-seg__item--on {
  color: #0a1628;
  background: #FFB400;
  box-shadow: 0 0 16px rgba(255, 180, 0, 0.28);
}

.bv-seg__item--on:hover {
  color: #0a1628;
  background: #FFB400;
}

/* ── "NOW JUDGING" CONTEXT BAR ────────────────────────────────────
   `p-6 rounded-xl bg-white/[0.03]` produced no panel at all. */
.bv-judge-context {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 24px 0;
  padding: 20px 24px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-judge-context__eyebrow {
  display: block;
  margin-bottom: 6px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 180, 0, 0.6);
}

.bv-judge-context__title {
  margin: 0;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: #fff;
}

.bv-judge-context__share {
  text-align: right;
}

.bv-judge-context__value {
  font-size: 26px;
  font-weight: 900;
  line-height: 1;
  color: #FFB400;
}

/* ── CANDIDATE CARD ───────────────────────────────────────────────*/
.bv-score-stack {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.bv-score-card {
  overflow: hidden;
}

.bv-score-card--locked {
  border-color: rgba(34, 197, 94, 0.35) !important;
}

/* .bv-card__body is padded and gapped; this sheet lays out its own
   sections, so the body is reset and each section pads itself. */
.bv-score-card > .bv-card__body {
  padding: 0 !important;
  gap: 0 !important;
}

.bv-score-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 26px;
  background: rgba(255, 255, 255, 0.02);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-score-identity {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}

.bv-score-num {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  font-size: 19px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.09);
  border: 1px solid rgba(255, 180, 0, 0.22);
}

.bv-score-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  min-width: 56px;
  border-radius: 50%;
  object-fit: cover;
  font-size: 16px;
  font-weight: 800;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.1);
  border: 2px solid #FFB400;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}

.bv-score-name {
  margin: 0;
  font-size: 21px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: #fff;
}

.bv-score-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-score-meta__role {
  color: #FFB400;
}

.bv-score-meta__dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
}

/* ── SCORING BODY ─────────────────────────────────────────────────*/
.bv-score-body {
  padding: 26px;
}

/* auto-fit rather than a `md:` breakpoint: the md: variants emit nothing
   in this build, and a container-driven fit is what the layout wanted
   anyway — two panels side by side while each still fits 300px, one
   column below that, at any viewport. */
.bv-score-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 18px;
}

.bv-score-item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.06);
  overflow: hidden;
  transition: border-color 0.2s;
}

.bv-score-item:focus-within {
  border-color: rgba(255, 180, 0, 0.35);
}

/* The criterion name is the thing being judged — it outranks its own
   metadata. It read at 35% opacity while the share below it was solid
   gold, which is exactly backwards. */
.bv-score-item__name {
  display: block;
  margin: 0;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-transform: none;
  color: rgba(255, 255, 255, 0.94);
}

.bv-score-item__share {
  display: inline-block;
  margin-top: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.2);
}

.bv-score-item__row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.bv-score-input {
  flex: 1;
  min-width: 0;
  height: 62px !important;
  padding: 0 16px !important;
  font-size: 30px !important;
  font-weight: 800 !important;
  line-height: 1 !important;
  text-align: left !important;
  font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, 0.28) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 12px !important;
  color: #fff !important;
}

.bv-score-input.is-dirty {
  border-color: rgba(255, 180, 0, 0.45) !important;
}

/* Replaces the four style-attribute writes the lock handler used to make. */
.bv-score-input.is-locked {
  background: transparent !important;
  border-color: transparent !important;
  color: #4ade80 !important;
  padding-left: 0 !important;
}

.bv-score-item__max {
  flex-shrink: 0;
  font-size: 17px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.3);
}

.bv-score-item__weighted {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 6px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-score-item__weighted span {
  font-size: 13px;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.75);
  font-variant-numeric: tabular-nums;
}

.bv-score-item__veil {
  position: absolute;
  inset: 0;
  z-index: 10;
  background: rgba(10, 22, 40, 0.45);
  backdrop-filter: blur(1px);
}

/* ── SECTION TOTAL ────────────────────────────────────────────────*/
.bv-score-total {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 20px;
  padding: 20px 26px;
  border-radius: 16px;
  background:
    linear-gradient(135deg, rgba(255, 180, 0, 0.09) 0%, rgba(255, 180, 0, 0.02) 60%),
    rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 180, 0, 0.18);
}

.bv-score-total__label {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 180, 0, 0.75);
}

.bv-score-total__value {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 40px;
  font-weight: 900;
  line-height: 1;
  color: #FFB400;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 18px rgba(255, 180, 0, 0.25);
}

.bv-score-total__max {
  font-size: 16px;
  font-weight: 800;
  color: rgba(255, 180, 0, 0.45);
  text-shadow: none;
}

/* ── ACTIONS ──────────────────────────────────────────────────────
   `.bv-btn` is width:100% by default, so both buttons stretched to half
   the card each and read as equally weighted. Locking a score is
   irreversible; saving a draft is not. They should not look alike. */
.bv-score-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 20px;
}

.bv-score-actions > .bv-btn {
  width: auto !important;
  /* Sized by their own padding rather than a fixed floor, so the label sets
     the width: "Save Draft" and "Lock & Submit" measure 166px and 185px,
     close enough to read as a pair without forcing the two identical slabs
     the old flex-1 pair produced. */
  padding: 0 26px;
  height: 52px;
  margin-bottom: 0 !important;
  font-size: 12px;
  letter-spacing: 0.1em;
}

.bv-score-lock {
  background: rgba(34, 197, 94, 0.16) !important;
  border: 1px solid rgba(34, 197, 94, 0.4) !important;
  color: #4ade80 !important;
}

.bv-score-lock:hover {
  background: rgba(34, 197, 94, 0.26) !important;
  border-color: rgba(34, 197, 94, 0.6) !important;
}

/* Second click of the two-step confirm. Was four style-attribute writes
   inside the handler. */
.bv-score-lock.is-confirming {
  background: rgba(239, 68, 68, 0.18) !important;
  border-color: rgba(239, 68, 68, 0.45) !important;
  color: #f87171 !important;
}

.bv-score-locked {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 20px;
  padding: 16px;
  border-radius: 14px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.22);
}

@media (max-width: 640px) {
  .bv-judge-context { padding: 16px 18px; }
  .bv-score-head { padding: 18px; }
  .bv-score-body { padding: 18px; }
  .bv-score-actions > .bv-btn { width: 100% !important; }
  .bv-score-total { justify-content: center; text-align: center; }
}

/* ═══════════════════════════════════════════════════════════════════
   JUDGING DECK  —  resources/views/judge/deck.blade.php

   One contestant per screen, for a judge holding a tablet in a dark
   auditorium. Everything here is sized for that: the contestant number
   and the score field are the two things readable at arm's length, and
   the two navigation buttons sit under the thumbs at the bottom edge.

   Sized in ch/px rather than with Tailwind utilities — this build emits
   no spacing or colour scale (see beevote-frontend-pipeline). Reflow is
   driven by container width via auto-fit, not by viewport breakpoints,
   because a tablet in landscape inside the dashboard shell is not the
   width the viewport reports.
   ═══════════════════════════════════════════════════════════════════ */

.bv-deck {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 24px 24px 8px;
  box-sizing: border-box;
  min-height: calc(100vh - 64px);
}

/* ── Stage rail ─────────────────────────────────────────────────── */
.bv-deck-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
}

.bv-deck-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  color: rgba(255, 255, 255, 0.6);
  text-decoration: none;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.07);
  transition: color 0.2s, border-color 0.2s;
}

.bv-deck-back:hover {
  color: #FFB400;
  border-color: rgba(255, 180, 0, 0.35);
}

.bv-deck-stages {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
}

.bv-deck-stage {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.45);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.bv-deck-stage:hover {
  color: rgba(255, 255, 255, 0.8);
}

.bv-deck-stage.is-open {
  color: #0a1628;
  background: #FFB400;
  border-color: #FFB400;
}

/* A stage this judge has closed. Reachable — a judge may want to see
   what they gave — but visibly finished. */
.bv-deck-stage.is-done {
  color: #4ade80;
  border-color: rgba(34, 197, 94, 0.3);
}

.bv-deck-stage.is-done.is-open {
  color: #0a1628;
  background: #4ade80;
  border-color: #4ade80;
}

.bv-deck-who {
  flex-shrink: 0;
}

/* ── Progress ───────────────────────────────────────────────────── */
.bv-deck-progress {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 18px;
  padding: 16px 20px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-deck-progress__label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.bv-deck-progress__stage {
  font-size: 17px;
  font-weight: 900;
  letter-spacing: -0.01em;
  color: #fff;
}

.bv-deck-progress__share {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-deck-progress__count {
  margin-left: auto;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #FFB400;
  white-space: nowrap;
}

/* The rail doubles as the map and the jump control: a judge who wants to
   revisit #3 taps #3 rather than swiping back through two cards. */
.bv-deck-rail {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
}

/* The crown a run of numbers belongs to. Contestant numbers restart at 01
   in each division, so without this the rail reads 01 02 01 02 with nothing
   explaining the repeat. Full-width so it forces a wrap and each crown
   starts its own line -- the boundary has to be visible at a glance to a
   judge holding a tablet in a dark auditorium. */
.bv-deck-rail__crown {
  flex: 0 0 100%;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bv-gold, #b8862b);
}

.bv-deck-rail__crown:first-child {
  margin-top: 0;
}

/* The rounds an award is decided on. A wrapping row of checkboxes rather
   than a multi-select: a multi-select hides how many are chosen behind a
   scroll, and 'which rounds decide the crown' is a question the organizer
   has to be able to answer at a glance before the show starts. */
.bv-award-scope {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin-top: 4px;
}

.bv-award-scope__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  cursor: pointer;
}

.bv-award-scope__item input {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  cursor: pointer;
}

/* The cut control on a round's roster panel. One row: a number and the
   button that proposes the cut, kept on the panel it applies to so the
   round is never ambiguous. */
.bv-roster__advance {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 10px 0 14px;
  padding-top: 12px;
  border-top: 1px solid var(--bv-rule, rgba(255,255,255,.08));
}

.bv-roster__advance .bv-label {
  margin: 0;
}

.bv-roster__advance input[type="number"] {
  width: 72px;
  flex: 0 0 auto;
}

.bv-deck-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.03) !important;
  border: 1px solid rgba(255, 255, 255, 0.08) !important;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}

/* Scored. Not the same as "current" — a judge needs both at a glance. */
.bv-deck-dot.is-done {
  color: #4ade80;
  border-color: rgba(34, 197, 94, 0.35) !important;
  background: rgba(34, 197, 94, 0.08) !important;
}

.bv-deck-dot.is-at {
  color: #0a1628;
  background: #FFB400 !important;
  border-color: #FFB400 !important;
}

.bv-deck-dot--review {
  color: rgba(255, 255, 255, 0.55);
}

.bv-deck-sealed {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-radius: 14px;
  font-size: 13px;
  font-weight: 600;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.22);
}

/* ── Panels ─────────────────────────────────────────────────────── */
.bv-deck-track {
  position: relative;
  flex: 1;
  display: flex;
}

.bv-deck-panel {
  display: none;
  flex-direction: column;
  gap: 22px;
  width: 100%;
  padding: 28px;
  box-sizing: border-box;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-deck-panel.is-on {
  display: flex;
}

/* The slide. Direction carries meaning — forward comes from the right,
   back from the left — so a judge can tell a correction from an advance
   without reading the counter. */
.bv-deck-panel.is-in-right { animation: bv-deck-right 0.22s ease-out; }
.bv-deck-panel.is-in-left  { animation: bv-deck-left  0.22s ease-out; }

@keyframes bv-deck-right {
  from { opacity: 0; transform: translateX(36px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes bv-deck-left {
  from { opacity: 0; transform: translateX(-36px); }
  to   { opacity: 1; transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .bv-deck-panel.is-in-right,
  .bv-deck-panel.is-in-left { animation: none; }
}

/* ── Identity ───────────────────────────────────────────────────── */
.bv-deck-identity {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}

/* A portrait, not a thumbnail. The brief is that the screen belongs to one
   contestant, and the seeded placeholders are 400x500 -- cropping those to a
   132px square threw away most of the picture and most of the point. Sized
   against the viewport so a phone, a tablet in portrait and a tablet in
   landscape each get as much portrait as they can afford, capped so it never
   pushes the score fields below the fold. */
.bv-deck-photo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: clamp(150px, 26vw, 240px);
  aspect-ratio: 4 / 5;
  height: auto;
  border-radius: 20px;
  object-fit: cover;
  /* Faces sit in the upper half of a portrait; centring the crop cuts heads. */
  object-position: top center;
  background: rgba(255, 180, 0, 0.08);
  border: 2px solid rgba(255, 180, 0, 0.5);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}

.bv-deck-photo--none {
  font-size: clamp(32px, 4vw, 52px);
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #FFB400;
}

.bv-deck-who-block {
  min-width: 0;
}

/* The number is the largest thing on the card on purpose: it is what the
   host calls and what the judge matches against the stage. */
.bv-deck-number {
  font-size: 58px;
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: #FFB400;
}

.bv-deck-name {
  margin: 6px 0 0;
  font-size: 26px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-deck-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-deck-meta__dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
}

/* ── Fields ─────────────────────────────────────────────────────── */
.bv-deck-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px;
  align-items: start;
}

/* A heading only appears when the stage has more than one group under it,
   so a flat stage does not grow a redundant label. */
.bv-deck-group {
  grid-column: 1 / -1;
  padding-top: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-deck-field {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
  transition: border-color 0.2s;
}

.bv-deck-field:focus-within {
  border-color: rgba(255, 180, 0, 0.4);
}

.bv-deck-field__name {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
}

.bv-deck-field__share {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-deck-field__entry {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* The global `input` rule sets padding with !important, so the touch
   target has to out-shout it. 64px tall, 30px digits: legible and
   hittable without looking, which is the condition a judge is in. */
.bv-deck-input {
  flex: 1;
  min-width: 0;
  height: 64px;
  padding: 0 18px !important;
  font-size: 30px !important;
  font-weight: 800 !important;
  text-align: center;
  letter-spacing: -0.02em;
  border-radius: 14px !important;
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
}

.bv-deck-input:focus {
  border-color: rgba(255, 180, 0, 0.5) !important;
  box-shadow: 0 0 0 4px rgba(255, 180, 0, 0.1) !important;
}

.bv-deck-input[readonly] {
  color: rgba(255, 255, 255, 0.55) !important;
  background: rgba(255, 255, 255, 0.02) !important;
}

.bv-deck-field__max {
  flex-shrink: 0;
  font-size: 15px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.3);
}

.bv-deck-total {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 10px;
  margin-top: auto;
  padding: 20px 24px;
  border-radius: 16px;
  background: rgba(255, 180, 0, 0.06);
  border: 1px solid rgba(255, 180, 0, 0.18);
}

.bv-deck-total__label {
  margin-right: auto;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
}

.bv-deck-total__value {
  font-size: 38px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.03em;
  color: #FFB400;
}

.bv-deck-total__max {
  font-size: 14px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.3);
}

/* ── Review ─────────────────────────────────────────────────────── */
.bv-deck-review-title {
  margin: 0;
  font-size: 24px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-deck-review-sub {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.45);
}

.bv-deck-review-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.bv-deck-review-row {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 16px 20px;
  border-radius: 14px;
  text-align: left;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
  transition: border-color 0.2s, background 0.2s;
}

.bv-deck-review-row:hover {
  border-color: rgba(255, 180, 0, 0.35);
  background: rgba(255, 255, 255, 0.05);
}

/* A contestant the judge left blank. The submit button refuses while any
   of these exist, and this is where it sends them. */
.bv-deck-review-row.is-missing {
  border-color: rgba(239, 68, 68, 0.4);
  background: rgba(239, 68, 68, 0.07);
}

.bv-deck-review-row__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 900;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.22);
}

.bv-deck-review-row__name {
  flex: 1;
  min-width: 0;
  font-size: 16px;
  font-weight: 700;
  color: #fff;
}

.bv-deck-review-row__score {
  font-size: 22px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-deck-review-row.is-missing .bv-deck-review-row__score {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #f87171;
}

.bv-deck-review-row__go {
  flex-shrink: 0;
  color: rgba(255, 255, 255, 0.25);
}

/* ── Skipped ────────────────────────────────────────────────────── */
.bv-deck-skipped {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.1);
}

.bv-deck-skipped__head {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-deck-skipped__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
}

.bv-deck-skipped__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.bv-deck-skipped__name {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.55);
}

.bv-deck-skipped__note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

.bv-deck-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 40px;
  border-radius: 16px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.08);
}

.bv-deck-final {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 20px;
  border-radius: 14px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.22);
}

.bv-deck-submit {
  padding: 20px !important;
  font-size: 14px !important;
  color: #0a1628 !important;
  background: #FFB400 !important;
  border: 1px solid #FFB400 !important;
}

.bv-deck-submit:hover {
  background: #ffc233 !important;
}

/* Armed for the second tap. Red, because this is the only thing a judge
   does that cannot be undone. */
.bv-deck-submit.is-armed {
  color: #fff !important;
  background: rgba(239, 68, 68, 0.9) !important;
  border-color: rgba(239, 68, 68, 0.9) !important;
}

.bv-deck-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.bv-deck-review-warn:empty {
  display: none;
}

.bv-deck-review-warn {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  color: #f87171;
}

/* ── Footer navigation ──────────────────────────────────────────── */
/* Sticky rather than static: on a tall card the judge's thumbs should
   not have to chase the buttons down the page. */
.bv-deck-nav {
  position: sticky;
  bottom: 0;
  display: flex;
  gap: 14px;
  padding: 14px 0 18px;
  background: linear-gradient(to top, #0a1628 55%, rgba(10, 22, 40, 0));
}

/* .bv-btn is width:100%, which in a flex row claims the whole container
   as its basis and starves its sibling. Out-specified here rather than by
   editing .bv-btn, which ~20 views depend on. */
.bv-deck-nav > .bv-btn {
  flex: 1;
  width: auto !important;
  padding: 20px !important;
  font-size: 14px !important;
}

.bv-deck-prev {
  max-width: 200px;
}

.bv-deck-next {
  color: #0a1628 !important;
  background: #FFB400 !important;
  border: 1px solid #FFB400 !important;
}

.bv-deck-next:hover {
  background: #ffc233 !important;
}

/* Disabled means "this contestant is not fully scored yet", which is the
   whole gate. It has to look unavailable, not merely dimmed. */
.bv-deck-next:disabled {
  color: rgba(255, 255, 255, 0.3) !important;
  background: rgba(255, 255, 255, 0.04) !important;
  border-color: rgba(255, 255, 255, 0.08) !important;
  cursor: not-allowed;
}

.bv-deck-next.is-hidden {
  display: none;
}

@media (max-width: 700px) {
  .bv-deck { padding: 16px 16px 8px; gap: 14px; }
  .bv-deck-panel { padding: 20px; gap: 18px; }
  .bv-deck-photo { width: 124px; }
  .bv-deck-number { font-size: 44px; }
  .bv-deck-name { font-size: 21px; }
  .bv-deck-total { flex-wrap: wrap; justify-content: space-between; }
  .bv-deck-total__value { font-size: 30px; }
  .bv-deck-nav > .bv-btn { padding: 17px !important; }
  .bv-deck-prev { max-width: 130px; }
  .bv-deck-who { display: none; }
}

/* ── JUDGING PORTAL CARDS ─────────────────────────────────────────
   The portal was drawn in dead utilities and style attributes; these
   are the real rules behind judge/dashboard.blade.php. */
.bv-judge-card__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 20px;
}

.bv-judge-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  font-size: 17px;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.22);
}

.bv-judge-card__title {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: #fff;
}

.bv-judge-card__desc {
  margin: 0 0 20px;
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

.bv-judge-card__facts {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

.bv-judge-card__fact {
  flex: 1;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-judge-card__fact span {
  display: block;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-judge-card__fact strong {
  display: block;
  margin-top: 4px;
  font-size: 20px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-judge-card__stages {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 20px;
}

.bv-judge-card__stage {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-judge-card__stage.is-done {
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.25);
}

.bv-judge-empty {
  grid-column: 1 / -1;
  background: transparent !important;
  border: 1px dashed rgba(255, 255, 255, 0.08) !important;
}

.bv-judge-empty .bv-card__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 60px 20px !important;
  color: rgba(255, 255, 255, 0.25);
}

/* ── RUNNING ORDER (COMELEC roster control) ───────────────────────
   Lives on the tabulation screen because the person watching the
   standing is the person who knows number 5 is not in the wings. */
.bv-roster__intro {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 20px;
  font-size: 13px;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.45);
}

.bv-roster__intro strong {
  color: #FFB400;
}

.bv-roster__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}

.bv-roster__tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.45);
  background: rgba(255, 255, 255, 0.03) !important;
  border: 1px solid rgba(255, 255, 255, 0.07) !important;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.bv-roster__tab.is-on {
  color: #0a1628;
  background: #FFB400 !important;
  border-color: #FFB400 !important;
}

.bv-roster__tab-lock {
  font-size: 9px;
  opacity: 0.7;
}

.bv-roster__stage {
  display: none;
  flex-direction: column;
  gap: 8px;
}

.bv-roster__stage.is-on {
  display: flex;
}

.bv-roster__state {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 14px 16px;
  margin-bottom: 6px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.05);
}

.bv-roster__state-note {
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

.bv-roster__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding: 12px 16px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-roster__row.is-out {
  background: rgba(255, 255, 255, 0.012);
  border-style: dashed;
}

.bv-roster__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  font-size: 13px;
  font-weight: 900;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.09);
  border: 1px solid rgba(255, 180, 0, 0.2);
}

.bv-roster__row.is-out .bv-roster__num {
  color: rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.03);
  border-color: rgba(255, 255, 255, 0.07);
}

.bv-roster__name {
  flex: 1;
  min-width: 160px;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
}

.bv-roster__row.is-out .bv-roster__name {
  color: rgba(255, 255, 255, 0.4);
}

.bv-roster__status {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.bv-roster__note {
  font-size: 11px;
  font-style: italic;
  color: rgba(255, 255, 255, 0.3);
}

.bv-roster__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.bv-roster__btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.04) !important;
  border: 1px solid rgba(255, 255, 255, 0.09) !important;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.bv-roster__btn:hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.2) !important;
}

.bv-roster__btn--cut:hover {
  color: #f87171;
  border-color: rgba(239, 68, 68, 0.4) !important;
}

.bv-roster__btn.is-armed {
  color: #fff !important;
  background: rgba(239, 68, 68, 0.85) !important;
  border-color: rgba(239, 68, 68, 0.85) !important;
}

.bv-roster__btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* A contestant who was cut still appears in the standing, ranked below
   everyone still competing. Dimmed so the line between the two groups is
   visible without reading the note. */
.bv-table tr.bv-row--out td {
  opacity: 0.55;
}

/* Cards in the portal grid are equal height, with the action pinned to the
   bottom edge so a row of them does not step. */
.bv-judge-card > .bv-card__body {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.bv-judge-card > .bv-card__body > .bv-btn {
  margin-top: auto;
}

/* The review panel is read, not filled in, so it is capped at a comfortable
   measure instead of stretching to a 1200px tablet in landscape. */
.bv-deck-panel--review {
  max-width: 820px;
  margin: 0 auto;
}

.bv-deck-review-head {
  padding-bottom: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* ── DECK: LANDSCAPE PANEL ────────────────────────────────────────
   Stacked, the portrait and the score fields do not fit one tablet
   screen: on a 1024x768 tablet the sidebar leaves ~790px of content,
   and rail + progress + a 300px portrait + fields + total + the
   sticky nav runs about 825px. The judge would scroll to reach the
   inputs, which is the one thing the brief rules out — picture,
   number and score are meant to be on screen together.

   So above 1000px the panel becomes two columns: the contestant on
   the left, the criteria stacked on the right. The portrait gets
   bigger rather than smaller, because it now has a column of its own.

   Keyed on the viewport rather than the container because the panel
   has no container query support to rely on here; 1000px viewport is
   ~770px of content, which is the width at which two columns stop
   squeezing the inputs. */
@media (min-width: 1000px) {
  .bv-deck-panel.is-on {
    display: grid;
    grid-template-columns: minmax(230px, 330px) 1fr;
    grid-template-areas:
      "who fields"
      "who total";
    /* Rows, explicitly. The identity column spans both, so whichever row is
       left to absorb the portrait's extra height decides where the slack
       goes. Unspecified, it landed in the TOTAL row and stretched a 75px
       box into a ~350px slab. Given to the fields row instead: the criteria
       breathe, and the total stays its own size. */
    grid-template-rows: 1fr auto;
    column-gap: 34px;
    row-gap: 20px;
  }

  .bv-deck-identity {
    grid-area: who;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  /* The number goes ABOVE the portrait, not below it. Measured at
     1280x720 with the portrait first, the name block landed at y=659
     -- under the sticky nav and off the screen -- which put the one
     thing the host actually calls out where the judge cannot see it.
     Ordered rather than reordered in the markup so the DOM still reads
     photo-then-name for assistive tech. */
  .bv-deck-who-block {
    order: -1;
  }

  /* Its own column now, so it is no longer competing with the inputs
     for width. Capped by height rather than width: uncapped it resolved
     to 363px from the 4:5 ratio and pushed the total row off screen.
     object-fit crops the overflow, and the crop is top-anchored. */
  .bv-deck-photo {
    width: 100%;
    max-width: none;
    max-height: 46vh;
  }

  /* 58px is right when the number sits beside a small photo; in this
     column it is competing with a portrait for the same vertical space. */
  .bv-deck-number {
    font-size: 46px;
  }

  .bv-deck-fields {
    grid-area: fields;
    grid-template-columns: 1fr;
    align-content: stretch;
    /* The row has to be told to take the space too, or the container grows
       and the cards sit at the top of it -- which is the same void, just
       moved inside an element with no background. */
    grid-auto-rows: minmax(150px, 1fr);
    /* And the base rule sets `align-items: start`, which pins every card to
       the top of its row no matter how tall the row is. That was the reason
       a 439px row still held a 153px card. */
    align-items: stretch;
  }

  /* A criterion card that has grown taller centres its input rather than
     leaving it stranded at the top of the extra space. */
  .bv-deck-field {
    justify-content: center;
  }

  /* align-self, because the default is `stretch` and the identity column
     spans BOTH rows: the total row therefore inherits whatever height the
     portrait leaves over, and the total box grew to fill it — a ~350px
     slab holding one number, next to a photo it dwarfed. Anchored to the
     end so its bottom edge lines up with the portrait's instead. */
  .bv-deck-total {
    grid-area: total;
    align-self: end;
    margin-top: 0;
    padding: 18px 24px;
  }
}

/* Wider still — a desktop or a large tablet in landscape — and the
   criteria can sit two across again without cramping. */
@media (min-width: 1500px) {
  .bv-deck-fields {
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  }
}

/* ═══════════════════════════════════════════════════════════════════
   DIGITAL BALLOT — redesign
   ═══════════════════════════════════════════════════════════════════ */

/* ── Contestant number ──
   Sits on the portrait, not under the name. A pageant audience is told
   "vote for number 3"; the number has to be findable at a glance down
   a grid of faces, which it is not when it trails the name in body
   text. Same numbering the judges' decks use. */
.bv-ballot-number {
  position: absolute;
  left: 10px;
  bottom: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 10px;
  border-radius: 12px;
  font-size: 17px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #0a1628;
  background: #FFB400;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}

/* ── Selection ──
   This is the single most important state on the screen and it was a
   26px ring in the corner. Bigger, and the whole card now lifts. */
.bv-ballot-check {
  top: 12px;
  right: 12px;
  width: 34px;
  height: 34px;
  font-size: 15px;
}

.bv-ballot-input:checked + .bv-ballot-card {
  border: 2px solid #FFB400 !important;
  border-top: 2px solid #FFB400 !important;
  background: rgba(255, 180, 0, 0.09) !important;
  box-shadow: 0 0 0 1px rgba(255, 180, 0, 0.35), 0 10px 34px rgba(255, 180, 0, 0.16) !important;
}

/* Unselected cards recede once a pick is made in that race, so the
   chosen face is the one the eye lands on. */
.bv-ballot-input:checked + .bv-ballot-card .bv-ballot-name {
  color: #FFB400;
}

/* ── Header ── */
.bv-ballot-pool {
  color: #fff;
  font-weight: 700;
}

.bv-ballot-session {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 18px;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.3);
}

/* ── Live per-race count ──
   The badge read "REQUIRED: 1 CHOICE" and never changed, so on a long
   ballot a voter could not tell which races they had already filled
   without scrolling back through all of them. */
.bv-ballot-count {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.45);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.bv-ballot-count.is-done {
  color: #4ade80;
  background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.3);
}

/* ── Review and commit ──
   Replaces a 3rem-padded box holding a heading, two lines of copy and
   a button — about 300px of vertical space that told the voter nothing
   about what they were making permanent. The ballot is irreversible
   and anonymous; the last thing on screen before committing should be
   the selection itself. */
.bv-ballot-commit {
  display: grid;
  grid-template-columns: 1fr minmax(280px, 380px);
  gap: 28px;
  align-items: center;
  margin-top: 36px;
  padding: 26px 28px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 180, 0, 0.28);
}

/* min-width:0 so a long candidate name wraps inside the column instead
   of forcing the grid track wider and squeezing the action column. */
.bv-ballot-commit__review {
  min-width: 0;
}

.bv-ballot-commit__eyebrow {
  display: block;
  margin-bottom: 14px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-ballot-commit__list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.bv-ballot-commit__empty {
  font-size: 14px;
  font-style: italic;
  color: rgba(255, 255, 255, 0.3);
}

.bv-ballot-commit__pick {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 9px;
  border-radius: 999px;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.3);
}

.bv-ballot-commit__pick-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 900;
  color: #0a1628;
  background: #FFB400;
}

.bv-ballot-commit__pick-name {
  font-size: 14px;
  font-weight: 700;
  color: #fff;
}

.bv-ballot-commit__action {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.bv-ballot-commit__warn {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.4);
}

.bv-ballot-commit__warn i {
  margin-top: 2px;
  color: #FFB400;
}

.bv-ballot-commit__btn {
  padding: 18px 24px !important;
  font-size: 13px !important;
  color: #0a1628 !important;
  background: #FFB400 !important;
  border: 1px solid #FFB400 !important;
}

.bv-ballot-commit__btn:hover:not(:disabled) {
  background: #ffc233 !important;
}

/* Disabled means "this ballot is not complete yet", which is the whole
   gate. It has to look unavailable rather than merely dimmed. */
.bv-ballot-commit__btn:disabled {
  color: rgba(255, 255, 255, 0.3) !important;
  background: rgba(255, 255, 255, 0.04) !important;
  border-color: rgba(255, 255, 255, 0.09) !important;
  cursor: not-allowed;
}

@media (max-width: 900px) {
  .bv-ballot-commit {
    grid-template-columns: 1fr;
    gap: 22px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   PAGEANT AWARDS
   A pageant produces a winner, runners-up, a "best in" per round and a
   set of specials. Each card states its winner AND the basis, because
   an award with no stated basis invites exactly the question it
   cannot answer.
   ═══════════════════════════════════════════════════════════════════ */

.bv-is-hidden {
  display: none !important;
}

.bv-award-empty {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 24px;
  font-size: 13px;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.4);
}

.bv-award-empty i {
  margin-top: 3px;
  color: #FFB400;
}

.bv-award-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  margin-bottom: 26px;
}

.bv-award {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px 20px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

/* Decided reads gold, because it is a result. Undecided stays neutral
   and dashed so a board mid-event does not look like six failures. */
.bv-award--decided {
  border-color: rgba(255, 180, 0, 0.32);
  background: rgba(255, 180, 0, 0.05);
}

.bv-award--tied {
  border-color: rgba(239, 68, 68, 0.35);
  background: rgba(239, 68, 68, 0.05);
}

.bv-award--undecided {
  border-style: dashed;
}

.bv-award__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.bv-award__name {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.bv-award--decided .bv-award__name,
.bv-award--tied .bv-award__name {
  color: #FFB400;
}

.bv-award__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 8px;
  font-size: 11px;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.3);
  background: transparent !important;
  border: 1px solid rgba(255, 255, 255, 0.08) !important;
  transition: color 0.2s, border-color 0.2s;
}

.bv-award__remove:hover {
  color: #f87171;
  border-color: rgba(239, 68, 68, 0.4) !important;
}

.bv-award__winners {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.bv-award__winner {
  display: flex;
  align-items: center;
  gap: 12px;
}

.bv-award__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  min-width: 38px;
  height: 38px;
  padding: 0 9px;
  border-radius: 11px;
  font-size: 14px;
  font-weight: 900;
  color: #0a1628;
  background: #FFB400;
}

.bv-award__who {
  font-size: 17px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: #fff;
}

.bv-award__value {
  font-size: 20px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-award__value span {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-award__tied {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #f87171;
}

.bv-award__pending {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-award__basis {
  font-size: 11px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

/* ── Add form ── */
.bv-award-add {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
  padding-top: 22px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-award-add__row {
  flex: 1;
  min-width: 190px;
}

.bv-award-add__row--go {
  flex: 0 0 auto;
  min-width: 0;
}

/* .bv-btn is width:100%, which in this flex row would claim the whole
   container as its basis and starve every field beside it. */
.bv-award-add__row--go > .bv-btn {
  width: auto !important;
}

.bv-award-add__note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  padding: 12px 14px;
  border-radius: 10px;
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.bv-award-add__note i {
  margin-top: 2px;
  color: #FFB400;
}

/* ═══════════════════════════════════════════════════════════════════
   PRINT
   Until now the app had NO print rules at all — not one @media print
   block in either stylesheet — so window.print() sent the dark-navy
   application UI to paper verbatim. What came out, measured against a
   real print preview: the sidebar, the topbar, the theme toggle, the
   PRINT button itself, and the Running Order CONTROL PANEL with its
   round tabs and status badges; the fixed footer collapsed on top of
   the Awards section; and it ended at page 1 of 1, so the standing and
   the per-judge breakdown — the only things a tabulator needs — never
   printed at all.

   Two other things fight this by default: `body { color: white }` with
   `background: #0a1628 !important`, and browsers printing backgrounds
   OFF unless the user ticks the box. So the theme drops out and the
   white text lands on white paper.
   ═══════════════════════════════════════════════════════════════════ */

/* Shown only on paper. Kept out of the screen flow entirely rather than
   with visibility, so it takes no space and is not read out. */
.bv-print-only {
  display: none;
}

@media print {

  @page {
    margin: 14mm 12mm;
  }

  /* Every colour is restated because the theme sets them !important and
     because a printer that drops backgrounds would otherwise leave the
     white body text invisible on white paper. */
  html, body {
    background: #fff !important;
    background-image: none !important;
    color: #000 !important;
    font-size: 10pt;
  }

  /* The shell. None of it is content. The footer matters most: it is
     position:fixed, which in print repeats on every page and lands on
     top of whatever is underneath — visible in the preview as the
     copyright line sitting across the Awards section. */
  .bv-sidebar,
  .bv-topbar,
  .bv-app-footer,
  .bv-sidebar-backdrop,
  .bv-hamburger,
  .bv-theme-toggle,
  .bv-toast-container,
  #bv-toast-container {
    display: none !important;
  }

  .bv-dashboard-layout,
  .bv-main-content,
  .bv-main-content > main {
    display: block !important;
    height: auto !important;
    width: auto !important;
    overflow: visible !important;
    padding: 0 !important;
    margin: 0 !important;
    background: none !important;
  }

  .bv-page {
    padding: 0 !important;
    min-height: 0 !important;
  }

  /* Anything that performs an action cannot be actioned on paper. */
  .bv-btn,
  button,
  select,
  input,
  .bv-roster__btn,
  .bv-award__remove {
    display: none !important;
  }

  .bv-print-only {
    display: block !important;
  }

  /* Panels become plain ruled blocks. The glass treatment is all
     translucency and shadow, neither of which survives paper. */
  .bv-card,
  .glass-card,
  .glass-panel,
  .bv-card--lg {
    background: none !important;
    border: 1px solid #999 !important;
    border-top: 1px solid #999 !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    border-radius: 0 !important;
    break-inside: auto;
  }

  .bv-card__body {
    padding: 8pt !important;
  }

  .bv-section {
    break-inside: auto;
    margin-bottom: 10pt !important;
  }

  .bv-section__heading h2,
  .bv-page-title,
  .bv-page-heading {
    color: #000 !important;
    font-size: 12pt !important;
  }

  /* Measured white-on-white: .bv-page-header p is rgba(255,255,255,0.4),
     which survives the theme drop and prints invisibly. Every page has
     one, so this is fixed globally rather than per screen. */
  .bv-page-header p,
  .bv-page-subheading,
  .bv-card__meta,
  .bv-label {
    color: #333 !important;
  }

  /* On the tabulation sheet the screen header is redundant — the printed
     document header above it already carries the event, the venue and the
     timestamp — and printing both reads as a mistake. */
  .bv-print-doc > .bv-page-header {
    display: none !important;
  }

  /* ── Tables ──
     thead as a header group so a standing that runs over a page repeats
     its column names; without it page two is a grid of bare numbers. */
  .bv-table {
    width: 100% !important;
    border-collapse: collapse !important;
    font-size: 8.5pt !important;
  }

  .bv-table thead {
    display: table-header-group;
  }

  .bv-table th,
  .bv-table td {
    padding: 4pt 5pt !important;
    color: #000 !important;
    border: 1px solid #999 !important;
    background: none !important;
  }

  .bv-table th {
    font-weight: 700 !important;
    background: #eee !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .bv-table tr {
    break-inside: avoid;
  }

  /* A cut contestant is dimmed on screen. On paper opacity prints as
     grey mush, so the fact is carried by the note in the cell instead. */
  .bv-table tr.bv-row--out td {
    opacity: 1 !important;
    color: #444 !important;
  }

  .bv-log-scroll {
    overflow: visible !important;
    max-height: none !important;
  }

  .bv-tab-sub,
  .bv-log-actor__name,
  .bv-status-source {
    color: #333 !important;
  }

  .bv-badge {
    color: #000 !important;
    background: none !important;
    border: 1px solid #999 !important;
    padding: 1pt 4pt !important;
    font-size: 7.5pt !important;
  }

  /* ─────────────────────────────────────────────────────────────────
     THE TABULATION SHEET
     ───────────────────────────────────────────────────────────────── */

  /* The Running Order panel is a live control — round tabs, Absent and
     Eliminate buttons, "round closed" notes. Printing it put a page of
     switches on paper. The same facts print as a plain list from
     .bv-print-exclusion instead. */
  .bv-print-doc [data-bv="roster"],
  .bv-print-doc .bv-award-add {
    display: none !important;
  }

  .bv-print-head {
    margin-bottom: 10pt;
    padding-bottom: 6pt;
    border-bottom: 2px solid #000;
  }

  .bv-print-head__org {
    font-size: 8pt;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #444;
  }

  .bv-print-head__title {
    margin: 2pt 0 0;
    font-size: 17pt;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: #000;
  }

  .bv-print-head__event {
    margin-top: 1pt;
    font-size: 11pt;
    font-weight: 600;
    color: #222;
  }

  .bv-print-meta {
    width: 100%;
    margin-top: 7pt;
    border-collapse: collapse;
    font-size: 8.5pt;
  }

  .bv-print-meta th {
    width: 15%;
    padding: 2pt 6pt 2pt 0;
    text-align: left;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #555;
  }

  .bv-print-meta td {
    width: 35%;
    padding: 2pt 10pt 2pt 0;
    color: #000;
  }

  .bv-print-block {
    margin-top: 10pt;
    break-inside: avoid;
  }

  .bv-print-block__title {
    margin: 0 0 5pt;
    padding-bottom: 2pt;
    font-size: 10pt;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #000;
    border-bottom: 1px solid #999;
  }

  .bv-print-exclusion {
    margin-bottom: 3pt;
    font-size: 8.5pt;
    color: #000;
  }

  .bv-print-exclusion__round {
    font-weight: 700;
  }

  .bv-print-exclusion__round::after {
    content: ' — ';
  }

  /* ── Awards on paper ── */
  .bv-print-doc .bv-award-grid {
    display: block !important;
  }

  .bv-print-doc .bv-award {
    display: block !important;
    padding: 4pt 0 !important;
    border: 0 !important;
    border-bottom: 1px solid #ccc !important;
    border-radius: 0 !important;
    background: none !important;
    break-inside: avoid;
  }

  .bv-print-doc .bv-award__name {
    color: #000 !important;
    font-size: 8.5pt !important;
  }

  .bv-print-doc .bv-award__who {
    font-size: 11pt !important;
    color: #000 !important;
  }

  .bv-print-doc .bv-award__num {
    color: #000 !important;
    background: none !important;
    border: 1px solid #999 !important;
    min-width: 0 !important;
    height: auto !important;
    padding: 0 3pt !important;
    font-size: 8.5pt !important;
  }

  /* The unit span carries its own colour at a deeper selector, so it
     survived the parent's override and printed white on white. */
  .bv-print-doc .bv-award__value span,
  .bv-print-doc .bv-award__value,
  .bv-print-doc .bv-award__basis,
  .bv-print-doc .bv-award__pending,
  .bv-print-doc .bv-award__tied {
    color: #333 !important;
    font-size: 8pt !important;
  }

  /* ── Certification ──
     The reason to print the sheet at all: it becomes the record of the
     night once the panel signs it, and there was nowhere to sign. */
  .bv-print-sign {
    margin-top: 14pt;
    break-inside: avoid;
  }

  .bv-print-sign__oath {
    margin: 0 0 12pt;
    font-size: 8.5pt;
    line-height: 1.5;
    color: #222;
  }

  .bv-print-sign__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20pt 24pt;
  }

  .bv-print-sign__slot {
    break-inside: avoid;
  }

  .bv-print-sign__line {
    display: block;
    height: 20pt;
    border-bottom: 1px solid #000;
  }

  .bv-print-sign__name {
    display: block;
    margin-top: 2pt;
    font-size: 9pt;
    font-weight: 700;
    color: #000;
  }

  .bv-print-sign__role {
    display: block;
    font-size: 7.5pt;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #555;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   ELECTION REGISTRY  —  partials/election-list.blade.php
   Shared by Batch, Real-time and Pageant Events, which were three
   copies of the same 330-line screen.
   ═══════════════════════════════════════════════════════════════════ */

.bv-elist-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
}

.bv-elist-head__text {
  min-width: 0;
}

/* ── The button fix ──
   `.bv-btn--primary` is `display: block !important; width: 100% !important`.
   Two consequences, both visible on these screens:

     display:block  — the button stops being the flex container .bv-btn
                      declares, so it loses `gap: 8px` and the icon fuses
                      onto the label. "LIVE MONITOR" with a glyph stuck to
                      it was a correctly-rendered icon with no space in
                      front of it, not a stray emoji.
     width:100%     — beats an inline `style="width:auto"`, because a
                      stylesheet !important outranks a non-important inline
                      style. Hence a Create Election button spanning the
                      entire page.

   Not fixed by editing `.bv-btn--primary`: ~20 views rely on it being a
   full-width block. Out-specified here at two classes deep instead. */
.bv-elist-head > .bv-btn,
.bv-elist-actions > .bv-btn,
.bv-elist-empty > .bv-btn {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: auto !important;
  margin-bottom: 0 !important;
  white-space: nowrap;
}

/* An icon-only button is a square, and the `width: auto !important` above
   takes that away from it. That rule exists to stop `.bv-btn--primary`
   stretching a LABELLED button across the row, but it is written two
   classes deep, so it also outranks `.bv-elist-icon`'s own
   `width: 36px !important` one class deep — collapsing Tabulation and
   Delete to the width of their glyph. Measured before this: 16.05px wide
   against a declared 36px, which is the amber sliver beside RESULTS and
   LIVE MONITOR on Pageant Events.

   Restored at three classes deep so it outranks the rule above without
   editing it. In the actions row the square also drops to 32px, matching
   the height of the `.bv-elist-go` pill it sits beside — at 36 against 32
   the two did not line up. */
.bv-elist-head > .bv-btn.bv-elist-icon,
.bv-elist-empty > .bv-btn.bv-elist-icon {
  width: 36px !important;
  flex-shrink: 0;
}

.bv-elist-actions > .bv-btn.bv-elist-icon {
  width: 32px !important;
  height: 32px !important;
  flex-shrink: 0;
}

.bv-elist-head > .bv-btn {
  padding: 13px 26px !important;
}

/* ── Table ── */
.bv-elist__table {
  min-width: 900px;
}

.bv-elist__actions-col {
  text-align: right;
}

/* The group row was drawn in bg-slate-900/80, py-4, px-6, border-b,
   font-black, text-xs and text-blue-400 — of which this build emits
   none, so it rendered as a bare line of text with no band behind it. */
.bv-elist__group td {
  padding: 14px 20px !important;
  background: rgba(255, 255, 255, 0.035) !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
}

.bv-elist__group-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #7dabff;
}

.bv-elist__group-label.is-pageant {
  color: #FFB400;
}

.bv-elist__title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
}

.bv-elist__sub {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
}

.bv-elist__type {
  font-size: 9px;
}

.bv-elist__date {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  white-space: nowrap;
}

/* ── Actions ── */
.bv-elist-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

/* Icon-only. A label would triple the width of a column that already
   carries up to four controls. */
.bv-elist-icon {
  width: 36px !important;
  height: 36px;
  padding: 0 !important;
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.04) !important;
  border: 1px solid rgba(255, 255, 255, 0.09) !important;
  transition: border-color 0.2s, background 0.2s;
}

.bv-elist-icon--gold { color: #FFB400 !important; }
.bv-elist-icon--green { color: #10b981 !important; }
.bv-elist-icon--red { color: #ef4444 !important; }

.bv-elist-icon:hover {
  background: rgba(255, 255, 255, 0.08) !important;
  border-color: rgba(255, 255, 255, 0.2) !important;
}

.bv-elist-go {
  padding: 9px 16px !important;
  font-size: 10px !important;
}

/* ── Empty ──
   One state, not two. The old screen rendered an empty table — column
   headers and all — reading "No elections have been created yet", and
   then a second card below it reading "No elections registered yet"
   with its own call to action. */
.bv-elist-empty {
  display: flex !important;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px !important;
  padding: 70px 24px !important;
  text-align: center;
}

.bv-elist-empty__icon {
  font-size: 40px;
  color: rgba(255, 255, 255, 0.14);
}

.bv-elist-empty__title {
  margin: 14px 0 0;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
}

.bv-elist-empty__copy {
  margin: 0;
  max-width: 460px;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

.bv-elist-empty__cta {
  margin-top: 20px !important;
  padding: 14px 28px !important;
}

@media (max-width: 700px) {
  .bv-elist-head { align-items: stretch; }
  .bv-elist-head > .bv-btn { width: 100% !important; }
}

/* ═══════════════════════════════════════════════════════════════════
   DISTRIBUTED LEDGER AUDIT
   Rebuilt on real figures. The stat values previously carried
   `.bv-hash` — the hash style, monospace at rgba(255,255,255,0.3),
   declared later than .bv-card__title so it won — which is why the
   headline numbers rendered at 30% opacity.
   ═══════════════════════════════════════════════════════════════════ */

.bv-verify {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 26px;
  padding: 18px 22px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.025);
}

.bv-verify.is-ok { border-color: rgba(34, 197, 94, 0.35); background: rgba(34, 197, 94, 0.07); }
.bv-verify.is-bad { border-color: rgba(239, 68, 68, 0.4); background: rgba(239, 68, 68, 0.07); }

.bv-verify__icon { font-size: 24px; }
.bv-verify.is-ok .bv-verify__icon { color: #4ade80; }
.bv-verify.is-bad .bv-verify__icon { color: #f87171; }

.bv-verify__title { font-size: 15px; font-weight: 700; color: #fff; }
.bv-verify__meta { margin-top: 3px; font-size: 12px; color: rgba(255, 255, 255, 0.4); }

/* ── Tiles ── */
.bv-audit-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
  margin-bottom: 30px;
}

.bv-audit-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 22px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-audit-tile__label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

/* Full white, not the 30%-opacity hash style the values inherited before. */
.bv-audit-tile__value {
  font-size: 26px;
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
}

.bv-audit-tile__value--num {
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 22px;
}

.bv-audit-tile__value.is-good { color: #4ade80; }
.bv-audit-tile__value.is-bad { color: #f87171; }

/* Nothing has been measured. It must not look like a pass. */
.bv-audit-tile__value.is-idle { color: rgba(255, 255, 255, 0.35); }

.bv-audit-tile__note {
  font-size: 11px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.35);
}

/* ── Provenance ── */
.bv-prov-bar {
  display: flex;
  height: 16px;
  margin-bottom: 22px;
  border-radius: 8px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.04);
}

.bv-prov-bar__band { height: 100%; }

.bv-prov-bar__band.is-onchain,   .bv-prov-item__dot.is-onchain   { background: #22c55e; }
.bv-prov-bar__band.is-simulated, .bv-prov-item__dot.is-simulated { background: #ef4444; }
.bv-prov-bar__band.is-unknown,   .bv-prov-item__dot.is-unknown   { background: #eab308; }
.bv-prov-bar__band.is-pending,   .bv-prov-item__dot.is-pending   { background: rgba(255, 255, 255, 0.28); }

.bv-prov-legend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 16px;
}

.bv-prov-item { display: flex; gap: 12px; }
.bv-prov-item.is-zero { opacity: 0.4; }

.bv-prov-item__dot {
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  margin-top: 5px;
  border-radius: 3px;
}

.bv-prov-item__body { min-width: 0; }

.bv-prov-item__head {
  display: block;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.65);
}

.bv-prov-item__head strong {
  font-size: 17px;
  font-weight: 900;
  color: #fff;
}

.bv-prov-item__pct {
  margin-left: 6px;
  font-size: 11px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.35);
}

.bv-prov-item__note {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.32);
}

/* ── Public anchors ── */
.bv-anchor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.bv-anchor__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.bv-anchor__block { display: block; font-size: 15px; font-weight: 800; color: #fff; }

.bv-anchor__state {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.bv-anchor__state.is-onchain { color: #4ade80; }
.bv-anchor__state.is-simulated { color: #f87171; }
.bv-anchor__state.is-unknown { color: #eab308; }

.bv-anchor__hash {
  display: block;
  padding: 10px 12px;
  border-radius: 8px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10px;
  line-height: 1.5;
  word-break: break-all;
  color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.05);
}

/* ── Ledger ── */
.bv-ledger__index {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  color: #818cf8;
  background: rgba(99, 102, 241, 0.1);
  border: 1px solid rgba(99, 102, 241, 0.25);
}

.bv-ledger__pool { font-size: 13px; font-weight: 700; color: #fff; }

.bv-ledger__sig { display: flex; align-items: center; gap: 8px; }

/* Shown, not hidden behind a Show Signature button that had to be clicked
   once per row to read a page of fifteen. */
.bv-ledger__hash {
  display: block;
  flex: 1;
  min-width: 0;
  max-width: 260px;
  padding: 5px 9px;
  border-radius: 6px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.55);
  background: rgba(0, 0, 0, 0.25);
}

.bv-ledger__tx {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 10px;
  color: #FFB400;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 180, 0, 0.4);
}

.bv-ledger__none { font-size: 11px; font-style: italic; color: rgba(255, 255, 255, 0.28); }

.bv-ledger__pager {
  padding: 16px 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}

.bv-badge--red {
  color: #f87171;
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.3);
}

/* ═══════════════════════════════════════════════════════════════════
   CANDIDATE REGISTRY
   Grouped by election and reusing the bv-elist-* registry pieces, so
   the two roster screens now look and behave the same.
   ═══════════════════════════════════════════════════════════════════ */

.bv-croster-filter {
  margin-bottom: 22px;
}

.bv-croster-filter__row {
  display: flex;
  align-items: center;
  gap: 14px;
}

.bv-croster-filter__row > .bv-input {
  max-width: 340px;
}

.bv-croster-filter__clear {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.4);
  transition: color 0.2s;
}

.bv-croster-filter__clear:hover { color: #FFB400; }

.bv-croster {
  min-width: 860px;
}

.bv-croster__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  height: 34px;
  padding: 0 9px;
  border-radius: 10px;
  font-family: 'JetBrains Mono', 'Roboto Mono', monospace;
  font-size: 13px;
  font-weight: 800;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.09);
  border: 1px solid rgba(255, 180, 0, 0.2);
}

.bv-croster__who {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

.bv-croster__photo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  object-position: top center;
  border: 2px solid rgba(255, 180, 0, 0.5);
}

.bv-croster__photo--none {
  font-size: 13px;
  font-weight: 800;
  color: #FFB400;
  background: rgba(255, 180, 0, 0.08);
}

.bv-croster__ident { min-width: 0; }

/* Wraps rather than truncating. The old cell was `max-w-[200px] truncate`
   — both of which this build DOES emit — so a full name was cut mid-word
   and only a hover title carried the rest. */
.bv-croster__name {
  display: block;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.35;
  color: #fff;
}

.bv-croster__role {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
}

.bv-croster__course {
  font-size: 12px;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.6);
}

.bv-croster__meta {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
}

/* Stated once on the group heading rather than as a LOCKED badge repeated
   in the actions column of every row of that election. */
.bv-croster__locked {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 14px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 9px;
  letter-spacing: 0.12em;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.1);
  border: 1px solid rgba(34, 197, 94, 0.28);
}

.bv-croster__sealed {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.1);
}

/* Portal tile extras: a ratio reads as one figure, not two. */
.bv-audit-tile__of {
  margin-left: 6px;
  font-size: 14px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.3);
}

/* Simulated anchors exist. Saying so quietly is still saying so. */
.bv-audit-tile__note.is-warn {
  color: #f87171;
}

/* ── PAGINATED TABLE FRAME ────────────────────────────────────────
   The candidate roster was wrapped in `.bv-log-scroll`, which is built
   for the SOC log: `max-height: 460px` with its own vertical scrollbar
   and a sticky header. On a table that is ALREADY paginated that gives
   two navigation mechanisms at once — the pager said "showing 1-10 of
   12" while the box showed four and a half rows and clipped the fifth
   through the middle of its avatar.

   Same framing, no vertical scroll: a paginated table should render its
   page at natural height and let the pager do the paging. Horizontal
   overflow is kept for narrow screens.                               */
.bv-table-frame {
  overflow-x: auto;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12px;
}

/* The receipt's copy control had no text of its own — the icon WAS the
   affordance — so removing the glyph would have left an invisible
   button. It is a word now, and the word changes on success. */
.bv-receipt-copy {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  transition: color 0.2s;
}

.bv-receipt-copy.is-done {
  color: #22c55e;
}


/* ── REGISTRY STATUS TABS ─────────────────────────────────────────
   The three registries and the voting booth were unfiltered, unpaginated
   lists, so every concluded election stayed on screen for the life of the
   system. These sit above the listing and switch it between Current,
   Concluded and Archived.

   Additive only: .bv-seg / .bv-seg__item / .bv-seg__item--on already exist
   above (written gold for the judge round tabs, and used by no view until
   now). Nothing there is modified -- gold stays the organizer's accent on
   the pageant registry, and .bv-seg--blue is the COMELEC and voter variant. */

.bv-elist__tabs,
.bv-booth__tabs {
  margin-bottom: 20px;
}

/* The booth is a single narrow column with its own centred layout, so its
   control is not allowed to stretch past the cards it filters. */
.bv-booth__tabs .bv-seg {
  width: 100%;
}

.bv-booth__tabs .bv-seg__item {
  flex: 1;
  text-align: center;
}

.bv-seg--blue .bv-seg__item--on,
.bv-seg--blue .bv-seg__item--on:hover {
  color: #fff;
  background: rgba(59, 130, 246, 0.32);
  border: 1px solid rgba(100, 150, 255, 0.45);
  /* The gold state has no border, so without this the blue one would sit a
     pixel taller than its neighbours and the row would jog on tab change. */
  padding: 8px 17px;
  box-shadow: 0 0 16px rgba(59, 130, 246, 0.22);
}

/* How many elections each tab holds. The count is the point: it says the
   archived ones still exist without putting them on screen. */
.bv-seg__count {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  background: rgba(255, 255, 255, 0.09);
  color: inherit;
}

.bv-seg__item--on .bv-seg__count {
  background: rgba(0, 0, 0, 0.18);
}

/* Pager under a registry table and under the booth's card column. Matches
   .bv-candidates-pager; mt-8 emits nothing in this build. */
.bv-elist__pager {
  margin-top: 24px;
}

/* ── ACTIVITY LOG: SHARED FEED ────────────────────────────────────
   Added 2026-09-05 with the transparency-feed rebuild. That partial
   now reuses the SOC audit-trail vocabulary (.bv-log-time, -ip,
   -actor, -details) instead of the inline hex it carried before, so
   only the pieces the SOC table did not already own live here. */
.bv-log-badge {
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
}

/* Relative age, under the absolute stamp rather than instead of it.
   The absolute time answers "when exactly", which an audit record
   has to; this answers "was that just now", which is the question
   somebody scanning their own history is actually asking. */
.bv-log-ago {
  display: block;
  margin-top: 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.28);
}

/* A field the row genuinely does not have. Distinct from a value, so
   an empty IP does not read as an IP nobody can quite make out. */
.bv-log-muted {
  font-size: 11px;
  font-style: italic;
  color: rgba(255, 255, 255, 0.25);
}

@media (max-width: 1023px) {
  /* .bv-log-details caps at 460px. On a table already forced to a
     600px minimum and scrolled horizontally, that one cell pushes
     the timestamp column past the far edge. */
  .bv-log-details {
    max-width: 200px;
  }
}

/* ══════════════════════════════════════════════════════════════════
   ISO/IEC 25010 AUDIT
   The screen read as filler because of how it presented its data, not
   because the data was wrong:

     - the word "Validated" was repeated on a green pill for every
       passing boolean, eighteen times over. A page where every row
       shouts the same thing gives the eye nothing to land on, and an
       audit is read to find the ONE row that failed.
     - five progress bars, each carrying a single number, four of them
       identical full-width green. A bar pinned at 100% is decoration.
     - booleans and measurements shared one row shape, so the only real
       data on the page — 23 blocks verified, 0 failed jobs, 12 voters —
       was the least prominent thing on it.

   Rebuilt around that split: a check is a state and stays quiet when it
   passes, a measurement is a figure and is typeset as one.
   ══════════════════════════════════════════════════════════════════ */

.bv-iso-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
}

.bv-iso-stamp {
  text-align: right;
  font-size: 11px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.35);
}

.bv-iso-stamp strong {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.7);
  font-variant-numeric: tabular-nums;
}

/* ── SUMMARY ──────────────────────────────────────────────────────
   The score earns its size; the pass ratio beside it is what makes the
   number credible. "100%" on its own is a claim — "100%, 18 of 18
   checks passed" is a result. */
.bv-iso-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 28px;
  margin: 20px 0 24px;
  padding: 22px 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-iso-summary__score {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: 46px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.bv-iso-summary__pct {
  font-size: 20px;
  font-weight: 800;
  opacity: 0.5;
}

.bv-iso-summary__label {
  display: block;
  margin-bottom: 8px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);
}

.bv-iso-summary__ratio {
  font-size: 15px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  font-variant-numeric: tabular-nums;
}

.bv-iso-summary__note {
  margin: 4px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.4);
  max-width: 46ch;
}

.bv-iso-summary__divider {
  width: 1px;
  align-self: stretch;
  background: rgba(255, 255, 255, 0.08);
}

/* ── CHARACTERISTIC CARD ──────────────────────────────────────────*/
.bv-iso-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 18px;
}

.bv-iso-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-iso-card__name {
  margin: 0;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, 0.94);
}

.bv-iso-card__tally {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.4);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bv-iso-card__tally b {
  color: rgba(255, 255, 255, 0.85);
}

/* ── CHECKS ───────────────────────────────────────────────────────
   A passing check is a tick and a sentence. No pill, no colour block,
   nothing repeated — so a failure, which gets all three, is the only
   thing on the card that draws attention. */
.bv-iso-checks {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.bv-iso-check {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.72);
}

.bv-iso-check + .bv-iso-check {
  border-top: 1px solid rgba(255, 255, 255, 0.04);
}

.bv-iso-check__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 9px;
  color: #4ade80;
  background: rgba(34, 197, 94, 0.12);
  border: 1px solid rgba(34, 197, 94, 0.3);
}

.bv-iso-check__label {
  flex: 1;
  min-width: 0;
}

.bv-iso-check--fail {
  margin: 0 -14px;
  padding: 9px 14px;
  border-radius: 8px;
  color: #fecaca;
  background: rgba(239, 68, 68, 0.09);
}

.bv-iso-check--fail + .bv-iso-check,
.bv-iso-check + .bv-iso-check--fail {
  border-top-color: transparent;
}

.bv-iso-check--fail .bv-iso-check__mark {
  color: #f87171;
  background: rgba(239, 68, 68, 0.14);
  border-color: rgba(239, 68, 68, 0.4);
}

.bv-iso-check__verdict {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #f87171;
}

/* ── MEASUREMENTS ─────────────────────────────────────────────────
   Not checks. These are the figures the audit actually took, so they
   are set as figures: tabular, larger than the label beside them. */
.bv-iso-measures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 2px 18px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

.bv-iso-measure {
  padding: 8px 0;
}

.bv-iso-measure__value {
  display: block;
  font-size: 22px;
  font-weight: 800;
  line-height: 1.1;
  color: rgba(255, 255, 255, 0.92);
  font-variant-numeric: tabular-nums;
}

.bv-iso-measure__label {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.33);
}

.bv-iso-foot {
  margin-top: 20px;
  font-size: 11.5px;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.35);
  max-width: 92ch;
}

@media (max-width: 640px) {
  .bv-iso-summary { gap: 18px; padding: 18px; }
  .bv-iso-summary__divider { display: none; }
  .bv-iso-summary__score { font-size: 38px; }
}

/* A transaction hash or a long token is one unbroken word. `pre-wrap`
   alone will not break it, so it runs horizontally out of the cell and
   the two-line clamp never reaches its ellipsis -- the string simply
   stops at the column edge, mid-character. Appears wherever an anchor
   detail lands in a feed, which the admin and COMELEC dashboards now
   render. Applies to the SOC audit trail too, where it is the same bug. */
.bv-log-details {
  overflow-wrap: anywhere;
}

/* ── TRANSPARENCY PORTAL: LEDGER ──────────────────────────────────
   Added 2026-09-05. The ledger table leaned on Tailwind classes this
   build does not emit: `w-32` (so `truncate` had no width to work
   against and the full 64-character vote hash took the widest column
   on the page), `max-h-96`, `p-6`, `border-white/5`, `text-blue-400`,
   `font-bold`, `text-white`. Checked against the bundle the container
   serves -- the host's public/build copy is stale and carries a
   different class set. */
.bv-hash-cell {
  display: block;
  max-width: 210px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bv-ledger-election {
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.88);
}

/* The one link on the page that leads off it, so it has to read as a
   link. `text-blue-400` emitted nothing, leaving it as body text. */
.bv-tx-link {
  color: #60a5fa !important;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.bv-tx-link:hover {
  color: #93c5fd !important;
}

/* A pager inside a card, where `p-6` emitted nothing and left it flush
   against the last row. Distinct from .bv-candidates-pager, which sits
   outside its card and so wants margin rather than padding. */
.bv-table-pager {
  padding: 6px 20px 18px;
}

.bv-avatar--sm {
  width: 24px;
  height: 24px;
  font-size: 8px;
}

/* ── ROOMY TABLE ROWS ─────────────────────────────────────────────
   `.bv-table td` pads 16px, which is right for a table of short
   values. The transparency ledger puts a hash, a link and a two-line
   timestamp on every row, and at 16px those rows read as a solid wall.
   Opt-in so the compact tables elsewhere are untouched. */
.bv-table--roomy th {
  padding-top: 18px;
  padding-bottom: 18px;
}

.bv-table--roomy td {
  padding-top: 20px;
  padding-bottom: 20px;
}

/* ── SETTINGS GRID ────────────────────────────────────────────────
   .bv-grid-2 stretches both cards to the taller one. On the settings
   screen the left card holds a single field and the right holds three
   status rows, so the left one gained a large void under its button.
   Opt-in: every other two-card row on the site wants equal heights. */
.bv-grid-2--top {
  align-items: start;
}

/* ── IDENTITY REGISTRY (admin/users) ──────────────────────────────
   Added 2026-09-05. Everything here replaces a Tailwind class this
   build does not emit, checked against the bundle the container
   serves. */

/* The search field earns more of the row than the role filter does.
   Needs !important to out-rank `.bv-form-row > .bv-input`, which is a
   class more specific. */
.bv-filter-search {
  flex: 2 1 260px !important;
}

/* Manage + role select, kept on one line and hard against the right
   edge of the cell. Was `flex justify-end gap-2`; only the first of
   those three emits a rule. */
.bv-user-ops {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
}

.bv-user-ops__form {
  margin: 0;
  display: flex;
  align-items: center;
}

/* `.bv-btn` pads 14px 20px and runs full width, which is right for a
   card action and far too heavy for a control sitting in a table row.
   This was six inline declarations on the anchor before. */
.bv-btn--row {
  width: auto !important;
  height: 32px;
  padding: 0 12px !important;
  font-size: 11px !important;
  margin-bottom: 0 !important;
}

/* Written as `select.bv-input--compact` on purpose: the rule it has to
   beat is `select.bv-input`, and a bare class would lose the
   specificity contest no matter where it sits in the file. */
select.bv-input--compact {
  width: auto !important;
  min-width: 124px;
  padding: 6px 10px !important;
  font-size: 11px !important;
  border-radius: 8px !important;
}

/* A pager sitting outside its card, where `mt-8` emitted nothing and
   left it flush against the table. The in-card case is
   .bv-table-pager, which wants padding instead. */
.bv-page-pager {
  margin-top: 24px;
}

/* ── JUDGING PORTAL: EVENT ROWS ───────────────────────────────────
   Added 2026-09-05. The portal listed events in .bv-grid-3, and a
   judge is assigned one or two pageants -- so the page rendered a
   single card beside two empty columns. A row uses whatever width it
   is given, at any count. The __title / __desc / __fact / __stage
   classes are deliberately reused from the card so the light theme,
   which styles each of them by name, needs nothing new. */
.bv-judge-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.bv-judge-row > .bv-card__body {
  display: flex;
  /* `.bv-card__body` is globally flex-direction: column. Without
     restating it here the row inherited that, and `flex: 1 1 300px`
     on the identity block then read as a 300px tall basis -- the card
     grew to 542px with its three blocks strung down it. */
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: 24px;
}

/* 300px basis: the identity block keeps the row on one line on a
   laptop and drops the facts and action beneath it on a tablet. */
.bv-judge-row__main {
  flex: 1 1 300px;
  min-width: 0;
}

.bv-judge-row__head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.bv-judge-row__head .bv-judge-card__title {
  margin: 0;
}

/* The card stacked these, so both carried a bottom margin sized for a
   column. In a row the last element is the chips. */
.bv-judge-row .bv-judge-card__desc {
  margin-bottom: 12px;
}

.bv-judge-row .bv-judge-card__stages {
  margin-bottom: 0;
}

.bv-judge-row__facts {
  flex: 0 0 auto;
  margin-bottom: 0 !important;
}

/* .bv-judge-card__fact is flex:1 for the card, where two of them split
   the width. Here they are fixed tiles beside a flexible block. */
.bv-judge-row__facts .bv-judge-card__fact {
  flex: 0 0 auto;
  min-width: 108px;
}

.bv-judge-row__action {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 196px;
}

.bv-judge-row__btn {
  margin-bottom: 0 !important;
  white-space: nowrap;
}

.bv-judge-row__note {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  color: rgba(255, 255, 255, 0.3);
}

/* The one genuinely evidential link in the personal log: a vote-cast
   row leading to that ballot receipt. Gold, because it is an action
   the voter takes, not a status. */
.bv-log-receipt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #FFB400;
  text-decoration: none;
}

.bv-log-receipt:hover {
  text-decoration: underline;
}


/* ── Board of judges ──────────────────────────────────────────────────────
   The panel editor on the judging-structure screen. Built on the same
   vocabulary as .bv-builder__list above rather than a new one: it sits in the
   same card stack and should read as another part of the same setup, not as a
   second design. */
.bv-panel-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 12px;
}

.bv-panel-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}

.bv-panel-row__who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.bv-panel-row__name {
  font-size: 13px;
  font-weight: 700;
  color: #fff;
}

.bv-panel-row__role {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
}

.bv-panel-row__ops {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bv-panel-add {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}

/* A seat that cannot be removed because the judge has already scored. The
   button stays visible rather than disappearing, so the reason can be read
   from its title instead of the row silently losing an action. */
.bv-node__add--danger {
  background: rgba(239, 68, 68, 0.1);
  border-color: rgba(239, 68, 68, 0.3);
  color: #f87171;
}

.bv-node__add--danger:hover { background: rgba(239, 68, 68, 0.2); }

.bv-node__add:disabled,
.bv-node__add--danger:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.bv-node__add:disabled:hover,
.bv-node__add--danger:disabled:hover {
  background: rgba(239, 68, 68, 0.1);
}

/* ── PAGER SUMMARY: FIGURES ARE PROSE, NOT CONTROLS ───────────────
   Added 2026-09-05. `nav[role="navigation"] span` (see ADDITIONAL
   PAGINATION SELECTORS above) paints every span inside a pager as a
   page button. That is right for the built-in pager, whose page links
   really are spans, and wrong for the "Showing 1-10 of 26" line: it
   put each figure in its own 40px bordered box, so the count read as
   three pages you could click. Both pagers keep that line in a <p>,
   which is the honest boundary between a control and a sentence. */
nav[role="navigation"] p span,
.bv-pager__meta span {
  display: inline !important;
  min-width: 0 !important;
  height: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  border: none !important;
  background: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  font-size: inherit !important;
  line-height: inherit !important;
}

/* The figures still read brighter than the words between them. */
.bv-pager__meta span {
  color: rgba(255, 255, 255, 0.85) !important;
  font-weight: 800 !important;
}

/* ── TOPBAR / SIDEBAR SEAM ────────────────────────────────────────
   Added 2026-09-05. Both bands carry a bottom border and together they
   read as one line across the top of the app -- except the sidebar
   header measured 67px against the topbar's 70px, so the line stepped
   3px at the seam. The header was sized by padding plus whatever the
   wordmark happened to measure; it now matches the topbar explicitly
   and centres its content, so the two borders meet. */
.bv-sidebar__header {
  min-height: 70px;
  display: flex;
  align-items: center;
  padding: 0 1.5rem;
}

/* ── APP FOOTER ───────────────────────────────────────────────────
   Was `position: fixed` with a translucent fill and a blur, pinned
   across the bottom of every page. Anything scrolling passed beneath
   it and showed THROUGH it, which is what a half-visible table row
   behind the copyright line was. It also wraps to two or three lines
   below roughly 1000px -- measured at 109px against the 48px of
   clearance `.bv-main-content > main` reserves -- so at those widths
   it covered the end of the page outright, not just mid-scroll.

   Static instead, with `margin-top: auto` so it still sits at the
   bottom of the viewport on a short page. The blur goes with it: the
   codebase already notes elsewhere that a repaint inside a blurred
   surface re-blurs the whole surface, and nothing scrolls under this
   any more to justify the cost. */
.bv-app-footer {
  position: static !important;
  left: auto !important;
  right: auto !important;
  bottom: auto !important;
  margin-top: auto;
  backdrop-filter: none !important;
}

/* ── TALLY CARD ───────────────────────────────────────────────────
   Added 2026-09-05, replacing the .bv-result-* card on the live
   monitor and the results page. That card carried a 56px round avatar
   in one corner and stacked the figures under it, so most of the box
   was empty background -- very visible on a position with a single
   candidate. Here the portrait IS the card and the figures sit on a
   scrim over its lower third.

   The scrim stays dark in both themes deliberately: it covers a
   photograph, not the page, so light mode must not lighten it or the
   name stops being readable. */
.bv-tally {
  position: relative;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  padding: 0 !important;
  aspect-ratio: 3 / 4;
  min-height: 300px;
}

.bv-tally__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Sources are 4:5 portraits with the head about 40% down. On a taller
     box a centred crop takes the forehead off. */
  object-position: 50% 28%;
  display: block;
}

/* No photo on file: the initials become the artwork rather than a
   68px circle floating in an empty card. */
.bv-tally__photo--text {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 64px;
  font-weight: 900;
  letter-spacing: 0.06em;
  color: rgba(255, 180, 0, 0.35);
  background: linear-gradient(160deg, rgba(255, 180, 0, 0.12), rgba(255, 255, 255, 0.02));
}

.bv-tally__flag {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  box-shadow: 0 2px 10px rgba(34, 197, 94, 0.3);
}

.bv-tally__body {
  position: relative;
  z-index: 1;
  width: 100%;
  padding: 64px 18px 18px;
  background: linear-gradient(to top,
      rgba(6, 13, 26, 0.96) 0%,
      rgba(6, 13, 26, 0.9) 45%,
      rgba(6, 13, 26, 0.55) 78%,
      rgba(6, 13, 26, 0) 100%);
}

.bv-tally__name {
  margin: 0;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.25;
  color: #ffffff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bv-tally__party {
  margin: 3px 0 0;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.bv-tally__figures {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
}

.bv-tally__count {
  display: block;
  font-size: 30px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.02em;
  color: #FFB400;
}

.bv-tally__label {
  display: block;
  margin-top: 5px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.bv-tally__share {
  font-size: 15px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.75);
}

.bv-tally__bar {
  margin-top: 12px;
  height: 6px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

.bv-tally__bar span {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: #FFB400;
  box-shadow: 0 0 8px rgba(255, 180, 0, 0.4);
  transition: width 1s ease-in-out;
}

/* .bv-card--leader was applied by the old card and defined nowhere, so
   the leader was distinguished by its badge alone. */
.bv-tally.bv-card--leader {
  border-color: rgba(34, 197, 94, 0.45) !important;
  box-shadow: 0 0 0 1px rgba(34, 197, 94, 0.25), 0 10px 30px rgba(34, 197, 94, 0.12);
}
