/* ============================================================================
   MTL STUDENTS · Direction A « Nuit »
   ----------------------------------------------------------------------------
   Every colour here is sampled from something the client already owns.
   Pink, orange and gold come from her logo. Oxblood comes from the seamless
   backdrop of her own studio portrait series. Nothing is invented.
   ========================================================================== */

@font-face { font-family: 'ArchivoFallback'; src: local('Helvetica Neue'); size-adjust: 97%; }

:root {
  /* ground */
  --ink:          #12100F;
  --ink-2:        #1A1618;
  --ink-3:        #241E21;

  /* from her portrait series */
  --oxblood:      #4A0810;
  --oxblood-deep: #30060C;

  /* from her logo */
  --pink:         #F860C0;
  --pink-deep:    #D8329C;
  --orange:       #F89040;
  --gold:         #F8D870;

  /* type */
  --cream:        #F7F0E8;
  --cream-70:     rgba(247, 240, 232, .70);
  /* .60, not .45. At .45 this token measured 3.67:1 on --oxblood and 4.11:1
     on --ink-2, so every place it carried text failed AA, including the
     newsletter placeholder and note on all five pages. .60 gives 5.61:1 and
     6.37:1. The name is kept so the 35 usages do not have to change. */
  --cream-45:     rgba(247, 240, 232, .60);
  --cream-14:     rgba(247, 240, 232, .14);

  --display: 'Archivo', 'ArchivoFallback', sans-serif;
  --body:    'Archivo', 'ArchivoFallback', sans-serif;
  --quote:   'Instrument Serif', Georgia, serif;

  --gut: clamp(1.25rem, 4vw, 4.5rem);
  --max: 1440px;

  --ease: cubic-bezier(.22, 1, .36, 1);
}

/* ---------------------------------------------------------------- reset -- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--body);
  font-size: clamp(1rem, .95rem + .2vw, 1.0625rem);
  line-height: 1.62;
  font-variation-settings: 'wdth' 100;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
h1, h2, h3, p, figure, blockquote { margin: 0; }
button { font: inherit; color: inherit; }

::selection { background: var(--pink); color: var(--ink); }

/* Wix shipped 48 elements at rgb(0,0,238), the browser default. Every link
   here is styled deliberately, including the ones nobody will click. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, summary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------- layout -- */

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }

.kicker {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold);
  display: flex;
  align-items: center;
  gap: .75em;
}
.kicker::before {
  content: '';
  width: clamp(1.5rem, 4vw, 3rem);
  height: 1px;
  background: var(--orange);
  flex: none;
}

.h2 {
  font-family: var(--display);
  font-variation-settings: 'wdth' 118;
  font-weight: 700;
  font-size: clamp(2rem, 1.2rem + 3.6vw, 4.25rem);
  line-height: .96;
  letter-spacing: -.025em;
  text-wrap: balance;
}

/* --------------------------------------------------------------- grain --- */
/* Atmosphere, not decoration: a flat near-black reads as cheap on a big
   screen. This is a 4% opacity noise tile, fixed so it never scrolls. */

.grain {
  position: fixed;
  inset: -50%;
  z-index: 9999;
  pointer-events: none;
  opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ nav -- */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(18, 16, 15, .82);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--cream-14);
}
.nav__in {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  min-height: 74px;
}
.nav__logo { flex: none; }
.nav__logo img { width: clamp(88px, 11vw, 124px); }
.nav__links {
  display: flex;
  gap: clamp(.85rem, 2vw, 2rem);
  margin-left: auto;
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .04em;
}
.nav__links a {
  text-decoration: none;
  color: var(--cream-70);
  padding: .3em 0;
  position: relative;
  transition: color .25s var(--ease);
  white-space: nowrap;
}
.nav__links a::after {
  content: '';
  position: absolute;
  left: 0; right: 100%; bottom: 0;
  height: 1px;
  background: var(--pink);
  transition: right .3s var(--ease);
}
.nav__links a:hover { color: var(--cream); }
.nav__links a:hover::after { right: 0; }
.nav__links a[aria-current] { color: var(--cream); }
.nav__links a[aria-current]::after { right: 0; background: var(--gold); }

/* ------------------------------------------------------------ burger ---- */

/* The three bars are absolutely positioned from one shared origin rather than
   laid out in flow. The flow version needed a translateY to pull the outer
   bars back to the centre before rotating, and that distance depended on how
   the button's rows happened to be sized: it silently became a chevron when
   the grid rows stretched. Here the open state is just two rotations about a
   single point, so it cannot drift. */
