:root {
  --blue: #003cff;
  --blue-hover: #116dff;
  --black: #111111;
  --gray: #eaeaea;
  --gray-light: #f4f4f4;
  --text: #2a2a2a;
  --muted: #555;
  /* LinkedIn's own brand blue, deliberately not --blue: the mark is
     recognisable by its colour, and recolouring it to the site palette makes it
     read as a generic glyph. */
  --linkedin: #0a66c2;
  --linkedin-hover: #004182;
  --error: #c0392b;
  --ok: #1a7d2e;
  --max: 1180px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: 'Spinnaker', sans-serif;
  color: var(--text);
  background: #fff;
  line-height: 1.6;
}

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

a { color: var(--blue); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--blue);
  color: #fff;
  padding: 12px 20px;
  z-index: 200;
}
.skip-link:focus { left: 0; }

/* ===== Header ===== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #fff;
  border-bottom: 1px solid var(--gray);
}
.nav {
  position: relative;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 28px;
  height: 84px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

/* The wordmark sits dead centre of the viewport, so it is taken out of the flow
   rather than given a grid column: the menu button and the CTA are different
   widths, and a centre computed from the space between them is visibly off. */
.logo {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Without max-content the box is shrink-to-fit against the space from the
     centre line to the right edge — half the viewport — and the global
     img { max-width: 100% } quietly trims the wordmark to that instead of the
     width set below. */
  width: max-content;
}
.logo img { width: 236px; height: auto; }

.nav-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 8px 4px;
  cursor: pointer;
  color: var(--black);
  font-family: 'Oswald', sans-serif;
  font-size: 15px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.nav-toggle:hover { color: var(--blue); }
