/* ============================================================
   HaysEvents.com — modern community-calendar design system
   ============================================================ */

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

:root {
  /* Brand palette */
  --oxford-navy: #00315c;
  --regal-navy: #0d356d;
  --dusk-blue: #0f508a;
  --steel-blue: #187bd6;

  --brand: #0f508a;          /* dusk blue — primary (links, buttons, active) */
  --brand-dark: #00315c;     /* oxford navy — hover */
  --brand-light: #e7f0f9;    /* pale steel tint — chips, badges, focus ring */
  --brand-tint: #d5e5f4;     /* one step down from brand-light — the second tier of a two-tone
                                tint, e.g. hover on a brand-light surface, or a selected row
                                that has to stay distinct from a hovered one */
  --accent: #187bd6;         /* steel blue — bright CTA / highlight pop */
  --accent-dark: #0f508a;    /* dusk blue — accent hover */

  /* Neutrals */
  --bg: #f6f7fb;
  --surface: #ffffff;
  --text: #0f172a;
  --text-muted: #64748b;
  --text-soft: #94a3b8;
  --border: #e6e8ef;
  --border-strong: #d6dae6;

  /* Status */
  --green: #16a34a;
  --green-bg: #dcfce7;
  --amber: #d97706;
  --amber-bg: #fef3c7;
  --red: #dc2626;
  --red-bg: #fee2e2;
  --blue-bg: #dbeafe;

  /* Shape & depth */
  --radius: 16px;
  --radius-sm: 10px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 6px 20px rgba(15, 23, 42, 0.08);
  --shadow-lg: 0 16px 40px rgba(15, 23, 42, 0.12);

  /* Lead-band geometry. Every route opens with one band (.hero / .search-band), and they all
     get the same height so moving between Events, Garage Sales, Regional and Organizations
     doesn't shift the page contents up and down. --band-content-h is the minimum content
     height inside the band; the tallest primary hero (a kicker over a 1.7rem title) needs ~45px,
     so 48 covers every one of them without padding any of them out. Pages whose masthead
     genuinely carries more (an org profile's logo + social row, /advertise's pitch paragraph)
     grow past it rather than truncating.
     --search-h is set as an explicit height, not derived from padding: it's the only way four
     search boxes with different font sizes and icon insets stay literally the same height. */
  --band-content-h: 48px;
  --search-h: 42px;

  --max-width: 1140px;
  --font-head: 'Plus Jakarta Sans', 'Segoe UI', system-ui, sans-serif;
  --font-body: 'Inter', 'Segoe UI', system-ui, sans-serif;
}

/* No scroll-behavior:smooth here — it animates the browser's scroll *restoration* on
   back/forward navigation (a visible "jump" on long pages), and nothing on the site
   uses in-page anchors that would benefit. */
html { font-size: 16px; }