.nav__burger {
  display: none;
  position: relative;
  /* flex:none, or the nav CTA that replaced the A/B switcher squeezes it to
     16px at 320px. It is a flex child of .nav__in and was shrinking. */
  flex: none;
  width: 40px; height: 40px;
  margin-left: auto;
  background: none;
  border: 1px solid var(--cream-14);
  border-radius: 999px;
  cursor: pointer;
}
.nav__burger span {
  position: absolute;
  left: 50%; top: 50%;
  width: 15px; height: 1.5px;
  margin-left: -7.5px;
  margin-top: -.75px;
  background: var(--cream);
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.nav__burger span:nth-child(1) { transform: translateY(-5.5px); }
.nav__burger span:nth-child(3) { transform: translateY(5.5px); }
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { transform: rotate(-45deg); }

/* --------------------------------------------------- direction switcher -- */

.switch {
  flex: none;
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .3rem;
  border: 1px solid var(--cream-14);
  border-radius: 999px;
  background: var(--ink-2);
}
.switch__label {
  font-size: .5625rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--cream-45);
  padding-left: .6rem;
}
.switch a {
  display: grid;
  place-items: center;
  /* 32px, not 30. Under the WCAG 2.5.8 target-size floor otherwise. */
  width: 32px; height: 32px;
  border-radius: 999px;
  font-size: .75rem;
  font-weight: 700;
  text-decoration: none;
  color: var(--cream-45);
  transition: background .25s var(--ease), color .25s var(--ease);
}
.switch a:hover { color: var(--cream); background: var(--ink-3); }
.switch a[aria-current] { background: var(--pink); color: var(--ink); }

/* -------------------------------------------------------------- marquee -- */
/* Her own site runs this line as a marquee. Keeping it is right: it is the
   most human sentence she wrote. Fixing it means readable size, one clean
   loop, and a pause on hover so it can actually be read. */

.marquee {
  overflow: hidden;
  border-bottom: 1px solid var(--cream-14);
  background: var(--oxblood-deep);
  padding-block: .85rem;
}
.marquee__track {
  display: flex;
  width: max-content;
  gap: 3rem;
  animation: slide 46s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee span {
  font-family: var(--quote);
  font-style: italic;
  font-size: clamp(.95rem, .9rem + .3vw, 1.2rem);
  color: var(--cream-70);
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 3rem;
}
.marquee span::after { content: '✦'; color: var(--orange); font-style: normal; font-size: .7em; }
@keyframes slide { to { transform: translateX(-50%); } }

/* ----------------------------------------------------------------- hero -- */

.hero {
  position: relative;
  padding-block: clamp(3rem, 7vw, 7rem) clamp(3rem, 6vw, 6rem);
  overflow: hidden;
}
/* Type-led, with the photograph full width beneath rather than cropped into a
   column. Three different photographers' watermarks sit in the lower-right of
   these frames (art_tonic, EXUTOIRE/@juliaeyd.jpg). A tight crop would cut
   somebody's credit off, which is not a thing we do. */
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .8fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: end;
}
.hero__title {
  font-family: var(--display);
  font-variation-settings: 'wdth' 112;
  font-weight: 800;
  /* Floor lowered from 2.75rem: at 320px the content box is 280px and
     « communauté » rendered at ~310px, so the final accented character was
     clipped by the viewport. overflow-x:hidden meant no test caught it. */
  font-size: clamp(2.3rem, 1.1rem + 7vw, 7rem);
  line-height: .89;
  letter-spacing: -.035em;
  margin-block: 1.1rem 1.5rem;
}
.hero__title em { font-style: normal; color: var(--pink); }
.hero__dek {
  font-family: var(--quote);
  font-style: italic;
  font-size: clamp(1.15rem, 1rem + .7vw, 1.75rem);
  line-height: 1.35;
  color: var(--cream-70);
  max-width: 30ch;
  text-wrap: pretty;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: .85rem; margin-top: 2.25rem; }

