/* ============================================================================
   GESDA ALUMNI PORTAL v3 — the page.
   v2, rearranged: the programme buttons under the lead, the map across the
   whole width with its note above it, then the filters and the list side
   by side underneath, and v5's footer. Built against designv2.1.md, in the
   style of experiences-page/v5: the same tokens, faces, topbar glass,
   totals ledger, map palette and footer.
   Loads after fonts.css and tokens.css.

   designv2.1 §0:
   1. Surface class — B, interactive tool. Class A tokens; {space.section}
      drops to {space.12} between blocks (§12). Loading, empty and error
      states exist for the list and the map.
   2. Theme — light. The footer is a local dark context (.theme-dark).
   3. Analytical claim — no. The map records where alumni are based, so
      §3.3 does not bind: the countries carry the action colour only.

   Band rhythm (§11.1): glass topbar → band-tinted intro → canvas explorer
   → band-deep footer.

   Layout: the page scrolls. From 980px the filters sit left of the list
   and stay in view (sticky) while the list scrolls past. Below that,
   one column: the map, the filters, the list.

   Recorded exceptions, to raise with the client:
   - §21 lists map styling as a known gap. The map takes v5's reach-map
     answer: land in a purple-100/050 mix, borders in the canvas, matching
     countries in the action colour, the picked one ringed in the orbit
     violet (map/alumni-map.html).
   - Topic pills are 36px tall; a ::before extends each one's hit area to
     the 44px of §13.2 without spreading the panel out.

   Naming: flat kebab-case, BEM-style elements. Every colour is a token.
   ========================================================================= */

/* --- page ---------------------------------------------------------------- */
html { scroll-padding-top: calc(var(--layout-topbar) + var(--space-4)); }

body {
  margin: 0;
  background: var(--color-canvas);
  color: var(--color-body);
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* The hidden attribute is only display:none in the UA stylesheet, so any
   author rule that sets display would silently override it. */
[hidden] { display: none !important; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

.wrap {
  max-width: var(--layout-container-max);
  margin: 0 auto;
  padding: 0 var(--space-6);
  box-sizing: border-box;
}

.skip-link {
  position: absolute; left: var(--space-4); top: -100px; z-index: 100;
  display: inline-flex; align-items: center; min-height: 48px; padding: 0 var(--space-8);
  border-radius: var(--radius-lg);
  background: var(--color-action-primary); color: var(--color-on-action);
  font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: var(--space-4); }
.skip-link:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }

/* --- buttons (§10.1), all five states ------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  box-sizing: border-box;
  min-height: 48px;
  padding: 0 var(--space-8);
  border: 0; border-radius: var(--radius-lg);
  font-family: var(--font-body);
  font-size: var(--type-button);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast), box-shadow var(--motion-fast);
}
.btn:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.btn:disabled { background: var(--purple-100); color: var(--color-muted); box-shadow: none; cursor: not-allowed; }
.btn--sm { min-height: 44px; padding: 0 var(--space-6); font-size: var(--type-body-sm); }

.btn--secondary {
  background: transparent;
  color: var(--color-action-primary);
  box-shadow: inset 0 0 0 1px var(--color-action-primary);
}
.btn--secondary:hover  { background: var(--color-canvas-tinted); }
.btn--secondary:active { background: var(--color-canvas-pressed); }
.btn svg {
  width: 12px; height: 12px;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
}

/* button-ghost: tertiary. No border or fill at rest. */
.btn-ghost {
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 0; border-radius: var(--radius-sm);
  background: none;
  color: var(--color-action-primary);
  font: 600 var(--type-body-sm) / 1.2 var(--font-body);
  cursor: pointer;
  transition: background-color var(--motion-fast);
}
.btn-ghost:hover  { background: var(--color-canvas-tinted); text-decoration: underline; }
.btn-ghost:active { background: var(--color-canvas-pressed); }
.btn-ghost:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; text-decoration: underline; }
.btn-ghost:disabled { color: var(--color-muted); opacity: 0.5; cursor: not-allowed; text-decoration: none; }

/* ============================================================================
   TOPBAR (§10.7) — v5's liquid glass, sticky. Logo left; the way back to the
   Experiences page right. No nav: the portal is one view.
   ========================================================================= */