.nav-toggle-box {
  position: relative;
  display: block;
  width: 24px;
  height: 16px;
}
/* Three bars from one element: the middle is the box itself, the outer two are
   its pseudo-elements, which is also what lets them fold into an X on open. */
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  position: absolute;
  left: 0;
  width: 24px;
  height: 2px;
  background: currentColor;
  transition: transform .18s, opacity .18s;
}
.nav-toggle-bars { top: 7px; }
.nav-toggle-bars::before { content: ''; top: -7px; }
.nav-toggle-bars::after { content: ''; top: 7px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after { transform: translateY(-7px) rotate(-45deg); }

.nav-cta {
  margin-left: auto;
  background: var(--blue);
  color: #fff;
  padding: 11px 26px;
  border-radius: 4px;
  font-family: 'Oswald', sans-serif;
  font-size: 15px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background .15s;
}
.nav-cta:hover { background: var(--blue-hover); }

/* The panel is closed until the button opens it. Without JavaScript it never
   opens — the footer carries the same five links in plain markup, so the site
   stays navigable either way. */
.nav-links {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0;
  padding: 10px 28px 18px;
  list-style: none;
  background: #fff;
  border-bottom: 1px solid var(--gray);
  box-shadow: 0 12px 24px rgba(0, 0, 0, .07);
}
.nav.open .nav-links { display: block; }
.nav-links li + li { border-top: 1px solid var(--gray-light); }
.nav-links a {
  display: block;
  padding: 14px 0;
  text-decoration: none;
  color: var(--black);
  font-size: 20px;
  letter-spacing: .3px;
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { color: var(--blue); }

/* ===== Hero ===== */
.hero {
  position: relative;
  min-height: 560px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 90px 24px;
  /* The live site paints this photo at opacity .18 over white; an 82%-white
     wash over the image is the same result in one layer. */
  background-color: #fff;
  background-image:
    linear-gradient(rgba(255,255,255,.82), rgba(255,255,255,.82)),
    url('/assets/hero-event.jpg');
  background-size: cover;
  background-position: center;
}
.hero-content {
  position: relative;
  max-width: 860px;
}
.hero-title {
  font-family: 'Spinnaker', sans-serif;
  font-weight: 400;
  font-size: clamp(30px, 4.4vw, 46px);
  line-height: 1.25;
  color: var(--black);
  margin: 0;
}
.divider {
  width: 44px;
  height: 3px;
  background: var(--black);
  margin: 34px auto;
}
.hero-lead,
.hero-sub {
  font-size: 21px;
  color: #333;
  margin: 0;
}
.hero-lead { margin-bottom: 26px; }

/* ===== Stats ===== */
.stats {
  max-width: var(--max);
  margin: 0 auto;
  padding: 70px 24px 80px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  text-align: center;
}
.stat-num {
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: clamp(48px, 6.4vw, 96px);
  line-height: 1;
  color: var(--blue);
  letter-spacing: -1px;
  /* The figures count up from zero when the band scrolls into view, so every
     digit is redrawn a few dozen times on the way. Fixed-width figures keep
     that from jiggling the number about as narrow and wide digits trade
     places. */
  font-variant-numeric: tabular-nums;
}
.stat-label {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 18px;
  letter-spacing: .5px;
  color: var(--black);
  margin-top: 14px;
}

/* ===== Section shared ===== */
.section-title {
  font-family: 'Spinnaker', sans-serif;
  font-weight: 400;
  font-size: clamp(28px, 3.4vw, 40px);
  text-align: center;
  color: var(--black);
  margin: 0 0 50px;
}
.team, .events, .new-members, .sponsors, .join { padding: 80px 24px; }
/* The bands alternate all the way down — team, events, new members, sponsors,
   join — so every section has an edge. Two greys in a row read as one long
   section with a heading stranded in the middle of it. */
.team, .new-members, .join { background: var(--gray-light); }

/* ===== Team ===== */
.team-grid {
  max-width: 860px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 60px;
  text-align: center;
}
.member-photo {
  width: 270px;
  height: 264px;
  margin: 0 auto 22px;
  object-fit: cover;
  background-color: #dcdee2;
}
.member-name {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-size: 24px;
  color: var(--black);
  margin: 0 0 10px;
}
.member-role {
  color: var(--muted);
  font-size: 17px;
  margin: 0;
}

/* ===== Past Events ===== */
/* 50 founders, so the grid auto-fits rather than fixing a column count. */
.events-grid {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 44px 28px;
  text-align: center;
}
.speaker { margin: 0; }
/* 4:3 at every width, with only the box the grid gives it changing. The frame
   used to go square on a phone, and a square keeps only the middle 75% of a 4:3
   photo's width: the same person, framed fine on a desktop, arrived on a phone
   with an ear or half a shoulder cropped away. */
.speaker-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  margin: 0 auto 16px;
  object-fit: cover;
  background-color: #dcdee2;
}
.speaker-name {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-size: 20px;
  color: var(--black);
  margin: 0 0 8px;
  line-height: 1.25;
}
.speaker-role { margin: 0; color: var(--muted); font-size: 15px; }
.speaker-company { margin: 4px 0 0; color: var(--black); font-weight: bold; font-size: 15px; }

/* The whole card is the target, so the button is laid over it rather than
   drawn: the photo and the caption keep their own markup and styling, and the
   click lands on a real button wherever on the card it falls. */
.speaker { position: relative; }
.speaker-open {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: 2px;
}
.speaker-open:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 6px;
}
/* The photo lifts a little under the pointer — enough to say the card does
   something, on the element the cursor is already over. */
.speaker-photo { transition: transform .25s ease, box-shadow .25s ease; }
.speaker:hover .speaker-photo,
.speaker:focus-within .speaker-photo {
  transform: translateY(-4px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .16);
}
@media (prefers-reduced-motion: reduce) {
  .speaker-photo { transition: none; }
  .speaker:hover .speaker-photo,
  .speaker:focus-within .speaker-photo { transform: none; }
}

/* ===== Speaker card ===== */
.speaker-dialog {
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 0;
  border-radius: 4px;
  overflow: auto;
  background: #fff;
  color: var(--black);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .3);
}
.speaker-dialog::backdrop { background: rgba(0, 0, 0, .62); }
.speaker-dialog-photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  /* The photo is the point of the card, but not at the cost of pushing what is
     known about the speaker below the fold on a laptop. A 4:3 frame gets the
     full height it asks for on a tall window and is cropped on a short one. */
  max-height: 44vh;
  object-fit: cover;
  background-color: #dcdee2;
}
/* Over the photo, where there is always something behind it to sit on. The
   white disc is what keeps it legible on a pale corner. */
