:root {
  --navy: #0a2559;
  --navy-deep: #061733;
  --blue: #1e50c4;
  --blue-light: #3f79ef;
  --sky: #eef3fc;
  --gold: #c9962c;
  --gold-bright: #f0c43c; /* the yellow from the Denver Democrats logo mark */
  --header-bg: #e8edf6;   /* light slate blue — pale enough that a logo's white background blends in */
  --header-line: #cdd7e8;
  --header-ink: #33456b;
  --ink: #16213e;
  --paper: #ffffff;
  --paper-dim: #f4f6fb;
  --line: #e0e4ee;
  --red: #b3352c;
  --green: #256b3f;
  --radius: 10px;
  font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  line-height: 1.55;
}

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 24px; }

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { font-family: inherit; font-weight: 800; line-height: 1.15; margin: 0 0 0.5em; color: var(--navy); letter-spacing: -0.01em; }
h1 { font-size: 2.4rem; }
h2 { font-size: 1.6rem; }
h3 { font-size: 1.15rem; }
p { margin: 0 0 1em; }

.eyebrow { display: block; font-size: 0.78rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--blue-light); margin-bottom: 6px; }

/* Header — light slate blue so an uploaded logo with a white background
   blends in instead of showing as a white box against dark navy.
   The gold bottom border gives the bar a defined edge, so it still
   reads as its own band on pages where a dark hero sits directly
   beneath it (without one, the contrast makes the light header look
   washed out on those pages but not others). */
