:root{
  --md-primary:#1a73e8;
  --md-primary-dark:#1558b0;
  --md-surface:#ffffff;
  --md-bg:#f6f8fb;
  --md-text:#202124;
  --md-muted:#5f6368;
  --md-danger:#d93025;
  --md-success:#188038;
  --md-radius:14px;
  --md-shadow:0 6px 18px rgba(0,0,0,.08);
  --md-shadow2:0 10px 28px rgba(0,0,0,.12);
  --md-border:1px solid rgba(32,33,36,.12);
  font-synthesis-weight: none;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;color:var(--md-text);background:var(--md-bg)}
/* Toggled by showInfoOverlay()/hideInfoOverlay() — keeps the page behind the
   info overlay from scrolling while it's open. Both elements get the class:
   iOS Safari can still rubber-band the page if only one of them is locked. */
html.scroll-locked,body.scroll-locked{overflow:hidden}
a{color:inherit}
.header-inner{
  max-width:980px;margin:0 auto;padding:16px 18px;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;
}
.brand{display:flex;align-items:center;gap:10px}
.brand-dot{width:12px;height:12px;border-radius:999px;background:var(--md-primary);box-shadow:0 0 0 6px rgba(26,115,232,.12)}
.brand h1{font-size:18px;margin:0;font-weight:650;letter-spacing:.2px}
.subtle{color:var(--md-muted);font-size:13px}

.container{max-width:980px;margin:0 auto;padding:18px}
.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}
.card{
  grid-column: span 12;
  background:var(--md-surface);
  border-radius:var(--md-radius);
  box-shadow:var(--md-shadow);
  border:var(--md-border);
  padding:16px 16px;
  cursor:pointer;
  transition: transform .08s ease, box-shadow .08s ease;
}
.card:hover{transform: translateY(-1px);box-shadow:var(--md-shadow2)}
/* Past events: visually subdued, but fully readable on hover/focus */
.card.past{
  opacity: .5;
  transition: opacity 140ms ease;
}
.card.past:hover,
.card.past:focus,
.card.past:focus-within{
  opacity: 1;
}

.card h2{margin:0 0 6px 0;font-size:16px;font-weight:700}
.meta{display:flex;flex-wrap:wrap;gap:8px;color:var(--md-muted);font-size:13px}
.chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 10px;border-radius:999px;
  border:var(--md-border);background:#fff;font-size:12px;color:var(--md-muted)
}
.chip.primary{border-color: rgba(26,115,232,.25); background: rgba(26,115,232,.06); color: var(--md-primary-dark)}
.chip.danger{border-color: rgba(217,48,37,.25); background: rgba(217,48,37,.06); color: var(--md-danger)}
.chip.success{border-color: rgba(24,128,56,.25); background: rgba(24,128,56,.06); color: var(--md-success)}
.right{margin-left:auto}
.count{font-weight:650;color:var(--md-text)}
.footer-note{color:var(--md-muted);font-size:13px;margin-top:10px}

