/**
 * Camp Alongside — Design System Stylesheet
 * Mobile-first, WCAG AA compliant, camp-vibes aesthetic.
 */

/* ─── Design Tokens ─────────────────────────────────────────────── */
:root {
  /* Brand palette */
  --color-deep-pine: #0E3B37;
  --color-forest: #055243;
  --color-teal: #2F887F;
  --color-plum: #724E91;
  --color-sand: #ECD8B4;
  --color-gold: #ECAE3F;
  --color-ember: #D78039;
  --color-rust: #C25232;
  --color-gold-deep: #946C2A; /* Deep mustard gold — same hue as --color-gold, dark enough for white text (4.73:1 AA) */
  --color-pink-deep: #B8497A; /* Deep rose pink for Sylvie Duty shifts — passes 4.82:1 contrast with white */

  /* Semantic: backgrounds */
  --color-bg-primary: #ECD8B4;
  --color-bg-surface: #FFFFFF;
  --color-bg-nav: #0E3B37;
  --color-bg-elevated: #FFFFFF;
  --color-bg-overlay: rgba(14, 59, 55, 0.5);
  --color-bg-input: #FFFFFF;

  /* Semantic: text */
  --color-text-primary: #1A1A1A;
  --color-text-secondary: #055243;
  --color-text-muted: #5C5C5C;
  --color-text-on-dark: #FFFFFF;
  --color-text-on-dark-muted: rgba(236, 216, 180, 0.7);
  --color-text-link: #055243;
  --color-text-placeholder: #9A9A9A;

  /* Semantic: actions */
  --color-action-primary: #0E3B37;
  --color-action-primary-hover: #055243;
  --color-action-secondary: #055243;
  --color-action-accent: #724E91;
  --color-action-warning: #C25232;

  /* Semantic: states */
  --color-state-active: #ECAE3F;
  --color-state-success: #055243;
  --color-state-error: #C25232;
  --color-state-info: #2F887F;

  /* Borders */
  --color-border: rgba(14, 59, 55, 0.12);
  --color-border-strong: rgba(14, 59, 55, 0.25);
  --color-border-input: rgba(14, 59, 55, 0.2);
  --color-border-focus: #0E3B37;

  /* Typography */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;

  /* Spacing (8px grid) */
  --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;

  /* Radius */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.12);

  /* Layout */
  --header-height: 56px;
  --tab-bar-height: 64px;
  --content-max-width: 600px;
  --safe-area-bottom: env(safe-area-inset-bottom, 0px);
  --safe-area-top: env(safe-area-inset-top, 0px);

  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-normal: 250ms ease;
}

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

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Ensure background covers entire viewport in standalone PWA mode */
  background-color: var(--color-bg-nav);
  height: 100%;
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text-primary);
  /* Pine green so any visible area beyond the app shell (notably the iOS
     PWA home-indicator safe-area zone below the tab bar) blends with the
     bottom nav instead of revealing the sand-colored body. The actual
     content surface gets its sand background via .content below. */
  background-color: var(--color-bg-nav);
  min-height: 100vh;
  min-height: 100dvh;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

a {
  color: var(--color-text-link);
  text-decoration: none;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

button {
  font: inherit;
  cursor: pointer;
  border: none;
  background: none;
  color: inherit;
}

input, select, textarea {
  font: inherit;
  color: var(--color-text-primary);
}

ul, ol {
  list-style: none;
}

/* ─── App Shell ─────────────────────────────────────────────────── */
#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  max-width: var(--content-max-width);
  margin: 0 auto;
  position: relative;
}

/* ─── Top Header ────────────────────────────────────────────────── */
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: calc(var(--header-height) + var(--safe-area-top));
  padding: 0 var(--space-4);
  padding-top: var(--safe-area-top);
  background-color: var(--color-bg-nav);
  color: var(--color-text-on-dark);
  flex-shrink: 0;
  z-index: 100;
}

.header-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  flex: 1;
  text-align: center;
}

.header-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--color-text-on-dark);
  border-radius: var(--radius-sm);
  transition: background-color var(--transition-fast);
}

.header-btn:active {
  background-color: rgba(255, 255, 255, 0.15);
}

.header-btn:empty {
  visibility: hidden;
}

.header-btn svg {
  width: 24px;
  height: 24px;
}

.header-committee-badge {
  font-size: var(--text-xs);
  margin-left: var(--space-1);
}

/* ─── Scrollable Content Area ───────────────────────────────────── */
.content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-4);
  padding-bottom: calc(var(--space-4) + var(--tab-bar-height) + var(--safe-area-bottom));
  /* Sand background lives here, not on body — see comment on body. */
  background-color: var(--color-bg-primary);
}

.content::-webkit-scrollbar {
  display: none;
}

/* ─── Bottom Tab Bar ────────────────────────────────────────────── */
.tab-bar {
  display: flex;
  align-items: stretch;
  height: calc(var(--tab-bar-height) + var(--safe-area-bottom));
  padding-bottom: var(--safe-area-bottom);
  background-color: var(--color-bg-nav);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  flex-shrink: 0;
  z-index: 100;
  position: relative;
}

.tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  color: var(--color-text-on-dark-muted);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  padding: var(--space-2) 0;
  transition: color var(--transition-fast);
  position: relative;
  -webkit-tap-highlight-color: transparent;
}

.tab-item:active {
  transform: scale(0.95);
}

.tab-item.active {
  color: var(--color-state-active);
}