/* The black outline around the pink wordmark is the logo's signature detail.
   It transfers to exactly one place: the primary button. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  padding: .95em 1.6em;
  border-radius: 999px;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .01em;
  text-decoration: none;
  border: 1px solid transparent;
  /* A <button> with no declared background paints itself `buttonface`: a solid
     light pill with cream text on it, unreadable. Invisible on the home page,
     where every ghost button is an <a>, and immediate on any page that uses a
     real <button>. Declared on .btn and NOT on button.btn, because the element
     selector would outrank .btn--primary and blank the pink fill. */
  background: transparent;
  transition: transform .3s var(--ease), background .3s var(--ease), color .3s var(--ease);
}
.btn--primary {
  background: var(--pink);
  color: var(--ink);
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 3px var(--pink);
}
.btn--primary:hover { background: var(--gold); box-shadow: 0 0 0 2px var(--ink), 0 0 0 3px var(--gold); transform: translateY(-2px); }
.btn--ghost { border-color: var(--cream-14); color: var(--cream); }
.btn--ghost:hover { border-color: var(--pink); color: var(--pink); transform: translateY(-2px); }
.btn svg { transition: transform .3s var(--ease); }
.btn:hover svg { transform: translateX(3px); }

/* The whole frame, uncropped. On the live site this exact photograph is
   served as a 170px blurred placeholder stretched to 980px. Showing it sharp
   and whole is the argument, so it does not get a decorative crop here. */
.hero__figure {
  position: relative;
  margin-top: clamp(2.5rem, 6vw, 5rem);
}
.hero__figure img {
  width: 100%;
  border-radius: 4px;
}
.hero__cap {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: .5rem 1.5rem;
  margin-top: .85rem;
  color: var(--cream-45);
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.hero__cap b { color: var(--cream-70); font-weight: 500; }

/* the globe wireframe, her ownable motif, used once and quietly */
.hero__globe {
  position: absolute;
  right: -14%;
  top: 50%;
  translate: 0 -50%;
  width: min(52vw, 640px);
  opacity: .16;
  pointer-events: none;
  color: var(--orange);
}

.stats {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 5vw, 4rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--cream-14);
}
.stat b {
  display: block;
  font-family: var(--display);
  font-variation-settings: 'wdth' 120;
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.6rem);
  font-weight: 700;
  line-height: 1;
  color: var(--cream);
}
.stat span { font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; color: var(--cream-45); }

/* ------------------------------------------------------------ manifesto -- */

.manifesto { background: var(--ink-2); padding-block: clamp(4rem, 9vw, 8.5rem); }
.manifesto__grid {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: clamp(2rem, 6vw, 5rem);
}
.manifesto p + p { margin-top: 1.35rem; }
.manifesto p { color: var(--cream-70); max-width: 62ch; }

.pull {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--oxblood);
  border-left: 2px solid var(--pink);
  font-family: var(--quote);
  font-size: clamp(1.3rem, 1.05rem + 1.1vw, 2.25rem);
  line-height: 1.24;
  color: var(--cream);
  text-wrap: balance;
}

/* ----------------------------------------------------------- next event -- */

.event { padding-block: clamp(4rem, 9vw, 8.5rem); }
.event__card {
  display: grid;
  grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
  margin-top: clamp(1.75rem, 4vw, 3rem);
  padding: clamp(1.25rem, 3vw, 2.25rem);
  background: linear-gradient(160deg, var(--oxblood) 0%, var(--ink-2) 78%);
  border: 1px solid var(--cream-14);
  border-radius: 6px;
}
/* Her event posters are Canva artwork with their own palettes (the Calypso one
   is bright blue). Framing them as artifacts stops them fighting the page. */
.event__poster {
  border-radius: 3px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
  rotate: -1.4deg;
  transition: rotate .5s var(--ease), scale .5s var(--ease);
}
.event__card:hover .event__poster { rotate: 0deg; scale: 1.015; }
.event__title {
  font-family: var(--display);
  font-variation-settings: 'wdth' 115;
  font-weight: 700;
  font-size: clamp(1.75rem, 1.2rem + 2.2vw, 3.25rem);
  line-height: .98;
  letter-spacing: -.02em;
  margin-block: .6rem .9rem;
}
.event__meta { display: flex; flex-wrap: wrap; gap: 1.75rem; margin-block: 1.5rem; }
.event__meta div { border-left: 1px solid var(--cream-14); padding-left: .9rem; }
.event__meta dt { font-size: .625rem; letter-spacing: .16em; text-transform: uppercase; color: var(--cream-45); }
.event__meta dd { margin: .25rem 0 0; font-weight: 600; font-size: 1.0625rem; }
.event__meta dd.px { color: var(--gold); }
.event__warn { font-size: .8125rem; color: var(--orange); font-weight: 600; }

/* ----------------------------------------------------------- ressources -- */
/* This page has zero photography on the live site. That is a constraint, not
   a gap: it gets carried on type, rule weight and a numeral, not on stock. */