body {
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 { font-family: var(--font-head); color: var(--text); line-height: 1.25; font-weight: 700; }
a { color: var(--brand); text-decoration: none; transition: color .15s; }
a:hover { color: var(--brand-dark); }
img { max-width: 100%; display: block; }

.container { width: 100%; max-width: var(--max-width); margin: 0 auto; padding: 0 20px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.main-content { flex: 1 0 auto; padding: 36px 0 64px; }

/* ===== Buttons ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-head); font-weight: 600; font-size: .95rem;
  padding: 11px 20px; border-radius: var(--radius-pill); border: 1.5px solid transparent;
  cursor: pointer; transition: all .15s; white-space: nowrap; line-height: 1;
}
.btn-primary { background: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dark); color: #fff; }
.btn-accent { background: var(--accent); color: #fff; }
.btn-accent:hover { background: var(--accent-dark); color: #fff; }
.btn-outline { background: transparent; color: var(--brand); border-color: var(--border-strong); }
.btn-outline:hover { border-color: var(--brand); background: var(--brand-light); }
.btn-ghost { background: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: #eef0f6; color: var(--text); }
.btn-danger { background: transparent; color: var(--red); border-color: var(--red-bg); }
.btn-danger:hover { background: var(--red-bg); }
.btn-large { padding: 14px 28px; font-size: 1.05rem; }
.btn-sm { padding: 7px 14px; font-size: .85rem; }
.btn-block { width: 100%; }

/* ===== Header / Nav ===== */
.site-header {
  background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 100; box-shadow: var(--shadow-sm);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; padding: 14px 0; gap: 16px; }
.site-logo { display: flex; align-items: center; gap: 12px; }
.site-logo .logo-icon { height: 64px; width: auto; display: block; flex-shrink: 0; }
.logo-text { display: flex; flex-direction: column; justify-content: center; line-height: 1.05; }
.logo-word { font-family: var(--font-head); font-weight: 800; font-size: 1.55rem; letter-spacing: -.02em; color: var(--oxford-navy); white-space: nowrap; }
.logo-word .logo-accent { color: var(--steel-blue); }
.logo-word .logo-dot { color: var(--oxford-navy); font-size: .62em; font-weight: 700; }
.logo-tag { font-size: .6rem; text-transform: uppercase; letter-spacing: .13em; color: var(--text-soft); font-weight: 600; margin-top: 3px; white-space: nowrap; }

.main-nav { display: flex; align-items: center; gap: 6px; }
.main-nav ul { list-style: none; display: flex; align-items: center; gap: 4px; }
/* nowrap because the failure mode here is a *label* breaking in half, not the row wrapping:
   the ul is flex-nowrap, so when the row runs out of room the items shrink and "Garage Sales"
   splits across two lines inside its own pill. Tighter than before because the desktop nav has
   to fit a logged-in org — Dashboard is one item more than a guest sees. */
.main-nav a.nav-link {
  color: var(--text-muted); font-weight: 600; font-size: .9rem; padding: 8px 11px;
  white-space: nowrap;
}
.main-nav ul > li { flex-shrink: 0; }
.nav-cta .btn { white-space: nowrap; flex-shrink: 0; }
.main-nav a.nav-link:hover { color: var(--text); }
.main-nav a.nav-link.active { color: var(--brand); }
/* Session links (Dashboard / Admin / Log Out) sit quiet like the nav, not as buttons. */
.nav-cta .btn-ghost:hover { background: transparent; color: var(--text); }
.nav-cta { display: flex; align-items: center; gap: 8px; margin-left: 8px; }
/* Header CTAs by session, toggled by .is-auth / .is-admin on <html> (set from the
   events_auth / events_admin companion cookies). Default = guest. Admin takes precedence. */
.nav-auth, .nav-admin { display: none; }
html.is-auth .nav-guest { display: none; }
html.is-auth .nav-auth { display: inline-flex; }
html.is-admin .nav-guest, html.is-admin .nav-post, html.is-admin .nav-auth { display: none; }
html.is-admin .nav-admin { display: inline-flex; }
.nav-cta .btn svg { width: 15px; height: 15px; }
.nav-toggle { display: none; background: none; border: none; font-size: 1.5rem; cursor: pointer; color: var(--text); }

/* ===== Hero / blue lead bands =====
   Shared gradient for the page-lead bands (.hero and the homepage .search-band).
   Every public page opens with one of these; the sponsor band renders directly
   below it — never above the page's own title/search. */
.hero, .search-band {
  background: linear-gradient(135deg, var(--oxford-navy) 0%, var(--dusk-blue) 55%, var(--steel-blue) 100%);
}
.hero { color: #fff; padding: 14px 0; }
.hero-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px 28px; flex-wrap: wrap; }
.hero-copy { min-width: 0; }
.hero h1, .hero h2 { color: #fff; font-size: 1.7rem; letter-spacing: -.02em; line-height: 1.15; }
.hero p { color: rgba(255,255,255,.85); font-size: .96rem; margin-top: 3px; }
.hero-actions { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; flex-shrink: 0; }
.hero .btn-outline { color: #fff; border-color: rgba(255,255,255,.5); }
.hero .btn-outline:hover { background: rgba(255,255,255,.12); border-color: #fff; }

/* Primary CTA: white pill — stays crisp at every gradient stop (the old accent fill matched
   the gradient's end color and lost contrast on the right, where it sits). */
.hero .btn-white { background: #fff; color: var(--brand-dark); font-weight: 700; box-shadow: 0 2px 10px rgba(0,20,45,.25); }
.hero .btn-white:hover { background: var(--brand-light); color: var(--brand-dark); }

/* Quiet secondary: underlined arrow link */
.hero-link { color: rgba(255,255,255,.85); font-family: var(--font-head); font-weight: 600; font-size: .92rem; border-bottom: 1px solid rgba(255,255,255,.35); padding-bottom: 2px; white-space: nowrap; }
.hero-link:hover { color: #fff; border-color: #fff; }

/* Slim variant — just a breadcrumb ribbon (event detail). */
.hero-strip { padding: 12px 0; }
.hero-strip .region-crumb { margin-bottom: 0; }

/* One-row variant — title, inline search, CTA on a single line (org pages), keeping
   the band as slim as the homepage search band. Wraps when the title runs long. */
.hero-row { padding: 14px 0; }
.hero-row-inner { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; min-height: var(--band-content-h); }
.hero .hero-row-inner h1 { font-size: 1.35rem; }
.hero-row-inner .search-bar { flex: 1 1 260px; min-width: 220px; margin: 0; }
.org-hero-logo { width: 40px; height: 40px; border-radius: 10px; object-fit: cover; background: #fff; flex-shrink: 0; }
/* Org hero: title block (name with the follow-us icon chips beneath it), a compact
   admin-search-sized search box, and website + tel right-aligned. Everything renders
   only when the org filled it in, so empty profiles collapse cleanly. The input/icon
   overrides are double-class selectors: the base .search-bar rules come later in this
   file and would win at equal specificity. */
/* Org page masthead: tiny steel-blue kicker, display-weight name, icons beneath.
   The h1 selector out-specifies .hero .hero-row-inner h1's 1.35rem compact size. */
.org-title-block { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.org-kicker {
  font-family: var(--font-head); font-size: .66rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .16em; color: #7fb8e8; line-height: 1;
}
/* h2 included so a page that leads with h2 rather than h1 (regional) gets the identical
   compact title, instead of falling through to the taller base .hero h1,.hero h2 rule. */
.hero .hero-row-inner .org-title-block h1,
.hero .hero-row-inner .org-title-block h2,
.hero .hero-row-inner .org-title-block .masthead-name {
  font-size: 1.7rem; font-weight: 800; letter-spacing: -.02em; line-height: 1.1;
}
/* A short line of guidance beside the title, replacing a block paragraph under it. */
.hero-note { color: rgba(255,255,255,.72); font-size: .9rem; min-width: 0; }
/* Actions sit at the far right of a compact band; the tall .hero-inner already does this
   with space-between, but hero-row is a plain flex row. */
.hero-row-inner .hero-actions { margin-left: auto; }
/* Event pages reuse the masthead with the org name as a link back to its page. */
.org-title-block .masthead-name { font-family: var(--font-head); color: #fff; }
.org-title-block .masthead-name:hover { color: rgba(255,255,255,.85); text-decoration: none; }

/* /this-week: the digest's public week pages. Hero shows the window + count on the right;
   past days of the current week collapse under a details block; prev/next week at the foot. */
/* One line, not a stacked pair: as a column this was the only lead band taller than
   --band-content-h, and it makes /this-week read identically to its sibling /garage-sales. */
.week-meta { margin-left: auto; display: flex; align-items: baseline; gap: 8px; }
.week-count::before { content: "·"; color: rgba(255,255,255,.5); margin-right: 8px; }
.week-window { font-family: var(--font-head); font-weight: 700; font-size: 1.05rem; color: #fff; white-space: nowrap; }
.week-count { font-size: .85rem; color: rgba(255,255,255,.75); }
.week-actions { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 14px; }
.week-note {
  background: var(--amber-bg); color: var(--amber); border-radius: var(--radius-sm);
  padding: 12px 18px; margin-bottom: 22px; font-size: .92rem;
}
.week-note a { color: inherit; font-weight: 700; }
.week-past { margin-bottom: 26px; }
.week-past > summary {
  cursor: pointer; list-style: none; font-family: var(--font-head); font-weight: 600;
  font-size: .9rem; color: var(--text-soft); padding: 10px 16px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.week-past > summary::-webkit-details-marker { display: none; }
.week-past > summary::before { content: "▸ "; }
.week-past[open] > summary::before { content: "▾ "; }
.week-past[open] > summary { margin-bottom: 16px; }
.week-past .day-section { opacity: .65; }
.week-aside { margin-top: 26px; padding: 12px 18px; background: var(--green-bg); border-radius: var(--radius-sm); }
.week-aside a { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: .92rem; color: var(--green); }
.week-aside a:hover { text-decoration: underline; }
.week-aside svg { flex-shrink: 0; }
.week-nav { display: flex; justify-content: space-between; gap: 12px; margin-top: 40px; flex-wrap: wrap; }
.week-nav a {
  font-weight: 600; font-size: .92rem; color: var(--text-muted);
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill); padding: 8px 18px;
}
.week-nav a:hover { color: var(--brand); border-color: var(--brand); text-decoration: none; }
@media (max-width: 768px) { .week-meta { margin-left: 0; } }
.org-title-block .org-social { margin-top: 3px; }
/* All controls sit snug in one right-aligned cluster; the hero's whitespace lands
   between identity and actions (navbar logic), never inside the cluster. */
.org-actions { display: flex; align-items: center; gap: 12px; margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
/* Narrower than a full-width search bar, but the same height as every other one. */
.search-bar.org-search { flex: 0 1 230px; min-width: 170px; margin: 0; }
.org-social:not(:has(a)) { display: none; }
@media (max-width: 768px) {
  .org-actions { margin-left: 0; justify-content: flex-start; }
}
.org-phone { display: inline-flex; align-items: center; gap: 6px; color: #fff; font-weight: 600; font-size: .92rem; white-space: nowrap; }
.org-phone svg { width: 15px; height: 15px; }
.org-phone:hover { text-decoration: none; opacity: .85; }
.org-social, .footer-social { display: inline-flex; gap: 8px; align-items: center; }
/* Sits under the newsletter form in the last column. inline-flex keeps it shrink-to-fit, so it
   aligns to that column's left edge (flush with the email input) without an alignment rule. */
.footer-social { margin-top: 14px; }
.org-social:empty, .footer-social:empty { display: none; }
.org-social a, .footer-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.25); color: #fff;
}
.org-social a:hover, .footer-social a:hover { background: rgba(255,255,255,.24); }
.org-social svg, .footer-social svg { width: 16px; height: 16px; display: block; }
.hero .search-bar input[type=text], .hero .search-bar input[type=search] { border-color: transparent; }

/* ===== Action band — homepage search / date-jump / post CTA on the hero gradient ===== */
/* The band's controls are sized down from the base .search-bar (which is built for a full-width
   standalone search): a ~51px input plus 18px of band padding made the lead-in taller than it
   needed to be and pushed the listing down the page. Same reduction the garage sale hero got —
   the controls stay comfortably tappable, the page just starts sooner. */
.search-band { padding: 14px 0; }
.search-band > .container {
  min-height: var(--band-content-h); display: flex; flex-direction: column; justify-content: center;
}
.search-band .search-bar { margin: 0; }
.search-band .search-bar input[type=text], .search-band .search-bar input[type=search] { border-color: transparent; }
/* Sits shoulder to shoulder with the search box in the same row, so it takes the same height. */
.search-band .date-jump input[type=date],
.search-band .date-jump-btn { height: var(--search-h); padding: 0 16px; font-size: .9rem; }
/* Town pages: slim location strip above the search bar (replaces the old town hero). */
.band-location { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; color: rgba(255,255,255,.92); }
.band-location-place { display: inline-flex; align-items: center; gap: 7px; font-family: var(--font-head); font-weight: 600; }
.band-location-place svg { width: 16px; height: 16px; flex-shrink: 0; }
.band-location a { color: rgba(255,255,255,.72); font-size: .88rem; font-weight: 600; }
.band-location a:hover { color: #fff; }

/* ===== Search ===== */
.search-bar { position: relative; margin: 0 0 4px; display: flex; align-items: center; gap: 10px; }
.search-bar input[type=text], .search-bar input[type=search] {
  flex: 1; min-width: 0; height: var(--search-h); padding: 0 16px 0 40px;
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-pill); font-size: .95rem; font-family: var(--font-body); background: var(--surface);
}
.search-bar input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-light); }
.search-bar::before {
  /* Pinned to the input row's center (half of --search-h), not 50% of the bar — when the bar
     wraps to two rows the icon must stay on the input. */
  content: ""; position: absolute; left: 15px; top: 21px; transform: translateY(-50%); width: 15px; height: 15px; opacity: .65;
  background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%2364748b" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>') center/contain no-repeat;
}

/* Date-jump — anchors a listing to a chosen date (homepage) or week (garage sales).
   One pill, not two controls: the trigger and its ✕ reset share a single surface with a
   divider between them. As a separate circle floating beside the pill the ✕ read as belonging
   to whatever button came next, at every width, and no amount of gap fixed that.
   The ends are rounded on the children rather than clipped with overflow:hidden on the row.
   This row is also .dj-host, the calendar popup's positioning context, so clipping it cropped
   the popup to the pill's own 34px box and left you reading one strip of digits. */
.date-jump {
  display: flex; align-items: stretch; gap: 0;
  background: var(--surface); border-radius: var(--radius-pill);
}
.date-jump input[type=date] {
  padding: 12px 16px; font-size: .95rem; font-family: var(--font-body); color: var(--text);
}
.date-jump .date-jump-btn,
.date-jump input[type=date] {
  background: transparent; border: none;
  border-radius: var(--radius-pill) 0 0 var(--radius-pill);
}
/* No reset beside it (no jump active): the trigger is the whole pill. */
.date-jump:not(:has(.date-jump-reset)) .date-jump-btn,
.date-jump:not(:has(.date-jump-reset)) input[type=date] { border-radius: var(--radius-pill); }
.date-jump input[type=date]:focus { outline: none; box-shadow: 0 0 0 4px var(--brand-light); }
/* width duplicates the flex-basis on purpose (the pattern the avatar/logo tiles below already
   use). Safari leaves flex-basis out of a flex container's intrinsic width, so .date-jump
   measured itself around the ✕ glyph rather than this 34px: the white pill stopped short and
   the ✕ hung off it onto the blue band. Chrome sizes it correctly, so it only showed there. */
.date-jump-reset {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 34px; width: 34px; background: transparent; color: var(--text-soft);
  border-left: 1px solid var(--border);
  border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
  font-size: .78rem; text-decoration: none; line-height: 1;
}
.date-jump-reset:hover { background: var(--brand-light); color: var(--brand); }

/* Custom calendar popup — injected by app.js on any input[type=date][data-calendar]
   (all pointer types; iPadOS/iOS render the native input iconless and blank). The
   hidden native input remains as the form value and the no-JS fallback. */
input[data-calendar].dj-done { display: none; }
.dj-host { position: relative; }
.date-jump-btn {
  display: inline-flex; align-items: center; gap: 8px; padding: 12px 18px;
  border: 1.5px solid var(--border-strong); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--text-muted); font-family: var(--font-body);
  font-size: .95rem; cursor: pointer; white-space: nowrap;
}
.date-jump-btn.has-date { color: var(--text); font-weight: 600; }
.date-jump-btn:hover { border-color: var(--text-soft); }
.date-jump-btn:focus-visible { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-light); }
/* Inside a form card the trigger matches the other form inputs, not the pill. */
.form-group .date-jump-btn {
  width: 100%; padding: 11px 14px; border-radius: var(--radius-sm); font-size: 1rem;
}
.dj-ico { flex: 0 0 auto; color: var(--brand); }
.dj-pop {
  position: absolute; left: 0; top: calc(100% + 8px); z-index: 60; width: 292px;
  max-width: calc(100vw - 24px);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 14px;
}
.date-jump .dj-pop { left: auto; right: 0; }
.dj-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.dj-month { font-family: var(--font-head); font-weight: 700; font-size: .95rem; }
.dj-nav {
  width: 30px; height: 30px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--brand); font-size: 1rem; cursor: pointer; line-height: 1;
}
.dj-nav:hover:not(:disabled) { background: var(--brand-light); }
.dj-nav:disabled { opacity: .35; cursor: default; }
.dj-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dj-dow {
  text-align: center; font-size: .68rem; font-weight: 600; letter-spacing: .05em;
  color: var(--text-soft); text-transform: uppercase; padding: 4px 0;
}
.dj-day {
  aspect-ratio: 1; border: 0; border-radius: var(--radius-sm); background: transparent;
  font-family: var(--font-body); font-size: .85rem; color: var(--text); cursor: pointer; line-height: 1;
}
/* The darker tint step, not brand-light: one 34px cell has to carry the same read as the week
   picker's seven-cell band, and at that size the paler tint barely separates from white. */
.dj-day:hover:not(:disabled) { background: var(--brand-tint); }
.dj-day:disabled { color: var(--text-soft); opacity: .45; cursor: default; }
.dj-day.is-today { box-shadow: inset 0 0 0 1.5px var(--brand); font-weight: 700; }
.dj-day.is-selected { background: var(--brand); color: #fff; font-weight: 700; }
.dj-day.is-selected:hover:not(:disabled) { background: var(--brand-dark); }
.dj-day:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
/* Week mode (.dj-week — the garage sale week jump): the selectable unit is a Mon–Sun row, so
   hover, focus, and the selection all paint the row rather than a single cell. Three steps of
   the same steel tint, because the two states have to be told apart at a glance: hovered is
   brand-light, the selected week is a step down from it, and its Monday is filled solid
   because that is the day the trigger names and the URL the click lands on. */
.dj-pop.dj-week .dj-day.is-week-hover:not(:disabled):not(.is-selected) { background: var(--brand-light); }
.dj-pop.dj-week .dj-day.is-selected { background: var(--brand-tint); color: var(--brand); }
.dj-pop.dj-week .dj-day.is-selected.is-week-start { background: var(--brand); color: #fff; }
.dj-foot { margin-top: 10px; display: flex; justify-content: flex-end; }
.dj-today-btn, .dj-clear-btn {
  border: 0; background: none; color: var(--brand); font-weight: 600; font-size: .85rem;
  cursor: pointer; padding: 4px 8px; border-radius: 6px; font-family: var(--font-body);
}
.dj-today-btn:hover, .dj-clear-btn:hover { background: var(--brand-light); }
.dj-clear-btn { color: var(--text-muted); margin-right: auto; }
@media (max-width: 480px) {
  .search-bar { flex-wrap: wrap; }
  .search-bar input[type=text], .search-bar input[type=search] { flex-basis: 100%; }
  .date-jump { flex: 1; }
  .date-jump input[type=date], .date-jump .date-jump-btn { flex: 1; }
}
.search-results { margin-top: 16px; }

/* ===== Category chips ===== */
.chip-bar { display: flex; gap: 9px; flex-wrap: wrap; margin: 20px 0 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 8px 15px; border-radius: var(--radius-pill);
  background: var(--surface); border: 1.5px solid var(--border); color: var(--text-muted);
  font-weight: 600; font-size: .9rem; transition: all .15s;
}
/* Chips carry their category's accent (--cat/--cat-tint set inline, same system as
   event items); the "All" chip sets none, so the fallbacks keep it brand navy. */
.chip:hover { border-color: var(--cat, var(--brand)); color: var(--cat, var(--brand)); }
.chip.active { background: var(--cat, var(--brand)); border-color: var(--cat, var(--brand)); color: #fff; }
.chip .chip-count {
  font-size: .72rem; min-width: 21px; height: 21px; padding: 0 5px;
  display: inline-grid; place-items: center; border-radius: var(--radius-pill);
  background: var(--cat-tint, var(--bg)); border: 1px solid var(--cat-tint, var(--border));
  color: var(--cat, inherit); font-weight: 700;
}
.chip.active .chip-count { background: rgba(255,255,255,.25); border-color: transparent; color: #fff; }

/* ===== Listing header ===== */
.list-header { display: flex; align-items: baseline; justify-content: space-between; margin: 28px 0 6px; flex-wrap: wrap; gap: 8px; }
.list-header h3 { font-size: 1.5rem; }
.list-count { color: var(--text-muted); font-size: .9rem; }

/* ===== Day sections + event grid ===== */
.day-section { margin-top: 28px; }
.day-heading {
  display: flex; align-items: center; gap: 12px; font-family: var(--font-head); font-weight: 700;
  color: var(--text); font-size: 1.05rem; margin-bottom: 16px;
}
.day-heading::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.event-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }

.event-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .15s, box-shadow .15s; display: flex; flex-direction: column;
}
.event-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.event-card .card-image { aspect-ratio: 16 / 9; background: var(--brand-light); position: relative; overflow: hidden; }
.event-card .card-image img { width: 100%; height: 100%; object-fit: cover; }
.event-card .card-image.placeholder { display: grid; place-items: center; }
.event-card .card-image.placeholder svg { width: 42px; height: 42px; color: var(--text-soft); opacity: .8; }
.date-badge {
  position: absolute; top: 12px; left: 12px; background: var(--surface); border-radius: 12px;
  padding: 6px 10px; text-align: center; box-shadow: var(--shadow-sm); min-width: 50px;
}
.date-badge .month { display: block; font-size: .68rem; font-weight: 800; color: var(--accent-dark); letter-spacing: .08em; }
.date-badge .day { display: block; font-size: 1.35rem; font-weight: 800; font-family: var(--font-head); line-height: 1; color: var(--text); }

.event-card .card-body { padding: 16px 18px 18px; display: flex; flex-direction: column; flex: 1; }
.cat-badge {
  display: inline-block; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: 3px 10px; border-radius: var(--radius-pill); background: var(--brand-light); color: var(--brand-dark); margin-bottom: 9px; align-self: flex-start;
}
.event-card h4 { font-size: 1.12rem; line-height: 1.3; margin-bottom: 6px; }
.event-card h4 a { color: var(--text); }
.event-card h4 a:hover { color: var(--brand); }
.event-meta { color: var(--text-muted); font-size: .88rem; display: flex; flex-direction: column; gap: 3px; margin-bottom: 10px; }
.event-meta .meta-row { display: flex; align-items: center; gap: 7px; }
.event-card .excerpt { color: var(--text-muted); font-size: .9rem; flex: 1; }
.event-card .card-foot { margin-top: 12px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.event-card .org-name { font-size: .82rem; color: var(--text-soft); font-weight: 600; }
.event-card .cost { font-size: .82rem; font-weight: 700; color: var(--green); }
.cancelled-tag { color: var(--red); font-weight: 700; font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; }

/* ===== List header tools + view toggle ===== */
.list-tools { display: flex; align-items: center; gap: 14px; }
.view-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-pill); overflow: hidden; }
.view-toggle a { padding: 7px 15px; font-weight: 600; font-size: .85rem; color: var(--text-muted); background: var(--surface); }
.view-toggle a:hover { color: var(--brand); }
.view-toggle a.active { background: var(--brand); color: #fff; }
.search-meta { color: var(--text-muted); font-weight: 600; margin: 4px 0 14px; }

/* ===== Event list (compact text cards + list rows) =====
   Category color system: every item sets --cat / --cat-tint inline (from
   EventCategory.color/tint). Content carries the color; sponsor units stay
   navy so events always read louder than ads. */
.event-list .events { display: flex; flex-direction: column; }
.event-item { display: flex; background: var(--surface); color: var(--text); text-decoration: none; }
.ei-title { font-family: var(--font-head); color: var(--text); line-height: 1.3; }
.event-item:hover .ei-title { color: var(--brand); }
.eh-icon {
  display: grid; place-items: center; width: 31px; height: 31px; border-radius: 9px;
  background: var(--cat-tint, var(--brand-light)); color: var(--cat, var(--brand)); flex-shrink: 0;
}
.eh-icon svg { width: 16px; height: 16px; }
.cat-label {
  font-size: .66rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; color: var(--cat, var(--brand-dark));
}
.ehw-date {
  font-family: var(--font-head); font-weight: 800; font-size: .74rem; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.meta-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.meta-row svg { width: 13px; height: 13px; color: var(--brand); flex-shrink: 0; }
.ei-cost { color: var(--green); font-weight: 700; font-size: .85rem; }
.ei-org { color: var(--text-soft); font-weight: 600; }

/* -- Cards view: text-only cards, icon chip top-left, category accent line -- */
.view-cards .events { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; }
.view-cards .event-item {
  position: relative; flex-direction: column; border: 1px solid var(--border);
  border-top: 3px solid var(--cat, var(--brand)); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .15s, box-shadow .15s;
}
.view-cards .event-item:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.view-cards .eh-icon { position: absolute; top: 13px; left: 15px; }
.view-cards .ei-body { flex: 1; padding: 13px 15px 15px; display: flex; flex-direction: column; }
.view-cards .ei-head {
  display: grid; grid-template-columns: 1fr auto; align-items: start; gap: 0 8px;
  margin-left: 40px; min-height: 33px; margin-bottom: 10px;
}
.view-cards .ei-head .ei-cost, .view-cards .ei-head .cancelled-tag { grid-column: 2; grid-row: 1 / 3; }
.view-cards .ei-title { font-size: 1.04rem; margin-bottom: 6px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.view-cards .ei-excerpt { color: var(--text-muted); font-size: .85rem; margin-bottom: 12px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.view-cards .ei-meta {
  margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 3px; font-size: .82rem; color: var(--text-muted);
}
.view-cards .mr-time { display: none; }   /* time already rides the date line */
.view-cards .ei-org { font-size: .78rem; }
.view-cards .ei-side { display: none; }

/* -- List view: compact rows, colored left accent, icon chip -- */
.view-list .events { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.view-list .event-item {
  align-items: center; gap: 14px; padding: 9px 18px; border-bottom: 1px solid var(--border);
  box-shadow: inset 3px 0 0 var(--cat, var(--brand));
}
.view-list .event-item:last-child { border-bottom: none; }
.view-list .event-item:hover { background: var(--cat-tint, var(--brand-light)); }
.view-list .ei-head, .view-list .ei-excerpt { display: none; }
.view-list .ei-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.view-list .ei-title { font-size: 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.view-list .ei-meta { display: flex; flex-wrap: wrap; gap: 2px 14px; font-size: .82rem; color: var(--text-muted); }
.view-list .ei-side { display: inline-flex; align-items: center; gap: 12px; flex-shrink: 0; }
.view-list .event-item.is-cancelled .ei-title { text-decoration: line-through; color: var(--text-soft); }

/* ===== Garage sales (/garage-sales) =====
   Rows, never cards: a sale is an address and a time window, and a grid of cards would give
   four fields the visual weight of a full event. Reuses the list view's row chrome so the two
   listings read as the same site. */
/* Single lead band: identity on the left, week + controls on the right, one row. Replaces a
   hero stacked on a separate action band, which spent ~76px of padding and a duplicate
   gradient on one button. */
.gs-hero-side { margin-left: auto; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.gs-hero-week { font-family: var(--font-head); font-weight: 700; font-size: .98rem; color: #fff; white-space: nowrap; }
.gs-hero-dot { color: rgba(255,255,255,.5); margin: 0 2px; }
/* The one-pill date-jump (trigger + divider + ✕ reset) is the shared base now; see it up in
   the Date-jump block. All this band needs is its own sizing.
   The date pill is sized for the homepage's tall search bar. In this band it would set the
   band's height on its own, so match it to the btn-sm next to it. */
.gs-hero .date-jump-btn,
.gs-hero .date-jump input[type=date] { padding: 7px 14px; font-size: .85rem; }
.gs-views { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-pill); overflow: hidden; margin-right: auto; }
.gs-view {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 16px;
  font-size: .85rem; font-weight: 600; color: var(--text-muted); background: var(--surface);
}
.gs-view + .gs-view { border-left: 1px solid var(--border-strong); }
.gs-view:hover { color: var(--brand); text-decoration: none; }
.gs-view.active { background: var(--brand); color: #fff; }

.gs-item {
  display: flex; align-items: center; gap: 14px; padding: 11px 18px;
  border-bottom: 1px solid var(--border); background: var(--surface);
  box-shadow: inset 3px 0 0 var(--green);
  transition: background .18s ease;
}
.gs-item:last-child { border-bottom: none; }
.gs-item:hover, .gs-item.hl { background: var(--green-bg); }
.gs-icon { display: inline-flex; color: var(--green); flex-shrink: 0; }
.gs-icon svg { width: 20px; height: 20px; }
.gs-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gs-head { display: flex; align-items: center; gap: 10px; }
.gs-time { font-size: .82rem; font-weight: 600; color: var(--text-muted); }
.gs-nopin {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  padding: 2px 8px; border-radius: var(--radius-pill); background: var(--bg); color: var(--text-soft);
}
.gs-address {
  font-family: var(--font-head); font-size: 1rem; font-weight: 700; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gs-notes { font-size: .86rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gs-directions {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  font-size: .82rem; font-weight: 600; color: var(--brand);
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill); padding: 6px 14px;
}
.gs-directions:hover { border-color: var(--brand); background: var(--brand-light); text-decoration: none; }

/* Map sits above the list, never instead of it. Fixed height so tiles have somewhere to land
   before Leaflet measures the container. */
.gs-map-wrap { margin-bottom: 22px; position: relative; }
/* Overlay panel, above Leaflet's panes (pinned to z-index 1 below) but out of its way. */
.gs-map-info { position: absolute; top: 12px; right: 12px; z-index: 2; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; max-width: min(320px, calc(100% - 24px)); pointer-events: none; }
.gs-map-info > * { pointer-events: auto; }
.gs-map-count {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 7px 14px; font-family: var(--font-head); font-weight: 600; font-size: .85rem;
  color: var(--text); box-shadow: var(--shadow-sm);
}
.gs-map-count svg { color: var(--green); flex-shrink: 0; }
.gs-map-warn {
  background: var(--amber-bg); border: 1px solid #f3d9a0; border-radius: var(--radius-sm);
  padding: 10px 13px; font-size: .8rem; color: #7c4a03; box-shadow: var(--shadow-sm);
}
.gs-map-warn strong { display: block; font-family: var(--font-head); margin-bottom: 2px; }
.gs-map-warn ul { list-style: none; margin: 5px 0; padding: 0; font-weight: 600; }
.gs-map-warn a { color: #7c4a03; font-weight: 700; text-decoration: underline; }
/* Taller than the old map-above-a-list layout: on this view the map is the whole answer. */
.gs-map { height: 620px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg); }
/* The rows inside the container before app.js takes it over. Scrolls rather than stretching
   the container, so a no-JS visitor sees a normal list in a normal-sized box. */
.gs-map-fallback { height: 100%; overflow-y: auto; padding: 4px 0; }
.gs-map-fallback-note { padding: 12px 18px; font-size: .88rem; color: var(--text-muted); }
.gs-map-note { margin-top: 8px; font-size: .88rem; color: var(--text-muted); }
.gs-map-note a { font-weight: 600; }
/* Leaflet draws its panes at z-index 400+, which would otherwise ride over the sticky header. */
.gs-map .leaflet-pane, .gs-map .leaflet-top, .gs-map .leaflet-bottom { z-index: 1; }

/* Basemap styling is parked: the tiles render in stock OpenStreetMap colours for now.
   A CSS filter was tried and removed. Before reaching for one again, note that it cannot do
   per-feature colour at all (a filter is a per-pixel transform that has no idea what a road
   is), and that partial desaturation does not even mute the basemap: `saturate(.4)` keeps the
   tan land and yellow roads, just paler, because those are its highest-area colours. Per-feature
   colour needs a style applied at render time, which means vector tiles or a provider whose
   style is configurable. Full rationale in docs/garage-sales.md. */

/* Brand pin. divIcon markup is plain DOM, so the colour lives here with the rest of the
   palette instead of inside a PNG. Green matches the accent on the list rows. */
.gs-pin svg { width: 30px; height: 30px; display: block; fill: var(--green); filter: drop-shadow(0 2px 3px rgba(15, 23, 42, .35)); transition: transform .12s ease; }
.gs-pin svg circle { fill: #fff; }
.gs-pin:hover svg, .gs-pin:focus svg { transform: scale(1.12); }

/* Popup, zoom buttons and attribution in the site's shapes rather than Leaflet's defaults. */
.gs-map .leaflet-popup-content-wrapper {
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  box-shadow: var(--shadow-md); color: var(--text);
}
.gs-map .leaflet-popup-content { margin: 12px 15px; font-family: var(--font-body); font-size: .87rem; line-height: 1.5; }
.gs-map .leaflet-popup-content strong { font-family: var(--font-head); font-size: .95rem; }
.gs-map .leaflet-popup-content a { color: var(--brand); font-weight: 600; }
/* A pin covers a location, which may run several days: list every one of them. */
.gs-pop-notes { display: block; color: var(--text-muted); margin-top: 2px; }
.gs-pop-days { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.gs-pop-days li { display: flex; align-items: baseline; gap: 7px; color: var(--text); }
.gs-pop-days li::before { content: ""; flex: 0 0 5px; width: 5px; height: 5px; border-radius: 50%; background: var(--green); }
.gs-pop-link { display: inline-block; margin-top: 9px; }
.gs-map .leaflet-bar a {
  color: var(--text-muted); border-bottom-color: var(--border);
  font-family: var(--font-body);
}
.gs-map .leaflet-bar a:hover { color: var(--brand); background: var(--brand-light); }
/* Attribution stays (required by the OSM tile usage policy), just quieter. */
.gs-map .leaflet-control-attribution {
  background: rgba(255, 255, 255, .82); font-size: .68rem; color: var(--text-soft);
  border-radius: var(--radius-sm) 0 0 0; padding: 2px 8px;
}
.gs-map .leaflet-control-attribution a { color: var(--text-muted); }

/* Submit form: the day-hours rows. */
.gs-hours { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px 16px; margin-bottom: 18px; }
.gs-hours legend { font-size: .85rem; font-weight: 700; color: var(--text-muted); padding: 0 6px; }
.gs-hour-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.gs-hour-row:last-child { margin-bottom: 0; }
.gs-hour-row[hidden] { display: none; }
.gs-day-label { font-size: .82rem; font-weight: 600; color: var(--text-muted); min-width: 52px; }
.gs-dash { font-size: .82rem; color: var(--text-soft); }
.gs-hour-row input[type=time] { flex: 1; min-width: 0; }

/* Status / manage pages: the sale's schedule read back to the submitter. */
.gs-summary { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px 18px; margin-bottom: 18px; }
.gs-summary-address { font-family: var(--font-head); font-weight: 700; margin-bottom: 8px; }
.gs-summary-days { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.gs-summary-days li { display: flex; justify-content: space-between; gap: 16px; font-size: .88rem; }
.gs-summary-day { color: var(--text); }
.gs-summary-hours { color: var(--text-muted); white-space: nowrap; }
.gs-cancel { margin-top: 18px; }

@media (max-width: 768px) {
  /* The side group wraps under the title and spreads across the full width rather than
     stacking three centered blocks. */
  .gs-hero-side { margin-left: 0; width: 100%; gap: 10px; }
  .gs-hero-side .date-jump { margin-left: auto; }
  .gs-views { margin-right: 0; }
  .gs-item { flex-wrap: wrap; }
  .gs-directions { margin-left: 34px; }
  .gs-map { height: 320px; }
}

/* ===== Five-column layout: 4 event columns + slim ad column =====
   The event grid is never resized for ads; the ad column is its own equal
   track. Below 1000px the column is gone (no mobile ads in v1). */
.five-col { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; align-items: start; margin-top: 4px; }
.five-col > .event-list { grid-column: 1 / 5; min-width: 0; }
.five-col .view-cards .events, .five-col .event-list.view-cards .events { grid-template-columns: repeat(4, 1fr); }
.ad-col { grid-column: 5; position: sticky; top: 88px; display: flex; flex-direction: column; gap: 16px; }

/* "Sponsor" bubble — top-right of every paid unit, always visible. Muted so
   it can never be confused with a category label. */
.sponsor-tag {
  display: inline-block; font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em;
  padding: 2px 9px; border-radius: var(--radius-pill);
  background: #eef0f6; color: var(--text-soft);
}

/* Paid mini — the one unit format (logo tile + name + one line + link). */
.sponsor-mini {
  position: relative; display: flex; flex-direction: column; gap: 7px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
  padding: 14px 14px 12px; text-decoration: none; color: var(--text);
  transition: transform .15s, box-shadow .15s;
}
.sponsor-mini:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); color: var(--text); }
.sponsor-mini .sponsor-tag { position: absolute; top: -8px; right: 10px; background: var(--bg); border: 1px solid var(--border); }
.sponsor-mini .sm-head { display: flex; align-items: center; gap: 9px; min-width: 0; }
.sponsor-mini .sm-logo {
  flex: 0 0 34px; width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--oxford-navy), var(--dusk-blue) 60%, var(--steel-blue));
  font-family: var(--font-head); font-weight: 800; font-size: .78rem;
}
.sponsor-mini img.sm-logo { object-fit: cover; background: var(--surface); }
.sponsor-mini .sm-name { font-family: var(--font-head); font-weight: 700; font-size: .9rem; line-height: 1.25; }
.sponsor-mini .sm-copy { color: var(--text-muted); font-size: .8rem; line-height: 1.45; }
.sponsor-mini .sm-link { font-size: .8rem; font-weight: 700; color: var(--brand); }

/* Paid band/banner variants carry the bubble on the corner. */
.ad-top-slot .ad-slot-wrap { position: relative; }
.ad-slot-wrap .sponsor-tag { position: absolute; top: -9px; right: 14px; z-index: 2; background: var(--bg); border: 1px solid var(--border); }

/* House unit — the unsold state. Never a blank gap. */
.house-mini {
  display: block; text-align: center; padding: 18px 14px;
  background: var(--bg); border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius); color: var(--text-muted); font-size: .82rem;
  line-height: 1.5; text-decoration: none; transition: border-color .15s, background .15s;
}
.house-mini strong { display: block; font-family: var(--font-head); font-size: .9rem; color: var(--text); margin-bottom: 2px; }
.house-mini .hm-cta { display: block; margin-top: 6px; font-weight: 700; color: var(--brand); }
.house-mini:hover { border-color: var(--brand); background: var(--brand-light); color: var(--text-muted); }

@media (max-width: 1000px) {
  .five-col { display: block; }
  .ad-col { display: none; }
  /* The 4-column lock is scoped to .five-col, and .five-col is still on the element after it
     becomes display:block — so that descendant selector kept matching and the card grid stayed
     4-across all the way down to a phone, at roughly 80px per card. Two here, one below. */
  .five-col .view-cards .events,
  .five-col .event-list.view-cards .events { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  /* Two 230px-minimum cards no longer fit the viewport once padding and the gap come out. */
  .five-col .view-cards .events,
  .five-col .event-list.view-cards .events { grid-template-columns: 1fr; }
}

/* ===== Sponsor band (surface 5) — white card below the action band =====
   Category-banner visual language: square logo tile + one message + link.
   Sold = solid white card; unsold (.band-house) = dashed "slot available" look,
   matching the house placeholders in the ad column. */
.ad-top-slot { padding: 18px 0 0; }
.ad-sponsor-band {
  display: flex; align-items: center; gap: 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 14px 20px;
  color: var(--text); font-size: .95rem; text-decoration: none;
  transition: border-color .15s, box-shadow .15s;
}
.ad-sponsor-band:hover { border-color: var(--brand); box-shadow: var(--shadow-md); color: var(--text); }
.ad-sponsor-band .sb-logo {
  flex: 0 0 56px; width: 56px; height: 56px; border-radius: 12px;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--oxford-navy), var(--dusk-blue) 60%, var(--steel-blue));
  font-family: var(--font-head); font-weight: 800; font-size: 1.2rem;
}
/* A real logo must NOT inherit the initials tile's gradient above: a transparent PNG would
   show navy through it, which is what a sponsor's mark looked like on the banner. The tile
   background is decoration for the two-letter fallback only. */
.ad-sponsor-band img.sb-logo { background: var(--surface); }
.ad-sponsor-band .sb-text { flex: 1; min-width: 0; color: var(--text-muted); }
.ad-sponsor-band .sb-text strong { color: var(--text); }
.ad-sponsor-band .sb-link { flex-shrink: 0; }
.ad-sponsor-band.band-house { background: var(--bg); border: 1.5px dashed var(--border-strong); box-shadow: none; }
.ad-sponsor-band.band-house:hover { border-color: var(--brand); background: var(--brand-light); box-shadow: none; }
/* Narrow: tile + copy share the first row; the CTA drops to its own full row
   (a bare flex-wrap squeezes the copy into a skinny column beside the tile). */
@media (max-width: 600px) {
  .ad-sponsor-band { flex-wrap: wrap; }
  .ad-sponsor-band .sb-text { flex: 1 1 calc(100% - 72px); }
  .ad-sponsor-band .sb-link { flex: 1; text-align: center; }
}

/* Category-sponsor banner (Tier 2) — slim strip above the category grid.
   .banner-house is the unsold placeholder. */
.cat-sponsor-banner {
  display: flex; align-items: center; gap: 14px;
  background: var(--brand-light); border: 1px solid #d5e5f4;
  border-radius: var(--radius-sm); padding: 10px 16px; margin-bottom: 16px;
  font-size: .92rem; color: var(--brand-dark); text-decoration: none;
}
.cat-sponsor-banner .csb-logo {
  flex: 0 0 40px; width: 40px; height: 40px; border-radius: 10px;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--oxford-navy), var(--dusk-blue) 60%, var(--steel-blue));
  font-family: var(--font-head); font-weight: 800; font-size: .95rem;
}
/* Same as the band: white behind the image, gradient only behind initials. White rather than
   transparent because this card's own background is brand-light, and most logos are drawn for
   a white backdrop. */
.cat-sponsor-banner img.csb-logo { background: var(--surface); }
.cat-sponsor-banner .csb-text { flex: 1; min-width: 0; }
.cat-sponsor-banner .csb-cta { flex-shrink: 0; font-weight: 700; color: var(--brand); font-size: .85rem; }
.cat-sponsor-banner.banner-house { background: var(--bg); border: 1.5px dashed var(--border-strong); color: var(--text-muted); }
.cat-sponsor-banner.banner-house strong { color: var(--text); }
.cat-sponsor-banner.banner-house:hover { border-color: var(--brand); background: var(--brand-light); }

/* ===== /advertise media kit ===== */
/* Lead paragraph at the top of a page body — copy that used to live under a hero heading and
   moved down when the lead bands were normalized to one height. */
/* No max-width: the container already caps the measure, and at 62ch this lead paragraph
   stopped around a third of the way across while the section sub-heads directly beneath it
   ran the full width. A lead-in narrower than the secondary text under it reads as a bug
   rather than as emphasis, so it takes the same measure and earns its rank on size instead. */
.page-intro { color: var(--text-muted); font-size: 1.05rem; line-height: 1.65; margin-bottom: 28px; }
.adv-section { margin-top: 40px; scroll-margin-top: 110px; /* anchor jumps clear the ~93px sticky header */ }
.adv-section:first-of-type { margin-top: 0; } /* .main-content already pads below the hero */
.adv-section > h2 { font-size: 1.45rem; margin-bottom: 6px; }
.adv-section > p.sub { color: var(--text-muted); margin-bottom: 20px; }
.tier-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 18px; }
.tier-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; gap: 8px; }
.tier-card.flagship { border: 2px solid var(--brand); box-shadow: var(--shadow-md); }
.tier-card .tc-cap { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--accent-dark); }
.tier-card h3 { font-size: 1.2rem; }
.tier-card .tc-price { font-family: var(--font-head); font-weight: 800; font-size: 1.7rem; color: var(--brand); }
.tier-card .tc-price span { font-size: .85rem; color: var(--text-muted); font-weight: 600; }
.tier-card ul { list-style: none; display: flex; flex-direction: column; gap: 6px; font-size: .9rem; color: var(--text-muted); padding: 0; }
.tier-card ul li::before { content: "✓ "; color: var(--green); font-weight: 700; }
.placement-diagram { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.pd-frame { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow-sm); }
.pd-frame h4 { font-size: .95rem; margin-bottom: 10px; }
.pd-page { border: 1.5px solid var(--border-strong); border-radius: 10px; overflow: hidden; font-size: .68rem; color: var(--text-soft); text-align: center; }
.pd-row { padding: 7px 6px; border-bottom: 1px dashed var(--border); }
.pd-row:last-child { border-bottom: none; }
.pd-ad { background: var(--brand-light); color: var(--brand-dark); font-weight: 700; }
.pd-cell { background: var(--bg); border: 1px dashed var(--border); border-radius: 4px; padding: 10px 2px; }
.pd-cell.pd-ad { border-style: solid; border-color: var(--brand); }
.pd-cols { display: grid; grid-template-columns: 2.4fr 1fr; gap: 4px; padding: 6px; }
.pd-5col { display: grid; grid-template-columns: 4fr 1fr; gap: 4px; padding: 6px; align-items: start; }
.pd-events { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.pd-events.pd-rows { grid-template-columns: 1fr; }
.pd-adcol { display: grid; gap: 4px; }
/* Full container width, like the tier grid and placement diagram — every exhibit on
   /advertise shares the same edges. */
.spec-table { width: 100%; margin-bottom: 16px; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); font-size: .92rem; }
.spec-table th, .spec-table td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: top; }
.spec-table th { background: #f9fafc; font-family: var(--font-head); font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--text-soft); }
.spec-table tr:last-child td { border-bottom: none; }
/* Column proportions keep prose cells wide enough to wrap at sentence boundaries;
   the unit name never breaks and its tier label sits on its own line beneath it. */
.spec-table th:nth-child(1) { width: 24%; }
.spec-table th:nth-child(2) { width: 42%; }
.spec-table td:first-child strong { white-space: nowrap; }
.spec-table .unit-tier { display: block; font-size: .78rem; color: var(--text-soft); margin-top: 2px; white-space: nowrap; }
.spec-table .no-wrap { white-space: nowrap; }
@media (max-width: 700px) { .placement-diagram { grid-template-columns: 1fr; } }


/* ===== Empty state ===== */
.empty-state { text-align: center; padding: 64px 20px; color: var(--text-muted); }
.empty-state .empty-icon { width: 56px; height: 56px; color: var(--brand); opacity: .55; margin: 0 auto; }
.empty-state h3 { margin: 14px 0 6px; color: var(--text); }

/* ===== Admin search box ===== */
.admin-search { display: flex; gap: 8px; align-items: center; }
.admin-search input[type="search"] {
  height: var(--search-h); padding: 0 16px; border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-pill);
  font-size: .95rem; font-family: var(--font-body); min-width: 240px; background: var(--surface); color: var(--text);
}
.admin-search input[type="search"]:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-light); }

/* ===== Pagination ===== */
.pagination { display: flex; justify-content: center; gap: 6px; margin-top: 40px; flex-wrap: wrap; }
.pagination a, .pagination span {
  min-width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0 12px;
  border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font-weight: 600;
}
.pagination a:hover { border-color: var(--brand); color: var(--brand); }
.pagination .active { background: var(--brand); border-color: var(--brand); color: #fff; }
.pagination .disabled { opacity: .4; pointer-events: none; }

/* ===== Event detail ===== */
.detail-hero-image { width: 100%; max-height: 420px; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow-md); }
.detail-layout { display: grid; grid-template-columns: 1fr 320px; gap: 32px; margin-top: 28px; align-items: start; }
.detail-main h1 { font-size: 2.1rem; letter-spacing: -.02em; margin-bottom: 10px; }
.detail-main .description { font-size: 1.05rem; color: #334155; white-space: pre-wrap; margin-top: 18px; }
.detail-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); position: sticky; top: 88px; }
/* The aside wraps the info card + the rail sponsor slot; the whole stack
   sticks together (a sticky card alone would slide over the slot below it). */
.detail-aside { position: sticky; top: 88px; }
.detail-aside .detail-card { position: static; }
.detail-card .detail-row { padding: 12px 0; border-bottom: 1px solid var(--border-light, var(--border)); }
.detail-card .detail-row:last-of-type { border-bottom: none; }
.detail-card .detail-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-soft); font-weight: 700; }
.detail-label svg { width: 12px; height: 12px; color: var(--brand); vertical-align: -2px; margin-right: 5px; }
/* Category lockup above the title — same system as the cards/list rows */
.detail-cat { display: inline-flex; align-items: center; gap: 9px; margin-bottom: 12px; }
.detail-cat .eh-icon { width: 36px; height: 36px; border-radius: 10px; }
.detail-cat .eh-icon svg { width: 19px; height: 19px; }
.detail-cat .cat-label { font-size: .74rem; }
.detail-aside .house-mini { margin-top: 18px; }
.detail-card .detail-value { font-size: 1rem; color: var(--text); margin-top: 3px; }
.detail-card .btn { margin-top: 8px; }
.cancelled-banner { background: var(--red-bg); color: var(--red); padding: 14px 18px; border-radius: var(--radius-sm); font-weight: 700; margin-bottom: 18px; }
.breadcrumb { font-size: .88rem; color: var(--text-soft); margin-bottom: 8px; }
/* Org profile: description sits in the content area (the one-row hero stays slim). */
.org-about { color: var(--text-muted); max-width: 70ch; margin-bottom: 18px; }

/* ===== Organizations ===== */
.org-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 18px; margin-top: 24px; }
.org-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); transition: box-shadow .15s; }
.org-card:hover { box-shadow: var(--shadow-md); }
.org-card .org-logo { width: 56px; height: 56px; border-radius: 14px; object-fit: cover; background: var(--brand-light); margin-bottom: 12px; }
/* brand-light is the empty-tile tint; a transparent logo would pick it up as a blue wash. */
.org-card img.org-logo { background: var(--surface); }
.org-logo-ph { display: grid; place-items: center; overflow: hidden; }
.org-logo-ph img { width: 74%; opacity: .32; mix-blend-mode: multiply; }
.org-card h4 { font-size: 1.1rem; }
.org-card p { color: var(--text-muted); font-size: .9rem; margin-top: 6px; }
.org-card .org-stat { margin-top: 12px; font-size: .85rem; color: var(--brand); font-weight: 700; }