.tab-item svg {
  width: 24px;
  height: 24px;
  display: block;
}

/* Wraps the icon so the badge can anchor to the icon's bounds (not the
   whole tab-item — which made placement drift with tab width). */
.tab-item .tab-icon {
  position: relative;
  display: inline-block;
  line-height: 0;
}

.tab-item .tab-label {
  font-size: 10px;
  letter-spacing: 0.02em;
}

/* Numeric unread badge — sits at the upper-right corner of the tab icon.
   Box-sizing border-box so the outer dimensions are exactly 16×16 px (auto-
   expanding wider for 2-digit numbers). Rust on pine has enough contrast
   that no separator border is needed. */
.tab-item .tab-badge {
  position: absolute;
  top: -5px;
  right: -8px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-full);
  background-color: var(--color-rust);
  color: white;
  font-size: 10px;
  font-weight: var(--font-bold);
  line-height: 1;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  pointer-events: none;
}
.tab-item .tab-badge[hidden] {
  display: none;
}

/* ─── Cards ─────────────────────────────────────────────────────── */
.card {
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.card-tappable {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.card-tappable:active {
  transform: scale(0.98);
  box-shadow: var(--shadow-md);
}

.card-featured {
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  box-shadow: var(--shadow-md);
}

.card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-2);
}

.card-title {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  line-height: var(--leading-tight);
  color: var(--color-text-primary);
}

.card-subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: 2px;
}

.card-meta {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

/* Vertical variant — used on event and shift cards so long location names
   never wrap awkwardly into the time column. Stacks each meta line on its own row. */
.card-meta-stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
}
.card-meta-stacked > span {
  white-space: normal;
}

.card-body {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text-primary);
  margin-top: var(--space-2);
}

.card-body-truncated {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

/* ─── Badges ────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

.badge-elective {
  background-color: var(--color-plum);
  color: white;
}

.badge-main {
  background-color: var(--color-rust);
  color: white;
}

.badge-meal {
  background-color: #236B62;
  color: white;
}

.badge-shift {
  background-color: var(--color-gold-deep);
  color: white;
}

/* Sylvie Duty shift variant — pink instead of gold. Only appears on the
   assigned volunteer's /schedule (filtered out everywhere else). */
.badge-shift-sylvie {
  background-color: var(--color-pink-deep);
  color: white;
}

.badge-full {
  background-color: var(--color-rust);
  color: white;
}

/* "New" pill for unread announcement cards — subtle enough to feel like a
   gentle nudge, not an alert. Same gold-deep family as the shift badge. */
.badge-new {
  background-color: var(--color-gold-deep);
  color: white;
}

/* Subtle accent on unread announcement cards — a thin gold left border so
   the card itself reads as "new" at a glance, in addition to the pill. */
.card.card-unread {
  border-left: 3px solid var(--color-gold-deep);
}

.badge-team {
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  text-transform: none;
}

.badge-rsvp-yes {
  background-color: rgba(5, 82, 67, 0.15);
  color: var(--color-forest);
}

.badge-rsvp-no {
  background-color: rgba(194, 82, 50, 0.15);
  color: #A24020;
}

.badge-rsvp-maybe {
  background-color: rgba(236, 174, 63, 0.2);
  color: #8B6B1A;
}

/* ─── Buttons ───────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--transition-fast), transform var(--transition-fast);
  min-height: 48px;
  -webkit-tap-highlight-color: transparent;
}

.btn:active {
  transform: scale(0.97);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.btn-primary {
  background-color: var(--color-action-primary);
  color: var(--color-text-on-dark);
}

.btn-primary:active:not(:disabled) {
  background-color: var(--color-action-primary-hover);
}

.btn-secondary {
  background-color: var(--color-action-secondary);
  color: var(--color-text-on-dark);
}

.btn-accent {
  background-color: var(--color-action-accent);
  color: white;
}

.btn-danger {
  background-color: var(--color-action-warning);
  color: white;
}

.btn-outline {
  border: 2px solid var(--color-action-primary);
  color: var(--color-action-primary);
  background: transparent;
}

.btn-ghost {
  color: var(--color-action-secondary);
  background: transparent;
}

.btn-ghost:active {
  background-color: rgba(5, 82, 67, 0.08);
}

.btn-sm {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  min-height: 36px;
}

.btn-lg {
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-lg);
  min-height: 56px;
  border-radius: var(--radius-md);
}

.btn-block {
  width: 100%;
}

/* ─── Avatar ────────────────────────────────────────────────────── */
.avatar {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  object-fit: cover;
  background-color: var(--color-teal);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--font-bold);
  font-size: var(--text-lg);
  flex-shrink: 0;
  overflow: hidden;
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-sm {
  width: 36px;
  height: 36px;
  font-size: var(--text-sm);
}

.avatar-lg {
  width: 72px;
  height: 72px;
  font-size: var(--text-2xl);
}

.avatar-xl {
  width: 96px;
  height: 96px;
  font-size: var(--text-3xl);
}

/* ─── Capacity Bar ──────────────────────────────────────────────── */
.capacity-bar {
  height: 6px;
  border-radius: var(--radius-full);
  background-color: var(--color-border);
  overflow: hidden;
  margin-top: var(--space-2);
}

.capacity-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
  background-color: var(--color-gold);
  transition: width var(--transition-normal);
}

.capacity-bar-fill.full {
  background-color: var(--color-rust);
}

.capacity-text {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

/* ─── Form Elements ─────────────────────────────────────────────── */
.form-group {
  margin-bottom: var(--space-5);
}

.form-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-text-primary);
  margin-bottom: var(--space-2);
}