.topbar {
  position: sticky; top: 0; z-index: 50;
  border-bottom: 1px solid var(--color-hairline-soft);
}
.topbar::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to bottom, var(--color-topbar-sheen), transparent 55%),
    var(--color-topbar);
  box-shadow: inset 0 1px 0 var(--color-topbar-sheen), var(--shadow-sm);
  -webkit-backdrop-filter: blur(24px) saturate(180%); backdrop-filter: blur(24px) saturate(180%);
}
.topbar__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  max-width: var(--layout-container-max);
  height: var(--layout-topbar);
  margin: 0 auto;
  padding: 0 var(--space-6);
  box-sizing: border-box;
}
.topbar__brand { display: inline-flex; border-radius: var(--radius-sm); }
.topbar__brand img { display: block; height: 52px; width: auto; }
.topbar__brand:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 4px; }

/* ============================================================================
   INTRO — band-tinted. The heading on the left, the totals on the right,
   set as v5's reach totals: figure beside label, one per row.
   ========================================================================= */
.intro {
  padding: var(--space-12) 0;
  background: var(--color-canvas-tinted);
}
.intro__frame {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  align-items: end;
  column-gap: var(--space-12);
  row-gap: var(--space-8);
}
.intro__title {
  margin: 0;
  font-size: var(--type-h1);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--color-ink);
}
.intro__lead {
  max-width: 56ch;
  margin: var(--space-4) 0 0;
  font-size: var(--type-lead);
  line-height: 1.65;
  color: var(--color-body);
}

/* The programme buttons: a single choice that sets what the whole page
   shows. All five states; pressed is the picked programme. A programme
   with no alumni in the data yet is disabled (and says so to screen
   readers). */
.programmes {
  display: flex; flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-6);
}
.programme {
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-canvas);
  box-shadow: inset 0 0 0 1px var(--color-hairline);
  color: var(--color-ink);
  font: 500 var(--type-body-sm) / 1.2 var(--font-body);
  cursor: pointer;
  transition: background-color var(--motion-fast), box-shadow var(--motion-fast), color var(--motion-fast);
}
.programme:hover { box-shadow: inset 0 0 0 1px var(--purple-300); }
.programme:active { background: var(--color-canvas-pressed); }
.programme:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.programme[aria-pressed="true"] {
  background: var(--color-action-primary);
  box-shadow: none;
  color: var(--color-on-action);
  font-weight: 600;
}
.programme[aria-pressed="true"]:hover { background: var(--color-action-primary-hover); }
.programme { position: relative; }   /* the tip hangs from it */
.programme[aria-disabled="true"],
.programme[aria-disabled="true"]:hover,
.programme[aria-disabled="true"]:active {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--color-hairline-soft);
  color: var(--color-muted);
  cursor: not-allowed;
}

/* "Coming soon", above a programme not yet available, on hover and on
   keyboard focus. It fades rather than hides, so screen readers always
   read it as part of the button's name. */
.programme__tip {
  position: absolute; z-index: 2;
  left: 50%; bottom: calc(100% + var(--space-2));
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-ink);
  color: var(--color-canvas);
  font: 600 var(--type-caption) / 1.45 var(--font-body);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  translate: -50% var(--space-1);
  transition: opacity var(--motion-fast), translate var(--motion-fast);
}
.programme__tip::after {   /* the pointer down to the button */
  content: "";
  position: absolute;
  top: 100%; left: 50%;
  margin-left: calc(var(--space-1) * -1);
  border: var(--space-1) solid transparent;
  border-top-color: var(--color-ink);
}
.programme:is(:hover, :focus-visible) .programme__tip { opacity: 1; translate: -50% 0; }

