/* Roboto + EB Garamond are loaded via a <link rel="stylesheet"> in every page's own <head>
   (preceded by two <link rel="preconnect"> tags), not an @import here — @import is discovered only
   after this whole file downloads and parses, forcing a second sequential round trip before the
   font CSS even starts fetching. A <link> in <head> is discovered by the browser's preloader
   immediately, in parallel with this file, cutting a full round trip off first paint. Moved
   2026-08-04. EB Garamond is an open-source stand-in for Adobe Garamond Pro (licensed, not
   available) — used for presenter business nameplates where the logo is image-only. */

:root{
  --orange: #F17923;
  --orange-link: #B84300;
  --orange-hover: #853000;
  /* Label color for text sitting on a solid --orange fill. White on #F17923 measures only
     2.80:1, failing WCAG AA (4.5:1) and even the 3:1 large-text threshold, so no font size
     rescues it. This near-black brown hits 5.06:1 on the same orange, which keeps the brand
     fill exactly as-is instead of darkening it — the alternative (darkening the fill to
     --orange-link for white text) would have made the hero CTA nearly vanish against the
     hero's own dark scrim, and would have broken again on the :hover white glaze below.
     Fixed, not theme-aware, for the same reason --white is: --orange never changes either. */
  --on-orange: #302A24;
  --brown: #4F463D;
  --header-bar: #333333;
  --bg-neutral: #EEEEEE;
  --white: #FFFFFF;
  --card-shadow: 0px 4px 15px rgba(0,0,0,0.18);
  --radius: 10px;
  --max-width: 1180px;

  /* Theme-aware tokens — light values here, dark overrides below. --white and --header-bar are
     deliberately NOT theme-aware: they're used for elements that stay fixed regardless of the
     toggle (header bar, footer, button text on colored backgrounds, partner/brand-kit logo chips). */
  --page-bg: #FFFFFF;
  --surface: #FFFFFF;
  --text-primary: var(--brown);
  --text-secondary: #6b6259;
  /* Darkened from #9a9186 2026-08-04 — the original only hit a 3.10:1 contrast ratio against
     white (4.5:1 needed for normal text), flagged by Lighthouse/axe. This value hits 5.25:1 on
     white and 4.53:1 on --bg-neutral (#EEEEEE, the other background this token appears against),
     both with real margin, fixing every --text-muted usage sitewide from one token — dark mode's
     own --text-muted below already passed (5.48:1 / 4.57:1) and didn't need changing. */
  --text-muted: #726b63;
}

:root[data-theme="dark"]{
  --bg-neutral: #201c1a;
  --page-bg: #181513;
  --surface: #2a2521;
  --text-primary: #f3ede7;
  --text-secondary: #c4bcb2;
  --text-muted: #948c82;
}