.form-input {
  width: 100%;
  max-width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 2px solid var(--color-border-input);
  border-radius: var(--radius-sm);
  background-color: var(--color-bg-input);
  font-size: var(--text-base);
  min-height: 48px;
  transition: border-color var(--transition-fast);
  /* Without border-box, width:100% + padding + border exceeds container width.
     Most visible on iOS where date inputs auto-size to their content. */
  box-sizing: border-box;
}

/* iOS Safari adds extra chrome to date/time inputs that can break the
   100% width. Strip the native appearance so the input behaves as a normal
   text-like field that respects the box. */
.form-input[type="date"],
.form-input[type="time"],
.form-input[type="datetime-local"] {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
}

.form-input:focus {
  outline: none;
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 3px rgba(14, 59, 55, 0.15);
}

.form-input::placeholder {
  color: var(--color-text-placeholder);
}

.form-input-error {
  border-color: var(--color-state-error);
}

.form-error {
  font-size: var(--text-sm);
  color: var(--color-state-error);
  margin-top: var(--space-1);
}

.form-hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

textarea.form-input {
  min-height: 100px;
  resize: vertical;
}

select.form-input {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235C5C5C' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 40px;
}

/* ─── Search Bar ────────────────────────────────────────────────── */
.search-bar {
  position: relative;
  margin-bottom: var(--space-4);
}

.search-bar input {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  padding-left: 44px;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-full);
  background-color: var(--color-bg-surface);
  font-size: var(--text-base);
  min-height: 48px;
}

.search-bar input:focus {
  border-color: var(--color-border-focus);
  outline: none;
}

.search-bar .search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  color: var(--color-text-muted);
}

/* ─── Filter Chips ──────────────────────────────────────────────── */
/* Centered on a single row. Chips shrink on narrow screens to fit — see
   @media (max-width: 480px) below for the compact variant. If chips still
   overflow (very narrow viewport or many chips), they scroll horizontally
   instead of wrapping to a second row. */
.filter-chips {
  display: flex;
  justify-content: center;
  flex-wrap: nowrap;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.filter-chips::-webkit-scrollbar {
  display: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  white-space: nowrap;
  border: 2px solid var(--color-border);
  background: var(--color-bg-surface);
  color: var(--color-text-primary);
  min-height: 36px;
  transition: all var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
  /* Don't let chips shrink below their content size — overflow handled by
     the parent's overflow-x:auto. */
  flex-shrink: 0;
}

/* Compact chip variant for phones — tighter padding, smaller text, smaller
   gap so 5+ chips fit on a single row on a 375px viewport. */
@media (max-width: 480px) {
  .filter-chips {
    gap: var(--space-1);
  }
  .chip {
    padding: var(--space-1) var(--space-3);
    font-size: 12px;
    min-height: 30px;
    border-width: 1.5px;
  }
}

.chip.active {
  background-color: var(--color-action-primary);
  color: var(--color-text-on-dark);
  border-color: var(--color-action-primary);
}

.chip:active {
  transform: scale(0.95);
}

/* Schedule filter chips — tinted to match their category color on the
   calendar/list views. Inactive: colored text on white. Active: filled
   with the category color. Higher specificity than .chip.active wins.
   Other surfaces (e.g. Teams year filter) use values that don't match
   these data-value selectors, so they keep the default pine treatment. */
.chip[data-value="events"]    { color: var(--color-rust);      }
.chip[data-value="electives"] { color: var(--color-plum);      }
.chip[data-value="meals"]     { color: #236B62;                }
.chip[data-value="shifts"]    { color: var(--color-gold-deep); }

.chip[data-value="events"].active {
  background-color: var(--color-rust);
  border-color: var(--color-rust);
  color: white;
}
.chip[data-value="electives"].active {
  background-color: var(--color-plum);
  border-color: var(--color-plum);
  color: white;
}
.chip[data-value="meals"].active {
  background-color: #236B62;
  border-color: #236B62;
  color: white;
}
.chip[data-value="shifts"].active {
  background-color: var(--color-gold-deep);
  border-color: var(--color-gold-deep);
  color: white;
}

/* ─── Section Headers ───────────────────────────────────────────── */
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
  margin-top: var(--space-6);
}

.section-header:first-child {
  margin-top: 0;
}

.section-title {
  font-size: var(--text-lg);
  font-weight: var(--font-bold);
  color: var(--color-text-primary);
}

.section-action {
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-text-link);
}

/* ─── Day Group Header (Schedule) ───────────────────────────────── */
/* Sticks flush to the bottom of the green top bar (no gap). The negative
   horizontal margins break the header out of the .content padding so it
   spans the full viewport width when stuck. Per-day color via
   [data-day-index]: 0=pine, 1=teal, 2=plum, 3=gold. */
.day-header {
  font-size: var(--text-sm);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-on-dark);
  background-color: var(--color-deep-pine);
  padding: var(--space-3) var(--space-4);
  margin: 0 calc(-1 * var(--space-4)) var(--space-3);
  position: sticky;
  top: calc(-1 * var(--space-4)); /* offset the content padding so it sticks flush to green bar */
  z-index: 10;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}