.res { background: var(--ink-2); padding-block: clamp(4rem, 9vw, 8.5rem); }
.res__list { margin-top: clamp(1.75rem, 4vw, 3rem); border-top: 1px solid var(--cream-14); }
.res__item {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) auto;
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: baseline;
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-bottom: 1px solid var(--cream-14);
  text-decoration: none;
  transition: background .35s var(--ease), padding-inline .35s var(--ease);
}
.res__item:hover { background: var(--ink-3); padding-inline: 1.25rem; }
.res__num { font-family: var(--quote); font-size: 1.5rem; color: var(--orange); }
.res__t {
  display: block; /* spans by default: without this the description runs on inline */
  font-family: var(--display);
  font-variation-settings: 'wdth' 108;
  font-weight: 600;
  font-size: clamp(1.15rem, 1rem + .9vw, 1.85rem);
  line-height: 1.12;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.res__d { display: block; margin-top: .55rem; color: var(--cream-45); font-size: .9375rem; max-width: 58ch; }
.res__go { color: var(--pink); font-size: 1.5rem; transition: transform .35s var(--ease); }
.res__item:hover .res__go { transform: translateX(6px); }

/* -------------------------------------------------------------- podcast -- */

.pod { padding-block: clamp(4rem, 9vw, 8.5rem); }
.pod__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .9fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.pod__art { position: relative; border-radius: 5px; overflow: hidden; }
.pod__art img { aspect-ratio: 16 / 9; object-fit: cover; width: 100%; }
.pod__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(18, 16, 15, .3);
  transition: background .35s var(--ease);
  text-decoration: none;
}
.pod__art:hover .pod__play { background: rgba(18, 16, 15, .12); }
.pod__play i {
  display: grid;
  place-items: center;
  width: 74px; height: 74px;
  border-radius: 999px;
  background: var(--pink);
  color: var(--ink);
  font-style: normal;
  font-size: 1.3rem;
  padding-left: 5px;
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 3px var(--pink);
  transition: transform .35s var(--ease), background .35s var(--ease);
}
.pod__art:hover .pod__play i { transform: scale(1.08); background: var(--gold); }

/* -------------------------------------------------------------- galerie -- */
/* The crimson portrait series is the best asset on the whole project and the
   current site shows it at thumbnail size. Here it runs at full bleed. */

.gal { padding-block: clamp(4rem, 9vw, 8.5rem) 0; overflow: hidden; }
.gal__rail {
  display: flex;
  gap: 1rem;
  margin-top: clamp(1.75rem, 4vw, 3rem);
  padding-inline: var(--gut);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: clamp(4rem, 9vw, 8.5rem);
}
.gal__rail::-webkit-scrollbar { display: none; }
.gal__rail figure {
  flex: none;
  width: clamp(200px, 24vw, 320px);
  scroll-snap-align: center;
}
.gal__rail img {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  border-radius: 3px;
  filter: saturate(.94);
  transition: filter .45s var(--ease), transform .45s var(--ease);
}
.gal__rail figure:hover img { filter: saturate(1.1); transform: translateY(-6px); }
.gal__note {
  margin-top: 1.1rem;
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--cream-45);
}

/* ----------------------------------------------------------- newsletter -- */

.news {
  background: var(--oxblood);
  padding-block: clamp(4rem, 9vw, 8rem);
  border-top: 1px solid rgba(248, 96, 192, .25);
}
.news__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .85fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: end;
}
.form { display: flex; gap: .6rem; flex-wrap: wrap; }
.form input {
  flex: 1 1 15rem;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(247, 240, 232, .3);
  color: var(--cream);
  font: inherit;
  padding: .8rem .2rem;
}
.form input::placeholder { color: var(--cream-45); }
.form input:focus { border-bottom-color: var(--gold); outline: none; }
.form__note { margin-top: 1rem; font-size: .75rem; color: var(--cream-45); }

/* --------------------------------------------------------------- footer -- */

.foot { padding-block: clamp(3rem, 6vw, 5rem) 2rem; }
.foot__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--cream-14);
}
/* h3, not h4: the last heading before the footer is an h2 on every page, and
   jumping straight to h4 fails a heading-order audit site-wide. Both selectors
   are kept so a page that still carries the old markup is not left unstyled. */