*{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
body{
  margin: 0;
  font-family: 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;
  color: var(--text-primary);
  background: var(--page-bg);
  transition: background-color 0.2s ease, color 0.2s ease;
}
img{ max-width: 100%; display: block; }
a{ color: var(--orange-link); }
a:hover{ color: var(--orange-hover); }

h1, h2, h3{
  font-family: 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
}

.wrap{ max-width: var(--max-width); margin: 0 auto; padding: 0 24px; }
.visually-hidden{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap;
}

/* ---------- header / nav ---------- */
/* White, not --header-bar: the horizontal lockup's wordmark is a muted brown tuned for a light
   background (print/business-card style) and reads poorly on dark. The vertical lockup used in
   the footer IS a white-knockout mark, so that stays on --header-bar. */
.site-header{
  background: var(--surface);
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
  position: sticky; top: 0; z-index: 100;
  transition: background-color 0.2s ease;
}
.site-header .wrap{
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 12px; padding-bottom: 12px; gap: 20px;
}
.site-header .logo img{ height: 44px; width: auto; }
/* Two logo files, one shown at a time via data-theme — same "both in the DOM, CSS picks one"
   approach as the theme-toggle's sun/moon icons, so there's no JS swap and no flash on load (the
   inline head script sets data-theme before first paint). Was a fixed var(--white) bar in every
   theme until 2026-08-01 — reads as blindingly high-contrast sitting above an otherwise dark page,
   so the header now follows the same var(--surface) dark background every card already uses. */
.site-header .logo .logo-dark{ display: none; }
:root[data-theme="dark"] .site-header .logo .logo-light{ display: none; }
:root[data-theme="dark"] .site-header .logo .logo-dark{ display: block; }
.main-nav{ display: flex; align-items: center; gap: 28px; }
.main-nav ul{ list-style: none; display: flex; gap: 24px; margin: 0; padding: 0; }
.main-nav a{
  color: var(--text-primary); text-decoration: none; font-weight: 500; font-size: 0.95rem;
}
.main-nav a:hover{ color: var(--orange-link); }
.main-nav a.active{ color: var(--orange-link); font-weight: 700; }

/* Light-switch style, sun/moon icons living inside the track itself with a sliding thumb that
   sits behind whichever one is current — matching RopeCobra's actual finish this time: a subtle
   bordered track (neutral, not a loud color, in either mode) and a thumb that always carries the
   brand accent color, rather than a plain white circle that never picks up any brand identity. */
.theme-toggle{ background: none; border: none; cursor: pointer; padding: 4px; }
.theme-toggle-track{
  position: relative; display: flex; align-items: center; justify-content: space-between;
  width: 54px; height: 28px; padding: 0 6px; border-radius: 999px;
  background: var(--bg-neutral); border: 1px solid rgba(0,0,0,0.14);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
:root[data-theme="dark"] .theme-toggle-track{ background: var(--surface); border-color: rgba(255,255,255,0.14); }
.theme-toggle-track svg{ width: 14px; height: 14px; position: relative; z-index: 1; flex-shrink: 0; }
/* These set `color`, not `fill`, on purpose: the icons are RopeCobra's own pair, and the sun is a
   *stroked* ring (fill:none, stroke:currentColor) while the moon is a *filled* crescent
   (fill:currentColor). `fill` would leave the stroked sun completely uncolored — `color` is the
   one property that reaches both through currentColor.
   Whichever icon is riding the thumb reads against orange (white does that cleanly); whichever
   is sitting bare on the track reads against a neutral — dark ink on light, light ink on dark. */
/* The two glyphs fill their shared 24×24 viewBox very differently — the sun's rays reach nearly
   edge to edge (~22 units) while the crescent only spans ~16.7 — so at an identical box size the
   moon renders ~32% smaller and looks lost inside the thumb. Scale it up to match the sun
   optically. A transform doesn't affect layout, so the flex centering and the thumb alignment
   both stay exactly where they were.
   The crescent's ink also sits a hair off-center inside its own viewBox (its shape is asymmetric),
   which scaling amplifies — the leading translate cancels that out so the active icon lands dead
   center in the thumb. Written before scale(), so it resolves in final pixels, not scaled units. */
.theme-toggle-track .icon-moon{ transform: translate(0.26px, -0.26px) scale(1.32); }
.theme-toggle-track .icon-sun{ color: #fff; }
.theme-toggle-track .icon-moon{ color: var(--brown); }
:root[data-theme="dark"] .theme-toggle-track .icon-sun{ color: var(--text-muted); }
:root[data-theme="dark"] .theme-toggle-track .icon-moon{ color: #fff; }
.theme-toggle-thumb{
  position: absolute; top: 2px; left: 2px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--orange); box-shadow: 0 1px 3px rgba(0,0,0,0.35);
  transition: transform 0.2s ease;
}
:root[data-theme="dark"] .theme-toggle-thumb{ transform: translateX(26px); }

.hamburger-btn{
  background: none; border: 2px solid var(--text-primary); border-radius: 6px;
  width: 34px; height: 30px; cursor: pointer; position: relative; flex-shrink: 0;
}
/* Bar positions are computed from the button's own height/width so shrinking this box later
   doesn't require re-deriving the centering by hand: middle bar at (height-thickness)/2. Absolute
   positioning here is relative to the padding box, which (with box-sizing:border-box) excludes
   the 2px border on each side — so the available height is 30-4=26px, not the full 30px; top:12px
   (not 14px) is what actually centers a 2px bar in that 26px space.
   var(--text-primary), not the fixed var(--brown) this used before 2026-08-01 — the header can now
   go dark (see .site-header above), and a fixed dark-brown border/bars would disappear against it. */
.hamburger-btn span{
  position: absolute; left: 7px; right: 7px; top: 12px; height: 2px; background: var(--text-primary);
}
.hamburger-btn span::before, .hamburger-btn span::after{
  content: ""; position: absolute; left: 0; right: 0; height: 2px; background: var(--text-primary);
}
.hamburger-btn span::before{ top: -5px; }
.hamburger-btn span::after{ top: 5px; }

.hamburger-menu{
  position: absolute; right: 24px; top: 100%; background: var(--surface);
  border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 10px 0; min-width: 220px; display: none; flex-direction: column;
}
.hamburger-menu.open{ display: flex; }
.hamburger-menu a.active{ background: var(--bg-neutral); color: var(--orange-link); font-weight: 700; }
.hamburger-menu a{
  padding: 10px 20px; text-decoration: none; color: var(--text-primary); font-weight: 500;
}
.hamburger-menu a:hover{ background: var(--bg-neutral); color: var(--orange-link); }
/* .hamburger-primary mirrors .main-nav ul's own links exactly (see every page's header markup) —
   hidden above 820px since they're already visible directly in the top nav there, so showing them
   again in the dropdown would just be redundant. Below 820px (the same breakpoint that hides
   .main-nav ul), the hamburger becomes the *only* nav affordance on the page, so it needs to carry
   the full set — without this, About/Presenters/When & Where/Partners/Team/FAQ have no way to be
   reached at all on a phone or tablet once the top nav disappears (only the secondary/utility
   links below ever lived in the hamburger before this). */
.hamburger-primary{ display: none; flex-direction: column; }
/* Wrapping the existing secondary links in their own div (to sit alongside .hamburger-primary)
   took them out of .hamburger-menu's own flex-column context, so without this they'd fall back to
   plain inline flow and wrap sideways instead of stacking — same vertical layout as before. */
.hamburger-secondary{ display: flex; flex-direction: column; }

@media (max-width: 820px){
  .main-nav ul{ display: none; }
  .hamburger-primary{ display: flex; }
  .hamburger-secondary{ border-top: 1px solid var(--bg-neutral); margin-top: 6px; padding-top: 6px; }
}

/* ---------- share / add-to-calendar action trays (js/actions.js) ---------- */
/* Generic popover shared by every [data-share-btn] and [data-calendar-btn] trigger — same
   open/close mechanic as .hamburger-menu just above (display:none -> .open{display:flex}), so
   dark mode is free from the same tokens every other popover on the site already uses.
   js/actions.js inserts the tray as the trigger <button>'s next sibling (a <button> can't contain
   nested interactive content like the tray's own links/buttons, so it can't nest inside) — .action-
   wrap is the small positioned span every trigger sits inside, giving that sibling tray a
   containing block sized to just the one button, not whatever bigger row it lives in. */
.action-wrap{ position: relative; display: inline-flex; }
.action-tray{
  position: absolute; top: 100%; right: 0; margin-top: 6px; z-index: 5;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 6px; min-width: 190px; display: none; flex-direction: column;
}
.action-tray.open{ display: flex; }
/* Optional leading label (js/actions.js's toggleTray heading param) — "Add this recurring event…"
   / "Add this session…" context line above the Google/Apple-Outlook rows, not a clickable row. */
.action-tray-heading{
  padding: 8px 12px 6px; font-size: 0.78rem; font-weight: 600; color: var(--text-secondary);
  line-height: 1.3;
}
.action-tray-item{
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 8px;
  text-decoration: none; color: var(--text-primary); font-size: 0.88rem; font-weight: 600;
  background: none; border: none; text-align: left; width: 100%; cursor: pointer; font-family: inherit;
}
.action-tray-item:hover{ background: var(--bg-neutral); color: var(--orange-link); }
.action-tray-icon{ display: flex; width: 20px; height: 20px; flex-shrink: 0; }
.action-tray-icon svg{ width: 100%; height: 100%; }
/* --orange-link, not --orange — this text is 0.88rem/weight 600, too small to qualify for the
   WCAG "large text" exemption, and --orange only hits 2.80:1 on the tray's white surface (needs
   4.5:1). --orange-link (already used one line up, for :hover) hits 5.47:1 and was presumably
   picked for exactly this reason there; this state just hadn't been given the same treatment. */
.action-tray-item.copied{ color: var(--orange-link); }

/* <button> reset — border/background/outline:none so no browser-default button chrome (a gray/
   black border + background box) shows behind icon-only triggers. Deliberately doesn't touch
   color, since every placement below fully specifies its own. Safe for .btn-icon too: .btn-icon's
   own explicit background/border (further down this file, so it wins the same-specificity tie by
   source order) still renders its orange circle normally for the When & Where/footer triggers. */
.action-btn{
  padding: 0; font: inherit; cursor: pointer; -webkit-appearance: none; appearance: none;
  border: none; background: none; outline: none;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ---------- hero ---------- */
.hero{
  background: linear-gradient(rgba(79,70,61,0.55), rgba(79,70,61,0.55)),
              url('../assets/1MCVV/1MCVV-hero-banner.jpg') center/cover no-repeat;
  color: var(--white);
  padding: 90px 0;
  text-align: center;
}
.hero h1{ color: var(--white); font-size: 2.6rem; margin-bottom: 14px; }
.hero p{ max-width: 680px; margin: 0 auto 30px; font-size: 1.1rem; line-height: 1.6; }
.hero .cta-row{ display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }

.btn{
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 48px; padding: 0 28px; border-radius: 30px;
  font-weight: 700; text-decoration: none; font-size: 0.95rem; border: 2px solid transparent;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
.btn:hover{ transform: translateY(-2px); }
.btn .external-link-icon{ width: 15px; height: 15px; flex-shrink: 0; }
/* border:2px solid transparent on the base .btn (matching .btn-outline's real border width) keeps
   both buttons' text sitting the same distance from the top regardless of which one has a visible
   border — without it, .btn-primary's text sat 2px higher than .btn-outline's. */
.btn-primary{ background: var(--orange); color: var(--on-orange); }
/* A soft highlight glaze (matching .btn-outline:hover's translucent-white approach) instead of
   swapping to the much darker --orange-hover, which read as too heavy for this button. */
.btn-primary:hover{ background: var(--orange); box-shadow: inset 0 0 0 999px rgba(255,255,255,0.18); color: var(--on-orange); }
.btn-outline{ background: transparent; color: var(--white); border-color: var(--white); }
/* A soft highlight instead of the old hard invert-to-solid-white-with-dark-text look. */
.btn-outline:hover{ background: rgba(255,255,255,0.18); color: var(--white); }

/* circular event-listing icon buttons next to Get Directions — explicit height:width:48px
   (matching .btn's own explicit min-height:48px) instead of relying on padding+content sizing
   to happen to agree, since a text+icon row and an icon-only button don't naturally settle on
   the same content height (a bare 20px svg vs. a ~18px text line-box, off by a couple px). */
.directions-row{ display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.btn-icon{
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border-radius: 50%; border: 2px solid transparent;
  background: var(--orange); color: var(--white); transition: transform 0.15s ease;
}
/* color explicitly repeated here (matching .btn-primary:hover) — without it, the generic
   `a:hover{ color: var(--orange-hover) }` rule wins on specificity and darkens the icon fill,
   since these are <a> tags and .btn-icon's own base color declaration alone can't out-rank that
   on :hover. */
.btn-icon:hover{ transform: translateY(-2px); box-shadow: inset 0 0 0 999px rgba(255,255,255,0.18); color: var(--white); }
.btn-icon svg{ width: 20px; height: 20px; }
/* The generic calendar-plus glyph reads visually lighter/smaller than the brand marks (Luma/
   Facebook/Meetup/Eventbrite) at the same 20px box, since those fill more of their own box —
   bumped up slightly to match perceived weight, not literal size. */
.directions-cal-btn svg{ width: 24px; height: 24px; }
/* A thin stroke on top of the solid fill nudges the share arrow's weight up slightly to match the
   bolder brand marks beside it (stroke-width is in the icon's own 4000-unit viewBox space, not CSS
   px, so this is a much smaller visual change than the number suggests). */
.directions-share-btn svg path{ stroke: currentColor; stroke-width: 96; }

/* ---------- sections ---------- */
section{ padding: 64px 0; }
section.alt{ background: var(--bg-neutral); }

/* What is 1MC + How it works, side by side on desktop; stacked (default DOM order) below 861px */
@media (min-width: 861px){
  .split-row{ display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
}
.section-head{ text-align: center; max-width: 720px; margin: 0 auto 40px; }
.section-head h2{ font-size: 2rem; margin-bottom: 10px; }
.section-head p{ color: var(--text-secondary); font-size: 1.02rem; line-height: 1.6; }

/* what is 1mc */
.whatis-copy{
  max-width: 680px; margin: 0 auto 32px; text-align: center; line-height: 1.7; font-size: 1.05rem;
}
/* Height comes from the Vimeo embed's own padding-percentage wrapper (padding-top:65%, sized to
   the actual video's aspect ratio) rather than a fixed aspect-ratio here — the two would conflict,
   since the wrapper's padding is a percentage of this container's width and doesn't know about a
   height this element might otherwise impose. */
.video-embed{
  max-width: 720px; margin: 0 auto; border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--card-shadow);
}
.video-embed iframe{ border: 0; }
/* Below the embedded video — invites visitors to the channel's full YouTube playlist. Icon is a
   fixed brand red (#FF0000, YouTube's own official red), unlike the footer's currentColor/theme-
   aware version, since this is a one-off brand callout rather than part of the themed icon row. */
.youtube-more{ max-width: 720px; margin: 16px auto 0; text-align: center; }
.youtube-more a{
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--text-primary); font-weight: 600; font-size: 0.95rem;
  transition: opacity 0.15s ease;
}
.youtube-more a:hover{ opacity: 0.75; }
.youtube-more-icon{ width: 28px; height: 28px; flex-shrink: 0; color: #FF0000; }

/* about / agenda */
.about-copy p{ line-height: 1.7; margin-bottom: 18px; max-width: 760px; }
/* Heights are proportional to duration (flex-grow set inline per item, see js/main.js) rather than
   every agenda item getting equal visual weight — the 22-minute Q&A blocks should read as the
   dominant part of the hour, and the 2-minute bookends shouldn't compete for attention at all. */
.agenda-list{
  list-style: none; margin: 30px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
  max-width: 480px; height: 440px;
}
.agenda-list li{ display: flex; align-items: center; gap: 16px; }
.agenda-list li.major{
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 0 20px; flex: 1 0 0; min-height: 0;
}
.agenda-list li.minor{
  flex: 0 0 auto; padding: 0 4px;
  color: var(--text-muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em;
}
.agenda-list li.minor .time{ min-width: auto; font-size: 0.75rem; }
.agenda-list .time{ color: var(--orange-link); font-weight: 700; min-width: 56px; flex-shrink: 0; }

/* card grids (organizers / partners) */
.card-grid{
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 36px;
}
/* presenter grid: always exactly 2 per row (each card is wide enough to need it, with the
   speaker/business columns forced side by side), dropping to 1 per row on mobile — not the
   auto-fit "however many happen to fit" behavior the other card grids use. minmax(0,1fr), not
   bare 1fr — a plain 1fr track has an implicit min-width:auto, so a card with more intrinsic
   content (e.g. the two-column presenter-row forced to nowrap) pushes its own track wider than
   its neighbor instead of splitting evenly; minmax(0,1fr) removes that implicit floor. */
/* Opted into by class, not by listing the grids that need it.

   This was two attribute selectors, and both times a new presenter grid was
   added it was left out of them — first the archive, which inherited
   .card-grid's auto-fit and packed four cards side by side, squeezing the
   two-column presenter-row into nothing; then the home page's "Recently
   Presented" strip, in exactly the same way. The comment recording the first
   miss was sitting directly above the selector that caused the second.

   The data- attributes are JavaScript hooks and say nothing about layout. A
   class says what the grid is, so a new one opts in by being what it is rather
   than by somebody remembering to extend a list. */
.presenter-pairs{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 700px){
  .presenter-pairs{ grid-template-columns: minmax(0, 1fr); }
}
.card{
  position: relative;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 22px; text-align: center; cursor: pointer;
}
.card .badge-img{
  /* Anchored by bottom/right (not top/left), so sizing it up grows the badge toward the card's
     center — its distance from the bottom-right edge stays exactly the same. Sized ~15% larger
     than the original 15%/34px/52px (2026-07-28). */
  position: absolute; bottom: 6px; right: 10px; width: 17%; min-width: 39px; max-width: 60px;
  height: auto; z-index: 2; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}
/* organizer card: orange "Certified Organizer" stripe bled flush to the card's bottom edge,
   matching the official 1millioncups.com organizer card pattern. margin-top:auto (in a flex
   column) keeps it pinned to the bottom even when CSS grid stretches shorter cards to match
   the tallest card in their row. */
.card.organizer-card{ padding-bottom: 0; overflow: hidden; display: flex; flex-direction: column; }
.card .certified-stripe{
  margin: auto -22px 0; padding: 9px 56px 9px 16px;
  background: var(--orange); color: #fff; font-weight: 600; font-size: 0.85rem;
  display: flex; align-items: center; text-align: left;
}
.card .avatar{
  width: 96px; height: 96px; border-radius: 50%; margin: 0 auto 14px; overflow: hidden;
  background: var(--bg-neutral); display: flex; align-items: center; justify-content: center;
}
.card .avatar img{ width: 100%; height: 100%; object-fit: cover; }
.card .avatar .initials{ font-size: 1.6rem; font-weight: 700; color: var(--text-primary); }
/* organizer headshots run 50% larger than the shared .card default — card top padding (22px)
   is untouched, so the gap above the headshot stays the same; the card just grows to fit. */
.organizer-card .avatar{ width: 144px; height: 144px; }
.organizer-card .avatar .initials{ font-size: 2.4rem; }
.organizer-card .avatar .placeholder-initials{ font-size: 0.93rem; }
/* recruitment card: same big-avatar/flex-column shell as a real organizer card, but no
   certified stripe, so restore the card's normal bottom padding and let the "Become an
   Organizer" button (not the whole card) be the clickable element, pinned toward the bottom
   via margin-top:auto the same way the stripe is on real organizer cards. */
.card.organizer-card.organizer-recruit-card{ padding-bottom: 22px; overflow: visible; cursor: default; }
.organizer-recruit-card .btn{ margin-top: auto; }
/* expanded views temporarily disabled (see EXPANDED_VIEWS_ENABLED in main.js) — cards render
   without their usual click-through, so drop the pointer cursor that implies one. */
.card.organizer-card.no-link{ cursor: default; }
.card .avatar .placeholder-initials{
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.02em; text-align: center;
  line-height: 1.25; padding: 0 10px; color: var(--text-muted);
}
.card h3{ font-size: 1.05rem; margin-bottom: 4px; }
.card .role{ color: var(--text-secondary); font-size: 0.85rem; margin-bottom: 10px; }
.card .social-row{ display: flex; gap: 10px; justify-content: center; margin-top: 10px; }
/* All social/link icons here (globe + platform marks) are inline SVG with fill="currentColor",
   so they follow the anchor's `color` — var(--text-primary), a real palette token (brand brown in
   light mode, its warm off-white counterpart in dark), uniformly across the whole row. */
.card .social-row a{ width: 22px; height: 22px; color: var(--text-primary); transition: color 0.15s ease; }
.card .social-row a:hover{ color: var(--orange); }
.card .social-row svg{ width: 100%; height: 100%; }
/* organizer cards: no role label anymore, so the icon row sits closer to the name — give it
   more breathing room (bigger icons, wider gaps) sized against Michael Norton's 4-icon card. */
.organizer-card .social-row{ gap: 14px; margin-top: 14px; margin-bottom: 26px; }
.organizer-card .social-row a{ width: 28px; height: 28px; }
/* .modal doesn't share the .card class, so it needs its own copy of the same var(--text-primary)
   treatment above rather than inheriting it. */
.modal .social-row a{ color: var(--text-primary); transition: color 0.15s ease; }
.modal .social-row a:hover{ color: var(--orange); }
/* The globe reads visibly smaller than the platform icons even at identical width/height:100% box
   sizing — not a box-size difference, but the source SVG itself: the platform marks (simple-icons)
   are drawn edge-to-edge in their 24x24 viewBox, while the globe (Material Design's "public" glyph)
   has a built-in ~2px margin on every side (circle spans 2-22 of 24), so its actual drawn content
   only fills 20/24 of the box. Scaling by 24/20 = 1.2 makes the drawn circle's effective diameter
   match the platform icons' full-bleed fill — same "compensate an oddly-proportioned icon with a
   CSS scale" trick already used for the moon glyph in the theme toggle (see .theme-toggle-track
   .icon-moon above). Scoped to .icon-globe specifically (set in WEBSITE_ICON_SVG, js/main.js) so it
   never touches the platform marks, which don't have this padding issue. */
.card .social-row svg.icon-globe, .presenter-card .social-row svg.icon-globe, .modal .social-row svg.icon-globe{ transform: scale(1.2); }

/* presenters — speaker on the left, business branding on the right, side by side. Two business-
   branding modes (see data/presenters.js) sized to occupy the same total footprint so an
   image-only logo + nameplate and a name-included logo look balanced next to each other
   regardless of how a founder's logo happens to be built. Avatar sized to match the organizer
   headshots (144px) for visual consistency between the two "meet a person" card types. */
/* .presenter-card is always a plain <div> — the inner .presenter-card-link (not the whole card) is
   the real, crawlable <a> to the presenter's detail page when expanded views are enabled (same
   reasoning as .partner-card / .partner-logo-link: real navigation, not a JS modal, and kept
   separate from the social icons below so the two links never nest, which would be invalid HTML).
   When disabled, .presenter-card-link is just a plain <div> instead — reset the anchor defaults so
   it renders identically either way, and the recruit card (which has no .presenter-card-link at
   all, just its own inner .btn) is unaffected by any of this. */
.presenter-card{
  position: relative; background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--card-shadow); padding: 22px; text-align: center;
}
.presenter-card-link{ display: block; color: inherit; text-decoration: none; }
a.presenter-card-link{ cursor: pointer; }
.presenter-row{ display: flex; align-items: center; justify-content: center; gap: 20px; flex-wrap: nowrap; }
.presenter-person, .presenter-business{ display: flex; flex-direction: column; align-items: center; }
.avatar-wrap{ display: inline-block; margin-bottom: 14px; }
.presenter-card .avatar{
  width: 144px; height: 144px; border-radius: 50%; overflow: hidden; margin: 0;
  background: var(--bg-neutral); display: flex; align-items: center; justify-content: center;
}
.presenter-card .avatar img{ width: 100%; height: 100%; object-fit: cover; }
.presenter-card .avatar .initials{ font-size: 2.4rem; font-weight: 700; color: var(--text-primary); }
.presenter-card .avatar .placeholder-initials{
  font-size: 0.93rem; font-weight: 700; letter-spacing: 0.02em; text-align: center;
  line-height: 1.25; padding: 0 10px; color: var(--text-muted);
}
.presenter-card h3{ font-size: 1rem; margin-bottom: 2px; }
/* Calendar-style date badge (month header + big day number) standing in for the old
   "Presenting August 5" text label — same "AUG / 5" shape as a phone calendar app icon.
   Pinned to the top-left corner of the card itself, popping slightly outside it, which is the
   standard placement for this kind of badge on an event/presenter card.
   .date-badge-wrap is the positioned wrapper (top-left corner-pop, matching the old .date-badge
   position exactly) — it owns the absolute positioning so the whole thing can be a real <button>
   (data-calendar-btn) that's also the containing block for its own sibling tray. .date-badge
   itself is just the visual box now, no longer positioned on its own, since it's also reused
   as a plain non-interactive div on the recruit card (see .presenter-recruit-card below). */
.date-badge-wrap{
  position: absolute; top: -8px; left: -8px; z-index: 1; display: inline-block;
  transition: transform 0.15s ease;
}
/* Note: .date-badge-wrap (this span) and .action-btn (the <button> inside it) are two different
   elements — a compound selector like .date-badge-wrap.action-btn would never match either one.
   :hover here on the wrapper still fires correctly whenever the button/badge/plus inside it is
   hovered (hover state applies to an element whenever the pointer is over it or any descendant),
   and lifting the wrapper itself (rather than the button) is what keeps .calendar-plus — a
   sibling of the button inside this same wrapper — moving in lockstep with the badge. */
.date-badge-wrap:hover{ transform: translateY(-2px); }
/* This wrapper sits at the card's top-left corner, so its tray needs to grow rightward (left-
   anchored) — the generic .action-tray default (right:0) was never overridden here, so the tray
   grew leftward from an already-far-left anchor and spilled off the left edge of the viewport on
   a single-column mobile layout. js/actions.js's keepTrayOnScreen() is the general safety net for
   any placement; this static anchor just means it rarely needs to do anything here. */
.date-badge-wrap .action-tray{ left: -8px; right: auto; }
.date-badge{
  display: block; position: relative; width: 58px; border-radius: 8px; overflow: hidden;
  box-shadow: var(--card-shadow);
}
/* var(--card-shadow) is a dark shadow tuned for a light page behind it — cards elsewhere still
   read fine in dark mode since their --surface background already separates them from the page,
   but these badges float directly over a photo/page background with no surface color of their
   own, so a dark shadow has nothing to contrast against and the badge visually disappears. A light
   glow (no offset, just blur) gives them the same "lifted off the page" depth cue in dark mode. */
:root[data-theme="dark"] .date-badge{ box-shadow: 0 0 14px rgba(255,255,255,0.1); }
.date-badge-month{
  display: block; background: var(--orange); color: var(--white); font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; text-align: center; padding: 4px 0;
}
.date-badge-day{
  display: block; background: var(--white); color: var(--text-primary); font-size: 1.6rem; font-weight: 700;
  line-height: 1.3; text-align: center; padding: 2px 0 4px;
}
:root[data-theme="dark"] .date-badge-day{ background: var(--surface); color: var(--text-primary); }
/* Small "add to calendar" plus, overlapping the date badge's right edge — a sibling of .date-badge
   (not nested inside it) so it isn't clipped by .date-badge's own overflow:hidden (needed there to
   round the month-stripe/day-box pair into one badge shape). Fixed orange, not currentColor —
   matches the date badge's own fixed-orange month stripe regardless of theme. */
/* top/right shifted 2px down-right from dead-center so the plus glyph's own vertical bar (dead
   center of its 24-unit viewBox) lands exactly on the date badge's right edge, instead of sitting
   2px inside it — top uses calc() rather than touching the transform, since the spin keyframes
   below bake in this same translateY(-50%) and shouldn't need to change to match. */
.calendar-plus{ position: absolute; top: calc(50% + 2px); right: -8px; width: 16px; height: 16px; color: var(--orange); transform: translateY(-50%); }
/* Playful one-time spin, triggered at random 3-10s intervals by initPlusSpin() in js/actions.js
   (not a fixed-period CSS loop, since the ask was "random intervals," not "every N seconds").
   Keyframes re-assert translateY(-50%) throughout so the spin doesn't undo the icon's own
   vertical centering on the badge's right edge. */
@keyframes calendar-plus-spin{
  from{ transform: translateY(-50%) rotate(0deg); }
  to{ transform: translateY(-50%) rotate(360deg); }
}
.calendar-plus.spin{ animation: calendar-plus-spin 0.6s ease-in-out; }
/* stroke on top of the fill thickens the plus by ~1 real px (stroke-width is in the icon's own
   24-unit viewBox, and it renders at 16px, so 1px on screen ≈ 1.5 user units here). */
.calendar-plus svg{ width: 100%; height: 100%; display: block; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3)); }
.calendar-plus svg path{ stroke: currentColor; stroke-width: 1.5; }
:root[data-theme="dark"] .calendar-plus svg{ filter: drop-shadow(0 0 5px rgba(255,255,255,0.35)); }
/* Share arrow — new top-right corner badge (mirrors .date-badge-wrap's corner-pop on the opposite
   side; used to be the .calendar-badge slot before this redesign moved calendar onto the date
   badge itself). Fixed orange (via currentColor + color:var(--orange), same as every other
   currentColor icon in the codebase — not theme-reactive, matching the date badge's own fixed
   orange month stripe) and the same drop-shadow weight as the organizer cards' certified badge
   (.badge-img) — both small badge-style icons floating over a photo/card edge. Shared with
   .profile-share-badge (presenter detail pages) below, same icon/sizing, different placement. */
.share-badge{ position: absolute; top: -8px; right: -8px; z-index: 1; }
.share-badge .action-btn, .profile-share-badge .action-btn{
  display: flex; align-items: center; justify-content: center; transition: transform 0.15s ease;
  color: var(--orange);
}
.share-badge .action-btn:hover, .profile-share-badge .action-btn:hover{ transform: translateY(-2px); }
.share-badge .action-btn svg, .profile-share-badge .action-btn svg{
  height: 34px; width: auto; display: block;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}
:root[data-theme="dark"] .share-badge .action-btn svg,
:root[data-theme="dark"] .profile-share-badge .action-btn svg{
  filter: drop-shadow(0 0 8px rgba(255,255,255,0.3));
}
/* "Hey, look — share me over there!" — a one-time wave, rotating on its own center axis like a
   hand greeting, triggered once by initShareNod() (js/actions.js) via IntersectionObserver when
   the icon scrolls to ~20% visible. Nudges the icon itself, not the button, so it doesn't fight
   the button's own hover-lift transform. transform-box:fill-box makes "center" mean the icon's own
   visual center rather than the SVG viewport's origin. */
@keyframes share-arrow-nod{
  0%, 100%{ transform: rotate(0deg); }
  20%{ transform: rotate(-14deg); }
  40%{ transform: rotate(12deg); }
  60%{ transform: rotate(-9deg); }
  80%{ transform: rotate(6deg); }
}
.share-badge .action-btn svg.nod, .profile-share-badge .action-btn svg.nod{
  animation: share-arrow-nod 0.9s ease-in-out;
  transform-box: fill-box;
  transform-origin: center;
}
.share-badge .action-tray{ right: -8px; }
/* recruitment card: no real date yet, so both the month stripe and day cell show "?" instead of
   a real month/day — same two-part badge shape as a real card, just flagged as TBD. Card itself
   drops the two-column presenter-row for a simple stacked layout (like the organizer recruit
   card), with the button pinned toward the bottom via margin-top:auto. */
.presenter-recruit-card{ display: flex; flex-direction: column; align-items: center; cursor: default; }
.presenter-recruit-card .btn{ margin-top: auto; }
.presenter-brand{
  /* min-height (not a fixed height) so a mark logo sized up via markHeight (see main.js) can push
     this taller without being squeezed by flex-shrink — wordmark logos still land on exactly
     144px same as before, since they have no nameplate underneath eating into the budget. */
  min-height: 144px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px;
}
.presenter-brand.mark img{ flex-shrink: 0; }
.presenter-brand.mark img{ max-height: 70px; width: auto; }
/* Nameplate color is per-business (set inline via --nameplate-color-light/-dark, see
   renderPresenters() in main.js) so it can echo each brand's own palette — a single fixed hex
   can't pass WCAG contrast against both a white card and this site's dark --surface at once, so
   businesses that want a themed color supply both variants; the --text-primary fallback keeps any
   future mark presenter legible even if only one (or neither) is set. */
.presenter-brand.mark .nameplate{ line-height: 1.15; max-width: 100%; color: var(--nameplate-color-light, var(--text-primary)); }
:root[data-theme="dark"] .presenter-brand.mark .nameplate{ color: var(--nameplate-color-dark, var(--text-primary)); }
.presenter-brand.wordmark img{ max-height: 144px; max-width: 100%; width: auto; object-fit: contain; }
/* Social icons on the presenter card itself, not just the detail page — only shows for presenters
   with real confirmed links (data/presenters.js `social`); no row at all if empty. Same icon
   sizing/hover language as .partner-card .social-row. */
.presenter-card .social-row{ display: flex; gap: 10px; justify-content: center; margin-top: 14px; }
.presenter-card .social-row a{
  width: 22px; height: 22px; display: flex; align-items: center; justify-content: center;
  color: var(--text-primary); transition: color 0.15s ease;
}
.presenter-card .social-row a:hover{ color: var(--orange); }
.presenter-card .social-row a svg{ width: 100%; height: 100%; }
.presenter-card .tagline{ margin-top: 22px; color: var(--text-secondary); font-size: 0.85rem; font-style: italic; }

/* individual presenter profile page (e.g. presenter-sylvia-crabtre.html) */
.profile-header{ text-align: center; margin-bottom: 40px; }
/* headshot + business logo side by side, mirroring the card's person/business pairing. Logo
   isn't circle-cropped like the headshot — logos aren't drawn to survive that, so it just gets
   a same-ish footprint box with object-fit:contain instead. Capped at the same 680px max-width as
   .profile-bio directly below (and centered the same way, margin:0 auto, inside the same .wrap
   padding) so the two boxes are always pixel-identical in rendered width at any viewport — that's
   what lets the badges below anchor to this row's own edges and land exactly on .profile-bio's
   edges "for free," with no separate calc()/vw math needed to track the bio's width. */
.profile-images{
  position: relative;
  max-width: 680px; margin: 0 auto 18px;
  display: flex; align-items: center; justify-content: center; gap: 28px; flex-wrap: wrap;
}
/* Detail-page badges (renderPresenterProfileBadges() in js/main.js) — no card border to pin these
   to like the grid card has. Anchored to .profile-images' own left/right edges (which, per above,
   always match .profile-bio's edges) and vertically centered on the row — at full desktop width
   this puts them well clear of the headshot/logo, aligned with the text box below instead. As the
   viewport narrows, .profile-images (and .profile-bio with it) shrinks fluidly, so the badges'
   anchor points move inward too — "squeezing in" exactly as asked, since they're pinned to a box
   that's shrinking, not a fixed pixel offset. Once the row gets narrow enough that its edges land
   inside where the (by-then-stacked) avatar/logo sit, the badges naturally end up layered over
   them instead of drifting off past them — still guaranteed on-screen at any width, since the box
   they're anchored to always fits the viewport by construction (position:absolute takes them out
   of flow entirely, so they never affect the avatar/logo's own flex-wrap row count either). */
.profile-date-badge, .profile-share-badge{ position: absolute; top: 50%; transform: translateY(-50%); z-index: 1; }
.profile-date-badge{ left: 0; }
.profile-share-badge{ right: 0; }
.profile-date-badge .action-btn:hover{ transform: translateY(-2px); }
.profile-date-badge .action-tray{ left: 0; right: auto; }
.profile-share-badge .action-tray{ right: 0; left: auto; }
.profile-avatar{
  width: 160px; height: 160px; border-radius: 50%; overflow: hidden; margin: 0;
  box-shadow: var(--card-shadow);
}
.profile-avatar img{ width: 100%; height: 100%; object-fit: cover; }
.profile-logo{ width: 160px; height: 160px; display: flex; align-items: center; justify-content: center; }
.profile-logo img{ max-width: 100%; max-height: 160px; object-fit: contain; }
/* partner profile pages: one logo image only, no headshot, so it stands alone centered. Same
   680px-cap-plus-inner-box split as .profile-images above: .profile-logo-solo is the wide
   positioning box (matches .profile-bio's edges, for the same share badge below to anchor to),
   .profile-logo-solo-img is the actual visual logo footprint, unchanged at 220x160. */
.profile-logo-solo{ position: relative; max-width: 680px; margin: 0 auto 18px; display: flex; justify-content: center; }
.profile-logo-solo-img{ width: 220px; height: 160px; display: flex; align-items: center; justify-content: center; }
.profile-logo-solo-img img{ max-width: 100%; max-height: 160px; object-fit: contain; }
.profile-header h1{ font-size: 1.8rem; margin-bottom: 6px; }
.profile-business{ color: var(--text-secondary); font-size: 1.05rem; margin-bottom: 18px; }
.profile-social-row{ display: flex; gap: 16px; justify-content: center; }
.profile-social-row a{ display: block; width: 30px; height: 30px; color: var(--text-primary); transition: color 0.15s ease; }
.profile-social-row a:hover{ color: var(--orange); }
.profile-social-row svg{ width: 100%; height: 100%; }
.profile-bio{ max-width: 680px; margin: 0 auto; }
.profile-bio p{ line-height: 1.7; margin-bottom: 18px; }

/* The 1MC closing question, made permanent. Deliberately set apart from the bio
   rather than reading as another paragraph of it: the bio is about who somebody
   is, this is a request addressed to the reader, and a visitor who skims should
   still land on it. Matches .profile-bio's measure so the column edge is
   unbroken. */
.community-ask{ max-width: 680px; margin: 28px auto 0; }
.community-ask h2{
  font-size: 1rem;
  font-weight: 650;
  margin: 0 0 10px;
  color: var(--text-secondary);
}
.community-ask blockquote{
  margin: 0;
  padding: 16px 20px;
  background: var(--surface);
  border-left: 3px solid var(--orange);
  border-radius: 8px;
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--text-primary);
}

/* .partner-card is always a plain <div> — the logo, not the whole card, is the real crawlable <a>
   to the partner's detail page (same reasoning as .presenter-card: real navigation, not a JS
   modal). Kept separate from the social icons below so the two links never nest (invalid HTML)
   and each icon keeps its own working href. */
.partner-card{
  position: relative;
  background: var(--white); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 24px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 150px; text-align: center;
}
.partner-card img{ max-height: 70px; width: auto; margin-bottom: 10px; }
.partner-logo-link{ display: block; }
/* open partner slot — no real logo yet, shown instead of an <img> (see PARTNERS in
   data/partners.js, logo:null). Sized to roughly match a real logo's footprint. */
.partner-logo-placeholder{
  display: flex; align-items: center; justify-content: center;
  width: 140px; height: 70px; margin-bottom: 10px; padding: 0 12px;
  border: 1.5px dashed var(--text-muted); border-radius: 6px;
  color: var(--text-muted); font-size: 0.8rem; font-weight: 600; text-align: center;
}
/* Inside .partner-card (the homepage grid) the surrounding background is permanently white — see
   the .partner-card comment block above — so this placeholder needs a fixed color there too. Left
   theme-aware everywhere else (e.g. the solo detail-page version), where it sits on the normal
   page background and var(--text-muted) is correct. */
.partner-card .partner-logo-placeholder{ border-color: #726b63; color: #726b63; }
.profile-logo-solo-img .partner-logo-placeholder{ width: 100%; height: 100%; margin-bottom: 0; font-size: 0.95rem; }
.partner-card h3{ font-size: 1rem; margin: 4px 0 0; color: var(--brown); }
.partner-card .role{ color: #6b6259; font-size: 0.82rem; }
/* .partner-card's background is permanently var(--white) (see the --white token comment near the
   top of this file) — it never goes dark, so unlike .card/.presenter-card, everything inside it
   must use fixed colors instead of the theme-aware --text-* tokens. Using a theme token here made
   the icons and tagline go light-on-white and nearly invisible in dark mode (reported 2026-07-28,
   worst on the website globe icon since it has no img-invert filter to (mis)compensate). */
.partner-card .tagline{ color: #6b6259; font-size: 0.85rem; font-style: italic; margin-top: 8px; }
.partner-card .social-row{ display: flex; gap: 10px; justify-content: center; margin-top: 10px; }
.partner-card .social-row a{ width: 22px; height: 22px; color: var(--brown); transition: color 0.15s ease; }
.partner-card .social-row a:hover{ color: var(--orange); }
.partner-card .social-row a svg{ width: 100%; height: 100%; }
.partner-card .social-row svg.icon-globe{ transform: scale(1.2); }
/* open-slot social icons: grayed out and unclickable (no href at all — a <span>, not an <a>), just
   to signal to a prospective partner that they'd get real, working links here. Fixed color for the
   same reason as .partner-card .social-row a above — the card they sit on never goes dark. */
.social-icon-disabled{ display: inline-block; width: 22px; height: 22px; color: #9a9186; opacity: 0.32; cursor: not-allowed; }
.social-icon-disabled svg{ width: 100%; height: 100%; }
.social-icon-disabled svg.icon-globe{ transform: scale(1.2); }

.host-org{
  display: flex; align-items: center; justify-content: center;
  margin-top: 36px; margin-bottom: 36px; text-align: left;
}
.host-org-link{
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  text-decoration: none; color: inherit;
}
.host-org img{ height: 56px; width: auto; }
.host-org .label{ font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-secondary); }
.host-org .name{ font-weight: 700; font-size: 1.1rem; }

/* venue */
.venue-grid{ display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 32px; align-items: start; }
@media (max-width: 860px){ .venue-grid{ grid-template-columns: 1fr; } }
.venue-name{ font-size: 1.7rem; margin-bottom: 16px; }
.venue-facts{ display: grid; gap: 14px; margin-bottom: 20px; }
.venue-facts .fact strong{ display: block; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--orange-link); }
.venue-images{ display: grid; gap: 14px; }
.venue-images img{ border-radius: var(--radius); box-shadow: var(--card-shadow); }
.venue-images .qr-row{ display: flex; gap: 14px; align-items: center; }
/* QR: 50% bigger than the old shared 120px (was easier to miss the corner detail at 120px);
   no expand-icon overlay on it — a graphic sitting near the code makes it harder for a phone
   camera to lock onto the pattern cleanly. Neighborhood map: 25% bigger than the old 120px. */
.venue-images .qr-row .qr-image img{ max-width: 180px; }
.venue-images .qr-row .neighborhood-image img{ max-width: 150px; }
.expandable-img{ cursor: zoom-in; transition: opacity 0.15s ease, transform 0.15s ease; display: block; }
.expandable-img:hover{ opacity: 0.85; transform: scale(1.01); }
.expandable-media{ position: relative; display: inline-block; line-height: 0; }
.expandable-media .expand-icon{
  position: absolute; top: 8px; right: 8px; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.55); color: #fff; border-radius: 6px; pointer-events: none;
}
.expandable-media .expand-icon svg{ width: 16px; height: 16px; }

/* placeholder page body */
.placeholder-note{
  max-width: 560px; margin: 0 auto; text-align: center; padding: 60px 24px;
  background: var(--bg-neutral); border-radius: var(--radius);
}
.placeholder-note h2{ margin-bottom: 10px; }
.placeholder-note p{ color: var(--text-secondary); line-height: 1.6; }

/* apply-to-present page */
.apply-hero .section-head{ max-width: 720px; }
.apply-steps{
  list-style: none; margin: 0 auto; padding: 0; max-width: 640px;
  display: grid; gap: 18px;
}
.apply-steps li{
  display: flex; gap: 18px; align-items: flex-start;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 20px 22px;
}
.apply-steps .step-num{
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%;
  background: var(--orange); color: var(--white); font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.apply-steps strong{ display: block; margin-bottom: 4px; }
.apply-steps p{ margin: 0; color: var(--text-secondary); font-size: 0.92rem; line-height: 1.5; }

.apply-expectations{
  list-style: none; margin: 0 auto; padding: 0; max-width: 720px; display: grid; gap: 12px;
}
.apply-expectations li{
  position: relative; padding-left: 26px; line-height: 1.6; color: var(--text-primary);
}
.apply-expectations li::before{
  content: "";
  position: absolute; left: 0; top: 0.55em; width: 8px; height: 8px;
  border-radius: 50%; background: var(--orange);
}

.apply-cta{ text-align: center; }
.apply-cta h2{ margin-bottom: 10px; }
.apply-cta p{ max-width: 560px; margin: 0 auto 24px; color: var(--text-secondary); line-height: 1.6; }

/* partnerships / become-an-organizer pages */
.benefit-grid{
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px;
}
.benefit-card{
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 24px;
}
.benefit-card h3{ font-size: 1.05rem; margin-bottom: 8px; }
.benefit-card p{ margin: 0; color: var(--text-secondary); font-size: 0.92rem; line-height: 1.55; }

/* press page */
.press-list{ display: grid; gap: 16px; max-width: 760px; margin: 0 auto; }
.press-empty{
  text-align: center; color: var(--text-secondary); background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--card-shadow); padding: 32px; max-width: 760px; margin: 0 auto;
}
.press-item{
  position: relative; background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 20px 24px;
}
/* PDF/TXT badges are separate links from the card's own title/summary link below — kept as
   siblings, not nested, since an <a> can't contain another <a> (same reasoning as
   .presenter-card-link vs. its social-row icons). */
.press-badges{ position: absolute; top: 14px; right: 16px; display: flex; gap: 6px; }
.press-badge{
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 20px; background: var(--bg-neutral); color: var(--text-secondary);
  text-decoration: none; transition: color 0.15s ease;
}
.press-badge:hover{ color: var(--orange-link); }
.press-item-link{ display: block; text-decoration: none; color: inherit; padding-right: 70px; }
.press-item .press-date{ font-size: 0.78rem; color: var(--orange-link); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
.press-item h3{ font-size: 1.05rem; margin-bottom: 6px; }
.press-item p{ margin: 0; color: var(--text-secondary); font-size: 0.92rem; line-height: 1.5; }

.press-contact-card{
  max-width: 620px; margin: 0 auto; background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--card-shadow); padding: 28px 30px; text-align: center;
}
.press-contact-card p{ margin: 0 0 10px; line-height: 1.6; }
/* gentle nudge on the Apply to Present page — attend as a guest before applying, not a hard gate. */
.attend-first-card{
  max-width: 620px; margin: 0 auto; background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--card-shadow); padding: 28px 30px; text-align: center;
}
.attend-first-card h3{ font-size: 1.3rem; margin-bottom: 10px; }
.attend-first-card p{ color: var(--text-secondary); line-height: 1.6; margin-bottom: 20px; }
.press-contact-card .placeholder-text{ color: var(--text-secondary); font-style: italic; }
.press-note{ font-size: 0.85rem; color: var(--text-muted); }

.brand-kit-grid{
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 18px;
  max-width: 760px; margin: 0 auto;
}
.brand-kit-item{
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  background: var(--white); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 24px 16px; text-decoration: none; color: var(--brown); font-size: 0.85rem; font-weight: 700;
}
.brand-kit-item img{ height: 60px; width: auto; max-width: 100%; }
.brand-kit-item.dark{ background: var(--header-bar); color: var(--white); }

/* faq page */
.faq-list{ display: grid; gap: 12px; max-width: 760px; margin: 0 auto; }
.faq-item{
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 4px 24px;
}
.faq-item summary{
  cursor: pointer; padding: 18px 0; font-weight: 700; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.faq-item summary::-webkit-details-marker{ display: none; }
.faq-item summary::after{
  content: "+"; flex-shrink: 0; font-size: 1.4rem; font-weight: 400; color: var(--orange-link);
  line-height: 1;
}
.faq-item[open] summary::after{ content: "–"; }
.faq-item p{ margin: 0 0 20px; color: var(--text-secondary); line-height: 1.6; }
.faq-item p a{ color: var(--orange-link); }

/* ---------- footer ---------- */
.site-footer{ background: var(--header-bar); color: #e7e3dc; padding-top: 56px; }
.footer-cols{
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 40px;
  padding-bottom: 40px; border-bottom: 1px solid #4d4d4d;
}
@media (max-width: 780px){ .footer-cols{ grid-template-columns: 1fr; } }
.footer-cols h4{
  color: var(--white); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em;
  margin-bottom: 16px; font-family: 'Roboto', sans-serif; font-weight: 700;
}
/* Logo and icon row both take their width from the same source — 100% of their shared parent,
   .footer-logo — rather than one trying to match the other's independently-computed size. That
   means they're always the same width at any viewport for free: full-width on mobile (.footer-logo
   is the whole single-column footer row there), narrower on desktop (whatever the 3-column grid
   track gives it), no breakpoint-specific duplication needed for the "keep them matching" part.
   max-width keeps the whole block from sprawling absurdly wide on a big desktop monitor. */
.footer-logo{ max-width: 260px; }
.footer-logo img{ width: 100%; height: auto; margin-bottom: 28px; }
/* two explicit rows (see renderSocialLinks in main.js — first 5 items / remaining 4), rather
   than relying on flex-wrap to break wherever it naturally fits, so the grouping is deliberate:
   row 1 LinkedIn/Facebook/Instagram/X/TikTok, row 2 Meetup/Eventbrite/Luma/YouTube/Reddit. */
.footer-social{ display: flex; flex-direction: column; gap: 28px; width: 100%; }
/* justify-content:space-between (not a fixed gap) is what actually makes the row "fill the width"
   at any size — icon size stays a plain fixed value, since the row's own stretching does the work. */
.footer-social-row{ display: flex; gap: 10px; align-items: center; justify-content: space-between; }
.footer-social a{
  display: flex; align-items: center; justify-content: center;
  color: var(--white); transition: color 0.15s ease;
}
.footer-social a:hover{ color: var(--orange); }
/* Doubled from 20px — reported as feeling small/undersized on mobile even once properly spread
   out across the row. Applies at every breakpoint, not just mobile. */
.footer-social .icon{ display: block; width: 40px; height: 40px; }
.footer-social .icon svg{ width: 100%; height: 100%; fill: currentColor; display: block; }
/* align-items:flex-start (instead of the flex default, stretch) keeps each <ul> at its own
   natural height — otherwise the shorter right-hand list gets stretched to match the taller
   left-hand list, and CSS grid's default row-stretch spreads its 4 items out to fill that
   extra height instead of keeping the same 10px gap, breaking the row-to-row alignment. */
.footer-nav-cols{ display: flex; gap: 32px; align-items: flex-start; }
.footer-nav ul{ list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.footer-nav a{ color: #c9c4bd; text-decoration: none; font-size: 0.92rem; }
.footer-nav a:hover{ color: var(--orange); }
.footer-nav a.active{ color: var(--orange); font-weight: 700; }
.footer-email p{ color: #c9c4bd; font-size: 0.9rem; line-height: 1.6; margin-bottom: 14px; }
/* Mailchimp signup — restyled from Mailchimp's default "classic" embed (which we don't load;
   see the .md file the embed code came from) to match the site's own input/button language
   instead of Mailchimp's generic black-border Helvetica look. The <form>'s action/method/honeypot
   field are untouched — that's what actually submits to the list, no JS required. */
.mc-signup-form{ display: flex; flex-direction: column; gap: 12px; max-width: 260px; }
.mc-field-group{ display: flex; flex-direction: column; gap: 4px; }
.mc-field-group label{ font-size: 0.78rem; color: #c9c4bd; }
.mc-asterisk{ color: var(--orange); }
.mc-signup-form input[type="email"], .mc-signup-form input[type="text"]{
  width: 100%; padding: 11px 14px; border-radius: var(--radius); border: 1px solid #5c5652;
  background: #fff; color: var(--brown); font-family: 'Roboto', sans-serif; font-size: 0.9rem;
}
.mc-signup-form input:focus{ outline: 2px solid var(--orange); outline-offset: 1px; }
.mc-signup-form button{
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 24px; border-radius: 30px; border: 2px solid transparent;
  background: var(--orange); color: var(--on-orange); font-weight: 700; font-size: 0.9rem;
  font-family: 'Roboto', sans-serif; cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease;
  margin-top: 4px;
}
.mc-signup-form button:hover{ transform: translateY(-2px); box-shadow: inset 0 0 0 999px rgba(255,255,255,0.18); }
/* Required-fields legend deliberately sits after the button, not above the form like Mailchimp's
   default — per instruction, so it doesn't compete with the fields themselves for attention. */
.mc-required-note{ margin: 0; font-size: 0.75rem; color: #a39d92; }
.footer-bottom{
  text-align: center; padding: 20px 0; font-size: 0.82rem; color: #a39d92;
}
.footer-bottom p{ margin: 0; }
.footer-bottom p + p{ margin-top: 4px; }

/* ---------- modal (organizer / partner profiles) ---------- */
.modal-overlay{
  position: fixed; inset: 0; background: rgba(20,17,15,0.6);
  display: none; align-items: center; justify-content: center;
  padding: 20px; z-index: 1000;
}
.modal-overlay.open{ display: flex; }
.modal{
  position: relative; background: var(--surface); border-radius: var(--radius);
  max-width: 480px; width: 100%; max-height: 85vh; overflow-y: auto;
  padding: 40px 32px 32px; text-align: center; box-shadow: 0 20px 60px rgba(0,0,0,0.35);
}
.modal-close{
  position: absolute; top: 12px; right: 12px; width: 32px; height: 32px;
  border-radius: 50%; border: none; background: var(--bg-neutral); color: var(--text-primary);
  font-size: 1.2rem; line-height: 1; cursor: pointer;
}
.modal-close:hover{ background: var(--orange); color: var(--white); }
.modal .modal-avatar{
  width: 120px; height: 120px; border-radius: 50%; margin: 0 auto 16px; overflow: hidden;
  background: var(--bg-neutral); display: flex; align-items: center; justify-content: center;
}
.modal .modal-avatar img{ width: 100%; height: 100%; object-fit: cover; }
.modal .modal-avatar .initials{ font-size: 2.2rem; font-weight: 700; color: var(--text-primary); }
.modal .modal-badge{ width: 56px; height: auto; margin: 0 auto 12px; display: block; }
.modal h3{ font-size: 1.3rem; margin-bottom: 4px; }
.modal .role{ color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 16px; }
.modal .modal-copy{ color: var(--text-secondary); line-height: 1.6; margin-bottom: 20px; text-align: left; }
.modal .modal-logo{ max-height: 64px; width: auto; margin: 0 auto 16px; }
.modal .social-row{ display: flex; gap: 12px; justify-content: center; margin-bottom: 20px; }
.modal .social-row a{ width: 26px; height: 26px; }
.modal .social-row svg{ width: 100%; height: 100%; }

.modal.modal-image{
  max-width: 96vw; max-height: 96vh; width: auto; padding: 0;
  background: transparent; box-shadow: none; overflow: visible;
}
.modal.modal-image img{
  display: block; max-width: 96vw; max-height: 92vh; width: auto; height: auto;
  border-radius: 8px; box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.modal.modal-image .modal-close{
  top: -14px; right: -14px; background: var(--white); color: var(--brown);
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}

/* ---------------------------------------------------------------------------
   Past-presenter archive: browse controls and the archive card variant.

   Controls sit above the grid rather than in a sidebar — this page is one
   column at every breakpoint the site supports, so a sidebar would collapse to
   exactly this layout on a phone anyway.

   Tokens here match the rest of the file: --orange, --surface, --text-secondary,
   --radius. There is no --border token; borders are written literally, following
   .mc-signup-form above.
   --------------------------------------------------------------------------- */
.presenter-browse{
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 0 0 22px;
}
.browse-input{
  flex: 1 1 220px; min-width: 0;
  padding: 11px 14px; border-radius: var(--radius); border: 1px solid #5c5652;
  background: var(--surface); color: var(--text-primary);
  font-family: 'Roboto', sans-serif; font-size: 0.9rem;
}
.browse-input:focus-visible{ outline: 2px solid var(--orange); outline-offset: 1px; }
.browse-select{ flex: 0 0 auto; cursor: pointer; }
.browse-check{
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 0.9rem; color: var(--text-secondary); white-space: nowrap; cursor: pointer;
}
.browse-count{
  margin-left: auto; font-size: 0.86rem; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.browse-empty{
  margin: 0 0 22px; padding: 18px; text-align: center;
  color: var(--text-secondary); background: var(--surface);
  border-radius: var(--radius); box-shadow: var(--card-shadow);
}
/* The founder's role at the business being presented. Sits under their name
   rather than beside the business, because it describes the person's relationship
   to the company — and a second venture can carry a different one. Rendered only
   when set, so cards without it keep exactly the spacing they have today. */
.presenter-person .presenter-role{
  font-size: 0.8rem; color: var(--text-secondary);
  margin-top: 2px; line-height: 1.3;
}

/* An archive entry is a presenter card without the invitation: no calendar
   button, and a line saying when it happened so it cannot be mistaken for
   something upcoming. */
.presenter-card.past .presented-on{
  font-size: 0.8rem; color: var(--text-secondary);
  margin: 2px 0 6px; letter-spacing: 0.02em;
}
.presenter-card[hidden]{ display: none; }
@media (max-width: 640px){
  .browse-count{ margin-left: 0; width: 100%; }
}

/* The archive's server-rendered content: what a crawler, a link preview, and a
   reader without JavaScript get. renderPastPresenters() replaces it with the
   interactive cards on load, so in a normal browser it is visible only for the
   moment before the script runs — styled anyway, because "only briefly visible"
   and "never visible" are different claims and one of them is false. */
.archive-fallback{
  list-style: none; margin: 0; padding: 0;
  /* Two columns, matching the cards that replace it — otherwise the page
     reflows the moment the script runs, which is the one thing a fallback
     should never cause. */
  display: grid; gap: 18px; grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 700px){
  .archive-fallback{ grid-template-columns: minmax(0, 1fr); }
}
.archive-fallback .archive-entry{
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--card-shadow); padding: 20px; text-align: left;
}
.archive-fallback h3{ margin: 0 0 4px; font-size: 1.05rem; }
.archive-fallback .archive-business{
  margin: 0 0 2px; font-size: 0.9rem; color: var(--text-secondary);
}
.archive-fallback .archive-date{
  margin: 0 0 8px; font-size: 0.8rem; color: var(--text-secondary);
}
.archive-fallback p:last-child{ margin: 0; font-size: 0.92rem; }
