/* ============================================================
   ENGENE Voting Calendar
   Art direction: deadline board / mission control.
   Ink-dark surfaces, crimson urgency accent, mono timestamps.
   ============================================================ */

/* ---------- Tokens ---------- */
:root {
  /* Type scale */
  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
  --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);
  --text-xl: clamp(1.5rem, 1.2rem + 1.25vw, 2.25rem);
  --text-2xl: clamp(2rem, 1.2rem + 2.5vw, 3.5rem);

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;

  /* Radius */
  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;

  --transition-interactive: 180ms cubic-bezier(0.16, 1, 0.3, 1);

  --content-wide: 1180px;

  --font-display: 'Archivo', 'Helvetica Neue', sans-serif;
  --font-body: 'Satoshi', 'Inter', system-ui, sans-serif;
  /* Dates, countdowns and counters use the body face, with tabular figures
     so digits still line up column to column. */
  --font-mono: 'Satoshi', 'Inter', system-ui, sans-serif;
}

/* Light mode */
:root,
[data-theme='light'] {
  --focus-ink-weight: 60%;
  --focus-ink-base: #16161a;
  --color-bg: #ececea;
  --color-surface: #ffffff;
  --color-surface-2: #f7f6f4;
  --color-surface-offset: #e4e3e0;
  --color-surface-dynamic: #dcdbd7;
  --color-divider: #dedcd8;
  --color-border: #cfcdc8;

  --color-text: #16161c;
  --color-text-muted: #6a6774;
  --color-text-faint: #a5a2ad;
  --color-text-inverse: #fbfaf9;

  --color-primary: #c81d31;
  --color-primary-hover: #a81527;
  --color-primary-active: #85101e;
  --color-primary-highlight: #f8e0e3;

  --color-live: #1c7a45;
  --color-live-bg: #e2f0e7;
  --color-prep: #5a6b91;
  --color-prep-bg: #e9ecf3;
  --color-done: #6a6774;
  --color-done-bg: #ececea;

  --shadow-sm: 0 1px 2px rgb(22 22 28 / 0.06);
  --shadow-md: 0 4px 14px rgb(22 22 28 / 0.08);
  --shadow-lg: 0 14px 34px rgb(22 22 28 / 0.1);

  --grain-opacity: 0.02;
}

/* Dark mode */
[data-theme='dark'] {
  --focus-ink-weight: 88%;
  --focus-ink-base: #ffffff;
  --color-bg: #050506;
  --color-surface: #0f0f13;
  --color-surface-2: #131318;
  --color-surface-offset: #17171d;
  --color-surface-dynamic: #21212a;
  --color-divider: #1c1c23;
  --color-border: #292933;

  --color-text: #e9e7ef;
  --color-text-muted: #8f8d9d;
  --color-text-faint: #5d5b6a;
  --color-text-inverse: #0f0f13;

  --color-primary: #f43d51;
  --color-primary-hover: #ff5c6d;
  --color-primary-active: #d42237;
  --color-primary-highlight: #331a20;

  --color-live: #5fd18b;
  --color-live-bg: #14291d;
  --color-prep: #93a4cc;
  --color-prep-bg: #1b2030;
  --color-done: #8f8d9d;
  --color-done-bg: #1d1d24;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.3);
  --shadow-md: 0 4px 14px rgb(0 0 0 / 0.38);
  --shadow-lg: 0 14px 34px rgb(0 0 0 / 0.46);

  --grain-opacity: 0.035;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --focus-ink-weight: 88%;
    --focus-ink-base: #ffffff;
    --color-bg: #050506;
    --color-surface: #0f0f13;
    --color-surface-2: #131318;
    --color-surface-offset: #17171d;
    --color-surface-dynamic: #21212a;
    --color-divider: #1c1c23;
    --color-border: #292933;
    --color-text: #e9e7ef;
    --color-text-muted: #8f8d9d;
    --color-text-faint: #5d5b6a;
    --color-text-inverse: #0f0f13;
    --color-primary: #f43d51;
    --color-primary-hover: #ff5c6d;
    --color-primary-active: #d42237;
    --color-primary-highlight: #331a20;
    --color-live: #5fd18b;
    --color-live-bg: #14291d;
    --color-prep: #93a4cc;
    --color-prep-bg: #1b2030;
    --color-done: #8f8d9d;
    --color-done-bg: #1d1d24;
  }
}