/* ===== Forms ===== */
.form-wrap { max-width: 760px; margin: 0 auto; }
.form-wrap.narrow { max-width: 460px; }
.form-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow-sm); }
.form-card h3 { font-size: 1.5rem; margin-bottom: 4px; }
.form-card .sub { color: var(--text-muted); margin-bottom: 22px; }
/* ===== Select — native element, restyled =====
   Reset the OS appearance and draw our own chevron (Catalyst-style double caret,
   stroke = --text-muted) so selects match the rest of the form controls everywhere. */
select {
  appearance: none;
  -webkit-appearance: none;
  display: inline-block;
  padding: 9px 36px 9px 12px;
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M5.75 10.75L8 13l2.25-2.25M10.25 5.25L8 3 5.75 5.25' stroke='%2364748b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px 16px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: .95rem;
  cursor: pointer;
  transition: border-color .15s;
}
select:hover { border-color: var(--text-soft); }
select:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-light); }
select:disabled { opacity: .55; cursor: not-allowed; }

.form-group { margin-bottom: 18px; }
.form-group label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: 6px; color: var(--text); }
.form-group .hint { font-weight: 400; color: var(--text-soft); font-size: .82rem; }
.form-group input[type=text], .form-group input[type=email], .form-group input[type=password],
.form-group input[type=tel], .form-group input[type=url], .form-group input[type=time],
.form-group input[type=date], .form-group select, .form-group textarea {
  width: 100%; padding: 11px 14px; border: 1.5px solid var(--border-strong); border-radius: var(--radius-sm);
  font-size: 1rem; font-family: var(--font-body); background-color: var(--surface); color: var(--text);
}
.form-group textarea { resize: vertical; min-height: 130px; }
/* Embed snippets — read-only code the org copies onto their own site */
.form-group textarea.embed-snippet {
  min-height: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .82rem; color: var(--text-muted); background-color: var(--bg); resize: none;
}
.form-group select { padding-right: 40px; }  /* room for the chevron at this size */