.foot h3, .foot h4 { font-size: .625rem; letter-spacing: .18em; text-transform: uppercase; color: var(--gold); margin: 0 0 1.1rem; font-weight: 600; }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
/* inline-block plus vertical padding, so the tap target is ~32px rather than
   the 16px the line box alone gives. Footer links were the worst offenders on
   touch. */
.foot ul a { display: inline-block; padding-block: .5rem; }
.foot a { color: var(--cream-70); text-decoration: none; font-size: .9375rem; transition: color .25s var(--ease); }
.foot a:hover { color: var(--pink); }
.foot__base {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  padding-top: 1.75rem;
  font-size: .75rem;
  color: var(--cream-45);
}

/* ---------------------------------------------------------------- reveal -- */

/* Progressive enhancement, deliberately.

   Content is visible by default. It is only hidden once the inline head script
   has confirmed that JS and IntersectionObserver are both available, by putting
   .js on <html>. If the animation layer fails to load (a blocked CDN on a
   client's office wifi, say, which is exactly the situation a live demo runs
   in), the page still reads perfectly. Never gate content on a network
   request to a third party. */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  [data-reveal] { opacity: 1; transform: none; }
  .marquee__track { animation: none; }
}

/* ------------------------------------------------------------ responsive -- */

@media (max-width: 900px) {
  .hero__grid, .manifesto__grid, .event__card, .pod__grid, .news__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__figure { order: -1; }
  .hero__figure img { aspect-ratio: 3 / 2; }
  .foot__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .hero__globe { display: none; }
  .pod__grid > div:first-child { order: 2; }

  /* The nav links become a panel rather than disappearing. An earlier pass
     simply hid them below 900px, which left mobile with no way to navigate
     at all: an unusually bad failure on a project whose whole argument is
     that the client's site does not work on a phone. */
  .nav__burger { display: block; }
  .nav__links {
    /* Anchored to the bar, not to a guessed offset. This was `inset: 74px 0
       auto 0`, but the logo's clamp makes the bar 89px tall at mobile and
       100px at 900px, so the panel opened 15 to 26px *underneath* its own
       header. top:100% on the sticky .nav is correct at every viewport. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 0;
    margin: 0;
    padding: .5rem var(--gut) 1.5rem;
    background: var(--ink-2);
    border-bottom: 1px solid var(--cream-14);
    opacity: 0;
    transform: translateY(-10px);
    pointer-events: none;
    /* visibility, not just opacity: an opacity-0 panel keeps its links in the
       tab order and in the accessibility tree. Tab disappeared for five stops
       and screen readers announced the nav twice. */
    visibility: hidden;
    transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
  }
  .nav__links[data-open] { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }
  .nav__links a {
    padding: .95rem 0;
    font-size: 1.0625rem;
    border-bottom: 1px solid var(--cream-14);
  }
  .nav__links a::after { display: none; }
  .switch { margin-left: 0; }
}
@media (max-width: 560px) {
  .res__item { grid-template-columns: 2rem minmax(0, 1fr); }
  .res__go { display: none; }
  .foot__grid { grid-template-columns: minmax(0, 1fr); }
  .event__meta { gap: 1rem 1.25rem; }
  .switch__label { display: none; }
}


/* ------------------------------------------------------- nav CTA + IP ----- */
/* The slot the A/B switcher used to occupy. The comparison moved to the root
   chooser, so the nav carries the site's real primary action instead. */
.nav__cta { flex: none; padding: .7em 1.2em; font-size: .8125rem; }
@media (max-width: 900px) { .nav__cta { margin-left: auto; } .nav__cta svg { display: none; } }
@media (max-width: 420px) { .nav__cta { padding: .6em .9em; font-size: .75rem; } }

/* standards/demo-protection.md: sits alongside her own copyright, not instead
   of it. The two say different things and both are correct. */
.foot__ip { flex: 1 1 100%; max-width: 78ch; color: var(--cream-45); font-size: .6875rem; line-height: 1.5; }

/* At 320px the nav row is logo + burger + CTA, and the CTA is new: it took the
   slot the A/B switcher used to hold, but it is wider than the switcher was.
   Shrink the logo and tighten the CTA rather than dropping either, because the
   phone is where a nav CTA earns its place. Measured at 320: 280px of content
   against roughly 226px of nav. */
@media (max-width: 420px) {
  .nav__logo img { width: 64px; }
  /* min-height, because shrinking the padding to fit 320px took the button
     under the 32px target floor. */
  .nav__cta { padding: .5em .7em; font-size: .6875rem; gap: .35em; min-height: 34px; }
  .nav__in { gap: .6rem; }
}