/* Focus accents — one hue per focus target */
[data-focus='ENHYPEN'] {
  --focus-hue: #f43d51;
}
[data-focus='Jay'] {
  --focus-hue: #3cc26b;
}
[data-focus='Jake'] {
  --focus-hue: #ff8a3c;
}
[data-focus='Jungwon'] {
  --focus-hue: #f2c230;
}
[data-focus='Ni-ki'] {
  --focus-hue: #9d6bf0;
}
[data-focus='Sunghoon'] {
  --focus-hue: #3d9bff;
}
[data-focus='Sunoo'] {
  --focus-hue: #ff74bd;
}

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

html {
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-16);
}

body {
  min-height: 100dvh;
  line-height: 1.6;
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-text);
  background-color: var(--color-bg);
  transition:
    background-color 260ms ease,
    color 260ms ease;
}

img,
svg {
  display: block;
  max-width: 100%;
}

ul[role='list'] {
  list-style: none;
}

input,
button,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  background: none;
  border: none;
}

[hidden] {
  display: none !important;
}

h1,
h2,
h3 {
  text-wrap: balance;
  line-height: 1.15;
}

p {
  text-wrap: pretty;
}

a {
  color: inherit;
}

::selection {
  background: var(--color-primary-highlight);
  color: var(--color-text);
}

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

a,
button,
input,
select {
  transition:
    color var(--transition-interactive),
    background var(--transition-interactive),
    border-color var(--transition-interactive),
    box-shadow var(--transition-interactive),
    transform var(--transition-interactive);
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  letter-spacing: 0;
}

.shell {
  width: 100%;
  max-width: var(--content-wide);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 50;
  padding: var(--space-3) var(--space-4);
  background: var(--color-primary);
  color: #fff;
  border-radius: 0 0 var(--radius-md) 0;
  text-decoration: none;
}
.skip-link:focus {
  left: 0;
}

/* ---------- Spectrum rule (member colours, in line order) ---------- */
.spectrum {
  height: 3px;
  background: linear-gradient(
    90deg,
    #f43d51 0 14.28%,
    #ff8a3c 14.28% 28.56%,
    #f2c230 28.56% 42.84%,
    #3cc26b 42.84% 57.12%,
    #3d9bff 57.12% 71.4%,
    #9d6bf0 71.4% 85.68%,
    #ff74bd 85.68% 100%
  );
}

/* ---------- Masthead ---------- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-divider);
}

.masthead-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
}
.brand-mark {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}
.brand-word {
  width: auto;
  height: 13px;
  flex-shrink: 0;
}
.brand-mark--on-light,
.brand-word--on-light {
  display: none;
}
[data-theme='light'] .brand-mark--on-dark,
[data-theme='light'] .brand-word--on-dark {
  display: none;
}
[data-theme='light'] .brand-mark--on-light,
[data-theme='light'] .brand-word--on-light {
  display: block;
}
.brand:hover {
  opacity: 0.78;
}

.masthead-tools {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.tz-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
  max-width: 46vw;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tz-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-live);
  flex-shrink: 0;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-muted);
  flex-shrink: 0;
}
.icon-btn:hover {
  color: var(--color-text);
  border-color: var(--color-text-faint);
}

/* ---------- Intro ---------- */
.intro {
  padding-block: clamp(var(--space-8), 4vw, var(--space-12)) var(--space-6);
  position: relative;
}