.totals { margin: 0; }
.totals > div {
  display: flex; align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-hairline);
}
.totals > div:last-child { border-bottom: 1px solid var(--color-hairline); }
.totals dt {
  order: 1;   /* figure first on screen; dt stays first in the DOM */
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
/* Numerals in data: Space Grotesk's defined home (§4.2 data-label, §4.3). */
.totals dd {
  flex: none;
  min-width: 4ch;
  margin: 0;
  font-family: var(--font-accent);
  font-size: var(--type-h2);
  font-weight: 600;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
}

/* ============================================================================
   EXPLORER — the map across the whole width, its note above it; under it
   the filters and the list, side by side.
   ========================================================================= */
.explorer { padding: var(--space-12) 0; }

/* The map and its note: 70% of the container's width, centred. Below
   980px the map takes the full width again. */
.explorer__map { width: 70%; margin-inline: auto; }

/* The note over the map, and under it, once something is picked, what is
   picked: the open card's alumnus, or the country filtered for. */
.map-head { max-width: var(--layout-container-narrow); margin-bottom: var(--space-4); }
.map-head__hint,
.map-head__selected {
  margin: 0;
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
.map-head__selected { margin-top: var(--space-2); color: var(--color-ink); font-weight: 600; }

.explorer__browse {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: start;
  column-gap: var(--space-12);
  margin-top: var(--space-12);
}
.explorer__list { min-width: 0; scroll-margin-top: calc(var(--layout-topbar) + var(--space-4)); }

/* The filters: grouped in a card-tinted (§10.5 form layout), kept in view
   beside the list as it scrolls. Should it outgrow the screen (the topic
   panel open on a short one), it scrolls inside itself. */
.filters-panel {
  position: sticky;
  top: calc(var(--layout-topbar) + var(--space-4));
  max-height: calc(100dvh - var(--layout-topbar) - var(--space-8));
  overflow-y: auto;
  box-sizing: border-box;
  padding: var(--space-6);
  border-radius: var(--radius-md);
  background: var(--color-canvas-tinted);
}
.filters-panel__title {
  margin: 0 0 var(--space-4);
  font-size: var(--type-h4);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-ink);
}

/* --- the list head: the title and the running count ---------------------- */
.list-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.list-head__title {
  margin: 0;
  font-size: var(--type-h3);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}
.list-head__count {
  margin: 0;
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
.list-head__figure {
  font-family: var(--font-accent);
  font-size: var(--type-data-label);
  font-weight: 600;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
}

/* --- the filters (§10.5): labelled fields, 48px, single focus style ------- */
/* Search and year on one line, the year narrow at the right; sector and
   topics each take a full line. */
.filters {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 8rem;
  gap: var(--space-4) var(--space-3);
  margin: 0;
}
.field { position: relative; min-width: 0; }
.field--wide { grid-column: 1 / -1; }
.field__label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--type-label);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-ink);
}

.input {
  display: block;
  width: 100%;
  min-height: 48px;
  box-sizing: border-box;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-sm);
  background: var(--color-canvas);
  color: var(--color-ink);
  font: 400 var(--type-body) / 1.4 var(--font-body);
  transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}
.input::placeholder { color: var(--color-muted); }
.input:hover { border-color: var(--purple-300); }
.input:focus { outline: none; }
.input:focus-visible,
.input:focus:not(button) {
  border-color: var(--color-action-primary);
  box-shadow: 0 0 0 3px var(--color-focus-glow);
}
.input:disabled { background: var(--color-canvas-tinted); color: var(--color-muted); cursor: not-allowed; }

/* The selects and the topics field draw one chevron in one place, in the
   ink colour, whatever the browser (a border-drawn mark, as v5's menu). */
.select { position: relative; display: block; }
.select select { appearance: none; -webkit-appearance: none; padding-right: var(--space-8); cursor: pointer; }
/* On its "All …" option a select reads as the search box's placeholder:
   muted. A picked value, and the options in the open list, take ink. */
.select select:has(option[value=""]:checked) { color: var(--color-muted); }
.select option { color: var(--color-ink); }
.select::after,
.topics-field::after {
  content: "";
  position: absolute;
  right: var(--space-4); top: 50%;
  width: 7px; height: 7px;
  margin-top: -6px;
  border-right: 2px solid var(--color-ink);
  border-bottom: 2px solid var(--color-ink);
  rotate: 45deg;
  pointer-events: none;
  transition: rotate var(--motion-medium), margin var(--motion-medium);
}

/* The topics field: a button set as a select. Closed, it lists what is
   picked, growing a line as more is picked; open, the chevron turns. */