.day-header[data-day-index="0"] {
  background-color: var(--color-deep-pine);
  color: var(--color-text-on-dark);
}
.day-header[data-day-index="1"] {
  background-color: var(--color-teal);
  color: var(--color-text-on-dark);
}
.day-header[data-day-index="2"] {
  background-color: var(--color-plum);
  color: var(--color-text-on-dark);
}
.day-header[data-day-index="3"] {
  background-color: var(--color-gold);
  color: var(--color-deep-pine);
}

/* Breathing room between the previous day's last card and the next day's
   sticky bar. Without this, .cards-grid > .card { margin-bottom: 0 } on
   desktop puts the next day-header flush against the last card. */
.cards-grid + .day-header,
.day-header + .day-header,
.cal-day + .day-header,
.cal-all-weekend + .day-header {
  margin-top: var(--space-4);
}

/* ─── Calendar (timeline) view ──────────────────────────────────── */
/* Each day is a flex row: time-axis column on the left, events area on the
   right. Blocks position absolutely INSIDE .cal-events only — so they can't
   bleed onto the time labels regardless of width. */
.cal-day {
  display: flex;
  background: var(--color-bg-surface);
  margin: 0 calc(-1 * var(--space-4));
}
.cal-time-axis {
  width: 52px;
  flex-shrink: 0;
  /* Vertical padding gives the first/last hour labels room to breathe.
     The labels carry top:-5px to align with their hour gridline, so the
     padding here needs to be ≥5px to prevent the label from clipping
     into anything above. */
  padding: var(--space-3) 0;
}
.cal-hour-label {
  height: 60px;
  text-align: right;
  padding-right: 8px;
  font-size: 10px;
  font-weight: var(--font-semibold);
  color: var(--color-text-muted);
  position: relative;
  top: -5px; /* nudge label so its baseline aligns with the hour gridline */
}
.cal-events {
  flex: 1;
  position: relative;
  /* Top/bottom padding matches .cal-time-axis so labels and block top
     edges align at the same y-coordinate. */
  padding: var(--space-3) var(--space-2);
  border-left: 1px solid var(--color-border);
  min-height: 100%;
}
.cal-hour-line {
  height: 60px;
  border-bottom: 1px dashed var(--color-border);
}
.cal-hour-line:last-of-type { border-bottom: 0; }

.cal-block {
  position: absolute;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  overflow: hidden;
  cursor: pointer;
  border-left: 3px solid;
  box-shadow: var(--shadow-sm);
  line-height: 1.2;
  -webkit-tap-highlight-color: transparent;
}
.cal-block .cal-block-title {
  font-weight: var(--font-bold);
  /* Wrap to multiple lines when the column is narrow — the user prefers
     wrapping to ellipsizing. Block has overflow:hidden so excess lines
     clip cleanly at the bottom edge. */
  word-break: break-word;
  hyphens: auto;
}
.cal-block .cal-block-time {
  font-size: 10px;
  opacity: 0.75;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}

.cal-block.type-main {
  background: rgba(194, 82, 50, 0.12);
  border-color: var(--color-rust);
  color: var(--color-rust);
}
.cal-block.type-meal {
  background: rgba(35, 107, 98, 0.12);
  border-color: #236B62;
  color: #236B62;
}
.cal-block.type-elective {
  background: rgba(114, 78, 145, 0.12);
  border-color: var(--color-plum);
  color: var(--color-plum);
}
.cal-block.type-shift {
  background: rgba(148, 108, 42, 0.12);
  border-color: var(--color-gold-deep);
  color: var(--color-gold-deep);
}
/* Sylvie Duty: same shape, pink palette */
.cal-block.type-shift-sylvie {
  background: rgba(184, 73, 122, 0.12);
  border-color: var(--color-pink-deep);
  color: var(--color-pink-deep);
}

/* ─── "Now" line on today's calendar ─────────────────────────────── */
/* Horizontal rust line spanning the events area, with a circular dot on
   the left edge to draw the eye. Rendered only on today's section and
   only when current time falls within the day's hour range. z-index
   keeps it above hour gridlines but allows event blocks (which have
   their own stacking via box-shadow) to still feel layered. */
.cal-now {
  position: absolute;
  left: -6px; /* extend slightly past the events area so the dot pokes out */
  right: 0;
  height: 0;
  border-top: 2px solid var(--color-rust);
  z-index: 5;
  pointer-events: none;
}
.cal-now::before {
  content: '';
  position: absolute;
  left: 0;
  top: -5px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-rust);
  box-shadow: 0 0 0 2px var(--color-bg-surface); /* small white halo so the dot reads against any underlying block */
}

/* ─── All-Weekend Strip ─────────────────────────────────────────── */
/* Pinned above each day's events. Events tagged "*ALL WEEKEND*" in their
   title surface here as pills, separate from the time grid. */
.cal-all-weekend {
  margin: 0 calc(-1 * var(--space-4));
  padding: var(--space-2) var(--space-4);
  background: rgba(236, 174, 63, 0.12);
  border-bottom: 1px solid rgba(236, 174, 63, 0.3);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.cal-all-weekend-label {
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-gold-deep);
  white-space: nowrap;
}
.cal-all-weekend-list {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  flex: 1;
}
.cal-all-weekend-pill {
  background: var(--color-bg-surface);
  border: 1px solid rgba(148, 108, 42, 0.3);
  border-radius: var(--radius-full);
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--color-gold-deep);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--transition-fast);
}
.cal-all-weekend-pill:hover {
  background: rgba(236, 174, 63, 0.12);
}

/* ─── Menu List (More tab) ──────────────────────────────────────── */
.menu-list {
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  transition: background-color var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
  min-height: 56px;
}