.intro-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.1rem + 3.4vw, 3.75rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  display: flex;
  flex-direction: column;
  text-wrap: initial;
}
.intro-title-1 {
  font-variation-settings: 'wdth' 112, 'wght' 900;
}
.intro-title-2 {
  font-variation-settings: 'wdth' 82, 'wght' 500;
  color: var(--color-primary);
  letter-spacing: 0.01em;
}

.intro-lede {
  margin-top: var(--space-4);
  max-width: 52ch;
  color: var(--color-text-muted);
  font-size: var(--text-base);
}

/* 52ch is measured for the calendar page, where the lede shares its row with
   the Recommend an Event button. On the submit and moderator pages the lede
   owns the whole row, so that same cap wrapped it at roughly half the width of
   the boxes directly below it — three short ragged lines under a full-width
   headline. These pages get a measure that still reads well (about 80
   characters) but tracks the width of the cards underneath. */
.intro--form .intro-lede,
.intro--admin .intro-lede {
  max-width: 78ch;
}

/* ---------- Tally strip ---------- */
.tally {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-5);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-divider);
}
.tally-item {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}
.tally-num {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.tally-item[data-tone='active'] .tally-num {
  color: var(--color-live);
}
.tally-item[data-tone='prep'] .tally-num {
  color: var(--color-prep);
}
/* ---------- Toolbar ---------- */
.toolbar {
  padding-bottom: var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.toolbar-row {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  align-items: center;
}

.search-wrap {
  position: relative;
  flex: 1 1 320px;
  min-width: 0;
}
.search-icon {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-faint);
  pointer-events: none;
}
#search {
  width: 100%;
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-10);
  font-size: var(--text-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
#search::placeholder {
  color: var(--color-text-faint);
}
#search:focus-visible {
  border-color: var(--color-primary);
}

.sort-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.sort-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-faint);
}
#sort {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
}

.filter-block {
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
  flex-wrap: wrap;
}
.filter-legend {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-faint);
  min-width: 3.5rem;
  padding-top: var(--space-1);
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  flex: 1 1 auto;
}

/* The filters speak the same visual language as the tags inside a card:
   focus filters are the member slab, status filters are the status badge. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.5rem 0.3125rem;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' 700;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  line-height: 1;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-muted);
}
.chip:hover {
  color: var(--color-text);
  border-color: var(--color-text-faint);
}
.chip[aria-pressed='true'] {
  background: var(--color-text);
  border-color: var(--color-text);
  color: var(--color-bg);
}
.chip-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: currentColor;
  flex-shrink: 0;
}

/* Focus filters: tinted member hue, same slab as the card's focus tag. */
.chip[data-focus] {
  border-color: transparent;
  background: color-mix(in srgb, var(--focus-hue) 16%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--focus-hue) 42%, transparent);
  font-variation-settings: 'wdth' 92, 'wght' 800;
  color: color-mix(
    in srgb,
    var(--focus-hue) var(--focus-ink-weight),
    var(--focus-ink-base)
  );
}
.chip[data-focus]:hover {
  background: color-mix(in srgb, var(--focus-hue) 26%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--focus-hue) 62%, transparent);
}
.chip[data-focus][aria-pressed='true'] {
  background: var(--focus-hue);
  box-shadow: inset 0 0 0 1px var(--focus-hue);
  color: #0a0a0c;
}

/* Status filters: the same pale badge treatment used on each card. */
.chip[data-status] {
  border-color: transparent;
}
.chip[data-status='active'] {
  background: var(--color-live-bg);
  color: var(--color-live);
}
.chip[data-status='preparation'] {
  background: var(--color-prep-bg);
  color: var(--color-prep);
}
.chip[data-status='concluded'] {
  background: var(--color-done-bg);
  color: var(--color-done);
}
/* Draft only exists on the moderator list. It reads as an outline, matching the
   Draft badge on the rows themselves rather than borrowing a status colour. */