.topics-field {
  position: relative;
  display: flex; align-items: center;
  padding-right: var(--space-12);
  text-align: left;
  cursor: pointer;
}
.topics-field.is-open {
  border-color: var(--color-action-primary);
  box-shadow: 0 0 0 3px var(--color-focus-glow);
}
.topics-field.is-open::after { rotate: 225deg; margin-top: -2px; }
.topics-field:active { background: var(--color-canvas-tinted); }
.topics-field__value {
  min-width: 0;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-1);
}
.topics-field.is-empty .topics-field__value { color: var(--color-muted); }   /* "All topics", as a placeholder */
.topics-field__tag {
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-canvas-tinted);
  color: var(--color-ink);
  font-size: var(--type-caption);
  font-weight: 600;
  line-height: 1.3;
}

/* The topic panel: filter pills on the tinted well, under the field. */
.topic-panel {
  display: flex; flex-wrap: wrap;
  gap: var(--space-2);
  max-height: 264px;
  overflow-y: auto;
  margin-top: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-canvas);   /* white on the tinted filters panel */
  box-shadow: inset 0 0 0 1px var(--color-hairline);
}

/* Filter pill, all five states. Pressed is the picked state. */
.filter-pill {
  position: relative;
  display: inline-flex; align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: 0 var(--space-4);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-canvas);
  box-shadow: inset 0 0 0 1px var(--color-hairline);
  color: var(--color-body);
  font: 500 var(--type-body-sm) / 1.2 var(--font-body);
  cursor: pointer;
  transition: background-color var(--motion-fast), box-shadow var(--motion-fast), color var(--motion-fast);
}
.filter-pill::before { content: ""; position: absolute; inset: -4px 0; }   /* the 44px hit area */
.filter-pill:hover { color: var(--color-ink); box-shadow: inset 0 0 0 1px var(--purple-300); }
.filter-pill:active { background: var(--color-canvas-pressed); }
.filter-pill:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }
.filter-pill[aria-pressed="true"] {
  background: var(--color-action-primary);
  box-shadow: none;
  color: var(--color-on-action);
  font-weight: 600;
}
.filter-pill[aria-pressed="true"]:hover { background: var(--color-action-primary-hover); }
.filter-pill:disabled { opacity: 0.5; cursor: not-allowed; }

/* The removable pill: the country picked on the map. */
.filter-pill--remove {
  background: var(--color-canvas-tinted);
  box-shadow: inset 0 0 0 1px var(--color-action-primary);
  color: var(--color-ink);
  font-weight: 600;
}
.filter-pill--remove svg {
  width: 10px; height: 10px;
  fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round;
}
.filter-pill--remove:hover { background: var(--color-canvas-pressed); box-shadow: inset 0 0 0 1px var(--color-action-primary); }

/* The Summit 2026 checkbox (§10.5): 20px box, the full 44px row the target. */
.check {
  display: flex; align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  font-size: var(--type-body-sm);
  color: var(--color-body);
  cursor: pointer;
}
.check input {
  width: 20px; height: 20px; margin: 0;
  accent-color: var(--color-action-primary);
  cursor: pointer;
}
.check input:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }

.active-filters {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-4);
}

/* --- the people: an editorial list of accordion rows (§10.8, §10.6) ------
   One row per alumnus between hairlines: the year, the name, then where
   they work. The row is a button; opened, it shows the facts below. */
.people {
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--color-hairline);
}
.person { border-bottom: 1px solid var(--color-hairline); }
.person__heading { margin: 0; font: inherit; }

.person__toggle {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--space-4);
  width: 100%;
  margin: 0;
  padding: var(--space-4) var(--space-3);
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--motion-fast);
}
.person__toggle > span:not(.person__chevron) { grid-column: 1; }
.person__toggle:hover,
.person.is-hovered .person__toggle,
.person.is-expanded .person__toggle { background: var(--color-canvas-tinted); }
.person__toggle:active { background: var(--color-canvas-pressed); }
.person__toggle:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: -3px; }
.person__toggle:disabled { opacity: 0.5; cursor: not-allowed; }

.person__meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-1) var(--space-3);
}
.person__year {
  font-family: var(--font-accent);
  font-size: var(--type-eyebrow);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.18em;
  color: var(--color-action-primary);
}
.person__name {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--type-h4);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-ink);
}
.person__org {
  display: block;
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
.person__chevron {
  grid-column: 2; grid-row: 1 / span 3;
  display: grid; place-items: center;
  width: 32px; height: 32px;
  border-radius: var(--radius-full);
  box-shadow: inset 0 0 0 1px var(--color-hairline);
  color: var(--color-ink);
}
.person__chevron svg {
  width: var(--space-4); height: var(--space-4);
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--motion-medium);
}
.person.is-expanded .person__chevron svg { transform: rotate(180deg); }