.menu-item:last-child {
  border-bottom: none;
}

.menu-item:active {
  background-color: rgba(14, 59, 55, 0.04);
}

.menu-item-icon {
  font-size: var(--text-xl);
  width: 28px;
  text-align: center;
  flex-shrink: 0;
}

.menu-item-label {
  flex: 1;
  font-size: var(--text-base);
  font-weight: var(--font-medium);
}

.menu-item-arrow {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.menu-divider {
  padding: var(--space-3) var(--space-4) var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
}

/* ─── Toast ─────────────────────────────────────────────────────── */
.toast-container {
  position: fixed;
  top: calc(var(--header-height) + var(--safe-area-top) + var(--space-4));
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  width: calc(100% - var(--space-8));
  max-width: var(--content-max-width);
  pointer-events: none;
}

.toast {
  background-color: var(--color-action-primary);
  color: var(--color-text-on-dark);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  text-align: center;
  box-shadow: var(--shadow-lg);
  animation: toast-in 0.3s ease;
  pointer-events: auto;
}

.toast-error {
  background-color: var(--color-state-error);
}

.toast-success {
  background-color: var(--color-state-success);
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ─── Loading ───────────────────────────────────────────────────── */
.loading-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  z-index: 9999;
  overflow: hidden;
}

.loading-bar::after {
  content: '';
  display: block;
  width: 40%;
  height: 100%;
  background-color: var(--color-gold);
  animation: loading-slide 1.2s ease infinite;
}

@keyframes loading-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

.skeleton {
  background: linear-gradient(90deg,
    var(--color-border) 25%,
    rgba(14, 59, 55, 0.08) 50%,
    var(--color-border) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}

@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skeleton-card {
  height: 100px;
  margin-bottom: var(--space-3);
  border-radius: var(--radius-md);
}

.skeleton-text {
  height: 16px;
  margin-bottom: var(--space-2);
  width: 80%;
}

.skeleton-text-short {
  width: 50%;
}

/* ─── Empty State ───────────────────────────────────────────────── */
.empty-state {
  text-align: center;
  padding: var(--space-12) var(--space-4);
}

.empty-state-icon {
  font-size: 3rem;
  margin-bottom: var(--space-4);
}

.empty-state-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--color-text-primary);
  margin-bottom: var(--space-2);
}

.empty-state-message {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  max-width: 280px;
  margin: 0 auto;
}

/* ─── Login Screen ──────────────────────────────────────────────── */
.login-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--space-8);
  background: linear-gradient(170deg, var(--color-deep-pine) 0%, var(--color-forest) 40%, var(--color-bg-primary) 100%);
}

/* When the login screen is showing, #app should NOT be a grid (otherwise the
   login is auto-placed into one of the named grid cells and ends up squished
   into the sidebar column on desktop). Reset to a regular block layout. */
#app:has(> .login-screen) {
  display: block !important;
  grid-template-columns: none !important;
  grid-template-rows: none !important;
  grid-template-areas: none !important;
  height: auto !important;
  max-width: 100% !important;
  margin: 0 !important;
}

.login-logo {
  font-size: 4rem;
  margin-bottom: var(--space-2);
  animation: campfire-glow 3s ease-in-out infinite;
}

@keyframes campfire-glow {
  0%, 100% { transform: scale(1); filter: brightness(1); }
  50% { transform: scale(1.05); filter: brightness(1.15); }
}

.login-title {
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  color: var(--color-sand);
  margin-bottom: var(--space-1);
}

.login-subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  margin-bottom: var(--space-8);
}

.login-form {
  width: 100%;
  max-width: 320px;
  background: var(--color-bg-surface);
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.login-error {
  background-color: rgba(194, 82, 50, 0.1);
  color: var(--color-state-error);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  margin-bottom: var(--space-4);
  text-align: center;
}

/* ─── Quick Links Grid ──────────────────────────────────────────── */
.quick-links {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.quick-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-2);
  background: var(--color-bg-surface);
  border: 1px solid rgba(14, 59, 55, 0.08);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-deep-pine);
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  overflow: hidden;
  text-align: center;
  min-height: 96px;
}

/* Subtle top accent stripe (gold) — adds the "this is interactive" cue */
.quick-link::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 32px;
  height: 3px;
  background: var(--color-gold);
  border-radius: 0 0 var(--radius-full) var(--radius-full);
  opacity: 0;
  transition: opacity var(--transition-fast), width var(--transition-fast);
}

.quick-link:hover::before {
  opacity: 1;
  width: 48px;
}

.quick-link:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(14, 59, 55, 0.16);
}

.quick-link:active {
  transform: translateY(0) scale(0.97);
  box-shadow: var(--shadow-sm);
}

.quick-link-icon {
  font-size: 2rem;
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.08));
}

/* ─── Scoreboard ────────────────────────────────────────────────── */
.scoreboard-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-2);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
}

.scoreboard-row:active {
  transform: scale(0.98);
}

.scoreboard-row.first-place {
  background: linear-gradient(135deg, rgba(236, 174, 63, 0.15), var(--color-bg-surface));
  border: 2px solid var(--color-gold);
}

.scoreboard-rank {
  font-size: var(--text-xl);
  font-weight: var(--font-bold);
  color: var(--color-text-muted);
  width: 32px;
  text-align: center;
}

.first-place .scoreboard-rank {
  color: var(--color-gold);
}

.scoreboard-team {
  flex: 1;
}

.scoreboard-team-name {
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
}