.site-header { background: var(--header-bg); color: var(--header-ink); border-bottom: 3px solid var(--gold-bright); }
.header-inner { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; }
.brand { display: flex; align-items: center; gap: 12px; color: var(--navy); }
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 40px; height: 40px; border-radius: 8px;
  background: var(--blue); color: #fff; font-weight: 900;
  display: flex; align-items: center; justify-content: center; font-size: 1.2rem;
}
.brand-text { font-weight: 800; font-size: 1.1rem; letter-spacing: -0.01em; color: var(--navy); }
.brand-text small { font-weight: 600; font-size: 0.65rem; letter-spacing: 0.1em; text-transform: uppercase; color: #6b7a99; display: block; }
/* Custom uploaded site logo — height-constrained so any aspect ratio fits
   the header bar. multiply blending lets a white or near-white logo
   background melt into the light header rather than sitting in a box. */
.site-logo { height: 70px; width: auto; max-width: 390px; object-fit: contain; display: block; mix-blend-mode: multiply; }
/* The menu button only exists on phones; on desktop the nav and badge sit
   inline exactly as before. */
.nav-toggle { display: none; }
.header-menu { display: flex; align-items: center; gap: 14px; }
.main-nav { display: flex; align-items: center; gap: 2px; }
.main-nav a { color: var(--header-ink); margin-left: 4px; font-weight: 700; font-size: 0.88rem; padding: 9px 16px; border-radius: 6px; }
.main-nav a:hover { color: var(--navy); text-decoration: none; background: #d7e0f0; }
/* Gold underline picks up the yellow in the Denver Democrats logo mark */
.main-nav a.active { color: var(--navy); background: transparent; border-radius: 0; box-shadow: inset 0 -3px 0 var(--gold-bright); }
.main-nav a.cta { background: var(--blue); color: #fff; border-radius: 100px; }
.main-nav a.cta:hover { background: var(--blue-light); color: #fff; }

/* Footer */
.site-footer { margin-top: 60px; padding: 30px 0 46px; border-top: 1px solid var(--line); color: #6b7280; font-size: 0.85rem; }
.footer-inner { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }

/* Hero */
.hero { background: linear-gradient(160deg, var(--navy) 0%, var(--navy-deep) 100%); color: #fff; padding: 72px 0 64px; }
.hero h1 { color: #fff; max-width: 720px; font-size: 2.6rem; }
.hero p.lede { color: #c3d1ec; max-width: 620px; font-size: 1.12rem; }
.hero-ctas { margin-top: 28px; display: flex; gap: 12px; flex-wrap: wrap; }

section { padding: 48px 0; }
section.alt { background: var(--paper-dim); }

/* Numbered steps (à la "how to get involved") */
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 22px; margin-top: 10px; }
.step-num { font-size: 2.2rem; font-weight: 900; color: var(--blue-light); margin-bottom: 6px; line-height: 1; }
.step-item h3 { margin-bottom: 6px; }
.step-item p { color: #4b5568; font-size: 0.92rem; margin-bottom: 0; }

/* Cards */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }
.card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 22px; transition: box-shadow 0.15s, transform 0.15s;
}
.card:hover { box-shadow: 0 10px 26px rgba(10,37,89,0.09); transform: translateY(-2px); }
/* container-type lets the position badge size itself against the card's own
   width rather than the viewport, so it stays on one line however the grid
   reflows. */
.seat-card { border-top: 4px solid var(--blue); container-type: inline-size; }
.seat-card .seat-office { font-size: 1.15rem; color: var(--navy); font-weight: 800; line-height: 1.25; }
/* Position badge ("Vote YES" / "Vote NO"). Roughly 3x the original 0.68rem
   so it reads as the headline claim it is. Colour comes from the measure's
   own positionColor, set in the admin. */
/* Size is set inline per measure, scaled to the text length so long
   positions stay on one line; nowrap enforces it. */
.seat-card .seat-flag { display: inline-block; font-size: 2rem; line-height: 1.15; font-weight: 900; letter-spacing: 0.02em; text-transform: uppercase; white-space: nowrap; color: var(--red); background: #fbe6e4; padding: 6px 18px; border-radius: 100px; margin-bottom: 12px; max-width: 100%; }

@media (max-width: 560px) {
  /* One card per row here, so there's more width — keep the computed size
     but trim the padding. */
  .seat-card .seat-flag { padding: 5px 14px; }
}
.seat-card .seat-meta { font-size: 0.85rem; color: #4b5568; margin-top: 8px; }

/* The candidate is the point of the card, so the name carries the weight and
   the label shrinks to a quiet caption above it. */
.seat-card .seat-candidate { margin-top: 8px; }
.seat-candidate-label {
  display: block; font-size: 0.66rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--blue); margin-bottom: 1px;
}
.seat-candidate-name { display: block; font-size: 1.05rem; font-weight: 800; color: var(--navy); line-height: 1.2; }
.seat-card .seat-links { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; }

/* Event list */
/* Date block, sponsor images and text all start at the same top edge.
   Without align-items the image column stretches and centres itself against
   the full card height, so it drifted below the date block. */
.event-card { display: flex; gap: 14px; align-items: flex-start; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 18px; margin-bottom: 14px; }
.event-card .event-date-block {
  flex: 0 0 64px; height: 64px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  background: var(--navy); color: #fff; border-radius: 8px; padding: 0;
}
.event-date-block .month { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: #9fb4e0; font-weight: 700; }
.event-date-block .day { font-size: 1.5rem; font-weight: 800; }
.event-card .event-body { flex: 1; min-width: 0; padding-top: 1px; }
.event-card h3 { margin-bottom: 4px; }
.event-candidate { color: var(--blue); font-weight: 800; font-size: 0.92rem; margin-bottom: 3px; }
.event-meta { font-size: 0.85rem; color: #4b5568; margin-bottom: 6px; }
.event-meta span { margin-right: 14px; }

.badge {
  display: inline-block; padding: 3px 10px; border-radius: 100px; font-size: 0.72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.03em; color: #fff;
}
.badge-pending { background: #a3792f; }
.badge-approved { background: var(--green); }
.badge-rejected { background: var(--red); }
.badge-auto { background: var(--blue); }
.badge-manual { background: #6b7280; }

/* Filters */
.filter-toggle { margin: 18px 0 24px; }
.filter-toggle summary { cursor: pointer; list-style: none; width: fit-content; }
.filter-toggle summary::-webkit-details-marker { display: none; }
.filter-toggle[open] summary { margin-bottom: 12px; }
.filter-bar { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; margin-bottom: 24px; display: flex; gap: 12px; flex-wrap: wrap; align-items: end; }
.filter-bar .field { display: flex; flex-direction: column; gap: 4px; min-width: 180px; }
.filter-bar label { font-size: 0.78rem; font-weight: 700; color: #4b5568; }

/* Forms */
form.stacked { max-width: 640px; }
.field-group { margin-bottom: 18px; }
.field-group label { display: block; font-weight: 700; font-size: 0.9rem; margin-bottom: 5px; color: var(--navy); }
.field-group .hint { font-size: 0.78rem; color: #6b7280; margin-top: 4px; }
input[type=text], input[type=email], input[type=password], input[type=date], input[type=time], input[type=url], input[type=file], textarea, select {
  width: 100%; padding: 9px 12px; border: 1px solid #ccd2e0; border-radius: 6px; font-size: 0.95rem; font-family: inherit; background: #fff; color: var(--ink);
}
textarea { min-height: 120px; resize: vertical; }
input:focus, textarea:focus, select:focus { outline: 2px solid var(--blue-light); outline-offset: 1px; border-color: var(--blue-light); }

.btn {
  display: inline-block; padding: 11px 22px; border-radius: 100px; font-weight: 800; font-size: 0.88rem;
  border: none; cursor: pointer; text-align: center; letter-spacing: 0.01em;
}
.btn-primary { background: var(--blue); color: #fff; }
.btn-primary:hover { background: var(--blue-light); text-decoration: none; }
.btn-gold { background: var(--navy); color: #fff; }
.btn-gold:hover { background: var(--navy-deep); text-decoration: none; }
.btn-donate { background: var(--gold); color: #3a2a06; }
.btn-donate:hover { background: #e0b04f; text-decoration: none; }
.btn-danger { background: var(--red); color: #fff; }
.btn-danger:hover { background: #93261f; text-decoration: none; }
.btn-ghost { background: transparent; color: var(--navy); border: 1px solid var(--line); border-radius: 7px; }
.btn-ghost:hover { background: var(--paper-dim); text-decoration: none; }
.btn-sm { padding: 6px 14px; font-size: 0.8rem; }

.alert { padding: 12px 16px; border-radius: 8px; margin-bottom: 18px; font-size: 0.9rem; }
.alert-error { background: #fbe6e4; color: #7a231c; border: 1px solid #eab3ac; }
.alert-success { background: #e3f1e8; color: #1c5233; border: 1px solid #a9d3ba; }
.alert-info { background: #eaf1fd; color: #0a2559; border: 1px solid #b9d0f2; }

.auth-shell { max-width: 400px; margin: 60px auto; }
.auth-shell .card { padding: 32px; }

table.admin-table { width: 100%; border-collapse: collapse; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
table.admin-table th, table.admin-table td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line); font-size: 0.9rem; }
table.admin-table th { background: var(--paper-dim); font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.04em; color: #4b5568; font-weight: 800; }
table.admin-table tr:last-child td { border-bottom: none; }

.tabs { display: flex; gap: 4px; margin-bottom: 20px; border-bottom: 2px solid var(--line); }
.tabs a { padding: 9px 16px; font-weight: 700; font-size: 0.88rem; color: #6b7280; border-bottom: 2px solid transparent; margin-bottom: -2px; }
.tabs a.active { color: var(--navy); border-bottom-color: var(--blue); }
.tabs a:hover { text-decoration: none; color: var(--navy); }

.admin-shell { display: flex; min-height: 100vh; }
.admin-sidebar { flex: 0 0 220px; background: var(--navy); color: #dbe4f7; padding: 24px 0; }
.admin-sidebar .brand-mini { padding: 0 20px 20px; font-weight: 800; font-size: 1.05rem; color: #fff; border-bottom: 1px solid rgba(255,255,255,0.15); margin-bottom: 12px; }
.admin-sidebar a { display: block; padding: 10px 20px; color: #b9c8ea; font-size: 0.9rem; font-weight: 700; }
.admin-sidebar a:hover, .admin-sidebar a.active { background: rgba(255,255,255,0.08); color: #fff; text-decoration: none; }
.admin-sidebar .sidebar-footer { margin-top: 30px; padding: 14px 20px 0; border-top: 1px solid rgba(255,255,255,0.15); }
.admin-main { flex: 1; padding: 32px 40px; max-width: 1100px; }

.stat-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin-bottom: 30px; }
.stat-cards .card { text-align: center; padding: 18px; }
.stat-cards .num { font-size: 2rem; font-weight: 800; color: var(--navy); }
.stat-cards .label { font-size: 0.78rem; text-transform: uppercase; color: #6b7280; letter-spacing: 0.04em; font-weight: 700; }

.img-thumbs { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.img-thumbs img { width: 96px; height: 96px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line); }
.img-thumbs figure { margin: 0; text-align: center; }
.img-thumbs figcaption { font-size: 0.7rem; margin-top: 3px; }

.event-detail-hero img { width: 100%; max-height: 380px; object-fit: cover; border-radius: var(--radius); margin-bottom: 20px; }

.empty-state { text-align: center; padding: 50px 20px; color: #6b7280; }

.color-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 4px; margin-right: 6px; vertical-align: middle; }

/* ---- Tablet ---- */
@media (max-width: 900px) {
  .wrap { padding: 0 18px; }
  .card-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
}

/* ---- Mobile ---- */
@media (max-width: 720px) {
  /* Admin shell stacks instead of sitting side-by-side */
  .admin-shell { flex-direction: column; }
  .admin-sidebar { flex: none; width: 100%; padding: 16px 0; }
  .admin-sidebar .brand-mini { padding: 0 18px 14px; }
  .admin-sidebar a { padding: 12px 18px; }
  .admin-main { padding: 22px 16px; }

  /* Header: let the nav wrap under the brand rather than squashing it.
     Nav links, buttons, and toggles all get a 44px minimum tap height —
     below that, taps get missed often enough to be genuinely annoying
     (44px is Apple's documented minimum touch target). */
  /* Logo and menu button on one row; nav and badge drop into a panel below.
     Cuts the header from three stacked rows to one. */
  .header-inner { flex-direction: row; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0; padding: 12px 16px; }

  .nav-toggle {
    display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 4px;
    width: 44px; height: 44px; flex-shrink: 0;
    background: #fff; border: 1px solid #c3cee2; border-radius: 9px; cursor: pointer;
  }
  .nav-toggle span { display: block; width: 17px; height: 2px; background: var(--navy); border-radius: 2px; transition: transform 0.15s ease, opacity 0.15s ease; }
  .nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  .header-menu { display: none; width: 100%; flex-direction: column; align-items: stretch; gap: 0; }
  .header-menu.is-open { display: flex; }

  .main-nav { flex-direction: column; align-items: stretch; gap: 0; margin: 10px 0 0; width: 100%; }
  .main-nav a { margin-left: 0; padding: 13px 4px; font-size: 0.92rem; min-height: 44px; display: flex; align-items: center; border-bottom: 1px solid #d7dfee; border-radius: 0; }
  .main-nav a.active { box-shadow: none; color: var(--navy); border-bottom: 2px solid var(--gold-bright); }

  .header-menu .ac-badge { margin: 12px 0 2px; justify-content: center; }

  .btn { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
  .btn-sm { min-height: 44px; }
  .view-toggle a { min-height: 44px; display: flex; align-items: center; }
  .admin-sidebar a { min-height: 44px; display: flex; align-items: center; }

  /* Hero: smaller type, stats wrap comfortably */
  .hero { padding: 44px 0 40px; }
  .hero h1 { font-size: 1.75rem; }
  .hero p.lede { font-size: 1rem; }
  .hero-ctas .btn { width: 100%; }

  h1 { font-size: 1.75rem; }
  h2 { font-size: 1.35rem; }
  section { padding: 32px 0; }

  /* Event cards stack; date block goes inline above the details */
  .event-card { flex-direction: row; gap: 12px; padding: 14px; }
  .event-card .event-date-block { flex: 0 0 56px; height: 56px; }
  .event-meta span { display: block; margin-right: 0; margin-bottom: 3px; }

  /* One card per row so the larger photos/logos have room */
  .card-grid { grid-template-columns: 1fr; }

  /* Filters stack full-width instead of cramming onto one line */
  .filter-bar { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px 12px; }
  .filter-bar .field { min-width: 0; width: 100%; gap: 2px; }
  .filter-bar label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; color: #6b7280; }
  .filter-bar input, .filter-bar select { padding: 8px 10px; }
  .filter-bar .btn { width: 100%; }

  /* Forms are full-width on small screens */
  form.stacked { max-width: 100%; }
  .field-group input, .field-group select, .field-group textarea { font-size: 16px; } /* 16px avoids iOS auto-zoom on focus */

  /* Wide admin tables scroll horizontally rather than overflowing the page */
  table.admin-table { display: block; overflow-x: auto; white-space: nowrap; }

  .stat-cards { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }

  .footer-inner { flex-direction: column; }
  .tabs { overflow-x: auto; }
}

/* ---- Small phones ---- */
@media (max-width: 420px) {
  .hero h1 { font-size: 1.5rem; }
  .brand-text { font-size: 1rem; }
  .btn { padding: 10px 16px; font-size: 0.85rem; }
  .site-logo { height: 52px; max-width: 260px; }
}

/* ---- List / Calendar view toggle ---- */
.view-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 100px; overflow: hidden; background: #fff; }
.view-toggle a { padding: 8px 20px; font-size: 0.85rem; font-weight: 700; color: #4b5568; }
.view-toggle a:hover { text-decoration: none; background: var(--paper-dim); }
.view-toggle a.active { background: var(--blue); color: #fff; }

/* ---- Calendar ---- */
/* Month navigation: fixed-width arrows either side of a centred title, so
   it stays one tidy row instead of wrapping into stacked buttons. */
.cal-nav { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px; margin: 8px 0 14px; }
.cal-nav-title { margin: 0; font-size: 1.15rem; text-align: center; color: var(--navy); }
.cal-nav-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  min-height: 40px; padding: 0 14px; border: 1px solid var(--line); border-radius: 100px;
  background: #fff; color: var(--navy); font-weight: 800; font-size: 1rem; text-decoration: none;
}
.cal-nav-btn:hover { background: var(--paper-dim); text-decoration: none; color: var(--navy); }
.cal-nav-btn.is-disabled { visibility: hidden; }
.cal-nav-word { font-size: 0.82rem; font-weight: 700; }

.calendar { border: 1px solid var(--line); border-radius: var(--radius); overflow: visible; background: #fff; }
/* minmax(0, 1fr) rather than plain 1fr: a grid item's default minimum
   size is its content, so a single long event title would force its
   column wide and squeeze the other six into slivers. minmax(0, ...)
   lets every column shrink to an equal share regardless of content. */
.cal-weekdays { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); background: var(--paper-dim); border-bottom: 1px solid var(--line); }
.cal-weekdays div { padding: 10px 6px; text-align: center; font-size: 0.75rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; color: #4b5568; }

.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-day { min-height: 116px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 6px; position: relative; min-width: 0; }
.cal-day:nth-child(7n) { border-right: none; }
.cal-day-empty { background: #fafbfd; }
.cal-day-today { background: var(--sky); }
.cal-day-today .cal-day-num { background: var(--blue); color: #fff; border-radius: 100px; }
.cal-day-num { font-size: 0.78rem; font-weight: 700; color: #6b7280; margin-bottom: 5px; display: inline-block; min-width: 21px; height: 21px; line-height: 21px; text-align: center; }

/* Event chip: truncated to one line; full details live in the popover */
/* The whole chip is a link to the event page — clicking anywhere on it
   goes straight to the details, on both pointer and touch devices. */
.cal-event {
  display: block; position: relative; background: var(--paper-dim);
  border-left: 3px solid var(--blue); border-radius: 4px; padding: 3px 6px;
  margin-bottom: 4px; cursor: pointer; font-size: 0.74rem; line-height: 1.3;
  color: var(--ink); text-decoration: none;
}
.cal-event:hover { text-decoration: none; }
.cal-event:hover, .cal-event:focus { background: #e4eafa; outline: none; }
/* Chips show a compact "HD 16 · Canvassing" rather than the full event
   title — long titles never fit a calendar cell no matter how they're
   truncated, and the sponsor + type is what's useful at a glance. The
   full title lives in the hover popover. */
.cal-event-label { display: block; }
.cal-event-sponsor { font-weight: 800; color: var(--navy); }
.cal-event-sponsor::after { content: ' · '; font-weight: 400; color: #9ca3af; }
.cal-event-type { font-weight: 600; }
.cal-event-time { display: block; font-size: 0.68rem; color: #6b7280; margin-top: 1px; }

/* Hover/focus popover with fuller detail + View Details link */
.cal-popover {
  display: none; position: absolute; z-index: 50; left: 0; top: calc(100% + 6px);
  width: 250px; background: #fff; border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 30px rgba(10,37,89,0.16); padding: 12px; white-space: normal;
  font-size: 0.82rem; cursor: default;
}
/* Preview on hover or keyboard focus. The popover is informational only —
   the chip itself is the link, so nothing inside it needs to be clicked. */
.cal-event:hover .cal-popover, .cal-event:focus .cal-popover { display: block; }
.cal-popover strong { display: block; margin-bottom: 5px; color: var(--navy); font-size: 0.9rem; line-height: 1.25; }
.cal-popover-meta { color: #4b5568; font-size: 0.78rem; margin-bottom: 3px; }
.cal-popover-cta { margin-top: 8px; font-size: 0.78rem; font-weight: 800; color: var(--blue); }

/* Flip the popover to the left edge for the last two columns so it
   doesn't get clipped off the right side of the calendar */
.cal-day:nth-child(7n) .cal-popover,
.cal-day:nth-child(7n-1) .cal-popover { left: auto; right: 0; }

/* Dots and the tapped-day panel are phone-only; hidden by default. */

.cal-day-detail { display: none; }
.cal-tap-hint { display: none; }

@media (max-width: 720px) {
  /* All seven columns fit without horizontal scrolling: the text chips are
     replaced by one dot per event, and tapping a day lists them underneath.
     Previously this scrolled sideways, which hid half the month. */
  .calendar { overflow-x: visible; }
  .cal-weekdays, .cal-grid { min-width: 0; }
  .cal-weekdays div { padding: 7px 0; font-size: 0.62rem; }

  .cal-day { min-height: 54px; padding: 4px 1px; text-align: center; }
  .cal-day-num { font-size: 0.76rem; min-width: 20px; height: 20px; line-height: 20px; margin-bottom: 2px; }
  .cal-day-has-events { cursor: pointer; }
  .cal-day-selected { background: #e4eafa; box-shadow: inset 0 0 0 2px var(--blue); }

  /* Chips and their hover popovers make no sense without a pointer */
  .cal-day .cal-event { display: none; }

  /* No badges or dots — the grid stays clean. Days that have events are
     distinguished only by their date being solid navy rather than grey, so
     you can still tell where to tap without anything being added to the cell. */
  .cal-day-has-events .cal-day-num { color: var(--navy); font-weight: 800; }
  .cal-day:not(.cal-day-has-events) .cal-day-num { color: #9ca3af; font-weight: 600; }

  .cal-tap-hint { display: block; text-align: center; font-size: 0.78rem; color: #6b7280; margin: 10px 0 0; }

  .cal-day-detail { display: block; margin-top: 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--paper-dim); padding: 10px 12px; }
  .cdd-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; }
  .cdd-head strong { font-size: 0.9rem; color: var(--navy); }
  /* Steps to the next day that has events. Compact by design — the word
     drops away on narrow screens, leaving just the chevron. */
  .cdd-next {
    display: inline-flex; align-items: center; gap: 3px;
    background: #fff; border: 1px solid var(--line); border-radius: 100px;
    font-size: 0.78rem; font-weight: 800; line-height: 1; color: var(--blue);
    cursor: pointer; padding: 0 10px; min-height: 34px; margin-left: auto;
  }
  .cdd-next:active { background: var(--sky); }
  .cdd-next-word { font-size: 0.72rem; }
  /* The campaign or ballot measure leads, since that's what people scan
     for; the event's own name and details sit underneath it. */
  .cdd-item { display: flex; align-items: stretch; gap: 10px; padding: 11px 0; border-bottom: 1px solid var(--line); color: inherit; min-height: 44px; }
  .cdd-item:last-child { border-bottom: none; }
  .cdd-item:hover { text-decoration: none; }
  .cdd-bar { width: 4px; border-radius: 3px; flex: 0 0 auto; }
  .cdd-body { flex: 1; min-width: 0; }
  .cdd-sponsor { display: block; font-weight: 800; font-size: 0.95rem; color: var(--navy); line-height: 1.25; }
  .cdd-sponsor.cdd-cancelled { text-decoration: line-through; opacity: 0.7; }
  .cdd-flag { font-size: 0.65rem; font-weight: 800; text-transform: uppercase; color: var(--red); text-decoration: none; margin-left: 4px; }
  .cdd-title { display: block; font-size: 0.84rem; color: var(--ink); margin-top: 1px; }
  .cdd-meta { display: block; font-size: 0.78rem; font-weight: 700; color: var(--blue); margin-top: 3px; }
  .cdd-loc { display: block; font-size: 0.74rem; color: #6b7280; margin-top: 1px; }
  .cdd-go { color: #9ca3af; font-weight: 800; font-size: 1.3rem; align-self: center; flex: 0 0 auto; }
}

/* The ⠿ drag handle only works with a pointer — HTML5 drag events never
   fire on touchscreens — so hide it there and rely on the ↑ ↓ buttons. */
@media (hover: none) {
  .drag-handle { display: none !important; }
}

/* ---- Bulk action bar (admin review queue) ---- */
.bulk-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; margin-bottom: 12px; border-radius: 8px;
  background: var(--paper-dim); border: 1px solid var(--line);
  font-size: 0.85rem; font-weight: 700; color: #6b7280;
  opacity: 0.55; transition: opacity 0.15s, background 0.15s;
}
/* Buttons stay visible but inert until something is selected, so the bar
   doesn't jump the table down the page when the first box is ticked. */
.bulk-bar .bulk-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.bulk-bar:not(.bulk-bar-active) .bulk-actions { pointer-events: none; }
.bulk-bar-active { opacity: 1; background: var(--sky); border-color: #b9d0f2; color: var(--navy); }

@media (max-width: 720px) {
  .bulk-bar { flex-direction: column; align-items: stretch; }
  .bulk-bar .bulk-actions .btn { flex: 1; }
}

/* Sortable column headers on the admin review queue */
.sort-link { color: inherit; text-decoration: none; display: inline-block; white-space: nowrap; }
.sort-link:hover { color: var(--blue); text-decoration: none; }
.sort-link.sort-active { color: var(--navy); }

/* Sponsor assignment picker (manager accounts) */
.sponsor-picker { display: flex; flex-wrap: wrap; gap: 18px; border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; background: var(--paper-dim); }
.sponsor-group { min-width: 170px; }
.sponsor-group-label { font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: #6b7280; margin-bottom: 6px; }
.sponsor-group label { display: flex; align-items: center; gap: 7px; font-weight: 500; font-size: 0.86rem; margin-bottom: 4px; cursor: pointer; }
.sponsor-group label input { width: auto; margin: 0; }

/* Candidate photo + campaign logo on event bars. Sits between the date
   block and the event text; hidden on narrow screens where the row is
   already tight and the sponsor name is shown in the meta line anyway. */
/* Same 64px height as the date block so the row reads as one line of
   elements. The logo keeps its natural aspect ratio instead of being
   letterboxed inside a square, which made it look smaller than the photo. */
.event-sponsor-imgs { display: flex; align-items: center; gap: 10px; flex-shrink: 0; height: 64px; }
.esi-photo { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; display: block; }
.esi-logo { height: 64px; width: auto; max-width: 104px; object-fit: contain; display: block; }

@media (max-width: 560px) {
  .event-sponsor-imgs { display: none; }
}

/* Subscribe button — visually distinct from Donate (gold) and View (ghost),
   so the three CTAs on a card don't compete. Only rendered when the
   campaign or measure has a newsletter link set. */
.btn-subscribe { background: var(--sky); color: var(--navy); border: 1px solid #b9d0f2; }
.btn-subscribe:hover { background: #dfeafb; color: var(--navy); text-decoration: none; }

/* Extra detail synced from the organizer (instructions, accessibility) */
.event-note { background: var(--paper-dim); border-left: 3px solid var(--line); padding: 10px 14px; border-radius: 6px; margin-bottom: 10px; font-size: 0.9rem; color: #4b5568; }
/* Cancelled events stay visible but clearly struck through */
.event-card.is-cancelled { opacity: 0.72; }
.event-card.is-cancelled h3 a { text-decoration: line-through; }
.badge-cancelled { background: #fbe6e4; color: var(--red); }
.cal-event.is-cancelled .cal-event-label { text-decoration: line-through; opacity: 0.75; }

/* Collapsible search/filter block. Open on desktop, collapsed on phones. */
/* Flex column so whitespace between <summary> and the form doesn't generate
   line boxes — with the form hidden those added ~44px of empty height. */
.filter-wrap { margin-top: 16px; display: flex; flex-direction: column; }
.filter-toggle { display: none; }
.filter-wrap > .filter-bar { margin-top: 0; }
/* Browsers clip a closed <details> rather than removing it from layout, which
   left the collapsed bar taller than its own content. Hide it outright. */
.filter-wrap:not([open]) > .filter-bar { display: none; }

@media (max-width: 720px) {
  .filter-wrap { border: 1px solid var(--line); border-radius: 10px; background: #fff; margin: 10px 0 0; }
  .filter-toggle {
    display: flex; align-items: center; gap: 8px;
    /* margin:0 matters — summary picks up the global element margin, which
       added ~42px of dead space around the collapsed bar. */
    margin: 0; padding: 9px 12px; min-height: 40px; cursor: pointer; list-style: none;
    font-weight: 700; font-size: 0.85rem; color: var(--navy);
  }
  .filter-toggle::-webkit-details-marker { display: none; }
  .filter-toggle::after { content: '⌄'; font-size: 1.1rem; color: #6b7280; margin-left: auto; }
  .filter-wrap[open] .filter-toggle::after { content: '⌃'; }
  .filter-count {
    background: var(--blue); color: #fff; border-radius: 100px;
    font-size: 0.72rem; padding: 1px 8px; font-weight: 800;
  }
  .filter-wrap > .filter-bar { border: none; border-top: 1px solid var(--line); border-radius: 0; margin: 0; }
  .filter-count { padding: 0 7px; font-size: 0.68rem; }
  .cal-nav { margin: 10px 0 10px; }

  /* Month nav on phones: arrows only, title carries the month name */
  .cal-nav-word { display: none; }
  .cal-nav-title { font-size: 1.05rem; }
  .cal-nav-btn { padding: 0 16px; }
}

/* Empty-events state that points people at the campaign instead of dead-ending */
.empty-state-cta { text-align: center; }
.empty-state-links { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 4px; }

/* Candidate name in the campaign detail hero */
.hero-candidate { margin: 6px 0 18px; }
.hero-candidate-label { display: block; font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.09em; color: #9fb4e0; margin-bottom: 2px; }
.hero-candidate-name { display: block; font-size: 1.6rem; font-weight: 800; color: #fff; line-height: 1.15; }

/* Separator between co-sponsors on a joint event */
.sponsor-join { color: #9ca3af; font-weight: 700; }

/* Ballot measure logos are shown whole rather than cropped to fill: these
   images carry text, and cover-cropping cut "FAMILIES NOT POLITICS" down to
   "LIES NOT POLIT". A light panel keeps letterboxing looking deliberate and
   gives dark logos something to sit on. */
.measure-logo { object-fit: contain; background: #fff; border-radius: 8px; display: block; }
.measure-logo-hero { width: 120px; height: 120px; padding: 8px; flex-shrink: 0; border-radius: 10px; }
.measure-logo-card { width: 100%; height: 140px; padding: 10px; margin: 0 0 12px; border: 1px solid var(--line); }
.measure-logo-home { height: 120px; }

/* Header link out to the Advance Colorado investigation. Red, tying it to the
   Republican-aligned group it points at rather than to our own navy. */
.ac-badge {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  background: var(--red); color: #fff; border: 1px solid #96281f;
  border-radius: 100px; padding: 7px 15px; font-size: 0.78rem; font-weight: 800;
  text-decoration: none;
}
.ac-badge:hover { background: #96281f; color: #fff; text-decoration: none; }
.ac-badge svg { flex-shrink: 0; }
.ac-lead { color: #ffe9a8; }  /* paler than the logo gold, which is unreadable on red */

@media (max-width: 900px) {
  /* The full line is too wide once the nav wraps; the question alone still
     says what the link is, and the icon carries the "money" cue. */
  /* "Dark Money Watch." stays visible at every width — the point of the link
     is the warning, so dropping the lead phrase weakened it. It wraps to two
     lines rather than being truncated when the row is narrow. */
  .ac-badge { font-size: 0.72rem; padding: 7px 13px; gap: 6px; white-space: normal; text-align: center; line-height: 1.25; }
}

/* Denver's nine state House candidates — a compact text list under the seat
   cards. No photos: this is meant to be scannable, not another card grid. */
.denver-slate { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px 24px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.denver-slate li { display: flex; align-items: baseline; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.ds-hd { flex: 0 0 auto; font-size: 0.68rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--blue); min-width: 38px; }
.ds-name { font-weight: 700; color: var(--navy); font-size: 0.95rem; }
a.ds-name:hover { color: var(--blue); }

@media (max-width: 900px) { .denver-slate { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .denver-slate { grid-template-columns: 1fr; gap: 0; } }

/* Chamber labels above each slate list */
.slate-heading { font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; color: #6b7280; margin: 20px 0 2px; }

/* Statewide seats carry no district number, so the label needs its own width */
/* Office label used where a district number would be ambiguous */
.ds-office { min-width: 78px; }

/* Flags an event that's an edit of something already reviewed */
.badge-update { background: #fff0d6; color: #8a5a00; }
.change-note { margin: 3px 0 0; font-size: 0.78rem; line-height: 1.35; }

/* "New" in the review queue's New/Update column */
.badge-new { background: #e6f0fb; color: #1e50c4; }

/* Sponsor branding on the event page — candidate photo and/or organisation
   logo. contain, never cover: these carry text and faces. */
.event-sponsor-marks { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.esm-link { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.esm-photo { width: 54px; height: 54px; border-radius: 50%; object-fit: cover; border: 2px solid var(--line); flex: 0 0 auto; }
.esm-logo { height: 54px; max-width: 190px; object-fit: contain; background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px; }
@media (max-width: 560px) {
  .esm-photo { width: 44px; height: 44px; }
  .esm-logo { height: 44px; max-width: 150px; }
}

/* Admin sidebar groups — headings over related links, always visible. */
.nav-group { margin-bottom: 14px; }
.nav-group-label {
  font-size: 0.63rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: #7d93c4; padding: 5px 12px 3px;
}
.admin-sidebar .nav-group a { display: flex; align-items: center; gap: 8px; }
.nav-badge {
  margin-left: auto; background: var(--gold-bright); color: #3a2c00;
  font-size: 0.66rem; font-weight: 800; border-radius: 100px; padding: 1px 7px; line-height: 1.5;
}
.admin-sidebar .nav-group a.active .nav-badge { background: #fff; color: var(--navy); }