/* chip-status (§10.2): the dot is never the only signal; the label says it. */
.status {
  display: inline-flex; align-items: center;
  gap: var(--space-2);
  font-size: var(--type-caption);
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-ink);
}
.status__dot {
  width: 7px; height: 7px;
  border-radius: var(--radius-full);
  background: var(--p4-orange);
}

/* The opened row: v5's reach facts, one per line ("Based: Singapore"),
   then the topics and the bio. */
.person__details {
  display: none;
  padding: 0 var(--space-3) var(--space-6);
  background: var(--color-canvas-tinted);
}
.person.is-expanded .person__details { display: block; }
.person__facts {
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-hairline-soft);
}
.person__facts > div + div { margin-top: var(--space-2); }
.person__facts dt,
.person__facts dd {
  display: inline;
  margin: 0;
  font-size: var(--type-body-sm);
  line-height: 1.5;
}
.person__facts dt { font-weight: 600; color: var(--color-ink); }
.person__facts dt::after { content: ":"; }
.person__facts dd { color: var(--color-body); }

.person__label {
  margin: var(--space-4) 0 var(--space-2);
  font-size: var(--type-body-sm);
  font-weight: 600;
  line-height: 1.5;
  color: var(--color-ink);
}
.tags {
  display: flex; flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0; padding: 0;
  list-style: none;
}
.tag {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-canvas);
  box-shadow: inset 0 0 0 1px var(--color-hairline);
  font-size: var(--type-caption);
  line-height: 1.45;
  color: var(--color-body);
}
.person__bio {
  max-width: 65ch;
  margin: 0;
  font-size: var(--type-body-sm);
  line-height: 1.6;
  color: var(--color-body);
}
/* While the bios are being written: muted, so it reads as a placeholder. */
.person__bio.is-pending { color: var(--color-muted); }

/* Loading, empty and error (§12 Class B). */
.people__state {
  display: grid; justify-items: start;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-3);
  font-size: var(--type-body-sm);
  line-height: 1.5;
  color: var(--color-muted);
}
.people__state p { margin: 0; }
.people__state--error { color: var(--color-error); font-weight: 600; }

/* --- the map ------------------------------------------------------------- */
.map {
  position: relative;
  display: grid; place-items: center;
  /* The drawing's proportions, cropped at the bottom: it has no Antarctica,
     so its lowest land (New Zealand) sits at y 533 of 620. The map's viewBox
     is cropped to match (map/alumni-map.html). */
  aspect-ratio: 950 / 540;
}
.map__frame {
  position: absolute; inset: 0;
  display: block;
  width: 100%; height: 100%;
  border: 0;
}
.map__status {
  margin: 0;
  font-size: var(--type-body-sm);
  color: var(--color-muted);
}
/* ============================================================================
   FOOTER — experiences-page/v5's footer (sections/footer.css), band-deep:
   the GESDA logo left of Follow GESDA; the funder marks under the rule,
   right-aligned. The social links are button-icon (§10.1), 44px targets.
   v5 has no top padding, as its close runs into it; here the footer
   follows the list, so it takes the section padding on both sides.
   ========================================================================= */

/* §10.4 — a band is a complete local theme context (v5's base.css). */
.theme-dark {
  --color-canvas:                var(--color-canvas-dark);
  --color-canvas-tinted:         var(--color-wash-on-band);
  --color-canvas-pressed:        var(--color-wash-on-band-strong);
  --color-hairline:              var(--color-hairline-on-dark);
  --color-hairline-soft:         var(--color-hairline-on-band-soft);
  --color-ink:                   var(--color-ink-on-dark);
  --color-body:                  var(--color-body-on-dark);
  --color-muted:                 var(--color-muted-on-dark);
  --color-action-primary:        var(--color-white);
  --color-action-primary-hover:  var(--purple-050);
  --color-action-primary-active: var(--purple-100);
  --color-on-action:             var(--purple-900);
  --color-focus-ring:            var(--color-focus-ring-dark);
  --shadow-sm: none;   /* §3.6: no shadows on dark */
  --shadow-md: none;
  background: var(--color-canvas);
  color: var(--color-body);
}