.scoreboard-mascot {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.scoreboard-points {
  font-size: var(--text-lg);
  font-weight: var(--font-bold);
  color: var(--color-deep-pine);
}

/* ─── Profile Detail ────────────────────────────────────────────── */
.profile-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-6) 0;
}

.profile-name {
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  margin-top: var(--space-3);
}

.profile-pronouns {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.profile-section {
  margin-bottom: var(--space-4);
}

.profile-section-title {
  font-size: var(--text-sm);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.profile-section-content {
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
}

/* ─── Offline Banner ────────────────────────────────────────────── */
.offline-banner {
  position: fixed;
  bottom: calc(var(--tab-bar-height) + var(--safe-area-bottom));
  left: 0;
  right: 0;
  background-color: var(--color-text-muted);
  color: white;
  text-align: center;
  padding: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  z-index: 200;
  display: none;
}

.offline-banner.visible {
  display: block;
}

/* ─── Card Image / Hero ────────────────────────────────────────── */
.card-image {
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-3);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  overflow: hidden;
  max-height: 200px;
}

.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ─── RSVP Featured Card (Home Screen) ─────────────────────────── */
.card-rsvp-featured {
  background: linear-gradient(135deg, var(--color-deep-pine), var(--color-forest) 60%, var(--color-teal));
  color: var(--color-text-on-dark);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  box-shadow: var(--shadow-lg);
  position: relative;
  overflow: hidden;
}

.card-rsvp-featured::before {
  content: '';
  position: absolute;
  top: -40%;
  right: -20%;
  width: 200px;
  height: 200px;
  background: radial-gradient(circle, rgba(236, 174, 63, 0.15) 0%, transparent 70%);
  border-radius: 50%;
  pointer-events: none;
}

.card-rsvp-featured .card-title {
  color: var(--color-text-on-dark);
  font-size: var(--text-2xl);
}

.card-rsvp-featured .card-subtitle {
  color: var(--color-text-on-dark-muted);
}

.card-rsvp-featured .btn {
  background-color: var(--color-gold);
  color: var(--color-deep-pine);
  font-weight: var(--font-bold);
}

.card-rsvp-featured .btn:active:not(:disabled) {
  background-color: var(--color-ember);
}

/* ─── Manifesto Card ───────────────────────────────────────────── */
.card-manifesto {
  background: var(--color-bg-surface);
  border-left: 4px solid var(--color-gold);
  position: relative;
}

.card-manifesto .card-title {
  color: var(--color-deep-pine);
}

.card-manifesto ol {
  padding-left: 1.5rem;
  margin-top: var(--space-2);
  counter-reset: manifesto;
}

.card-manifesto li {
  margin-bottom: var(--space-1);
  font-size: var(--text-sm);
  list-style: none;
  counter-increment: manifesto;
  position: relative;
  padding-left: var(--space-1);
}

.card-manifesto li::before {
  content: counter(manifesto) ".";
  position: absolute;
  left: -1.5rem;
  font-weight: var(--font-bold);
  color: #8B5E24;
}

.card-manifesto .manifesto-tagline {
  font-style: italic;
  color: var(--color-text-secondary);
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

/* ─── Modal & Bottom Sheet ─────────────────────────────────────── */
.modal-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: var(--color-bg-overlay);
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  animation: modal-backdrop-in 0.2s ease;
}

.modal-overlay.bottom-sheet {
  align-items: flex-end;
  padding: 0;
}

@keyframes modal-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.modal {
  background: var(--color-bg-surface);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  width: 100%;
  max-width: 400px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
  animation: modal-slide-up 0.3s ease;
}

.bottom-sheet .modal {
  max-width: 500px;
  max-height: 70vh;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  animation: sheet-slide-up 0.3s ease;
}

@keyframes modal-slide-up {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes sheet-slide-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

.modal-title {
  font-size: var(--text-xl);
  font-weight: var(--font-bold);
  color: var(--color-text-primary);
  margin-bottom: var(--space-4);
}

/* ─── Stat Cards (Dashboard) ───────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.stat-card {
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  text-align: center;
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast);
}

.stat-card-icon {
  font-size: 1.5rem;
  margin-bottom: var(--space-1);
}

.stat-card-value {
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  line-height: 1.2;
}

.stat-card-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: 2px;
}

/* ─── Task Row ─────────────────────────────────────────────────── */
.task-card {
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-2);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  transition: opacity var(--transition-normal);
}

.task-card.completed {
  opacity: 0.55;
}

.task-checkbox {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  border: 2px solid var(--color-border-strong);
  background: transparent;
  color: white;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all var(--transition-fast);
  margin-top: 2px;
}

.task-checkbox:active {
  transform: scale(0.9);
}

.task-checkbox.checked {
  border-color: var(--color-forest);
  background: var(--color-forest);
}

.task-card .task-name {
  font-weight: var(--font-semibold);
}

.task-card.completed .task-name {
  text-decoration: line-through;
  color: var(--color-text-muted);
}

/* ─── Admin Row Card (Manage People) ──────────────────────────── */
.admin-card {
  background: var(--color-bg-surface);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-2);
  box-shadow: var(--shadow-sm);
}

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

.admin-card-actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
}

/* ─── Note Card (Callout) ──────────────────────────────────────── */
.note-card {
  background: rgba(236, 174, 63, 0.12);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-top: var(--space-4);
  border-left: 3px solid var(--color-gold);
}

.note-card strong {
  color: var(--color-deep-pine);
}