.btn{
  display:inline-flex;align-items:center;justify-content:center;
  border:none;border-radius:999px;
  padding:10px 14px;font-weight:650;
  background:var(--md-primary);color:#fff;
  cursor:pointer;transition:background .12s ease, transform .08s ease;
}
.btn:hover{background:var(--md-primary-dark)}
.btn:active{transform: translateY(1px)}
.btn.secondary{background:#fff;color:var(--md-text);border:var(--md-border)}
.btn.danger{background:var(--md-danger)}
.btn.success{background:var(--md-success)}
.btn.small{padding:7px 10px;font-size:13px}
.btn:disabled{opacity:.55;cursor:not-allowed}

/* nowrap: the two pills stay together as a unit — if they don't fit next to
   the brand text, the whole row wraps onto its own line below (handled by
   header-inner's flex-wrap) instead of the pills stacking on top of each
   other, which would misalign the brand block vertically. */
.topnav{display:flex;align-items:center;gap:10px;flex-wrap:nowrap;justify-content:flex-end}
.topnav-link{
  text-decoration:none;
  padding:8px 10px;
  border-radius:999px;
  border:var(--md-border);
  background:#fff;
  font-size:13px;
  color:var(--md-muted);
}
.topnav-link.active{border-color: rgba(26,115,232,.25); background: rgba(26,115,232,.06); color: var(--md-primary-dark)}
.topnav-status{font-size:13px;color:var(--md-muted)}

.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.field{display:flex;flex-direction:column;gap:6px;min-width:240px;flex:1}
label{font-size:12px;color:var(--md-muted)}
input, textarea, select{
  padding:10px 12px;border-radius:12px;border:var(--md-border);
  background:#fff;font-size:14px;outline:none;
}
textarea{min-height:90px;resize:vertical}
small.help{color:var(--md-muted)}

/* Rich text rendering (public) */
.richtext :where(p,div){margin:0 0 10px 0}
/* No margin-left: indentation is left to the browser's own default
   padding-left on ul/ol (bullet/number sits in that padding, not pushed
   over by an extra margin on top of it). Mobile still sets its own
   padding-left explicitly — see the media query below. */
.richtext :where(ul,ol){margin:0 0 1.5em 0}
.richtext li{margin-bottom:.5em}
.richtext a{color:var(--md-primary-dark)}

/* Simple RTE */
.rte-toolbar{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0 8px 0}
.rte-btn{
  border:var(--md-border);
  background:#fff;
  border-radius:999px;
  padding:6px 10px;
  cursor:pointer;
  font-size:13px;
  color:var(--md-text);
}
.rte-btn:hover{box-shadow:0 1px 0 rgba(0,0,0,.04)}
.rte-editor{
  min-height:120px;
  padding:10px 12px;
  border-radius:12px;
  border:var(--md-border);
  background:#fff;
  font-size:14px;
  outline:none;
}
.rte-editor:empty:before{
  content: attr(data-placeholder);
  color: rgba(95,99,104,.75);
}

/* Tabs in admin */
.tabs{display:flex;gap:8px;flex-wrap:wrap;margin: 6px 0 12px 0}
.tab-btn{background:#fff;color:var(--md-text);border:var(--md-border);border-radius:999px;padding:9px 12px;font-weight:650;cursor:pointer}
.tab-btn.active{border-color: rgba(26,115,232,.25); background: rgba(26,115,232,.06); color: var(--md-primary-dark)}

hr.sep{border:0;border-top:var(--md-border);margin:14px 0}

/* Modal */
.modal-backdrop{
  position:fixed;inset:0;background:rgba(0,0,0,.38);
  display:flex;
  padding:18px;z-index:30;
  overflow:auto;
  /*
    Modal responsiveness:
    - Scroll the backdrop (container), not the modal body.
    - Center the modal when it fits; if it exceeds viewport height,
      margins collapse and it becomes naturally top-aligned within padding.
  */
  flex-direction:column;
  /* Never display:none — the open/close animation (opacity + translateY on
     .event-modal) needs the element mounted to transition. Hidden state is
     opacity:0 + pointer-events:none instead, same pattern as the info overlay. */
  opacity:0;pointer-events:none;
  transition:opacity .22s ease;
}
.modal-backdrop.open{opacity:1;pointer-events:auto}
.notice{
  padding:10px 12px;border-radius:12px;border:var(--md-border);
  background:rgba(95,99,104,.06);color:var(--md-text);font-size:13px
}
.notice.danger{border-color: rgba(217,48,37,.25); background: rgba(217,48,37,.06)}
.notice.success{border-color: rgba(24,128,56,.25); background: rgba(24,128,56,.06)}
/* margin-bottom is intentionally 0, not .5rem to match margin-top: the next
   sibling (.event-modal-desc-wrap) already carries its own margin-top:8px,
   and flex children's margins don't collapse — .5rem here would double up
   to 16px below vs 8px above. Zero here + that 8px gives the same 8px both
   sides. */
#modalNotice{margin-top:.5rem;margin-bottom:0}

.table{
  width:100%;border-collapse:collapse;font-size:14px;
}
.table th, .table td{border-bottom:var(--md-border);padding:10px 8px;text-align:left}
.table th{font-size:12px;color:var(--md-muted);font-weight:700}
.table td .btn{padding:7px 10px;font-size:13px}
.kbd{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;background:rgba(0,0,0,.06);padding:2px 6px;border-radius:6px;font-size:12px}


/* Update banner: a floating toast (not pushed into normal flow) so it reads
   as a transient prompt, consistent with the card2/CTA redesign rather than
   the older flat .btn/.notice look. */
.update-banner{
  position:fixed;left:50%;bottom:18px;transform:translateX(-50%);
  z-index:40;
  display:flex;gap:14px;align-items:center;
  padding:12px 14px 12px 18px;
  border-radius:999px;
  box-shadow:var(--md-shadow2);
  background:var(--md-surface);
  border:var(--md-border);
  font-size:14px;color:var(--md-text);
  max-width:calc(100vw - 32px);
}
.update-banner.hidden{display:none;}
.update-banner-btn{
  display:inline-flex;align-items:center;justify-content:center;
  border:none;border-radius:999px;white-space:nowrap;
  padding:9px 16px;font-weight:500;font-size:14px;
  background:#1d1d1f;color:#fff;
  cursor:pointer;transition:background .12s ease, transform .08s ease;
}
.update-banner-btn:hover{background:#000}
.update-banner-btn:active{transform:translateY(1px)}


/* Tabs row (admin) */
.tabs-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  flex-wrap:wrap;
  margin: 6px 0 12px 0;
}
.tabs-row .tabs{ margin:0; }

/* Admin lists */
#eventsList, #pastEventsList{
  display:flex;
  flex-direction:column;
  gap:1rem;
}

/* Snackbar */
.snackbar{
  position:fixed;
  right:16px;
  bottom:16px;
  min-width:260px;
  max-width:min(420px, calc(100vw - 32px));
  background:rgba(50,50,50,.98);
  color:#fff;
  padding:12px 14px;
  border-radius:12px;
  box-shadow:var(--md-shadow2);
  opacity:0;
  transform:translateY(8px);
  pointer-events:none;
  transition: opacity .18s ease, transform .18s ease;
  z-index:120;
  font-size:14px;
}
.snackbar.show{
  opacity:1;
  transform:translateY(0);
  pointer-events:auto;
}
.snackbar.success{ background: rgba(24,128,56,.95); }
.snackbar.danger{ background: rgba(217,48,37,.95); }

/* ===== Redesign (public pages): pulled from Figma (WZJbfQ14pKVA5QFf8qkpWH) ===== */
body.public-theme{ min-height:100vh; background:linear-gradient(180deg,#E1E4FF 0%,#FBFCFF 100%); }

.icon-img{display:block;width:100%;height:100%;object-fit:contain}

.brand-logo{
  width:40px;height:40px;border-radius:999px;flex:0 0 auto;
  background:#626ff1;
  display:flex;align-items:center;justify-content:center;
}
.brand-logo .icon-img{width:24px;height:24px}
.brand-text{display:flex;flex-direction:column;line-height:1.1}
.brand-org{font-size:18px;font-weight:500;color:#626ff1}
.brand-name{font-size:24px;font-weight:700;color:#000}

.pill-btn{
  display:inline-flex;align-items:center;gap:8px;
  border:none;border-radius:999px;
  padding:14px 16px;font-weight:500;font-size:14px;
  background:#fff;color:#1d1d1f;
  box-shadow:0 2px 6px rgba(0,0,0,.08);
  transition:box-shadow .2s ease;
  cursor:pointer;
}
.pill-btn:hover{box-shadow:0 4px 8px rgba(0,0,0,.16)}
.pill-btn .icon-wrap{width:14px;height:14px;flex:0 0 auto}

.admin-menu{position:relative}
.admin-flyout{
  position:absolute;top:calc(100% + 8px);right:0;
  background:#fff;border-radius:14px;box-shadow:0 6px 18px rgba(0,0,0,.1);border:var(--md-border);
  min-width:180px;padding:6px;z-index:20;
  display:flex;flex-direction:column;gap:2px;
}
/* Explicit override: the [hidden] attribute selector needs to out-specificity
   the class rule above, or the browser's default [hidden]{display:none} loses
   and the flyout renders (as flex) even while "hidden" is set. */
.admin-flyout[hidden]{display:none}
.flyout-item{
  display:block;width:100%;text-align:left;
  padding:9px 10px;border-radius:9px;border:none;background:none;
  font-size:14px;color:var(--md-text);text-decoration:none;cursor:pointer;
  font-family:inherit;
}
.flyout-item:hover{background:rgba(32,33,36,.06)}

.pill-tabs{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0 18px 0}
.pill-tab{
  display:inline-flex;align-items:center;justify-content:center;
  border:none;border-radius:999px;height:39px;padding:12px 16px;font-size:12px;
  background:#fff;color:#1d1d1f;font-weight:500;cursor:pointer;
}
.pill-tab.active{background:#1d1d1f;color:#fff;font-weight:700}

.section-heading{font-size:14px;color:var(--md-muted);margin:22px 0 10px 0;font-weight:650}
.section-heading:first-child{margin-top:0}

.grid2{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;margin-bottom:4px}

.card2{
  background:#fff;border-radius:20px;box-shadow:0 2px 6px rgba(0,0,0,.07);
  cursor:pointer;transition:transform .15s ease, box-shadow .2s ease;
  display:flex;flex-direction:column;gap:10px;padding:12px;
}
.card2:hover{transform:translateY(-1px);box-shadow:0 6px 14px rgba(0,0,0,.18)}
.card2.past{opacity:.55;transition:opacity 140ms ease}
.card2.past:hover,.card2.past:focus,.card2.past:focus-within{opacity:1}

/* Only rendered by app.js when the event has an image — never present-but-hidden,
   so no [hidden] rule is needed here (unlike .event-modal-media below). */
.card2-image{border-radius:10px;height:155px;background:#e3e6f5 center/cover no-repeat}

.card2-content{display:flex;flex-direction:column;gap:12px}
.card2-textgroup{display:flex;flex-direction:column;gap:6px}
.card2-date{font-size:13px;color:#374151}
.card2-title{margin:0;font-size:18px;font-weight:500;color:#000}
.card2-meta{display:flex;align-items:center;gap:10px}
.card2-location{display:flex;flex:1;align-items:center;gap:6px;color:#6b7280;font-size:13px;min-width:0}
.card2-location .icon-wrap{width:14px;height:14px;flex:0 0 auto}
.card2-location span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card2-attendees{
  position:relative;flex:0 0 auto;
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 10px;border-radius:999px;
  border:1px solid #cbd5e1;background:transparent;
  font-size:13px;color:#374151;white-space:nowrap;
}
.card2-attendees .icon-wrap{width:14px;height:14px;flex:0 0 auto}
.card2-attendees.below-min{border-color:transparent;background:#f9dedc;color:#1d1d1f}
.card2-attendees-warning{position:absolute;top:-3px;right:-3px;width:10px;height:10px}

.card2-cta{
  border:none;border-radius:999px;padding:14px 8px;font-size:14px;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;cursor:pointer;width:100%;
}
.card2-cta .icon-wrap{width:16px;height:16px;flex:0 0 auto}
.card2-cta.cta-join{background:#1d1d1f;color:#fff;font-weight:500}
.card2-cta.cta-joined{background:#626ff1;color:#fff;font-weight:500}
.card2-cta.cta-canceled{background:#f9dedc;color:#8c1d18;font-weight:700}
.card2-cta.cta-full{background:rgba(29,29,31,.08);color:#374151;font-weight:700}

/* Info overlay: floating panel near the top-right, distinct from the centered event modal */
.info-overlay-backdrop{
  position:fixed;inset:0;background:rgba(20,20,40,0);
  display:flex;align-items:flex-start;justify-content:flex-end;
  padding:16px;z-index:35;
  pointer-events:none;
  transition:background-color .3s ease;
}
.info-overlay-backdrop.open{
  background:rgba(20,20,40,.4);
  pointer-events:auto;
}
.info-overlay-panel{
  position:relative;width:min(568px,100%);height:calc(100vh - 32px);background:#fff;
  border-radius:16px;overflow:hidden;box-shadow:0 4px 16px rgba(0,0,0,.12);display:flex;flex-direction:column;
  transform:translateX(calc(100% + 16px));
  transition:transform .32s cubic-bezier(.32,.72,0,1);
}
.info-overlay-backdrop.open .info-overlay-panel{
  transform:translateX(0);
}
.info-overlay-close{
  position:absolute;top:20px;right:28px;
  width:40px;height:40px;border-radius:999px;border:none;background:#f1f5f9;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:#1d1d1f;
  z-index:1;
}
.info-overlay-close .icon-wrap{width:16px;height:16px}
.info-overlay-scroll{overflow-y:auto;padding:48px;flex:1}
.info-overlay-scroll h2{margin:0 0 16px 0;font-size:24px;font-weight:700;color:#1d1d1f}
.info-overlay-scroll .richtext{font-size:14px;color:#374151;line-height:1.5}

/* ===== Event detail modal (Figma nodes 1:947 / 1:1072 / 1:983) ===== */
.event-modal{
  position:relative;
  width:min(801px,100%);
  max-height:calc(100vh - 36px);
  overflow-y:auto;
  background:#fff;border-radius:16px;
  box-shadow:0 4px 16px rgba(0,0,0,.25);
  display:flex;gap:24px;padding:12px;
  margin:auto;
  /* Open animation: fade + small upward move, reversed on close via the
     same .open class the info overlay uses. */
  opacity:0;transform:translateY(16px);
  transition:opacity .22s ease, transform .22s ease;
}
.modal-backdrop.open .event-modal{opacity:1;transform:translateY(0)}

.event-modal-media{
  flex:0 0 276px;width:276px;align-self:stretch;
  border-radius:10px;background:#e3e6f5 center/cover no-repeat;
}
/* A class rule of equal specificity later in the cascade beats a bare
   [hidden]{display:none} — this project has hit that trap repeatedly, so
   the override goes directly on the element's own class. */
.event-modal-media[hidden]{display:none}

.event-modal-panel{
  /* Deliberately NOT display:flex: a flex container with overflow:hidden and
     an oversized (200%) flex-item child renders that child anchored to the
     END instead of the START in this browser — a real, reproduced quirk, not
     a typo. Keeping .event-modal-views as a plain block child of a
     non-flex, overflow:hidden panel sidesteps it entirely and behaves
     predictably: block children stack from the container's start edge. */
  flex:1;min-width:0;position:relative;overflow:hidden;
}
.event-modal-views{
  display:flex;width:200%;flex-shrink:0;
  transition:transform .32s cubic-bezier(.32,.72,0,1);
}
.event-modal-views.show-form{transform:translateX(-50%)}
.event-modal-view{
  width:50%;flex:0 0 50%;display:flex;flex-direction:column;min-width:0;
}

.event-modal-body{display:flex;flex-direction:column;flex:1;min-height:0;padding-right:52px}
.event-modal-date{font-size:13px;color:#374151;padding:6px 0}
.event-modal-deadline{font-size:13px;color:#374151;text-align:center;margin-top:8px}
/* Same [hidden]-vs-class-display specificity issue documented elsewhere in
   this file (admin-flyout, admin-nav-sub, event-modal-more) — explicit
   override required since this element has no other class-based display
   rule of its own, but the pattern is easy to reintroduce by copy-paste. */
.event-modal-deadline[hidden]{display:none}
.event-modal-title{margin:0;font-size:24px;font-weight:500;color:#000}
/* -48px, not the full -52px .event-modal-body padding-right: the low-
   attendance warning badge (.card2-attendees-warning) sits at right:-3px on
   the signups pill, so flush-against-the-edge (-52px) let .event-modal-panel's
   overflow:hidden clip it. 4px of clearance keeps the badge fully visible
   while the pill still reads as right-aligned with the close button. */
.event-modal-meta{display:flex;gap:10px;align-items:center;margin-right:-48px}
.event-modal-location{display:flex;flex:1;align-items:center;gap:6px;color:#6b7280;font-size:13px;min-width:0}
.event-modal-location .icon-wrap{width:14px;height:14px;flex:0 0 auto}
.event-modal-signups{
  position:relative;flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;
  padding:6px 10px;border-radius:999px;border:1px solid #cbd5e1;background:transparent;
  font-size:13px;color:#374151;white-space:nowrap;
}
.event-modal-signups .icon-wrap{width:14px;height:14px;flex:0 0 auto}
.event-modal-signups.below-min{border-color:transparent;background:#f9dedc;color:#1d1d1f}

/* max-height is animated between 200px and a JS-measured pixel value (see
   modalMoreBtn's click handler in app.js) — CSS can't transition to/from
   "none", so the expanded end-state's exact height is computed at click
   time from scrollHeight, then swapped to "none" once the transition
   finishes so later content changes (e.g. an image loading in) aren't
   pinned to a stale measurement. */
.event-modal-desc-wrap{
  margin-top:8px;max-height:200px;overflow:hidden;
  transition:max-height .3s cubic-bezier(.32,.72,0,1);
}
@media (prefers-reduced-motion: reduce){
  .event-modal-desc-wrap{transition:none}
}
.event-modal-desc-wrap .richtext{font-size:15px;color:#000;line-height:1.5}
.event-modal-more{
  display:flex;align-items:center;justify-content:center;gap:4px;
  margin:4px 0 0 0;padding:4px;border:none;background:none;cursor:pointer;
  font-size:15px;font-weight:700;color:#626ff1;font-family:inherit;
}
/* Same [hidden]-vs-class-display specificity issue caught earlier this
   project (admin-flyout, admin-nav-sub) — the explicit override is required. */
.event-modal-more[hidden]{display:none}
.event-modal-chevron{width:16px;height:16px;transition:transform .15s ease}
.event-modal-more.expanded .event-modal-chevron{transform:scaleY(-1)}

.event-modal-footer{padding:12px 0 8px 0}
.event-modal-cta{
  width:100%;border:none;border-radius:999px;height:45px;padding:0 8px;font-size:14px;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;cursor:pointer;font-family:inherit;
}
.event-modal-cta .icon-wrap{width:16px;height:16px;flex:0 0 auto}
.event-modal-cta.cta-join{background:#1d1d1f;color:#fff;font-weight:500}
.event-modal-cta.cta-joined{background:#626ff1;color:#fff;font-weight:500}
.event-modal-cta.cta-canceled{background:#f9dedc;color:#8c1d18;font-weight:700;cursor:default}
.event-modal-cta.cta-full{background:rgba(29,29,31,.08);color:#374151;font-weight:700;cursor:default}

/* Signup/cancel feedback: join gets a bouncy pop + icon pop-in + confetti,
   cancel gets a shorter, plainer pulse and no confetti (see app.js
   animateCtaTransition/animateCardCtaTransition). Shared between the modal
   footer button and the card quick-action button — same markup shape
   (optional .icon-wrap span + label span). Classes are re-applied fresh
   each time the button's className is rebuilt from scratch (renderModalInfo,
   or the card being replaced wholesale by loadEvents' re-render), so no
   manual cleanup of a previous run is needed before adding one of these. */
.event-modal-cta.cta-anim-join, .card2-cta.cta-anim-join{animation:ctaJoinPulse .45s cubic-bezier(.34,1.56,.64,1)}
.event-modal-cta.cta-anim-leave, .card2-cta.cta-anim-leave{animation:ctaLeavePulse .25s ease}
.event-modal-cta.cta-anim-join .icon-wrap, .card2-cta.cta-anim-join .icon-wrap{animation:ctaIconPop .45s cubic-bezier(.34,1.56,.64,1)}
.event-modal-cta.cta-anim-join span:last-child, .card2-cta.cta-anim-join span:last-child{animation:ctaLabelIn .35s ease}
@keyframes ctaJoinPulse{
  0%{transform:scale(1)}
  30%{transform:scale(1.08)}
  55%{transform:scale(.96)}
  100%{transform:scale(1)}
}
@keyframes ctaLeavePulse{
  0%{transform:scale(1);opacity:1}
  50%{transform:scale(.96);opacity:.85}
  100%{transform:scale(1);opacity:1}
}
@keyframes ctaIconPop{
  0%{transform:scale(0);opacity:0}
  60%{transform:scale(1.3);opacity:1}
  100%{transform:scale(1);opacity:1}
}
@keyframes ctaLabelIn{
  0%{opacity:0;transform:translateY(3px)}
  100%{opacity:1;transform:translateY(0)}
}
.confetti-burst{position:fixed;width:0;height:0;pointer-events:none;z-index:60}
.confetti-piece{
  position:absolute;top:0;left:0;width:6px;height:6px;border-radius:1px;
  animation:confettiFly .7s ease-out forwards;
}
@keyframes confettiFly{
  0%{transform:translate(-50%,-50%) rotate(0deg);opacity:1}
  100%{transform:translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) rotate(var(--rot));opacity:0}
}
@media (prefers-reduced-motion: reduce){
  .event-modal-cta.cta-anim-join,
  .event-modal-cta.cta-anim-leave,
  .event-modal-cta.cta-anim-join .icon-wrap,
  .event-modal-cta.cta-anim-join span:last-child,
  .card2-cta.cta-anim-join,
  .card2-cta.cta-anim-leave,
  .card2-cta.cta-anim-join .icon-wrap,
  .card2-cta.cta-anim-join span:last-child{animation:none}
}

.event-modal-close{
  position:absolute;top:12px;right:12px;
  width:40px;height:40px;border-radius:999px;border:none;background:#f1f5f9;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:#1d1d1f;
  z-index:1;
}
.event-modal-close .icon-wrap{width:16px;height:16px}

.event-modal-form-head{display:flex;align-items:center;gap:10px;padding-right:52px}
.event-modal-back{
  width:40px;height:40px;flex:0 0 auto;border-radius:999px;border:none;background:#f1f5f9;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:#1d1d1f;
}
.event-modal-back .icon-wrap{width:16px;height:16px}
.event-modal-form-heading{display:flex;flex-direction:column;gap:2px;min-width:0}
.event-modal-form-title{margin:0;font-size:18px;font-weight:400;color:#000}
.event-modal-form-date{font-size:12px;color:#6b7280}
.event-modal-form-body{display:flex;flex-direction:column;gap:16px;padding-top:16px}
.event-modal-form-body .field{min-width:0}
.event-modal-form-body input{
  border:1px solid #d1d5db;border-radius:4px;height:45px;padding:0 12px;font-size:14px;
}
.event-modal-form-submit{background:#626ff1;color:#fff;height:45px;padding:0 20px;border-radius:999px}
.event-modal-form-body .btn.secondary{height:45px;padding:0 20px;border-radius:999px;background:#f1f5f9;border:none;color:#374151}

.switch-field{
  display:flex;align-items:center;gap:10px;cursor:pointer;
  font-size:13px;color:#374151;line-height:1.4;
}
.switch-toggle{position:relative;flex:0 0 auto;width:36px;height:20px}
.switch-toggle input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.switch-track{
  display:block;width:36px;height:20px;border-radius:999px;background:#d1d5db;
  padding:2px;box-sizing:border-box;transition:background-color .15s ease;
}
.switch-thumb{
  display:block;width:16px;height:16px;border-radius:50%;background:#fff;
  box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s ease;
}
.switch-toggle input:checked + .switch-track{background:#626ff1}
.switch-toggle input:checked + .switch-track .switch-thumb{transform:translateX(16px)}
.switch-toggle input:focus-visible + .switch-track{outline:2px solid #626ff1;outline-offset:2px}
.consent-terms-link{
  border:none;background:none;padding:0;margin:0;font:inherit;
  color:#626ff1;text-decoration:underline;cursor:pointer;
}

@media (max-width:600px){
  .event-modal{width:100%;border-radius:16px;padding:16px}
  .event-modal-media{display:none !important}
  /* The 52px/-48px split (see the comment on .event-modal-meta above) is
     sized for the desktop layout's image column; there's no image on
     mobile; the warning badge still gets its 4px of overhang clearance
     from .event-modal-panel's overflow:hidden, just via smaller numbers. */
  .event-modal-body{padding-right:4px}
  .event-modal-meta{margin-right:0}
  .event-modal-footer{padding-bottom:0}
  .event-modal-more{justify-content:flex-start}

  .info-overlay-scroll{padding:24px}
  .info-overlay-close{top:16px;right:16px}
  /* padding-left (not margin-left) so the bullet marker sits inside the
     list's own box — margin-left would just shift the whole list, marker
     included, further right without changing how far the marker sits from
     the item text next to it. */
  .richtext :where(ul,ol){padding-left:32px}

  .container{padding:16px;padding-top:0}
  .header-inner{padding:16px}
  /* .container's own top padding is zeroed above — header-inner's bottom
     16px is the ONLY gap above .pill-tabs. Without both of these, the two
     paddings stack (16 + 16 = 32) on top of .pill-tabs' own 6px margin,
     which is what made the logo-to-tabs gap roughly double what it should
     be. */
  .pill-tabs{margin-top:0}

  /* Icon-only round button: the label stays in the DOM (still announced by
     screen readers) but is visually hidden, not display:none. */
  #infoBtn{width:44px;height:44px;padding:0;justify-content:center}
  #infoBtn .pill-btn-label{
    position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
  }
}