.site-footer { padding: var(--space-16) 0; }
.site-footer__grid {
  display: grid; gap: var(--space-12) var(--space-16); align-items: center;
  grid-template-columns: minmax(0, 1fr) auto;
}
.site-footer__brand img { display: block; height: calc(var(--space-12) * 1.3); width: auto; max-width: 100%; }
.site-footer__funders { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-6) var(--space-8); margin-left: auto; }
/* Heights are set per mark so the three read at an even visual size: the
   wide Confederation lockup sits lower, the stacked Canton emblem taller. */
.site-footer__funders img { display: block; width: auto; max-width: 100%; }
.site-footer__funders .site-footer__swiss  { height: calc(var(--space-8) + var(--space-2)); }
.site-footer__funders .site-footer__canton { height: var(--space-16); }
.site-footer__funders .site-footer__ville  { height: var(--space-16); }
.site-footer__group h3 { margin: 0 0 var(--space-3); font: 600 var(--type-h4) / 1.4 var(--font-body); color: var(--color-ink); }
.site-footer__group ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-2); }
.site-footer__group a,
.site-footer__legal a {
  color: var(--color-muted);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: color var(--motion-fast), background-color var(--motion-fast), border-color var(--motion-fast);
}
.site-footer__group a { font: 400 var(--type-body-sm) / 1.5 var(--font-body); }
.site-footer__group a:hover,
.site-footer__legal a:hover  { color: var(--color-ink); text-decoration: underline; }
.site-footer__group a:active,
.site-footer__legal a:active { color: var(--color-action-primary-active); }
.site-footer__group a:focus-visible,
.site-footer__legal a:focus-visible { outline: 3px solid var(--color-focus-ring); outline-offset: 2px; }

.site-footer__group .site-footer__social { flex-direction: row; gap: var(--space-3); }
.site-footer__social a {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-full);
}
.site-footer__social svg { fill: currentColor; }
.site-footer__social a:hover { text-decoration: none; border-color: var(--color-muted); background: var(--color-canvas-tinted); }
.site-footer__social a:active { background: var(--color-canvas-pressed); }

.site-footer__legal {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-6);
  margin-top: var(--space-12); padding-top: var(--space-6);
  border-top: 1px solid var(--color-hairline);
}
.site-footer__legal p,
.site-footer__legal a { margin: 0; font: 400 var(--type-caption) / 1.45 var(--font-body); color: var(--color-muted); }
.site-footer__legal ul { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-6); }

/* ---- responsive (§13.1) — review at 1440, 1180, 980, 720, 480, 390 ------ */

@media (min-width: 1440px) {
  .wrap, .topbar__inner { padding: 0 var(--space-12); }
}

/* Below 980px one column: the head and totals stacked; the map, then the
   filters (no longer sticky), then the list. The footer as v5's. */
@media (max-width: 979px) {
  .explorer__map { width: auto; }
  .intro__frame { grid-template-columns: minmax(0, 1fr); }
  .totals { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--space-4); }
  .totals > div { flex-direction: column; gap: 0; border-bottom: 1px solid var(--color-hairline); }
  .totals dt { order: 1; }
  .explorer__browse {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-8);
    margin-top: var(--space-8);
  }
  .filters-panel { position: static; max-height: none; overflow: visible; }

  .site-footer__grid { grid-template-columns: 1fr; gap: var(--space-12); justify-items: center; text-align: center; }
  .site-footer__group .site-footer__social { justify-content: center; }
  .site-footer__brand { display: none; }   /* the topbar already carries it */
  .site-footer__funders { margin-left: 0; }
}

/* Below 720px the map runs edge to edge, as v5's does. */
@media (max-width: 719px) {
  .wrap, .topbar__inner { padding: 0 var(--space-4); }
  .topbar__brand img { height: 44px; }
  .intro { padding: var(--space-8) 0; }
  .explorer { padding-top: var(--space-8); }
  .explorer__map .map { margin-inline: calc(var(--space-4) * -1); }
  .filters-panel { padding: var(--space-4); }
}

@media (max-width: 479px) {
  .filters { grid-template-columns: minmax(0, 1fr); }
  .field { grid-column: 1 / -1; }
  .topbar__back { padding: 0 var(--space-4); }
}