.chip[data-status='draft'] {
  background: transparent;
  color: var(--color-text-muted);
  box-shadow: inset 0 0 0 1px var(--color-border);
}
.chip[data-status]:hover {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 40%, transparent);
}
.chip[data-status][aria-pressed='true'] {
  box-shadow: inset 0 0 0 1.5px currentColor;
}
.chip[data-status='active'][aria-pressed='true'] .chip-dot {
  animation: pulse 2s ease-in-out infinite;
}

.chip-count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0;
  opacity: 0.65;
}

/* ---------- Event list ---------- */
.block-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' 700;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-muted);
  padding-bottom: var(--space-3);
  margin-top: var(--space-2);
}
#pinned-block .block-title {
  color: var(--color-primary);
}

.event-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-bottom: var(--space-10);
}

.event {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  overflow: hidden;
  position: relative;
}
.event::before {
  content: '';
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 4px;
  background: var(--focus-hue, var(--color-border));
  opacity: 1;
}
.event[data-status='concluded'] {
  background: var(--color-surface-2);
}
.event[data-status='concluded']::before {
  opacity: 0.3;
}
.event[data-pinned='true'] {
  border-color: color-mix(in srgb, var(--color-primary) 45%, var(--color-border));
  box-shadow: var(--shadow-md);
}

.event-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  align-items: start;
}

.event-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.1875rem var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1.5;
  white-space: nowrap;
}
.badge-active {
  background: var(--color-live-bg);
  color: var(--color-live);
}
.badge-preparation {
  background: var(--color-prep-bg);
  color: var(--color-prep);
}
.badge-concluded {
  background: var(--color-done-bg);
  color: var(--color-done);
}
/* Admin only — a draft never reaches the public calendar. Outlined rather than
   filled so it reads as "not real yet" next to the filled status badges. */
.badge-draft {
  background: transparent;
  color: var(--color-text-muted);
  box-shadow: inset 0 0 0 1px var(--color-border);
}
.badge-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: currentColor;
  flex-shrink: 0;
}
.badge-active .badge-dot {
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.8);
  }
}

/* The focus is the single most useful fact on a card, so it gets the member
   hue as a tinted slab rather than a grey pill with a small dot. */
.focus-tag {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.4375rem 0.1875rem;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--focus-hue, var(--color-text)) 16%, transparent);
  box-shadow: inset 0 0 0 1px
    color-mix(in srgb, var(--focus-hue, var(--color-text)) 42%, transparent);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' 800;
  font-size: 0.6875rem;
  line-height: 1;
  letter-spacing: 0.07em;
  color: color-mix(
    in srgb,
    var(--focus-hue, var(--color-text)) var(--focus-ink-weight),
    var(--focus-ink-base)
  );
  white-space: nowrap;
}

.pin-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-primary);
}

.app-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.app-icon {
  width: 20px;
  height: 20px;
  border-radius: 5px;
  flex-shrink: 0;
  object-fit: cover;
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--color-text) 12%, transparent),
    var(--shadow-sm);
}
.app-icon--mono {
  display: grid;
  place-items: center;
  background: hsl(var(--mono-hue, 240) 62% 52%);
  color: #fff;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' 800;
  font-size: 0.6875rem;
  line-height: 1;
  box-shadow: none;
}

.event-name {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 104, 'wght' 700;
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-3);
  overflow-wrap: anywhere;
}

.times {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
}
.time-pair {
  min-width: 0;
}
.time-key {
  display: block;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-faint);
}
.time-local {
  display: block;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.time-kst {
  display: block;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  color: var(--color-text-faint);
}

.event-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-3);
  text-align: right;
}