/* ─── Content Animation (fade-in on screen change) ─────────────── */
.content > * {
  animation: content-fade-in 0.25s ease both;
}

.content > *:nth-child(1) { animation-delay: 0ms; }
.content > *:nth-child(2) { animation-delay: 40ms; }
.content > *:nth-child(3) { animation-delay: 80ms; }
.content > *:nth-child(4) { animation-delay: 120ms; }
.content > *:nth-child(5) { animation-delay: 160ms; }
.content > *:nth-child(6) { animation-delay: 200ms; }
.content > *:nth-child(n+7) { animation-delay: 240ms; }

@keyframes content-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ─── Tab Bar Active Indicator ─────────────────────────────────── */
.tab-item.active::after {
  content: '';
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 4px;
  height: 4px;
  border-radius: var(--radius-full);
  background-color: var(--color-state-active);
}

/* (Login screen styles consolidated above) */

/* ─── Range Slider (Cabin Vibe) ────────────────────────────────── */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-border);
  outline: none;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-action-primary);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
  transition: transform var(--transition-fast);
}

input[type="range"]::-webkit-slider-thumb:active {
  transform: scale(1.15);
}

input[type="range"]::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-action-primary);
  cursor: pointer;
  border: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}

/* ─── Cabin Card Polish ────────────────────────────────────────── */
.cabin-occupant-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
}

.cabin-occupant-row .avatar-sm {
  border: 2px solid var(--color-bg-surface);
}

/* ─── Song Request Row ─────────────────────────────────────────── */
.song-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}

.song-icon {
  font-size: 1.25rem;
  flex-shrink: 0;
}

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

.song-title {
  font-weight: var(--font-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.song-requester {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ─── Announcement Card Polish ─────────────────────────────────── */
.card-announcement {
  border-left: 3px solid var(--color-teal);
}

.card-announcement .card-label {
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-teal);
  margin-bottom: var(--space-1);
}

/* ─── Memory Card Polish ───────────────────────────────────────── */
.card-memory {
  overflow: hidden;
  padding: 0;
}

.card-memory .card-memory-image {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.card-memory .card-memory-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.card-memory:active .card-memory-image img {
  transform: scale(1.03);
}

.card-memory .card-memory-body {
  padding: var(--space-3);
}

/* ─── Progress Bar (larger, for RSVP dashboard) ────────────────── */
.progress-bar {
  height: 10px;
  border-radius: var(--radius-full);
  background-color: var(--color-border);
  overflow: hidden;
}

.progress-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--color-forest), var(--color-teal));
  transition: width 0.5s ease;
}

/* ─── Summary Row (dietary, check-in) ──────────────────────────── */
.summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-border);
}

.summary-row:last-child {
  border-bottom: none;
}

.summary-row-label {
  font-size: var(--text-sm);
}

.summary-row-value {
  font-weight: var(--font-bold);
  font-size: var(--text-sm);
  color: var(--color-deep-pine);
}

/* ─── Person List Row (compact) ────────────────────────────────── */
.person-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  transition: background-color var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
}

.person-row:last-child {
  border-bottom: none;
}

.person-row:active {
  background-color: rgba(14, 59, 55, 0.04);
}

/* ─── Header Badge ─────────────────────────────────────────────── */
.header-committee-badge {
  display: inline-flex;
  align-items: center;
  background: rgba(236, 174, 63, 0.25);
  color: var(--color-gold);
  padding: 1px 6px;
  border-radius: var(--radius-full);
  font-size: 10px;
  font-weight: var(--font-bold);
  letter-spacing: 0.03em;
  vertical-align: middle;
}

/* ─── Pull-to-Refresh Indicator ────────────────────────────────── */
.refresh-indicator {
  text-align: center;
  padding: var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* ─── Utility Classes ───────────────────────────────────────────── */
.text-center { text-align: center; }
.text-right { text-align: right; }
.text-muted { color: var(--color-text-muted); }
.text-sm { font-size: var(--text-sm); }
.text-xs { font-size: var(--text-xs); }
.text-lg { font-size: var(--text-lg); }
.text-2xl { font-size: var(--text-2xl); }
.font-bold { font-weight: var(--font-bold); }
.font-semibold { font-weight: var(--font-semibold); }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.justify-between { justify-content: space-between; }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.w-full { width: 100%; }
.hidden { display: none !important; }

/* ─── Responsive (tablets/desktop) ──────────────────────────────── */
@media (min-width: 640px) {
  #app {
    border-left: 1px solid var(--color-border);
    border-right: 1px solid var(--color-border);
  }

  .quick-links {
    grid-template-columns: repeat(4, 1fr);
  }

  .stat-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ─── Reduced Motion ────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── Dark overlay fix for iOS ──────────────────────────────────── */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .tab-bar {
    padding-bottom: env(safe-area-inset-bottom);
  }
}

/* ─── Desktop Layout (>= 900px) ─────────────────────────────────── */
/* Light-touch desktop adaptation: persistent left sidebar (replacing the
   bottom tab bar), wider content area, and multi-column grids on list
   screens via the .cards-grid utility class. Mobile is untouched. */