/* File inputs — dashed upload affordance; restyle the native button via ::file-selector-button */
.form-group input[type=file] {
  width: 100%; padding: 8px; border: 1.5px dashed var(--border-strong); border-radius: var(--radius-sm);
  background-color: var(--surface); color: var(--text-muted); font-size: .92rem; cursor: pointer;
}
.form-group input[type=file]:hover { border-color: var(--text-soft); }
.form-group input[type=file]:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-light);
}
input[type=file]::file-selector-button {
  border: 0; border-radius: 8px; padding: 8px 14px; margin-right: 12px;
  background: var(--brand-light); color: var(--brand);
  font-family: var(--font-body); font-size: .9rem; font-weight: 600;
  cursor: pointer; transition: background .15s;
}
input[type=file]::file-selector-button:hover { background: #d5e5f4; }
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-light);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.checkbox-row { display: flex; align-items: center; gap: 9px; }
.checkbox-row input { width: 18px; height: 18px; accent-color: var(--brand); }
.checkbox-row label { margin: 0; font-weight: 500; }
.honeypot { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }
.form-actions { display: flex; gap: 10px; margin-top: 24px; flex-wrap: wrap; }
.field-image-preview { margin-top: 10px; max-height: 180px; border-radius: var(--radius-sm); }

/* ===== Alerts / banners ===== */
.alert { padding: 13px 16px; border-radius: var(--radius-sm); font-weight: 500; margin-bottom: 18px; font-size: .92rem; }
.alert.error { background: var(--red-bg); color: var(--red); }
.alert.success { background: var(--green-bg); color: var(--green); }
.alert.info { background: var(--blue-bg); color: #1d4ed8; }
.banner {
  display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-radius: var(--radius-sm); margin-bottom: 22px; font-size: .92rem;
}
.banner.pending { background: var(--amber-bg); color: var(--amber); }
.banner.suspended { background: var(--red-bg); color: var(--red); }
.banner strong { font-family: var(--font-head); }

/* ===== Status pills ===== */
.pill { display: inline-block; padding: 3px 11px; border-radius: var(--radius-pill); font-size: .76rem; font-weight: 700; text-transform: capitalize; }
.pill.published, .pill.approved { background: var(--green-bg); color: var(--green); }
.pill.draft, .pill.pending { background: var(--amber-bg); color: var(--amber); }
.pill.cancelled, .pill.suspended { background: var(--red-bg); color: var(--red); }

/* ===== Dashboard / Admin shared ===== */
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 22px; flex-wrap: wrap; }
.page-head h1 { font-size: 1.8rem; }
.org-context { font-size: .92rem; color: var(--text-muted); margin-top: 2px; }
.org-context strong { color: var(--text); }