.countdown {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.125rem;
}
.countdown-key {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-faint);
  white-space: nowrap;
}
.countdown-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.event[data-status='active'] .countdown-value {
  color: var(--color-text);
}
.event[data-urgent='true'] .countdown-value {
  color: var(--color-primary);
}
.event[data-status='concluded'] .countdown-value {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 500;
}
.event[data-status='preparation'] .countdown-value {
  color: var(--color-prep);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: 700;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  text-decoration: none;
  white-space: nowrap;
}
.btn-primary {
  background: var(--color-primary);
  color: #fff;
}
.btn-primary:hover {
  background: var(--color-primary-hover);
}
.btn-quiet {
  border-color: var(--color-border);
  color: var(--color-text-muted);
  background: var(--color-surface);
}
.btn-quiet:hover {
  color: var(--color-text);
  border-color: var(--color-text-faint);
}

.progress {
  width: 100%;
  height: 3px;
  background: var(--color-surface-dynamic);
  position: relative;
  overflow: hidden;
}
.progress-fill {
  position: absolute;
  inset-block: 0;
  left: 0;
  background: linear-gradient(90deg, var(--focus-hue, var(--color-primary)), var(--color-primary));
  transition: width 1s linear;
}

/* Details disclosure */
.event-details {
  border-top: 1px solid var(--color-divider);
}
.event-details[hidden] {
  display: none;
}
.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-4) var(--space-6);
  padding: var(--space-5);
  background: var(--color-surface-offset);
}
.detail-item {
  min-width: 0;
}
/* Quiet link at the bottom of an opened card: it belongs to the event, but it is
   not part of the information someone came to read. */
.detail-report {
  grid-column: 1 / -1;
  padding: 0 var(--space-5) var(--space-5);
  background: var(--color-surface-offset);
  margin: 0;
  font-size: 0.8125rem;
}
.detail-report a {
  color: var(--color-text-muted);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.detail-report a:hover {
  color: var(--color-text);
}
.detail-item--full {
  grid-column: 1 / -1;
}
.detail-item--full .detail-value {
  max-width: 90ch;
}
.detail-key {
  display: block;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-faint);
  margin-bottom: var(--space-1);
}
.detail-value {
  font-size: var(--text-sm);
  color: var(--color-text);
  overflow-wrap: anywhere;
  white-space: pre-line; /* keeps the line breaks written in the sheet */
}
.detail-value a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.detail-value.is-empty {
  color: var(--color-text-faint);
  font-style: italic;
}

/*
  Card footer: Details on the left, the icon-only Share on the right. Share used
  to sit in `.event-side` next to the countdown, but that row flips to
  `space-between` on mobile for exactly two children, so a third one pushed the
  Vote button into the middle of the card.
*/
.event-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding-right: var(--space-5);
  border-top: 1px solid var(--color-divider);
}
/* Keeps Share hard right when a card has no details to expand. */
.disclosure-spacer {
  flex: 1;
}

.disclosure {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  background: transparent;
}
.disclosure:hover {
  color: var(--color-text);
  background: var(--color-surface-offset);
}
.disclosure svg {
  transition: transform var(--transition-interactive);
}
.disclosure[aria-expanded='true'] svg {
  transform: rotate(180deg);
}

/* ---------- Skeleton ---------- */
@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}
.skeleton {
  background: linear-gradient(
    90deg,
    var(--color-surface-offset) 25%,
    var(--color-surface-dynamic) 50%,
    var(--color-surface-offset) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skeleton-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.skeleton-line {
  height: 0.75rem;
}

/* ---------- Empty / error ---------- */
.empty-state,
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-16) var(--space-6);
  color: var(--color-text-muted);
  margin-bottom: var(--space-12);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-lg);
}
.empty-icon {
  color: var(--color-text-faint);
  margin-bottom: var(--space-4);
}
.empty-state h3,
.error-state h3 {
  color: var(--color-text);
  font-size: var(--text-lg);
  font-weight: 700;
  margin-bottom: var(--space-2);
}
.empty-state p,
.error-state p {
  max-width: 44ch;
  font-size: var(--text-sm);
  margin-bottom: var(--space-5);
}

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--color-divider);
  background: var(--color-surface-2);
  padding-top: var(--space-12);
}