.speaker-dialog-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--black);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.speaker-dialog-close:hover { background: #fff; }
.speaker-dialog-body { padding: 26px 28px 30px; }
.speaker-dialog-name {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-size: 26px;
  margin: 0 0 8px;
  line-height: 1.2;
}
.speaker-dialog-role { margin: 0; color: var(--muted); font-size: 16px; }
.speaker-dialog-company { margin: 4px 0 0; font-weight: bold; font-size: 16px; }
/* Label above value rather than beside it: "Stage when presenting" is a long
   label for a short answer, and putting the two side by side would either wrap
   the label or strand the answer far to the right. */
.speaker-facts {
  display: grid;
  gap: 18px 24px;
  margin: 24px 0 0;
  padding-top: 22px;
  border-top: 1px solid #e6e8ec;
}
/* Two to a line at every width, including a phone: the stages are a pair and
   stop being one the moment they are read a screen apart. */
.speaker-fact-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px 24px;
}
.speaker-fact { min-width: 0; }
.speaker-facts dt {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .5px;
  font-size: 12px;
  color: var(--muted);
}
.speaker-facts dd {
  margin: 6px 0 0;
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: 22px;
  line-height: 1.1;
  color: var(--blue);
}
.speaker-fact-note {
  display: block;
  margin-top: 4px;
  font-family: inherit;
  font-weight: normal;
  font-size: 13px;
  color: var(--muted);
}

/* ===== Sponsors ===== */
.sponsor-row {
  max-width: var(--max);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  justify-content: center;
}
.sponsor-row:empty { display: none; }
.sponsor-logo {
  margin: 0;
  width: 260px;
  height: 130px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
}
/* The link fills the tile so the whole logo is the target, not just the ink. */
.sponsor-logo a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  transition: opacity .15s;
}
.sponsor-logo a:hover { opacity: .7; }
.sponsor-logo img { max-height: 100%; width: auto; object-fit: contain; }

/* ===== Forms ===== */
.form { max-width: 640px; margin: 0 auto; }
.row.two {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.field { margin-bottom: 20px; }
.field label {
  display: block;
  margin-bottom: 8px;
  font-size: 15px;
  color: var(--black);
}
.field input,
.field textarea {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 16px;
  font-family: inherit;
  color: inherit;
  background: #fff;
}
.field textarea { resize: vertical; min-height: 130px; line-height: 1.6; }
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(0,60,255,.12);
}
.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: var(--error);
  box-shadow: 0 0 0 3px rgba(192,57,43,.10);
}
.field-error {
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--error);
  min-height: 0;
}
.field-error:empty { display: none; }

/* Honeypot: off-screen rather than display:none, which some bots skip. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.submit-btn {
  display: inline-block;
  background: var(--blue);
  color: #fff;
  border: 0;
  padding: 14px 46px;
  font-size: 17px;
  font-family: 'Oswald', sans-serif;
  letter-spacing: 1px;
  text-transform: uppercase;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
  transition: background .15s;
}
.submit-btn:hover { background: var(--blue-hover); }
.submit-btn:disabled { background: #8fa4e8; cursor: progress; }

.form-status { margin-top: 16px; font-size: 15px; }
.form-status.ok { color: var(--ok); }
.form-status.err { color: var(--error); }

.form-success {
  max-width: 640px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid var(--gray);
  border-left: 4px solid var(--blue);
  border-radius: 6px;
  padding: 32px 34px;
}
.form-success h3 {
  font-family: 'Spinnaker', sans-serif;
  font-weight: 400;
  font-size: 26px;
  color: var(--black);
  margin: 0 0 12px;
}
.form-success p { margin: 0 0 12px; font-size: 16px; }
.form-success p:last-child { margin-bottom: 0; }

/* ===== Standalone pages ===== */
.page { min-height: 60vh; }
.contact-section { background: var(--gray-light); }
.contact-lead {
  max-width: 640px;
  margin: -30px auto 40px;
  text-align: center;
  color: var(--muted);
  font-size: 17px;
}