/* Org switcher (multi-org accounts) + the account page's organizations list */
.org-switcher select { max-width: 220px; font-size: .9rem; }
.org-list { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.org-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px; border: 1px solid var(--border); border-radius: 10px;
}
.org-list .org-meta { display: block; font-size: .82rem; color: var(--text-muted); margin-top: 2px; }
.org-current {
  font-size: .78rem; font-weight: 700; color: var(--brand);
  background: var(--brand-light); padding: 4px 12px; border-radius: var(--radius-pill);
}
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 28px; }
.stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow-sm); }
.stat-card .num { font-family: var(--font-head); font-size: 2rem; font-weight: 800; color: var(--brand); }
.stat-card .label { color: var(--text-muted); font-size: .9rem; }

.data-table { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
.data-table th, .data-table td { text-align: left; padding: 13px 16px; border-bottom: 1px solid var(--border); font-size: .92rem; vertical-align: middle; }
.data-table th { background: #f9fafc; font-family: var(--font-head); font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--text-soft); }
.data-table tr:last-child td { border-bottom: none; }
.data-table .actions { display: flex; gap: 6px; flex-wrap: nowrap; justify-content: flex-end; align-items: center; }
.data-table .actions form { display: inline-flex; margin: 0; }

/* Repeating series: title badge + scoped-delete disclosure menu (dashboard event rows) */
.repeat-badge {
  display: inline-block; font-size: .66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--brand-dark); background: var(--brand-light);
  padding: 1px 8px; border-radius: var(--radius-pill); white-space: nowrap; vertical-align: middle;
}
.row-menu { display: inline-block; }
.row-menu > summary { list-style: none; cursor: pointer; }
.row-menu > summary::-webkit-details-marker { display: none; }
.row-menu > summary::marker { content: ""; }
/* Floating overlay: fixed to the viewport (JS positions it under the button) so it lifts above
   the table on its own z-layer instead of expanding the row. */
.row-menu-pop {
  position: fixed; z-index: 1000; top: 0; left: 0; width: 232px; visibility: hidden;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: 6px; text-align: left;
}
.row-menu[open] .row-menu-pop { visibility: visible; }
.row-menu-label { font-size: .74rem; color: var(--text-soft); margin: 0; padding: 4px 8px 6px; }
.data-table .actions .row-menu-pop form { display: block; margin: 0; }
.row-menu-item {
  display: block; width: 100%; text-align: left; padding: 8px 10px; border: 0; background: transparent;
  border-radius: var(--radius-sm); font-family: var(--font-body); font-size: .88rem; color: var(--text); cursor: pointer;
}
.row-menu-item:hover { background: var(--red-bg); color: var(--red); }

/* Rows queued for deletion by the open menu (anchor row, or the sibling set a menu item targets). */
.data-table tbody tr.row-deleting > td { background: var(--red-bg); }
.data-table tbody tr.row-deleting > td:first-child { box-shadow: inset 3px 0 0 var(--red); }

/* Minimal, monochrome icon buttons (admin table actions) */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
  width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-soft); cursor: pointer; transition: all .15s;
}
.icon-btn svg { width: 16px; height: 16px; display: block; }
.icon-btn:hover { color: var(--text); border-color: var(--border-strong); background: #f3f5fa; }
.icon-btn.go:hover { color: var(--brand); border-color: var(--brand); background: var(--brand-light); }
.icon-btn.danger:hover { color: var(--red); border-color: var(--red-bg); background: var(--red-bg); }
.table-wrap { overflow-x: auto; }

/* Newsletter issues table: dates and counts never wrap; the subject (which repeats the
   window + count in prose) truncates with the full text on hover instead of stealing rows. */
.issues-table th, .issues-table td { white-space: nowrap; font-variant-numeric: tabular-nums; }
.issues-table .col-subject { max-width: 30ch; overflow: hidden; text-overflow: ellipsis; }

/* Read-only inputs (e.g. the campaign form's list-priced monthly rate) read as values, not fields. */
input[readonly] { background: var(--bg); color: var(--text-muted); cursor: default; }
.data-table td.cell-clip { max-width: 170px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sponsor-logo-thumb { display: block; width: 36px; height: 36px; border-radius: 8px; object-fit: cover; background: var(--brand-light); }
/* .placeholder keeps the tint; a real <img> gets white so transparency doesn't tint the mark. */
img.sponsor-logo-thumb { background: var(--surface); }
.filter-tabs { display: flex; gap: 6px; margin-bottom: 18px; flex-wrap: wrap; }
.filter-tabs a { padding: 7px 15px; border-radius: var(--radius-pill); border: 1px solid var(--border); color: var(--text-muted); font-weight: 600; font-size: .88rem; }
.filter-tabs a.active { background: var(--brand); color: #fff; border-color: var(--brand); }

/* ===== Admin organization review ===== */
.org-review-head { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; margin-bottom: 22px; }
.org-review-id { display: flex; align-items: center; gap: 16px; min-width: 0; }
.org-review-avatar { width: 60px; height: 60px; border-radius: 16px; object-fit: cover; background: var(--brand-light); flex-shrink: 0; }
.org-review-avatar-ph { display: grid; place-items: center; overflow: hidden; }
.org-review-avatar-ph img { width: 74%; opacity: .32; mix-blend-mode: multiply; }
.org-review-id h1 { font-size: 1.5rem; }
.org-review-meta { display: flex; align-items: center; gap: 12px; margin-top: 6px; flex-wrap: wrap; }
.org-review-meta .muted { color: var(--text-soft); font-size: .85rem; }
.detail-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.detail-actions form { margin: 0; }
.card-title { font-size: 1.1rem; margin-bottom: 16px; }
.info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 18px 28px; }
.info-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .07em; color: var(--text-soft); font-weight: 700; margin-bottom: 3px; }
.info-value { font-size: .98rem; color: var(--text); word-break: break-word; }

/* Grouped admin nav: flat top-level items (accent underline = active section) with
   white dropdown panels. Dropdowns open on hover/focus (desktop) or via the .open
   class app.js toggles on tap; active section is marked by app.js from the URL. */
.admin-bar { background: var(--oxford-navy); color: #fff; position: relative; z-index: 50; box-shadow: var(--shadow-sm); }
.admin-bar .inner { display: flex; align-items: stretch; justify-content: space-between; min-height: 52px; gap: 12px; }
.admin-bar .bar-left { display: flex; align-items: stretch; min-width: 0; }
.admin-brand { display: flex; align-items: center; gap: 9px; color: #fff; font-family: var(--font-head); font-weight: 700; font-size: .95rem; padding-right: 18px; white-space: nowrap; }
.admin-brand svg { flex-shrink: 0; }
.admin-links { display: flex; align-items: stretch; }
.admin-links .nav-item { position: relative; display: flex; }
.admin-links .top {
  display: flex; align-items: center; gap: 6px; padding: 0 13px;
  color: rgba(255,255,255,.8); font-weight: 500; font-size: .9rem;
  background: none; border: 0; border-bottom: 2px solid transparent;
  font-family: var(--font-body); cursor: pointer; border-radius: 0;
}
.admin-links .top:hover, .admin-links .nav-item.open > .top,
.admin-links .nav-item:focus-within > .top { color: #fff; background: rgba(255,255,255,.07); text-decoration: none; }
.admin-links .nav-item.active > .top { color: #fff; border-bottom-color: var(--accent); font-weight: 600; }
.admin-links .caret { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg) translateY(-2px); }
.admin-menu {
  position: absolute; top: 100%; left: 0; min-width: 190px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  box-shadow: var(--shadow-md); padding: 6px;
  display: none; flex-direction: column; z-index: 60;
}
.nav-item:hover .admin-menu, .nav-item:focus-within .admin-menu, .nav-item.open .admin-menu { display: flex; }
.admin-menu a { padding: 8px 12px; border-radius: 8px; color: var(--text); font-size: .88rem; font-weight: 500; }
.admin-menu a:hover { background: var(--brand-light); text-decoration: none; }
.admin-bar .bar-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.admin-bar .bar-right .site-link { color: rgba(255,255,255,.8); font-size: .85rem; font-weight: 600; }
.admin-bar .bar-right .site-link:hover { color: #fff; }
.admin-bar .logout-btn {
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.25); color: #fff;
  border-radius: var(--radius-pill); padding: 5px 14px; font-size: .82rem; font-weight: 600;
  font-family: var(--font-body); cursor: pointer;
}
.admin-bar .logout-btn:hover { background: rgba(255,255,255,.18); }
@media (max-width: 900px) {
  .admin-bar .inner { flex-wrap: wrap; padding: 8px 0; }
  .admin-bar .bar-left { flex-wrap: wrap; }
  .admin-links { flex-wrap: wrap; }
  .admin-links .top { padding: 8px 11px; }
}

/* ===== Admin dashboard (sectioned layout) ===== */
.dash-asof { color: var(--text-soft); font-size: .85rem; }
.dash-attention {
  background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--amber);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 16px 20px; margin-bottom: 34px;
}
.dash-attention h2 {
  font-size: .8rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--amber); display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
}
.dash-attention.all-clear { border-left-color: var(--green); padding: 12px 20px; }
.dash-attention.all-clear h2 { color: var(--green); margin-bottom: 0; }
.dash-attention .all-clear-text { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--text-muted); font-size: .9rem; }
.dash-attention ul { list-style: none; }
.dash-attention li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--border); font-size: .92rem;
}
.dash-attention li:first-child { border-top: 0; }
.dash-attention .act {
  font-size: .85rem; font-weight: 600; white-space: nowrap;
  background: var(--brand-light); color: var(--brand);
  border-radius: var(--radius-pill); padding: 4px 14px;
}
.dash-attention .act:hover { text-decoration: none; filter: brightness(.96); }
.dash-section { margin-bottom: 38px; }
.dash-section-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; gap: 10px; flex-wrap: wrap; }
.dash-section-head h2 { font-size: .8rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }
.dash-section-head .sub { font-size: .85rem; color: var(--text-soft); }
.dash-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
.dash-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 18px 20px; display: flex; flex-direction: column; gap: 4px; color: inherit;
}
a.dash-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); text-decoration: none; }
.dash-kpi { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.dash-num { font-family: var(--font-head); font-weight: 700; font-size: 2.1rem; font-variant-numeric: tabular-nums; line-height: 1.1; color: var(--text); }
.dash-label { font-size: .9rem; color: var(--text-muted); }
.dash-delta { font-size: .76rem; font-weight: 600; border-radius: var(--radius-pill); padding: 2px 9px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dash-delta.up { color: var(--green); background: var(--green-bg); }
.dash-delta.flat { color: var(--text-soft); background: var(--bg); }
.dash-breakdown {
  display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; padding-top: 10px;
  border-top: 1px solid var(--border); font-size: .85rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.dash-breakdown b { color: var(--text); font-weight: 600; }
.dash-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 5px; vertical-align: 1px; }
.dash-dot.green { background: var(--green); } .dash-dot.amber { background: var(--amber); }
.dash-dot.red { background: var(--red); } .dash-dot.grey { background: var(--text-soft); }
.dash-rev {
  display: flex; flex-wrap: wrap; gap: 8px 26px; margin-bottom: 14px; align-items: baseline;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 14px 20px;
}
.dash-rev .item { display: flex; align-items: baseline; gap: 8px; font-size: .85rem; color: var(--text-muted); }
.dash-rev .item.push { margin-left: auto; }
.dash-rev .val { font-family: var(--font-head); font-weight: 700; font-size: 1.45rem; color: var(--text); font-variant-numeric: tabular-nums; }
.dash-rev .val.unsold { color: var(--amber); }
.dash-inv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 14px; }
/* Now an <a> to /admin/inventory: display:block so the whole card is the hit area, and its
   own color so the card text doesn't inherit link blue. */
.dash-inv { display: block; color: inherit; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 16px 18px; }
.dash-inv:hover { border-color: var(--brand); text-decoration: none; }
.dash-inv .inv-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; gap: 8px; }
.dash-inv .inv-name { font-family: var(--font-head); font-weight: 600; font-size: .9rem; }
.dash-inv .inv-frac { font-size: .85rem; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dash-inv .inv-frac b { color: var(--text); }
.dash-meter { height: 8px; border-radius: var(--radius-pill); background: var(--bg); border: 1px solid var(--border); overflow: hidden; }
.dash-meter > span { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--accent); }
.dash-inv .inv-foot { display: flex; justify-content: space-between; gap: 8px; margin-top: 8px; font-size: .78rem; color: var(--text-soft); font-variant-numeric: tabular-nums; }
.dash-perf { display: flex; flex-wrap: wrap; gap: 6px 26px; margin-top: 12px; font-size: .85rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.dash-perf b { color: var(--text); }
.dash-gauge-track { height: 10px; border-radius: var(--radius-pill); background: var(--bg); border: 1px solid var(--border); overflow: hidden; margin-top: 10px; }
.dash-gauge-track > span { display: block; height: 100%; background: var(--green); border-radius: var(--radius-pill); }
.dash-gauge-label { display: flex; justify-content: space-between; font-size: .78rem; color: var(--text-soft); margin-top: 5px; font-variant-numeric: tabular-nums; }
.dash-digest-title { font-family: var(--font-head); font-weight: 600; font-size: .95rem; color: var(--text); }
.dash-digest-sub { font-size: .85rem; color: var(--text-muted); }
.dash-digest-line { display: flex; justify-content: space-between; gap: 10px; font-size: .85rem; padding: 7px 0; border-top: 1px solid var(--border); font-variant-numeric: tabular-nums; }
.dash-digest-line:first-of-type { border-top: 0; }
.dash-digest-line .k { color: var(--text-muted); }
.dash-digest-line .v { font-weight: 600; }
.dash-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* Digest preview page: full-height email frame in a card */
.digest-preview-meta { display: flex; flex-wrap: wrap; gap: 8px 26px; align-items: baseline; margin-bottom: 16px; font-size: .9rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.digest-preview-meta b { color: var(--text); }
.digest-frame {
  width: 100%; height: 78vh; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-sm);
}

/* ===== Footer ===== */
.site-footer { background: var(--regal-navy); color: rgba(255,255,255,.7); padding: 44px 0 24px; margin-top: auto; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1.4fr; gap: 32px; }
.site-footer h4 { color: #fff; font-size: 1.05rem; margin-bottom: 12px; }
.site-footer p { font-size: .9rem; max-width: 40ch; }
.footer-links { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.footer-links a { color: rgba(255,255,255,.7); font-size: .9rem; }
.footer-links a:hover { color: #fff; }
.footer-bottom { border-top: 1px solid rgba(255,255,255,.12); margin-top: 32px; padding-top: 18px; display: flex; justify-content: space-between; font-size: .82rem; color: rgba(255,255,255,.5); flex-wrap: wrap; gap: 8px; }
.footer-bottom a { color: rgba(255,255,255,.7); }
/* ===== Error pages (404 / 429 / 500 …) =====
   One big muted numeral, centred, and nothing else competing with it. Muted rather than brand
   on purpose: the code is a wayfinding sign, not an alarm — the message underneath is the part
   worth reading, so that's what carries the colour. */
.err-page { display: flex; align-items: center; min-height: 58vh; }
.err-block { max-width: 46rem; margin: 0 auto; text-align: center; padding: 40px 0 64px; }
.err-code {
  font-family: var(--font-head); font-weight: 800; line-height: .9;
  /* Scales with the viewport so it stays "plastered in the middle" on a phone as well as a
     desktop, without a stack of breakpoints. */
  font-size: clamp(5rem, 22vw, 11rem);
  color: var(--border-strong); letter-spacing: -.04em; margin-bottom: 8px;
}
.err-headline { font-size: 1.6rem; margin-bottom: 10px; }
.err-detail { color: var(--text-muted); font-size: 1rem; line-height: 1.6; max-width: 34rem; margin: 0 auto; }
.err-retry {
  margin-top: 16px; display: inline-block; background: var(--brand-light); color: var(--brand);
  font-weight: 600; font-size: .92rem; padding: 8px 16px; border-radius: var(--radius-pill);
}
.err-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 26px; }
@media (max-width: 480px) {
  .err-actions { flex-direction: column; }
  .err-actions .btn { width: 100%; }
}

/* Webhook address on /admin/newsletter — the value SendGrid must be pointed at. */
.hook-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px; margin-bottom: 14px; font-size: .85rem;
}
.hook-label { font-family: var(--font-head); font-weight: 700; color: var(--text); }
.hook-url {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .82rem;
  background: var(--brand-light); color: var(--brand); padding: 3px 8px; border-radius: 6px;
  user-select: all;
}
.hook-note { color: var(--text-muted); font-size: .8rem; }

/* ===== /admin/inventory — what's open, per product =====
   Rows rather than cards: a slot is a name and a status, and 38 of them (10 categories,
   14 towns, 12 pooled seats, 1 board) as cards would be a wall. Open slots are links and
   carry the brand tint so the eye lands on what can still be sold. */
.inv-group { margin-bottom: 26px; }
.inv-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.inv-group-head h2 { font-size: 1.05rem; }
.inv-group-meta { font-size: .85rem; color: var(--text-muted); }
.inv-open-note { color: var(--brand); font-weight: 600; }
.inv-full { color: var(--text-soft); }
.inv-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 8px; }
.inv-slot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); font-size: .9rem;
}
.inv-slot-main { display: flex; flex-direction: column; min-width: 0; }
.inv-slot-label { font-weight: 600; color: var(--text); }
.inv-slot-sub { font-size: .76rem; color: var(--text-soft); }
.inv-slot-open { border-color: var(--brand-light); background: var(--brand-light); }
.inv-slot-open:hover { border-color: var(--brand); text-decoration: none; }
.inv-slot-cta { color: var(--brand); font-weight: 600; font-size: .82rem; white-space: nowrap; }
.inv-slot-sold { display: flex; flex-direction: column; align-items: flex-end; text-align: right; min-width: 0; }
.inv-sponsor { font-weight: 600; color: var(--text); font-size: .85rem; }
.inv-until { font-size: .76rem; color: var(--text-muted); white-space: nowrap; }