/* ---------- Footer: scope statement ---------- */

/* Set as a pull quote rather than another footer column: it is the site's one
   editorial line, and a column would bury it next to the housekeeping copy. The
   red rule down the left carries the emphasis so the type can stay calm. */
.footer-scope {
  padding-bottom: var(--space-10);
  border-bottom: 1px solid var(--color-divider);
}
/* No max-width: the two lines are broken by hand below, so capping the box only
   held the quote to half the page for no reason. The size stops at `--text-xl`
   (36px) rather than `--text-2xl` (56px): this is a footer aside, and at 2xl it
   read louder than the page's own headline on a wide display. */
.footer-scope-lead {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--color-text);
  padding-left: var(--space-5);
  border-left: 3px solid var(--color-primary);
}
.footer-scope-line {
  display: block;
}
/* Below this the hand-placed break would leave a short first line and a wrapped
   second one, so the spans go back to being inline and the text wraps to fit. */
@media (max-width: 780px) {
  .footer-scope-lead {
    font-size: var(--text-lg);
  }
  .footer-scope-line {
    display: inline;
  }
}
.footer-scope-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-4) var(--space-8);
  margin-top: var(--space-6);
  padding-left: var(--space-5); /* aligned with the quote's text, not its rule */
}
.footer-scope-body p {
  font-size: var(--text-sm);
  line-height: 1.65;
  color: var(--color-text-muted);
  max-width: 52ch;
}

/* ---------- Footer: the voting teams ---------- */

.footer-teams {
  display: grid;
  gap: var(--space-8);
  padding-block: var(--space-10);
  border-bottom: 1px solid var(--color-divider);
}
.footer-teams-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text);
  margin-bottom: var(--space-4);
}
/* auto-fill, not auto-fit: with 5 chips in the second group auto-fit stretched
   them to fill the row, so a chip in the short group ended up twice as wide as
   the same chip in the long one. */
.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: var(--space-2);
  list-style: none;
}
.team-chip {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 2.75rem; /* comfortable tap target */
  padding: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.team-chip:hover,
.team-chip:focus-visible {
  background: var(--color-surface);
  border-color: var(--color-divider);
}
.team-avatar {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  /* Several of these logos are white-on-white, so the ring keeps every avatar a
     visible circle rather than a floating mark. */
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  object-fit: cover;
}
.team-meta {
  display: flex;
  flex-direction: column;
  min-width: 0; /* keeps a long handle from widening the grid track */
}
/* Wraps rather than ellipsizes: these names are all "<something> VOTING TEAM",
   so cutting the tail off left several chips reading identically. Two lines is
   enough for every name in the list at every width. */
.team-name {
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.3;
  color: var(--color-text);
}
.team-handle {
  font-size: var(--text-xs);
  color: var(--color-text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.team-chip:hover .team-handle,
.team-chip:focus-visible .team-handle {
  color: var(--color-primary);
}
.footer-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-8);
  padding-block: var(--space-10);
}
.footer-col h3 {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text);
  margin-bottom: var(--space-2);
}
.footer-col p {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  max-width: 40ch;
}
/* The submit link used to be a bare text link tucked straight under the
   paragraph, close enough to read as part of it. It is a real button now, with
   its own breathing room above so it reads as an action. */
.footer-cta {
  margin-top: var(--space-5);
}
.btn-footer {
  padding-inline: var(--space-6);
}
.footer-base {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding-block: var(--space-5);
  border-top: 1px solid var(--color-divider);
  font-size: var(--text-xs);
  color: var(--color-text-faint);
}