@media (min-width: 900px) {
  :root {
    --sidebar-width: 240px;
    --desktop-content-max: 1200px;
    --desktop-form-max: 720px;
  }

  /* Allow normal scroll behavior on desktop. Use overflow:visible (not auto)
     so the body itself isn't a scroll container — otherwise its background
     stays pinned to the viewport while content scrolls past it. With visible,
     the page scrolls and the tan background follows the content. */
  html {
    height: auto;
  }
  body {
    overflow: visible;
    position: static;
  }

  /* App becomes a 2-col grid: sidebar + content, header on top.
     The whole page scrolls (not just .content) so the mouse wheel works
     anywhere on the page, regardless of cursor position. The header and
     sidebar stick to the top while content scrolls past them. */
  #app {
    display: grid;
    grid-template-columns: var(--sidebar-width) 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "header  header"
      "sidebar content";
    /* Override the mobile `height: 100vh` so the app grows with content
       — otherwise body's tan background only paints one viewport tall. */
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    max-width: 100%;
    margin: 0;
    border-left: 0;
    border-right: 0;
  }

  /* Header spans the full top, stays visible while scrolling */
  .header {
    grid-area: header;
    position: sticky;
    top: 0;
    z-index: 100;
  }

  /* Bottom tab bar → vertical left sidebar; pinned to the viewport so it
     never scrolls away. Keeping `grid-area: sidebar` reserves the 240px
     column in the grid even though the element itself is out of flow. */
  .tab-bar {
    grid-area: sidebar;
    position: fixed;
    top: var(--header-height);
    left: 0;
    width: var(--sidebar-width);
    height: calc(100vh - var(--header-height));
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    padding: var(--space-3) var(--space-2);
    padding-bottom: var(--space-3);
    border-top: 0;
    border-right: 1px solid rgba(255, 255, 255, 0.08);
    gap: 4px;
    overflow-y: auto;
    z-index: 90;
  }

  .tab-bar .tab-item {
    flex: none;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    padding: var(--space-3) var(--space-3);
    gap: var(--space-3);
    height: auto;
    border-radius: var(--radius-sm);
    width: 100%;
  }

  .tab-bar .tab-item svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
  }

  .tab-bar .tab-item .tab-label {
    font-size: 0.95rem;
    letter-spacing: 0;
  }

  .tab-bar .tab-item.active {
    background: rgba(255, 255, 255, 0.12);
    color: var(--color-state-active);
  }

  .tab-bar .tab-item:hover:not(.active) {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-on-dark);
  }

  /* Hide the mobile-style "top-center dot" active indicator on desktop —
     the sidebar's background + text-color change already conveys active state. */
  .tab-bar .tab-item.active::after {
    display: none;
  }

  /* Hide unread/notification badge dot — no longer relevant in sidebar layout */
  .tab-bar .tab-badge {
    display: none;
  }

  /* Content area: lets the page (body) handle scrolling so wheel events work
     regardless of cursor position. */
  .content {
    grid-area: content;
    overflow: visible;
    padding: var(--space-5);
    /* Override the JS-set padding-bottom (which accounts for the bottom tab bar) */
    padding-bottom: var(--space-5) !important;
    max-width: var(--desktop-form-max);
    width: 100%;
    margin-left: auto;
    margin-right: auto;
    box-sizing: border-box;
  }

  /* When the content has a .cards-grid container, expand to wider max-width
     so the grid can breathe. */
  .content:has(> .cards-grid),
  .content:has(.cards-grid) {
    max-width: var(--desktop-content-max);
  }

  /* The cards-grid container itself — multi-column responsive grid */
  .cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--space-4);
    align-content: start;
    align-items: start;
  }

  /* Reset bottom margin on cards inside a grid (gap handles spacing) */
  .cards-grid > .card {
    margin-bottom: 0;
  }

  /* Desktop: page (body) is the scroll container, not .content. The sticky
     header is at top: 0 — so day-headers need to stick BELOW the header.
     Mobile uses `top: calc(-1 * var(--space-4))` to offset the content
     padding; that doesn't apply on desktop. */
  .day-header {
    top: var(--header-height);
    /* Break out of .content's desktop padding (var(--space-5) = 20px) instead
       of the mobile var(--space-4). */
    margin-left: calc(-1 * var(--space-5));
    margin-right: calc(-1 * var(--space-5));
    padding-left: var(--space-5);
    padding-right: var(--space-5);
  }

  /* Headers, search bars, day labels, count text inside grids span full row */
  .cards-grid > :is(.section-header, .day-header, .filter-chips, .search-bar, h1, h2, h3, p, .text-muted) {
    grid-column: 1 / -1;
  }

  /* Masonry variant — for content with highly variable card heights (e.g.
     announcements where one is a short title-only and another is a long
     body). Uses CSS multi-column layout to flow cards top-down within
     columns, filling vertical space without leaving rectangular gaps.
     Override `display: grid` from `.cards-grid` so column-count applies. */
  .cards-grid.cards-grid-masonry,
  .cards-grid-masonry {
    display: block;
    column-count: 2;
    column-gap: var(--space-4);
  }
  .cards-grid-masonry > .card {
    break-inside: avoid;
    display: inline-block; /* Safari needs this so border-radius/shadow honor column breaks */
    width: 100%;
    margin-bottom: var(--space-4);
  }
}

/* On mobile, masonry collapses to a single column naturally. */
.cards-grid-masonry > .card {
  break-inside: avoid;
}

  /* Hover effects for cards on desktop (mobile uses :active) */
  .card-tappable:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }

  .card-tappable:active {
    transform: translateY(0);
  }

  /* Ensure inputs and selects don't stretch obnoxiously wide on desktop forms */
  .form-input {
    max-width: 100%;
  }

  /* Offline banner: anchor at bottom of content area, not above mobile tab bar */
  .offline-banner {
    bottom: 0;
  }
}