/* ===== App store badges (footer column one) =====
   Delete this block and partials/app-badges.leaf to remove the feature; nothing else uses
   these classes. Sized to the ~135×40 proportions of the real store badges so the official
   artwork can drop straight into the same row later without the layout moving.
   .app-badge is the pre-launch placeholder (a span, not a link); .app-badge-live is the
   linked wrapper for the real badge images once the apps are listed. */
.app-badges { margin-top: 18px; }
.app-badges-label {
  display: block; font-size: .72rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: rgba(255,255,255,.45); margin-bottom: 9px;
}
.app-badges-row { display: flex; flex-wrap: wrap; gap: 10px; }
.app-badge {
  display: inline-flex; align-items: center; gap: 9px; min-width: 148px; padding: 7px 14px;
  border: 1px solid rgba(255,255,255,.22); border-radius: 9px;
  background: rgba(255,255,255,.06); color: rgba(255,255,255,.85);
}
.app-badge svg { flex: 0 0 20px; width: 20px; color: rgba(255,255,255,.55); }
.ab-text { display: flex; flex-direction: column; line-height: 1.15; }
.ab-kicker { font-size: .62rem; letter-spacing: .04em; text-transform: uppercase; color: rgba(255,255,255,.55); }
.ab-store { font-family: var(--font-head); font-weight: 700; font-size: .92rem; color: #fff; }
.app-badge-live { display: inline-flex; }
.app-badge-live img { display: block; height: 40px; width: auto; }

.footer-newsletter-pitch { color: rgba(255,255,255,.7); font-size: .9rem; margin-bottom: 10px; }
.footer-newsletter { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.footer-newsletter input[type=email] { padding: 9px 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,.25); background: rgba(255,255,255,.08); color: #fff; font-size: .9rem; }
.footer-newsletter input[type=email]::placeholder { color: rgba(255,255,255,.45); }
.footer-newsletter input[type=email]:focus { outline: 2px solid rgba(255,255,255,.4); border-color: transparent; }

/* ===== Prose (about / tos) ===== */
.prose { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 32px; box-shadow: var(--shadow-sm); max-width: 820px; margin: 0 auto; }
.prose h1 { font-size: 2rem; margin-bottom: 14px; }
.prose h2 { font-size: 1.3rem; margin: 26px 0 10px; }
.prose p, .prose li { color: #334155; margin-bottom: 12px; }
.prose ul { padding-left: 22px; }

/* ===== Responsive ===== */
@media (max-width: 860px) {
  .detail-layout { grid-template-columns: 1fr; }
  .detail-card, .detail-aside { position: static; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}
/* --- Header breakpoints -------------------------------------------------------------
   The header collapses in two stages, because one stage isn't enough to keep it inside the
   viewport. Measured: the full header (logo + tagline + 4 nav links + CTAs) needs ~950px, and
   ~845px once the tagline is dropped. Collapsing straight to the hamburger at 768px, as this
   did, left the desktop nav overflowing the page and scrolling it sideways between 769px and
   ~950px. Adding the Garage Sales link widened the nav and made that band wider still.
   Stage one: drop the tagline, which buys ~100px and is the least useful thing in the header. */
@media (max-width: 960px) {
  .logo-tag { display: none; }
}
/* Stage two: the hamburger takes over. Raised from 860px because 860 was measured against a
   GUEST header — a logged-in org also renders Dashboard, and four nav links plus three buttons
   need roughly 1000px inside a 1140px container. Below that the row ran out of room and the
   labels wrapped instead. Sized for the widest case (logged in) so the nav never breaks for
   anyone, rather than for the narrowest. */
@media (max-width: 1000px) {
  .nav-toggle { display: block; }
  .main-nav {
    position: absolute; top: 100%; left: 0; right: 0; background: var(--surface); border-bottom: 1px solid var(--border);
    flex-direction: column; align-items: stretch; padding: 12px; gap: 6px; box-shadow: var(--shadow-md); display: none;
  }
  .main-nav.open { display: flex; }
  .main-nav ul { flex-direction: column; align-items: stretch; gap: 2px; }
  .main-nav a.nav-link { padding: 12px 14px; }
  .nav-cta { margin-left: 0; padding-top: 8px; border-top: 1px solid var(--border); }
  .nav-cta .btn { flex: 1; }
}
@media (max-width: 768px) {
  .hero h1, .hero h2 { font-size: 1.45rem; }
  .hero-actions { width: 100%; }
  .hero-actions .btn { flex: 1; }
  .form-row { grid-template-columns: 1fr; }
  /* Band wraps early: search takes the full row, date-jump + post CTA share the next. */
  .search-band .search-bar { flex-wrap: wrap; }
  .search-band .search-bar input[type=text] { flex-basis: 100%; }
  .search-band .date-jump { flex: 1; }
  .search-band .date-jump .date-jump-btn { flex: 1; }
  .search-band .search-bar > .btn { flex: 1; }
}
@media (max-width: 480px) {
  .hero h1, .hero h2 { font-size: 1.3rem; }
  .footer-grid { grid-template-columns: 1fr; }
  .event-grid { grid-template-columns: 1fr; }
  .main-content { padding: 24px 0 48px; }
  .site-logo .logo-icon { height: 54px; }
  .logo-word { font-size: 1.3rem; }
}

/* ============================================================
   Regional — homepage entry strip, /regional map + town list
   ============================================================ */

/* Blue-band breadcrumb — regional hero, event-detail strip, org-profile hero */
.region-crumb { font-size: .85rem; color: rgba(255,255,255,.75); margin-bottom: 6px; }
.region-crumb a { color: rgba(255,255,255,.9); }
.region-crumb a:hover { color: #fff; }
/* Content-area variant (org page): the crumb opens the white area below the sponsor
   band instead of adding a line to the navy hero. */
.region-crumb.crumb-content { color: var(--text-soft); margin-bottom: 14px; }
.region-crumb.crumb-content a { color: var(--text-muted); }
.region-crumb.crumb-content a:hover { color: var(--brand); }

/* Toolbar + month range toggle */
.map-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin: 18px 0 16px; }
.map-lead { font-family: var(--font-head); font-weight: 700; font-size: 1.2rem; color: var(--text); }
.map-lead span { display: block; font-family: var(--font-body); font-weight: 500; font-size: .9rem; color: var(--text-muted); margin-top: 2px; }
.month-toggle { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-pill); overflow: hidden; background: var(--surface); }
.month-toggle .mt-btn { font-family: var(--font-head); font-weight: 600; font-size: .85rem; border: 0; cursor: pointer; padding: 9px 16px; background: var(--surface); color: var(--text-muted); transition: background .15s, color .15s; }
.month-toggle .mt-btn:hover { color: var(--brand); }
.month-toggle .mt-btn.active { background: var(--brand); color: #fff; }

/* Map + list layout */
.region-layout { display: grid; grid-template-columns: 1.55fr 1fr; gap: 20px; align-items: start; }
.map-panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 12px; }
.map-panel svg { width: 100%; height: auto; display: block; background: #f0f5fb; border-radius: var(--radius-sm); }

/* SVG county outlines — decorative background layer under the town markers */
#mapCounties { pointer-events: none; }
.county rect { fill: #fff; fill-opacity: .45; stroke: #ccd9e8; stroke-width: 1; }
.county text { font-family: var(--font-body); font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; fill: #a9b9cd; }

/* SVG town markers */
.town { cursor: pointer; }
.town:focus { outline: none; }
.town .halo { fill: var(--steel-blue); opacity: 0; transition: opacity .15s; }
.town.hl .halo, .town:hover .halo, .town:focus-visible .halo { opacity: .16; }
.town .dot { stroke-width: 2; transition: r .35s cubic-bezier(.4, 0, .2, 1); }
.town.core .dot { fill: var(--brand); stroke: var(--oxford-navy); }
.town.hub .dot { fill: var(--accent); stroke: var(--oxford-navy); }
.town.near .dot { fill: #fff; stroke: var(--steel-blue); }
.town.region .dot { fill: #fff; stroke: var(--text-soft); stroke-dasharray: 3 3; }
.town .cnt { font-family: var(--font-head); font-weight: 800; text-anchor: middle; dominant-baseline: central; fill: var(--text); font-size: 13px; pointer-events: none; }
.town.core .cnt, .town.hub .cnt { fill: #fff; }
.town .lbl { font-family: var(--font-body); text-anchor: middle; fill: var(--text-muted); font-size: 12px; font-weight: 600; pointer-events: none; }
.town.hl .lbl { fill: var(--brand-dark); }

/* Legend */
.map-legend { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 12px 6px 2px; font-size: .82rem; color: var(--text-muted); }
.map-legend .lg { display: inline-flex; align-items: center; gap: 7px; }
.map-legend .lg-size { margin-left: auto; }
.map-legend .sw { width: 14px; height: 14px; border-radius: 50%; }
.map-legend .sw-core { background: var(--brand); }
.map-legend .sw-near { background: #fff; border: 2px solid var(--steel-blue); }
.map-legend .sw-region { background: #fff; border: 2px dashed var(--text-soft); }

/* Ranked town list */
.town-list { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.tl-head { padding: 16px 18px 12px; border-bottom: 1px solid var(--border); }
.tl-head h3 { font-size: 1.15rem; }
.tl-head p { font-size: .82rem; color: var(--text-muted); margin-top: 2px; }
.town-row { display: grid; grid-template-columns: 1fr auto; gap: 5px 12px; align-items: center; padding: 11px 18px; border-bottom: 1px solid var(--border); color: var(--text); }
.town-row:last-child { border-bottom: none; }
.town-row:hover, .town-row.hl { background: var(--brand-light); }
.town-row .tr-name { font-family: var(--font-head); font-weight: 700; font-size: .95rem; color: var(--text); display: flex; align-items: center; gap: 8px; }
.town-row:hover .tr-name { color: var(--brand-dark); }
.tier-tag { font-size: .6rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 2px 7px; border-radius: var(--radius-pill); }
.tt-core { background: var(--brand-light); color: var(--brand-dark); }
.tt-near { background: #eef4fb; color: var(--steel-blue); }
.tt-region { background: #f1f3f7; color: var(--text-muted); }
.town-row .tr-count { font-family: var(--font-head); font-weight: 800; font-size: 1.05rem; color: var(--brand); font-variant-numeric: tabular-nums; grid-row: span 2; }
.town-row .tr-bar { grid-column: 1 / 2; height: 6px; border-radius: var(--radius-pill); background: #eef1f6; overflow: hidden; }
.town-row .tr-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--dusk-blue), var(--steel-blue)); border-radius: var(--radius-pill); transition: width .4s ease; }

/* Summary cards */
.region-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 22px; }
.region-summary .sum-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm); }
.region-summary .sum-card .num { font-family: var(--font-head); font-weight: 800; font-size: 1.9rem; color: var(--brand); font-variant-numeric: tabular-nums; }
.region-summary .sum-card .lab { font-size: .85rem; color: var(--text-muted); margin-top: 2px; }

@media (max-width: 820px) {
  .region-layout { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .region-summary { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .town .dot, .town-row .tr-bar i, .hero-region { transition: none; }
}