/* ---------- Responsive ---------- */
@media (max-width: 640px) {
  /*
    No search box on phones.

    Mobile Safari zooms the whole page in whenever a text field smaller than
    16px takes focus, and it does not zoom back out on blur — tapping search
    left the calendar magnified and horizontally scrollable, which read as a
    broken page. The focus filters and the sort control cover the same ground on
    a screen this narrow, so the field is dropped here rather than reworked.
    display:none also takes it out of the tab order and the accessibility tree,
    so nothing can focus a control the visitor cannot see.
  */
  .search-wrap {
    display: none;
  }
  .shell {
    padding-inline: var(--space-4);
  }
  .tally {
    gap: var(--space-2) var(--space-4);
  }
  .intro-title {
    font-size: 1.7rem;
  }
  .intro-title-1 {
    font-variation-settings: 'wdth' 104, 'wght' 900;
  }
  .brand-mark {
    width: 24px;
    height: 24px;
  }
  .brand-word {
    height: 11px;
  }
  .brand {
    gap: var(--space-2);
    min-width: 0;
  }
  .tz-pill {
    max-width: 46vw;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.625rem;
    padding: var(--space-1) var(--space-2);
  }
  .event-head {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--space-4);
    gap: var(--space-4);
  }
  .event-side {
    align-items: flex-start;
    text-align: left;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
  .countdown {
    align-items: flex-start;
  }
  .filter-legend {
    min-width: 100%;
  }
  .sort-wrap {
    width: 100%;
  }
  #sort {
    flex: 1;
  }
  .detail-grid,
  .disclosure {
    padding-inline: var(--space-4);
  }
  .event-foot {
    padding-right: var(--space-4);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Quiet moderator entrance in the footer base. */
.footer-base-right {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
}
.footer-quiet-link {
  color: var(--color-text-faint);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition:
    color var(--transition-interactive),
    border-color var(--transition-interactive);
}
.footer-quiet-link:hover {
  color: var(--color-text);
  border-bottom-color: var(--color-text-faint);
}
/* The credit line is the only place the two fandoms behind this calendar are
   named, so it reads at body scale in full-strength ink rather than at the
   faint --text-xs the rest of the footer base uses. */
.footer-credit {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text);
}
.footer-credit-mark {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  /* The mark ships as a solid green square, so it needs its own edge to sit on
     a surface of any theme without looking like a pasted crop. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.footer-credit-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--color-divider);
  transition:
    color var(--transition-interactive),
    border-color var(--transition-interactive);
}
.footer-credit-link:hover {
  color: var(--color-text);
  border-bottom-color: currentColor;
}

/* ---------- Sharing one event ---------- */

/*
  Quieter than the vote CTA: sharing is secondary and must not compete with it.
  Icon-only, so it needs no width beyond the round .icon-btn base.
*/
.share-btn {
  width: 32px;
  height: 32px;
  border-color: transparent;
  background: transparent;
}
.share-btn:hover {
  border-color: var(--color-text-faint);
  background: var(--color-surface-offset);
}
.share-btn[data-copied='true'],
.share-btn[data-copied='true']:hover {
  color: var(--color-primary);
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  background: transparent;
}

/*
  Shared with the admin and review pages, which load this file before their own.
  Markup is `<p class="toast" id="toast" hidden>`.
*/
.toast {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%);
  z-index: 60;
  margin: 0;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
  font-size: var(--text-sm);
  color: var(--color-text);
  max-width: min(90vw, 60ch);
  text-align: center;
  animation: toast-in 200ms ease-out;
}
.toast[data-tone='bad'] {
  border-color: color-mix(in srgb, var(--color-primary) 50%, transparent);
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
}

/* The card a shared link just opened, so it is obvious which one was meant. */
.event[data-deeplinked='true'] {
  border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 18%, transparent);
}

.deeplink-note {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid color-mix(in srgb, var(--color-primary) 30%, var(--color-border));
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-primary) 7%, var(--color-surface));
  color: var(--color-text);
  font-size: var(--text-sm);
}