/* ===== Members directory ===== */
.members-section { padding: 80px 24px; background: var(--gray-light); }
.members-lead {
  max-width: 640px;
  margin: -30px auto 34px;
  text-align: center;
  color: var(--muted);
  font-size: 17px;
}

.members-search { max-width: 560px; margin: 0 auto 44px; }
.members-search input {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 16px;
  font-family: inherit;
  color: inherit;
  background: #fff;
}
.members-search input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(0,60,255,.12);
}
.members-search input:disabled { background: #f7f7f7; cursor: progress; }
.members-count {
  margin: 12px 0 0;
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  /* Reserves its line so the grid doesn't jump when the count appears. */
  min-height: 24px;
}

/* Auto-fit rather than a fixed column count, like the speakers grid: the roster
   is over a thousand people and the page has to hold a phone and a wide desktop. */
.members-grid {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}
.member-card {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #fff;
  border: 1px solid var(--gray);
  border-radius: 6px;
  padding: 16px 18px;
}
.member-card-text { min-width: 0; flex: 1; }
.member-card-name {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  letter-spacing: .6px;
  text-transform: uppercase;
  font-size: 17px;
  line-height: 1.3;
  color: var(--black);
  margin: 0;
  overflow-wrap: anywhere;
}
.member-card-title {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.member-linkedin {
  flex: none;
  display: inline-flex;
  color: var(--linkedin);
  transition: color .15s;
}
.member-linkedin:hover,
.member-linkedin:focus-visible { color: var(--linkedin-hover); }

.members-empty {
  max-width: 560px;
  margin: 30px auto 0;
  text-align: center;
  color: var(--muted);
  font-size: 16px;
}

/* ===== New Members (homepage) ===== */
/* The directory's cards, twelve of them, faded out over a link to the rest — so
   the homepage says who has just joined without becoming a second roster. Only
   what differs from the directory is set here; the cards are the same component,
   rendered by lib/new-members.js the way public/members.js renders them.
   Selected through the section rather than by a class of their own so that the
   directory's own rules, further down this file, cannot outrank them. */

/* Whole rows at every width. Four columns here, then three, two and one as the
   page narrows, and twelve cards divides by all four. Fixed counts rather than
   the directory's auto-fill, which fits in as many as will go and leaves the
   remainder on the last row: a row with a gap in it says the group ran out of
   founders, which is the opposite of what the fade beneath it is for. Each
   breakpoint is the width at which the next column down would be too narrow to
   hold a name and a title. */
.new-members .members-grid { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1120px) { .new-members .members-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 860px) { .new-members .members-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 580px) { .new-members .members-grid { grid-template-columns: 1fr; } }

/* Twelve cards two abreast is six rows to scroll past to reach the button, and
   twelve in a single column is a page of its own. A narrow screen gets fewer,
   in counts that still fill their rows. The rest stay in the markup, and all of
   them are on the members page. */
@media (max-width: 860px) { .new-members .member-card:nth-child(n + 9) { display: none; } }
@media (max-width: 580px) { .new-members .member-card:nth-child(n + 7) { display: none; } }

/* A title is free text — some are two words, some are a sentence about a 5G
   private-network business. Clamped to two lines so the cards in a row stay the
   same height and the fade crosses them in a straight line. */
.new-members .member-card-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* When someone joined, under what they do. A label rather than a third line of
   prose: smaller than the title, spaced out and in capitals, so it is read as a
   tag on the card and never competes with the name or the title above it. */
.new-members .member-joined {
  margin: 7px 0 0;
  font-family: 'Oswald', sans-serif;
  font-weight: 500;
  font-size: 11px;
  line-height: 1.2;
  letter-spacing: 1px;
  text-transform: uppercase;
  /* Lighter than the title's --muted, and still past 4.5:1 on the card. */
  color: #767676;
}

/* The roster carries on past the bottom of the strip, and the fade is what says
   so. Measured in pixels rather than as a share of the grid so that it is the
   last row that fades whether the grid is four columns or one — a percentage
   would fade one row on the wide layout and three on the narrow. */
.new-members-fade {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 116px), rgba(0, 0, 0, .08));
  mask-image: linear-gradient(to bottom, #000 calc(100% - 116px), rgba(0, 0, 0, .08));
}
/* A LinkedIn link in the faded row is still a link, and tabbing onto something
   that cannot be seen is no way to meet it. Reaching the strip with a keyboard
   lifts the fade for as long as the focus is in there. */
.new-members-fade:focus-within {
  -webkit-mask-image: none;
  mask-image: none;
}

.new-members-more { margin: 22px 0 0; text-align: center; }
.new-members-cta {
  display: inline-block;
  background: var(--blue);
  color: #fff;
  padding: 14px 34px;
  border-radius: 4px;
  font-family: 'Oswald', sans-serif;
  font-size: 16px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-decoration: none;
  transition: background .15s;
}
.new-members-cta:hover { background: var(--blue-hover); }

/* Labels that belong to screen readers only — the search field is captioned by
   its own placeholder for everyone else. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.notfound {
  max-width: 620px;
  margin: 0 auto;
  padding: 110px 24px;
  text-align: center;
}
.notfound-logo { width: 220px; height: auto; margin: 0 auto 40px; }
.notfound h1 {
  font-family: 'Spinnaker', sans-serif;
  font-weight: 400;
  font-size: 32px;
  color: var(--black);
  margin: 0 0 12px;
}
.notfound p { color: var(--muted); margin: 0 0 26px; }

/* ===== Footer ===== */
.site-footer {
  background: var(--black);
  color: #fff;
  text-align: center;
  padding: 54px 24px;
}
/* The wordmark artwork is black, so it gets inverted on the dark footer. */
.footer-logo {
  width: 200px;
  height: auto;
  margin: 0 auto 20px;
  filter: invert(1);
}
.footer-nav {
  display: flex;
  gap: 26px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.footer-nav a { color: #ddd; text-decoration: none; font-size: 15px; }
.footer-nav a:hover { color: #fff; }
.footer-copy { color: #aaa; font-size: 14px; margin: 0; }

/* ===== Responsive ===== */
@media (max-width: 900px) {
  .stats { grid-template-columns: repeat(2, 1fr); row-gap: 46px; }
}
@media (max-width: 720px) {
  .speaker-dialog-body { padding: 22px 20px 26px; }
  .speaker-dialog-name { font-size: 22px; }
  .speaker-facts,
  .speaker-fact-row { gap: 16px 18px; }
  .nav { height: 64px; padding: 0 18px; gap: 12px; }
  .nav-toggle-label { display: none; }
  .nav-cta { padding: 8px 12px; font-size: 11px; letter-spacing: .4px; }
  .nav-links { padding: 6px 18px 14px; }
  .nav-links a { font-size: 17px; padding: 12px 0; }
  /* The wordmark is centred on the viewport while the CTA sits at the right
     edge, so it is the gap on that side — not the slack next to the menu
     button — that caps the width. 100vw - 164px is the width that keeps a 12px
     gap on that side; a roomier phone spends what it has, a 320px one holds at
     the floor instead. */
  .logo img { width: clamp(140px, calc(100vw - 164px), 220px); }
  .hero { min-height: 460px; padding: 64px 20px; }
  .hero-lead, .hero-sub { font-size: 18px; }
  .team, .events, .new-members, .sponsors, .join { padding: 60px 20px; }
  .team-grid { grid-template-columns: 1fr; gap: 46px; }
  .members-section { padding: 60px 20px; }
  .members-grid { grid-template-columns: 1fr; }
  .new-members-cta { width: 100%; padding: 14px 20px; font-size: 15px; }
  .events-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 40px 20px; }
  .sponsor-logo { width: 200px; height: 100px; }
  .speaker-name { font-size: 17px; }
  .row.two { grid-template-columns: 1fr; gap: 0; }
  .submit-btn { width: 100%; }
  .form-success { padding: 26px 22px; }
}

@media (max-width: 360px) {
  .nav { padding: 0 14px; }
  .nav-cta { padding: 7px 10px; font-size: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}
