/* ==========================================================================
   v2.css - the second design pass (2 Sep 2026).
   Everything added after the 25 Aug review: video hero, interactive history
   timeline, sponsor marquee, alumni outcome cards, ecosystem pipeline.

   Two rules govern this file:
     1. Nothing here may drop below WCAG 2.1 AA. Text over media always sits
        on an engineered scrim, never on raw photography.
     2. prefers-reduced-motion kills every animation in here, and the video
        never loads at all. That is not a nicety - accessibility is the
        programme's own curriculum.
   ========================================================================== */

/* ==========================================================================
   1. VIDEO HERO
   ========================================================================== */

.hero--video {
  min-height: min(92vh, 860px);
  display: flex;
  align-items: flex-end;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.hero--video .hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

.hero--video .hero__media video,
.hero--video .hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: var(--photo-treatment);
}

/* Optional Spline 3D layer. Sits INSIDE .hero__media, above the video but
   still below the scrim, so the scrim keeps doing the contrast work measured
   below. Present only when a self-hosted export exists; see spline.js.

   Starts at opacity 0 and is revealed by .is-live once a frame has actually
   painted, so a slow scene shows the video rather than a black rectangle.
   No transition on opacity going the other way - if spline.js gives up it
   removes the node outright.

   WARNING: the contrast ratios recorded on .hero__scrim below were sampled
   against the VIDEO. A brighter scene invalidates them. Re-measure the
   headline, lead and eyebrow against the rendered scene before shipping one,
   and darken the scrim ramp if the eyebrow drops under 4.5:1. It is the first
   thing to fail. */
.hero--video .hero__media .hero__spline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 1;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
  pointer-events: none;
}

.hero--video .hero__media .hero__spline.is-live {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /* Belt and braces. spline.js already refuses to mount under reduced
     motion, but if it never runs the canvas must not paint either. */
  .hero--video .hero__media .hero__spline {
    display: none;
  }
}

/* The scrim is doing real accessibility work, not decoration.
   Measured, not asserted: the hero copy was sampled against the actual
   rendered pixels behind it, across the whole 22s loop, taking the brightest
   frame - headline 8.4:1, lead 11.6:1, eyebrow 4.6:1. (axe cannot check text
   over an image; it falls back to the nearest opaque ancestor and reports
   nonsense, which is why /about read 1.16:1 before this was measured
   properly.) Lighten this ramp and the eyebrow is the first thing to fail. */
.hero--video .hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      rgba(4, 6, 9, 0.58) 0%,
      rgba(4, 6, 9, 0.42) 26%,
      rgba(4, 6, 9, 0.72) 62%,
      rgba(4, 6, 9, 0.95) 100%),
    linear-gradient(90deg,
      rgba(4, 6, 9, 0.78) 0%,
      rgba(4, 6, 9, 0.35) 52%,
      rgba(4, 6, 9, 0.15) 100%);
}

.hero--video .hero__grid {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 80% 70% at 50% 30%, #000 30%, transparent 78%);
}

.hero--video .hero__inner {
  position: relative;
  z-index: 3;
  padding-block: clamp(6rem, 14vh, 10rem) clamp(3.5rem, 8vh, 6rem);
}

/* The hero always renders light-on-dark, in both skins, so it must not
   inherit the light skin's near-black text. */
.hero--video .hero__inner,
.hero--video .hero__inner h1 {
  color: #f4f7fb;
}
.hero--video .hero__inner .lead {
  color: #dfe6ee; /* 11.6:1 measured over the scrimmed footage */
  max-width: 54ch;
}
.hero--video .hero__inner .eyebrow {
  color: #8fd4ff; /* 4.6:1 measured - the tightest value on the page */
}

.hero--video h1 {
  font-size: clamp(2.6rem, 6.4vw, 5.4rem);
  line-height: 1.02;
  letter-spacing: var(--tracking-display);
  max-width: 17ch;
  margin: 0.6rem 0 1.4rem;
  text-wrap: balance;
}

/* ---- Video controls ---------------------------------------------------
   WCAG 2.2.2: motion that runs longer than five seconds needs a way to stop
   it. The hero loop runs 22s, so this control is required, not optional. */
.hero__vidctl {
  position: absolute;
  z-index: 4;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: rgba(6, 8, 11, 0.62);
  backdrop-filter: blur(10px);
  color: #f4f7fb;
  font: 500 0.78rem/1 var(--font-body);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.hero__vidctl:hover {
  background: rgba(6, 8, 11, 0.85);
  border-color: rgba(255, 255, 255, 0.5);
}
.hero__vidctl svg { width: 12px; height: 12px; flex: none; }
.hero__vidctl .ico-pause { display: block; }
.hero__vidctl .ico-play { display: none; }
.hero__vidctl[aria-pressed="true"] .ico-pause { display: none; }
.hero__vidctl[aria-pressed="true"] .ico-play { display: block; }

.hero__hint {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  width: 1px;
  height: 46px;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.6));
  overflow: hidden;
}
.hero__hint::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  animation: hintdrop 2.4s var(--ease-in-out) infinite;
}
@keyframes hintdrop {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(100%); }
  100% { transform: translateY(100%); }
}

@media (max-width: 720px) {
  .hero--video { min-height: 78vh; }
  .hero__hint { display: none; }
  /* The preview's skin switcher is pinned bottom-right and collides with the
     pause control once the viewport narrows. Send the pause control left. */
  .hero__vidctl {
    right: auto;
    left: clamp(1rem, 4vw, 1.5rem);
  }
}

/* ==========================================================================
   2. HISTORY TIMELINE
   A tablist, not a scrolljack. Keyboard-drivable, screen-reader correct, and
   it cannot strand the visitor mid-animation on a slow machine.
   ========================================================================== */

.history { position: relative; }

/* padding-top is the fin's swimming room. Without it the fin is clipped by
   the rail box and only its tip shows. */
.history__rail {
  position: relative;
  margin: 2.25rem 0 0;
  padding-top: 38px;
  padding-bottom: 3.25rem;
}

.history__track {
  position: absolute;
  left: 0;
  right: 0;
  top: 46px; /* centre of the 17px marker dot, which starts at padding-top */
  height: 2px;
  background: var(--border);
  border-radius: 2px;
}
.history__progress {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent-soft), var(--accent));
  border-radius: 2px;
  transition: width var(--dur-slow) var(--ease-out);
}

/* The fin rides ABOVE the track, not on it - sitting it on the line buried
   the active marker dot underneath and both read as one blue smudge. */
.history__fin {
  position: absolute;
  top: 3px;
  left: 0;
  width: 28px;
  height: 28px;
  margin-left: -14px;
  color: var(--accent);
  transition: left var(--dur-slow) var(--ease-out);
  pointer-events: none;
  z-index: 3;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}
/* A small idle bob so the fin looks like it is sitting in water rather than
   pinned to the page. Amplitude stays under 2px on purpose - anything more
   competes with the copy. */
.history__fin svg {
  width: 100%;
  height: 100%;
  display: block;
  animation: finbob 3.6s var(--ease-in-out) infinite;
}
@keyframes finbob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-1.5px) rotate(2deg); }
}

.history__marks {
  position: relative;
  z-index: 2;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0.5rem;
}

.history__mark {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  font: inherit;
  color: var(--text-faint);
  text-align: center;
  transition: color var(--dur-base) var(--ease-out);
}
.history__mark::before {
  content: "";
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border-strong);
  box-shadow: 0 0 0 5px var(--bg);
  transition: background var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.history__mark:hover { color: var(--text); }
.history__mark:hover::before { border-color: var(--accent); transform: scale(1.15); }
.history__mark[aria-selected="true"] { color: var(--text); }
.history__mark[aria-selected="true"]::before {
  background: var(--accent);
  border-color: var(--accent);
  transform: scale(1.25);
}
.history__year {
  font: 500 0.82rem/1.15 var(--font-mono);
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.history__tag {
  font-size: 0.72rem;
  line-height: 1.25;
  color: var(--text-faint);
  max-width: 13ch;
  display: block;
}
.history__mark[aria-selected="true"] .history__tag { color: var(--text-muted); }

.history__panels { position: relative; margin-top: 0.5rem; }

.history__panel[hidden] { display: none; }
.history__panel {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
  animation: tlin var(--dur-slow) var(--ease-out) both;
}
@keyframes tlin {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

.history__era {
  font: 500 0.75rem/1 var(--font-mono);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  display: block;
  margin-bottom: 0.9rem;
}
.history__panel h3 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.8vw, 2.15rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
  max-width: 22ch;
}
.history__panel p { color: var(--text-muted); max-width: 52ch; }
.history__panel p + p { margin-top: 0.85rem; }

.history__facts {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.history__facts li {
  font: 500 0.78rem/1 var(--font-body);
  padding: 0.5rem 0.8rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
}

.history__media {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow);
  aspect-ratio: 4 / 3;
  margin: 0;
}
.history__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: var(--photo-treatment);
}
.history__media figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.5rem 1rem 0.85rem;
  font-size: 0.76rem;
  color: #e8edf4;
  background: linear-gradient(180deg, transparent, rgba(4, 6, 9, 0.9));
}

/* Empty state for eras with no cleared photography yet. Designed rather than
   apologetic: it reads as a deliberate slot with an open request in it, and
   doubles as the asset list Robyn is working from. */
.history__media--empty {
  display: grid;
  place-items: center;
  gap: 0.85rem;
  padding: 1.5rem;
  background:
    repeating-linear-gradient(45deg,
      var(--surface) 0 12px,
      var(--surface-2) 12px 24px);
  border-style: dashed;
}
.history__media--empty svg {
  width: 34px;
  height: 34px;
  color: var(--text-faint);
  opacity: 0.75;
}
.history__media--empty p {
  margin: 0;
  max-width: 24ch;
  text-align: center;
  font: 500 0.82rem/1.5 var(--font-body);
  color: var(--text-muted);
}
.history__media--empty .tag {
  font: 500 0.66rem/1 var(--font-mono);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--signal);
  border: 1px dashed currentColor;
  border-radius: var(--r-pill);
  padding: 0.4rem 0.75rem;
}

@media (max-width: 900px) {
  .history__panel { grid-template-columns: 1fr; }
  .history__media { order: -1; aspect-ratio: 16 / 10; }
  /* The rail becomes a horizontal scroller rather than compressing to
     unreadable 40px columns. */
  .history__rail {
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
    padding-top: 0; /* no fin down here, so no swimming room needed */
    padding-bottom: 1.5rem;
    -webkit-overflow-scrolling: touch;
  }
  .history__marks { grid-auto-columns: 132px; }
  .history__track, .history__fin { display: none; }
  .history__mark { align-items: flex-start; text-align: left; }
  .history__tag { max-width: none; }
}

/* ==========================================================================
   3. SUPPORTING PARTNER NAMES
   Was an auto-scrolling marquee. Retired 10 Sep - see the docstring on
   components_v2.partner_strip. Short version: a credibility wall whose funder
   names are clipped mid-scroll is worse than no motion, and it duplicated the
   partner wall sitting directly above it.
   (v2.js initMarquee duplicated the track at runtime so the loop itself had
   no seam - that part was never broken. It simply no-ops now that nothing
   emits [data-marquee].)

   What replaced it is the treatment prefers-reduced-motion was already
   serving: one static wrapped row. Nothing here animates, nothing is ever
   half-visible, and every funder's name is on screen whenever the visitor
   looks - which is the entire job of this component.
   ========================================================================== */

.partner-names {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 0.85rem;
}

.partner-names__item {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 1.15rem;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font: 600 0.92rem/1 var(--font-display);
  letter-spacing: -0.01em;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.partner-names__item::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
.partner-names__item:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

/* ==========================================================================
   3b. LEGACY MARQUEE - currently dead
   Nothing emits [data-marquee] any more; grepped across every builder on
   10 Sep and partner_strip() was the only one. Retained rather than deleted
   for one reason only: v2.js still carries initMarquee(), which is Agent 7's
   file, and CSS for a component whose JS is still shipping is cheaper to keep
   than a half-removed component is to debug. Delete both together or neither.
   ========================================================================== */

.marquee {
  position: relative;
  overflow: hidden;
  padding: 0.35rem 0;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee + .marquee { margin-top: 0.85rem; }

.marquee__track {
  display: flex;
  width: max-content;
  gap: 0.85rem;
  animation: slide 64s linear infinite;
}
.marquee--rev .marquee__track { animation-direction: reverse; }
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

@keyframes slide {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.marquee__item {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.3rem;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font: 600 0.94rem/1 var(--font-display);
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.marquee__item:hover { color: var(--text); border-color: var(--border-strong); }
.marquee__item .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* ==========================================================================
   4. ALUMNI OUTCOME CARDS
   Deliberately not styled as testimonials. A testimonial says the programme
   was good; these say where the student ended up, which is the claim a grant
   reviewer actually weighs.
   ========================================================================== */

.outcomes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
  gap: 1rem;
  margin-top: 2.5rem;
}

/* Five alumni, not four, since the anonymous "And more" card was split into
   named cards for Nitya and Marcin. auto-fit at minmax(238px) resolves to four
   columns in the 1200px container - 5x238 + 4x16 = 1254 - which would strand
   the fifth card alone on row two, the last-row-orphan fault the review
   flagged across the card grids. Pin five equal columns once there is room for
   them; below that the auto-fit fallback takes over and reflows honestly. */
@media (min-width: 1080px) {
  /* 16 Sep: only alumni with a photograph are shown, currently three. */
  .outcomes { grid-template-columns: repeat(3, 1fr); }
}

.outcome {
  position: relative;
  padding: 1.6rem;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  background: var(--surface);
  overflow: hidden;
  transition: transform var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.outcome::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), transparent);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.outcome:hover { transform: translateY(-3px); border-color: var(--border-strong); }
.outcome:hover::before { opacity: 1; }

.outcome__avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  border: 1px solid var(--border);
  color: var(--accent);
  font: 600 1.05rem/1 var(--font-display);
  letter-spacing: -0.02em;
  margin-bottom: 1.15rem;
  overflow: hidden;
}
.outcome__avatar img { width: 100%; height: 100%; object-fit: cover; }

.outcome__name {
  font-family: var(--font-display);
  font-size: 1.12rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0 0 0.15rem;
}
.outcome__role {
  font-size: 0.86rem;
  color: var(--text-muted);
  margin: 0 0 1rem;
}
/* Stacked, not inline. This was `flex` + `align-items: baseline`, which put the
   prefix and the employer side by side as two flex items - fine while the
   prefixes were two words ("Engineer at" / "Apple"), but the 10 Sep role
   corrections made them four ("Backend engineering intern at"). The prefix
   then wrapped inside its own flex item while the bold employer stayed
   baseline-aligned to the prefix's FIRST line, so "PayPal" floated up and
   right, visually detached from the sentence it belongs to. That is the same
   two-columns-wrapping-independently fault the review flagged on /alumni.

   Stacking makes the card read the same way at any prefix length, and puts
   the employer - the part a grant reviewer actually scans for - on its own
   line where it carries. */
.outcome__now {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-faint);
}
.outcome__now b {
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}

/* ==========================================================================
   5. ECOSYSTEM PIPELINE (K-5 through Industry)
   ========================================================================== */

.pipeline {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin-top: 3rem;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--surface);
}
.pipeline__stage {
  padding: 1.6rem 1.35rem;
  border-right: 1px solid var(--border);
  position: relative;
  transition: background var(--dur-base) var(--ease-out);
}
.pipeline__stage:last-child { border-right: 0; }
.pipeline__stage:hover { background: var(--surface-2); }
.pipeline__stage h3 {
  font: 600 0.94rem/1.2 var(--font-display);
  letter-spacing: -0.01em;
  margin: 0 0 0.55rem;
}
.pipeline__stage p {
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--text-muted);
  margin: 0;
}
.pipeline__idx {
  display: block;
  font: 500 0.68rem/1 var(--font-mono);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.85rem;
}
@media (max-width: 900px) {
  .pipeline { grid-template-columns: 1fr 1fr; }
  .pipeline__stage { border-bottom: 1px solid var(--border); }
}
@media (max-width: 520px) {
  .pipeline { grid-template-columns: 1fr; }
  .pipeline__stage { border-right: 0; }
}

/* A grid or flex child defaults to min-width:auto, so it refuses to shrink
   below its own content. That let the financial table on /about widen its
   column to 520px inside a 390px viewport and scroll the whole page
   sideways, instead of scrolling inside its own .scroll-x container. */
.split > *,
.grid > * {
  min-width: 0;
}
.scroll-x {
  min-width: 0;
  max-width: 100%;
}

/* A button whose destination we do not have yet. The placeholder goes BELOW
   the button, never inside its href - putting markup in an attribute breaks
   the attribute, which is exactly what the first attempt did. */
.needs-url {
  margin-top: 0.7rem !important;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--text-faint);
}
.needs-url::before {
  content: "Needs: ";
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}

/* ==========================================================================
   6. CONTRAST FIXES carried over from the 25 Aug notes
   White text was sitting directly on photography. Any caption or label over
   an image now gets a real gradient behind it.
   ========================================================================== */

/* THE BAD ONE. Every hero stays cinematic dark in both skins - that is a
   deliberate call in tokens.css, because a white scrim over black-backdrop
   photography just turns it grey. But .hero h1 and .hero .lead were left
   inheriting --text, which on the light skin is #0b1220. Near-black type on a
   dark scrim measured 1.08:1 on /about, /programs and /donate: invisible.
   Pin the hero's own light-on-dark scale here, independent of skin. */
.hero .hero__inner,
.hero .hero__inner h1,
.hero .hero__inner h2 {
  color: #f4f7fb; /* 8.4:1 measured on the video hero, 4.4:1 on the photo heroes */
}
.hero .hero__inner .lead {
  color: #dfe6ee; /* 11.6:1 / 6.0:1 measured */
}
.hero .hero__inner .eyebrow {
  color: #8fd4ff; /* 4.6:1 measured */
}
.brand-sharkmakers .hero .hero__inner .eyebrow {
  color: #7ef0dd; /* the programme accent, lifted to 11.6:1 for the same job */
}
/* A secondary button on the hero is outlined, so its label needs the same
   treatment as the surrounding copy rather than the page's text token. */
.hero .hero__actions .btn-secondary,
.hero .hero__actions .btn-ghost {
  color: #f4f7fb;
  border-color: rgba(255, 255, 255, 0.42);
}
.hero .hero__actions .btn-secondary:hover,
.hero .hero__actions .btn-ghost:hover {
  border-color: rgba(255, 255, 255, 0.75);
}

/* Preview chrome, but it should not fail its own audit. The unpressed skin
   button was inheriting --text-muted against a surface it does not sit on. */
.skin-switch button {
  color: var(--text);
}
.skin-switch button[aria-pressed="true"] {
  color: var(--accent-ink);
}

.figure { position: relative; }
.photo-strip img { filter: var(--photo-treatment); }

.on-media {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 3rem 1.25rem 1rem;
  color: #f2f6fa;
  background: linear-gradient(180deg, transparent, rgba(4, 6, 9, 0.88) 72%);
  font-size: 0.82rem;
}

/* ==========================================================================
   8. MILESTONE RAIL - the compact history, /sharkmakers only
   The full tablist was rendered verbatim on both `/` and `/sharkmakers`. This
   is the flagship page's version: same seven milestones out of the same ERAS
   list, one line each, static. No tabs, no panels, no second tab stop.
   ========================================================================== */

.railway {
  list-style: none;
  margin: 2.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  /* Four across, not five. Seven milestones into a five-column grid left two
     on the second row - the last-row orphan fault the review flagged across
     the card grids - and the three empty cells rendered as a visible grey
     block, because the hairline grid was faked with `gap: 1px` over a
     --border container background. 4 + 3 is a far less ragged break, and the
     hairlines below are drawn per item so an empty cell is genuinely absent
     rather than merely a different colour. */
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
@media (min-width: 1000px) {
  .railway { grid-template-columns: repeat(4, 1fr); }
}

.railway__step {
  background: var(--surface);
  padding: 1.5rem 1.35rem 1.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  position: relative;
  /* Hairlines belong to the item, so the ragged last row simply ends. */
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
/* A hairline tick in the accent along the top edge, so the row scans as a
   sequence rather than as five unrelated tiles. */
.railway__step::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 26px;
  height: 2px;
  background: var(--accent);
}

.railway__year {
  font: 600 0.82rem/1 var(--font-mono);
  letter-spacing: var(--tracking-eyebrow);
  color: var(--accent);
}
.railway__tag {
  font: 600 1.02rem/1.25 var(--font-display);
  letter-spacing: -0.015em;
  color: var(--text);
}
.railway__what {
  margin: 0.3rem 0 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--text-muted);
}

/* ==========================================================================
   9. JUDGES BAND - where the Kevin Harrington endorsement went
   He was the hero thumbnail and the brightest object on the page: a warm
   domestic living room against a near-black lab register. The grade below is
   the "re-treat" half of demote-or-re-treat - it cools the cast and drops the
   highlights so the still sits in the page's register instead of fighting it.
   ========================================================================== */

.judges__row {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: center;
  margin-top: 2rem;
}
@media (min-width: 900px) {
  .judges__row { grid-template-columns: 0.85fr 1fr; }
}
.judges__card { margin: 0; }
.judges__card .videocard img {
  /* Pull the warm living room down toward the plate so the still stops being
     the brightest object in view.

     Desaturation and exposure ONLY. A first pass used hue-rotate to cool the
     cast and it turned a real person's skin green - which is both worse
     design and not a thing to do to somebody who did the organisation a
     favour on camera. Neutral desaturation gets the same "sits in the
     register" result and leaves him looking like himself. */
  filter: saturate(0.45) contrast(1.05) brightness(0.8);
  transition: filter var(--dur-slow, 400ms) var(--ease-out, ease),
              transform var(--dur-slow, 400ms) var(--ease-out, ease);
}
/* Hover restores him. The grade is there to keep him quiet at rest, not to
   hide what the visitor is about to click. */
.judges__card .videocard:hover img {
  filter: saturate(0.9) contrast(1.02) brightness(0.95);
}
.judges__copy h2 { max-width: 20ch; }
.judges__copy .lead { max-width: 46ch; }

/* ==========================================================================
   10. LOCAL SCRIM UNDER PHOTO-HERO TYPE
   /about's headline line 2 crosses a bright face at x~700-870 and the type
   loses its edge against it. The global hero scrim (tokens.css:97) is
   deliberately light at the top - 0.12 - so that students stay visible on
   black-backdrop photography, and that is the right call and must not change.

   So the darkening is LOCAL: a soft pool behind the copy column only, thrown
   from the bottom-left where the type sits, falling to nothing before it
   reaches the right 40% of the frame where the faces are. The photo heroes
   only - .hero--video already carries its own measured two-axis scrim, and
   .hero--split has no photograph behind its type at all.
   ========================================================================== */

.hero:not(.hero--video):not(.hero--split) .hero__inner {
  position: relative;
  isolation: isolate;
}
.hero:not(.hero--video):not(.hero--split) .hero__inner::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* Bleeds well past the container on the left so the pool reaches the
     viewport edge rather than stopping at the 1200px gutter. */
  inset: -2.5rem 0 -2.5rem -50vw;
  pointer-events: none;
  background: radial-gradient(ellipse 78% 118% at 26% 62%,
    rgba(4, 6, 9, 0.66) 0%,
    rgba(4, 6, 9, 0.34) 46%,
    rgba(4, 6, 9, 0) 72%);
}

/* ==========================================================================
   7. REDUCED MOTION - everything above degrades to static.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; flex-wrap: wrap; width: 100%; }
  .marquee { mask-image: none; overflow: visible; }
  .hero__hint { display: none; }
  .history__fin,
  .history__progress { transition: none; }
  .history__fin svg { animation: none; }
  .history__panel { animation: none; }
  .outcome:hover { transform: none; }
}

/* ==========================================================================
   SPLIT HERO - copy left, one named video right
   Used on the SharkMakers page. The homepage keeps .hero--video, so the two
   pages no longer open on the same footage.
   ========================================================================== */

.hero--split {
  /* REBUILT 10 Sep. This block used to read `min-height: 0; display: block`,
     which was the one place in the codebase that explicitly opted a hero out
     of the pack's "hero treatment is cinematic dark in both skins" - on the
     flagship programme's own landing page. The result was ~95px of dead plate
     above the eyebrow, no atmosphere, and the weakest fold on the site.

     The two-column grid stays (the right column earns its place and going
     full-bleed would lose it). What comes back is presence: a real minimum
     height with the content vertically centred in it, so there is no dead
     plate above the eyebrow and the fold has somewhere to breathe. */
  min-height: clamp(560px, 78vh, 760px);
  display: flex;
  align-items: center;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-block: clamp(3rem, 7vh, 5rem);

  /* NOT var(--bg-deep). The base .hero hard-codes white type because it always
     sits on dark footage; --bg-deep is #f4f6f9 in the light skin, which would
     put white type on near-white. The recorded decision is that heroes are
     cinematic dark in BOTH skins, so this plate is dark in both. */
  background: #06080b;
}

/* The lab glow. --accent-sm at roughly 6% over the near-black, thrown from the
   top-left behind the copy so the headline sits in the brightest part of the
   plate and the plate falls away to #06080b before it reaches the photograph.
   This is what makes the sub-brand feel like a different place rather than the
   parent page in a different wordmark, and it costs two tokens and no markup
   weight. Deliberately NOT a colour block: sampled at its brightest the plate
   is #0d2b28, which leaves the h1 at #f4f7fb well clear of AA. */
.hero--split .hero__plate {
  position: absolute;
  inset: 0;
  /* NEGATIVE, and that is load-bearing. .hero--split isolates, so -3/-2 paint
     above this section's own background but below its in-flow content - which
     lets .hero__split stay at `z-index: auto` and therefore NOT form a
     stacking context of its own. That is the only reason the photograph's
     mix-blend-mode: lighten can see the plate as its backdrop. Give
     .hero__split a z-index and the blend silently stops working. */
  z-index: -3;
  pointer-events: none;
  background:
    radial-gradient(ellipse 120% 90% at 15% 0%,
      color-mix(in srgb, var(--accent) 16%, #06080b) 0%,
      #06080b 62%);
}

/* Same 72px lattice as the video hero, same radial mask. The homepage hero's
   only real texture is this grid; carrying it here is what ties the two folds
   together as one system while the colour tells them apart. */
.hero--split .hero__grid {
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 80% 70% at 30% 30%, #000 30%, transparent 78%);
}

/* The fin, used big and used once. PLAN records it as "the best asset either
   brand has" and until now it appeared only at 8px as an eyebrow bullet. It
   bleeds off the right edge behind the photograph at 4% so it reads as
   watermark rather than as a graphic sitting on the plate. currentColor picks
   up --accent, which is the programme teal on this page. */
.hero--split .hero__fin {
  position: absolute;
  z-index: -2;
  /* Fully in frame, not bled off the edge. Cropped against the section edge
     the silhouette stopped reading as a fin and became an ambiguous soft
     wedge, which is decoration - exactly what the pack's "spending it on
     decoration" warning is about. Whole shape, once, quiet. */
  right: clamp(1.5rem, 4vw, 4rem);
  bottom: clamp(1rem, 3vh, 2.5rem);
  width: clamp(180px, 19vw, 250px);
  color: var(--accent);
  opacity: 0.09;
  pointer-events: none;
  line-height: 0;
}
.hero--split .hero__fin svg { width: 100%; height: auto; display: block; }

@media (max-width: 900px) {
  /* Behind a stacked single column the fin turns into noise under the type,
     and the plate is doing the atmosphere work on its own by then. */
  .hero--split .hero__fin { display: none; }
  .hero--split { min-height: 0; }
}

.hero__split {
  position: relative;   /* no z-index - see .hero--split .hero__plate */
  width: 100%;
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

/* The right column. The photograph is a cut-out on black, so it is deliberately
   NOT boxed in a card with a border and a radius the way .videocard was - a
   frame around it would re-create exactly the bright rectangle this fold was
   rebuilt to remove. It dissolves into the plate instead. */
.hero__plate-photo {
  margin: 0;
  position: relative;
}
.hero__plate-photo img {
  width: 100%;
  height: auto;
  display: block;
  filter: var(--photo-treatment);

  /* The source is a subject cut out on black, but "black" in the webp is a
     shade or two off the plate's #06080b, so a plain <img> showed a hard
     rectangular seam on all four edges - re-creating the boxed-bright-object
     problem this fold was rebuilt to remove. A four-sided feather mask only
     fixed two edges, because the seam is a colour difference and not an
     alpha one.

     `lighten` is the actual fix: max(source, backdrop) per channel, so every
     pixel of the photo darker than the plate simply IS the plate and the
     rectangle stops existing, while the students - all well above the plate's
     luminance - pass through untouched. The teal glow reads through the empty
     black exactly as it does across the rest of the fold.

     Guarded: if a browser does not support mix-blend-mode it falls back to a
     normal composite, which is the hard-edged version - correct, just less
     good. The subject is never at risk either way. */
  mix-blend-mode: lighten;
}

@supports not (mix-blend-mode: lighten) {
  /* Feather the edges instead, so the seam is at least soft. */
  .hero__plate-photo img {
    mask-image: radial-gradient(ellipse 82% 82% at 50% 45%, #000 58%, transparent 100%);
  }
}

/* The light skin flips the ground to white, where `lighten` against a light
   backdrop would erase the whole photograph. The recorded decision is that
   heroes stay cinematic dark in BOTH skins and this plate is #06080b either
   way - but the blend mode is composited against whatever actually sits
   behind, so it is pinned to the plate explicitly rather than left to inherit
   a stacking context that might change. */
.hero--split .hero__split { background: transparent; }
.hero__plate-photo figcaption {
  margin-top: var(--s-3);
  font: 500 0.78rem/1.5 var(--font-mono);
  letter-spacing: 0.02em;
  color: #b9c4d1; /* 7.9:1 on the #06080b plate */
}
@media (min-width: 900px) {
  .hero__split { grid-template-columns: 1.05fr 1fr; }
}
.hero--split h1 {
  font-size: clamp(2.4rem, 5.2vw, 4.2rem);
  line-height: 1.04;
  letter-spacing: var(--tracking-display);
  max-width: 15ch;
  margin: 0.6rem 0 1.3rem;
  text-wrap: balance;
}
.hero--split .lead { max-width: 46ch; }

/* The card is one link. The play badge is decoration on top of it, never a
   second tab stop, and the focus ring belongs to the anchor. */
.videocard {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  background: var(--surface);
  line-height: 0;
}
.videocard img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  transition: transform var(--dur-slow, 400ms) var(--ease-out, ease);
}
.videocard:hover img { transform: scale(1.03); }
.videocard:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.videocard__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.videocard__play svg {
  position: relative;
  z-index: 1;
  width: 26px;
  height: 26px;
  margin-left: 3px; /* optical centring - a triangle's mass sits left of centre */
  color: #0b1220;
}
.videocard__play::before {
  content: "";
  position: absolute;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, 0.55);
  transition: transform var(--dur-fast, 180ms) var(--ease-out, ease);
}
.videocard:hover .videocard__play::before { transform: scale(1.06); }

.videocard__cap {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: var(--s-3) 0 0;
  font-size: 0.875rem;
  line-height: 1.4;
}
.videocard__cap strong { color: var(--text); font-weight: 600; }
.videocard__cap span { color: var(--text-muted); }

.hero__video { margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .videocard img,
  .videocard__play::before { transition: none; }
  .videocard:hover img { transform: none; }
}

/* ==========================================================================
   V1 (16 Sep 2026) - Robyn's 11 Sep recap
   Mission, three-figure stat band, hero feature video, Student Journey,
   program materials links.
   ========================================================================== */

/* Three lifetime figures, not four. */
@media (min-width: 900px) {
  .statband__grid--3 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 899px) {
  .statband__grid--3 { grid-template-columns: 1fr; }
}

/* Mission - one of the first things a visitor reads. */
.mission { padding-block: clamp(3rem, 7vw, 5.5rem); }
.mission__lead {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.6vw, 2.1rem);
  line-height: 1.3;
  max-width: 44ch;
  margin-top: var(--s-4);
  color: var(--text);
}
.mission__lead strong { color: var(--accent); font-weight: 700; }
.mission__close {
  max-width: 62ch;
  margin-top: var(--s-5);
  font-size: 1.125rem;
  color: var(--text-muted);
}

/* Hero with the Kevin Harrington video beside the copy. */
.hero__inner--feature { display: grid; gap: var(--s-6); align-items: end; }
@media (min-width: 1000px) {
  .hero__inner--feature { grid-template-columns: 1.05fr 1fr; gap: var(--s-7); }
  .hero__inner--feature h1 { font-size: clamp(2.6rem, 4.6vw, 4.4rem); }
}
.hero .feature-video .videocard__cap strong { color: #f4f7fb; }
.hero .feature-video .videocard__cap span { color: #dfe6ee; }

.feature-video { margin: 0; }
.feature-video video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
  border: 1px solid var(--border-strong);
  background: #000;
  box-shadow: var(--shadow);
}
.feature-video--portrait { max-width: 340px; justify-self: center; }
.alumni-feature { align-items: center; margin-bottom: var(--s-7); }

/* Student Journey. Simplified on Home, detailed on SharkMakers.
   Five stages on a rail: the line and its nodes say that a team walks the
   stages in order, which five separate boxes did not. Desktop runs the rail
   across the top of the cards, mobile runs it down the left. Everything here
   rests in its finished state - v2.js only adds .is-armed/.is-on to play it
   in, and not at all under prefers-reduced-motion. */
/* The rail lives in the wrap's own top padding, above the cards, and each
   card's node reaches up into it. The cards therefore cannot clip their own
   nodes - which is why nothing here hides overflow. */
.journey-wrap {
  position: relative;
  margin-top: var(--s-7);
  padding-top: 2.1rem;
}

.journey__rail {
  position: absolute;
  left: 0; right: 0;
  top: 0.65rem;
  height: 2px;
  background: color-mix(in srgb, var(--border) 85%, transparent);
  overflow: hidden;
}
.journey__rail-fill {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg,
              var(--accent-sm, var(--accent)),
              color-mix(in srgb, var(--accent-sm, var(--accent)) 35%, transparent));
  transform-origin: left center;
}

.journey {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--s-3);
}
@media (min-width: 900px) {
  .journey { grid-template-columns: repeat(5, 1fr); }
}
.journey__stage {
  position: relative;
  padding: var(--s-5);
  /* Room for the numeral above the title, so titles keep the full width
     rather than wrapping around it. */
  padding-top: 3rem;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1),
              border-color 0.3s ease, background 0.3s ease, opacity 0.35s ease;
}
/* The node that sits the card on the rail. */
.journey__dot {
  position: absolute;
  top: -1.77rem;
  left: var(--s-5);
  width: 0.7rem; height: 0.7rem;
  border-radius: 50%;
  background: var(--bg-deep);
  border: 2px solid var(--accent-sm, var(--accent));
  transition: background 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}
/* The stage number IS the card's figure, set large in the top right. It
   replaced a small mono index in the top left: two copies of the same number
   on one card, and the big one was sitting under the body text. */
.journey__ghost {
  position: absolute;
  right: 0.85rem;
  top: 0.35rem;
  font-family: var(--font-display, inherit);
  font-size: 2.9rem;
  font-weight: 800;
  line-height: 1;
  color: var(--accent-sm, var(--accent));
  opacity: 0.22;
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.journey__stage h3 { font-size: 1.05rem; line-height: 1.25; margin: 0; }
.journey__stage p { margin: var(--s-3) 0 0; color: var(--text-muted); font-size: 0.95rem; }
.journey--detailed .journey__stage { padding-bottom: var(--s-6); }

@media (hover: hover) {
  .journey__stage:hover {
    transform: translateY(-4px);
    border-color: color-mix(in srgb, var(--accent-sm, var(--accent)) 55%, var(--border));
    background: color-mix(in srgb, var(--accent-sm, var(--accent)) 6%, var(--surface));
  }
  .journey__stage:hover .journey__dot {
    background: var(--accent-sm, var(--accent));
    transform: scale(1.15);
    box-shadow: 0 0 0 4px color-mix(in srgb,
                var(--accent-sm, var(--accent)) 22%, transparent);
  }
  .journey__stage:hover .journey__ghost { opacity: 0.5; }
}

/* ---- Entrance, added by v2.js only ---- */
.journey-wrap.is-armed .journey__stage { opacity: 0; transform: translateY(14px); }
.journey-wrap.is-armed .journey__rail-fill { transform: scaleX(0); }
.journey-wrap.is-armed .journey__dot { transform: scale(0); }

.journey-wrap.is-on .journey__rail-fill {
  transform: scaleX(1);
  transition: transform 0.75s cubic-bezier(0.22, 0.7, 0.25, 1);
}
.journey-wrap.is-on .journey__stage {
  opacity: 1;
  transform: none;
  transition-delay: calc(var(--i, 0) * 45ms + 90ms);
}
.journey-wrap.is-on .journey__dot {
  transform: scale(1);
  transition-delay: calc(var(--i, 0) * 45ms + 140ms);
}

@media (prefers-reduced-motion: reduce) {
  .journey__stage, .journey__dot, .journey__rail-fill { transition: none; }
}

@media (max-width: 899px) {
  /* Stacked, the rail runs down the left and the cards hang off it. */
  .journey-wrap { padding-left: 1.6rem; padding-top: 0; }
  .journey__rail {
    left: 0.3rem; right: auto;
    top: 0.9rem; bottom: 0.9rem;
    width: 2px; height: auto;
  }
  .journey__rail-fill {
    width: 100%;
    background: linear-gradient(180deg,
                var(--accent-sm, var(--accent)),
                color-mix(in srgb, var(--accent-sm, var(--accent)) 35%, transparent));
    transform-origin: top center;
  }
  .journey-wrap.is-armed .journey__rail-fill { transform: scaleY(0); }
  .journey-wrap.is-on .journey__rail-fill { transform: scaleY(1); }
  /* Stacked, the numeral sits beside the title rather than above it, so the
     title needs the room reserved. */
  .journey__stage { padding-top: var(--s-5); }
  .journey__stage h3 { padding-right: 3.2rem; }
  .journey__dot {
    top: 1.6rem;
    left: -1.95rem;
    background: var(--accent-sm, var(--accent));
  }
  .journey__ghost { font-size: 2.4rem; }
}

/* Canva materials under each registration button. */
.materials {
  list-style: none;
  padding: 0;
  margin: var(--s-4) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  font-size: 0.875rem;
}
.materials a { color: var(--text-muted); text-underline-offset: 3px; }
.materials a:hover { color: var(--text); }

/* Calendar audience filter. */
.cal-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--s-4) var(--s-5);
  margin: 0;
  background: var(--surface);
}
.cal-filter legend { float: left; margin: 0 var(--s-3) 0 0; padding: 0; }
.cal-filter__opt { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 500; cursor: pointer; }
.cal-filter__opt input { width: 1.1rem; height: 1.1rem; accent-color: var(--accent); }
.cal-filter__empty { width: 100%; margin: 0; color: var(--text-muted); }

/* ==========================================================================
   Homepage pass 2 (16 Sep): logo marquee, pillar icons, judges photo
   ========================================================================== */

/* One line of principal partner logos, scrolling forever. Spacing lives on
   the items (padding), not a track gap, so both halves of the doubled list
   are the same width and the -50% loop has no jump. */
.logo-marquee-band {
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-bottom: 1px solid var(--border);
}
.logo-marquee-band .partner-wall__label { text-align: center; margin-bottom: var(--s-4); }
.logo-marquee { padding: 0; mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); }
.logo-marquee__track {
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 0;
  align-items: center;
  animation-duration: 38s;
}
.logo-marquee__item {
  flex: none;
  display: flex;
  align-items: center;
  height: 64px;
  padding-inline: clamp(1.5rem, 3vw, 2.75rem);
}
.logo-marquee__item img {
  height: var(--cap, 32px);
  width: auto;
  max-width: 190px;
  object-fit: contain;
}
[data-logos="mono"] .logo-marquee__item img { filter: var(--logo-filter); }
@media (max-width: 640px) {
  .logo-marquee__item img { height: calc(var(--cap, 32px) * 0.8); max-width: 140px; }
}
@media (prefers-reduced-motion: reduce) {
  .logo-marquee__track { flex-wrap: wrap; justify-content: center; width: 100%; }
}

/* What We Do pillars: a colored line icon on a soft tint of the same color. */
.pillar__icon {
  display: inline-grid;
  place-items: center;
  width: 3.75rem;
  height: 3.75rem;
  border-radius: 16px;
  margin-bottom: var(--s-4);
  color: var(--pill);
  background: color-mix(in srgb, var(--pill) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--pill) 32%, transparent);
}
.pillar__icon svg { width: 1.9rem; height: 1.9rem; }
.pillar__icon--blue   { --pill: #5aa9ff; }
.pillar__icon--amber  { --pill: #ffb84d; }
.pillar__icon--pink   { --pill: #f472b6; }
.pillar__icon--green  { --pill: #4ade80; }
.pillar__icon--gold   { --pill: #facc15; }
.pillar__icon--violet { --pill: #a78bfa; }
:root[data-skin="light"] .pillar__icon--blue   { --pill: #1b4de4; }
:root[data-skin="light"] .pillar__icon--amber  { --pill: #b45309; }
:root[data-skin="light"] .pillar__icon--pink   { --pill: #be185d; }
:root[data-skin="light"] .pillar__icon--green  { --pill: #15803d; }
:root[data-skin="light"] .pillar__icon--gold   { --pill: #a16207; }
:root[data-skin="light"] .pillar__icon--violet { --pill: #6d28d9; }

/* The judges band now shows the finalists photograph. */
.judges__photo { margin: 0; }
.judges__photo img { max-width: 520px; margin-inline: auto; mix-blend-mode: normal; border-radius: var(--r-lg); }
.judges__photo figcaption { color: var(--text-muted); }

/* SharkMakers hero with the video in the right column. */
.hero--split .feature-video { align-self: center; }
.hero--split .feature-video .videocard__cap strong { color: #f4f7fb; }
.hero--split .feature-video .videocard__cap span { color: #dfe6ee; }

/* ==========================================================================
   Calendar and event registration (Sep 16)
   ========================================================================== */

/* Audience colors, one per group, used by badges, chips and the legend. */
:root { --aud-hs: #5aa9ff; --aud-college: #a78bfa; --aud-open: #4ade80; }
:root[data-skin="light"] { --aud-hs: #1b4de4; --aud-college: #6d28d9; --aud-open: #15803d; }

.aud {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font: 600 0.72rem/1 var(--font-body, inherit); letter-spacing: 0.02em;
  padding: 0.3rem 0.55rem; border-radius: 999px;
  color: var(--aud, var(--text-muted));
  background: color-mix(in srgb, var(--aud, var(--text-muted)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--aud, var(--text-muted)) 35%, transparent);
}
.aud--hs { --aud: var(--aud-hs); }
.aud--college { --aud: var(--aud-college); }
.aud--open { --aud: var(--aud-open); }
.aud--tentative { --aud: var(--signal); }

.cal-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center;
  justify-content: space-between;
}
.cal-toolbar .cal-filter { flex: 1 1 auto; }
.cal-filter__opt--hs input { accent-color: var(--aud-hs); }
.cal-filter__opt--college input { accent-color: var(--aud-college); }
.cal-filter__opt--open input { accent-color: var(--aud-open); }

.cal-views {
  display: inline-flex; border: 1px solid var(--border); border-radius: 999px; padding: 3px;
  background: var(--surface);
}
.cal-view {
  font: 600 0.9rem/1 inherit; color: var(--text-muted); background: transparent;
  border: 0; border-radius: 999px; padding: 0.6rem 1.1rem; cursor: pointer;
}
.cal-view[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }
.cal-view:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.cal-legend { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-4) 0 0; }
.cal-empty { margin-top: var(--s-5); color: var(--text-muted); }

/* Month view */
.cal-monthview { margin-top: var(--s-5); }
.cal-nav { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-4); }
.cal-nav__label { margin: 0; font: 700 1.35rem/1.2 var(--font-display); }
.cal-nav__btn {
  width: 2.75rem; height: 2.75rem; border-radius: 999px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); font-size: 1.1rem; cursor: pointer;
}
.cal-nav__btn:disabled { opacity: 0.35; cursor: default; }
.cal-nav__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cal-month__title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  border-top: 1px solid var(--border); border-left: 1px solid var(--border);
  border-radius: var(--r-lg); overflow: hidden;
}
.cal-dow {
  padding: 0.55rem 0.6rem; font: 500 0.72rem/1 var(--font-mono); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-faint); background: var(--surface);
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
.cal-cell {
  min-height: 7.25rem; padding: 0.45rem; display: flex; flex-direction: column; gap: 0.3rem;
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.cal-cell--pad { background: color-mix(in srgb, var(--surface) 55%, transparent); }
.cal-cell__n { font: 500 0.8rem/1 var(--font-mono); color: var(--text-muted); }
.cal-cell.is-today .cal-cell__n {
  color: var(--accent-ink); background: var(--accent); border-radius: 999px;
  width: 1.6rem; height: 1.6rem; display: grid; place-items: center;
}
.cal-cell.is-past { opacity: 0.55; }
.cal-chip {
  --c: var(--aud-hs);
  display: block; width: 100%; text-align: left; cursor: pointer;
  font: 600 0.75rem/1.25 inherit; color: var(--text);
  padding: 0.3rem 0.4rem; border-radius: 6px; border: 0;
  border-left: 3px solid var(--c);
  background: color-mix(in srgb, var(--c) 16%, transparent);
}
.cal-chip:hover { background: color-mix(in srgb, var(--c) 26%, transparent); }
.cal-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cal-chip--college { --c: var(--aud-college); }
.cal-chip--open { --c: var(--aud-open); }
.cal-chip__t { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

@media (max-width: 720px) {
  .cal-cell { min-height: 3.6rem; padding: 0.25rem; }
  .cal-dow { padding: 0.45rem 0.2rem; text-align: center; font-size: 0.62rem; }
  /* A tap target, not a hairline: the visible bar sits inside a 24px button. */
  .cal-chip { height: 1.5rem; padding: 0.5rem 0; border-left: 0; border-radius: 4px;
              background: linear-gradient(var(--c), var(--c)) center / 100% 0.45rem no-repeat; }
  .cal-chip__t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}

/* List view */
.cal-listview { margin-top: var(--s-5); }
.evt-month + .evt-month { margin-top: var(--s-7); }
.evt-month__title { font: 700 1.2rem/1.2 var(--font-display); margin: 0 0 var(--s-4); }
.evt-list { display: grid; gap: var(--s-3); }
.evt {
  display: grid; grid-template-columns: 4.5rem 1fr; gap: var(--s-5);
  padding: var(--s-5); border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface);
}
.evt__date {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border-radius: 12px; background: var(--bg); border: 1px solid var(--border);
  height: 4.5rem;
}
.evt__mon { font: 500 0.72rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); }
.evt__day { font: 700 1.7rem/1.1 var(--font-display); }
.evt__badges { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0 0 0.6rem; }
.evt__title { margin: 0; font-size: 1.2rem; }
.evt__when { margin: 0.35rem 0 0; font-weight: 600; }
.evt__where { margin: 0.15rem 0 0; color: var(--text-muted); }
.evt__blurb { margin: 0.6rem 0 0; color: var(--text-muted); max-width: 62ch; }
.evt__note { margin: 0.8rem 0 0; font-size: 0.9rem; color: var(--text-muted); }
.evt .btn-sm { margin-top: 1rem; }
.btn-sm { padding: 0.55rem 1rem; font-size: 0.9rem; }
@media (max-width: 560px) {
  .evt { grid-template-columns: 1fr; gap: var(--s-3); }
  .evt__date { flex-direction: row; gap: 0.5rem; height: auto; padding: 0.4rem 0.75rem; justify-self: start; }
  .evt__day { font-size: 1.1rem; }
}

/* Event dialog */
.evt-dialog {
  width: min(32rem, calc(100vw - 2rem)); padding: var(--s-6); border: 1px solid var(--border-strong);
  border-radius: var(--r-lg); background: var(--surface); color: var(--text);
}
.evt-dialog::backdrop { background: rgba(4, 6, 9, 0.7); }
.evt-dialog__close {
  position: absolute; top: 0.6rem; right: 0.6rem; width: 2.5rem; height: 2.5rem;
  border: 0; border-radius: 999px; background: transparent; color: var(--text-muted);
  font-size: 1.6rem; cursor: pointer;
}
.evt-dialog__title { margin: 0.2rem 0 0; font-size: 1.5rem; }

/* ===========================================================================
   Event cards - the picker, the confirmation, and the parts they share
   ===========================================================================
   Arel, Sep 25: the registration pages "read as just one big block of text"
   and should feel like an actual event registration. Three devices out of the
   Luma references do most of that work, and all three are shared by the
   server-rendered picker (pages_events.py) and the confirmation cards v2.js
   draws from the query string:

     .ico        icons as CSS masks, painted with currentColor. A mask rather
                 than inline SVG precisely BECAUSE two renderers draw these
                 cards - one in Python, one in JavaScript. Neither ships an
                 SVG, and there is one definition to change.
     .evt-meta   an icon, a strong line, and a muted line under it. This is
                 what replaced "Thursday, November 5, 2026 - 5:30-8 PM ET -
                 Tampa, FL - In person" running together as one grey sentence.
     the chip    month over day. Already the calendar's idiom (.evt__date),
                 reused rather than reinvented, so one event looks like itself
                 wherever it turns up.
*/

.ico {
  display: inline-block; width: 1.05rem; height: 1.05rem; flex: 0 0 auto;
  background: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
}
.ico--when    { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%275%27%20width%3D%2718%27%20height%3D%2716%27%20rx%3D%272.5%27%2F%3E%3Cpath%20d%3D%27M3%2010h18M8%203v4M16%203v4%27%2F%3E%3C%2Fsvg%3E");    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%275%27%20width%3D%2718%27%20height%3D%2716%27%20rx%3D%272.5%27%2F%3E%3Cpath%20d%3D%27M3%2010h18M8%203v4M16%203v4%27%2F%3E%3C%2Fsvg%3E"); }
.ico--where   { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2021.2S19%2015%2019%2010.2a7%207%200%201%200-14%200C5%2015%2012%2021.2%2012%2021.2Z%27%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2710%27%20r%3D%272.6%27%2F%3E%3C%2Fsvg%3E");   mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%2021.2S19%2015%2019%2010.2a7%207%200%201%200-14%200C5%2015%2012%2021.2%2012%2021.2Z%27%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2710%27%20r%3D%272.6%27%2F%3E%3C%2Fsvg%3E"); }
.ico--virtual { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%275%27%20width%3D%2714%27%20height%3D%2714%27%20rx%3D%272.5%27%2F%3E%3Cpath%20d%3D%27m22%208.5-6%203.5%206%203.5v-7Z%27%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%275%27%20width%3D%2714%27%20height%3D%2714%27%20rx%3D%272.5%27%2F%3E%3Cpath%20d%3D%27m22%208.5-6%203.5%206%203.5v-7Z%27%2F%3E%3C%2Fsvg%3E"); }

/* --- when / where rows --- */

.evt-meta { display: flex; flex-direction: column; gap: 0.55rem; margin-top: 0.7rem; }
.evt-meta__row { display: flex; gap: 0.6rem; align-items: flex-start; }
.evt-meta__row .ico { margin-top: 0.15rem; color: var(--text-muted); }
.evt-meta__text { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.evt-meta__k { font-weight: 600; line-height: 1.35; }
.evt-meta__v { color: var(--text-muted); font-size: 0.88rem; line-height: 1.4; }

/* --- format label --- */

.fmt {
  display: inline-flex; align-items: center;
  font: 500 0.72rem/1.6 var(--font-mono); letter-spacing: 0.06em;
  text-transform: uppercase; padding: 0.1rem 0.5rem; border-radius: 999px;
  border: 1px solid var(--border-strong); color: var(--text-muted);
}
.fmt--virtual {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}

/* --- the picker --- */

.evt-picks { display: grid; gap: var(--s-3); margin-top: var(--s-3); }

.evt-pick {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr);
  gap: 0 var(--s-4); align-items: start; cursor: pointer;
  padding: var(--s-4) var(--s-5); border: 1px solid var(--border);
  border-radius: var(--r-lg); background: var(--surface);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.evt-pick:hover { border-color: var(--border-strong); }
.evt-pick:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.evt-pick:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}
.evt-pick input {
  margin-top: 0.85rem; width: 1.15rem; height: 1.15rem; accent-color: var(--accent);
}

.evt-pick__date {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 3.4rem; height: 3.4rem; border-radius: 12px;
  background: var(--bg); border: 1px solid var(--border);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.evt-pick__mon {
  font: 500 0.64rem/1 var(--font-mono); letter-spacing: 0.1em; color: var(--accent);
}
.evt-pick__day { font: 700 1.35rem/1.15 var(--font-display); }
/* Checked has to read from across the form, not by hunting for a tick. */
.evt-pick:has(input:checked) .evt-pick__date {
  background: var(--accent); border-color: var(--accent);
}
/* --accent-ink, not --bg. Both happen to resolve to the same thing in both
   skins today, so this fixes no live contrast bug - but --accent-ink is the
   token that CARRIES the contract for text sitting on the accent, it is
   contrast-checked per skin in tokens.css, and .brand-sharkmakers remaps it
   in the same rule that remaps --accent. Pointing at --bg would hold only
   for as long as the two stayed accidentally equal. */
.evt-pick:has(input:checked) .evt-pick__mon,
.evt-pick:has(input:checked) .evt-pick__day { color: var(--accent-ink); }

.evt-pick__body { display: flex; flex-direction: column; min-width: 0; }
.evt-pick__title { font: 700 1.08rem/1.3 var(--font-display); }
.evt-pick__aud {
  display: flex; gap: 0.35rem; flex-wrap: wrap; align-items: center; margin-top: 0.8rem;
}

@media (max-width: 560px) {
  .evt-pick {
    grid-template-columns: auto minmax(0, 1fr); gap: 0.7rem var(--s-3);
    padding: var(--s-4);
  }
  .evt-pick input { margin-top: 0.15rem; }
  /* The chip becomes a pill above the title. A 3.4rem square plus a checkbox
     leaves a long event name about 250px, which wraps it to four lines. */
  .evt-pick__date {
    grid-column: 2; grid-row: 1; flex-direction: row; gap: 0.45rem;
    width: auto; height: auto; padding: 0.25rem 0.6rem; justify-self: start;
    border-radius: 999px;
  }
  .evt-pick__day { font-size: 0.95rem; }
  .evt-pick__body { grid-column: 2; grid-row: 2; }
}

/* --- the confirmation --- */

.confirm-head { display: flex; gap: var(--s-4); align-items: flex-start; }
.confirm-head__mark {
  position: relative; flex: 0 0 auto; margin-top: 0.4rem;
  width: 2.6rem; height: 2.6rem; border-radius: 999px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
.confirm-head__mark::after {
  content: ""; position: absolute; inset: 0.62rem; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m4.5%2012.6%205%205L19.5%207%27%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m4.5%2012.6%205%205L19.5%207%27%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
}
@media (max-width: 560px) {
  .confirm-head { gap: var(--s-3); }
  .confirm-head__mark { width: 2.1rem; height: 2.1rem; margin-top: 0.2rem; }
  .confirm-head__mark::after { inset: 0.5rem; }
}

/* A list of cards, not one box with rules drawn through it. */
.evt-confirm {
  display: grid; gap: var(--s-3);
  margin-top: var(--s-6); padding: 0; border: 0; background: none; max-width: none;
}
.evt-confirm__one {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--s-4);
  align-items: start; padding: var(--s-5);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface);
}
.evt-confirm__date {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 3.6rem; height: 3.6rem; border-radius: 12px;
  background: var(--bg); border: 1px solid var(--border);
}
.evt-confirm__mon {
  font: 500 0.66rem/1 var(--font-mono); letter-spacing: 0.1em; color: var(--accent);
}
.evt-confirm__day { font: 700 1.45rem/1.15 var(--font-display); }
.evt-confirm__body { min-width: 0; }
.evt-confirm__title { margin: 0; font: 700 1.1rem/1.3 var(--font-display); }

@media (max-width: 560px) {
  .evt-confirm__one {
    grid-template-columns: minmax(0, 1fr); gap: 0.7rem; padding: var(--s-4);
  }
  .evt-confirm__date {
    flex-direction: row; gap: 0.45rem; width: auto; height: auto;
    padding: 0.25rem 0.6rem; justify-self: start; border-radius: 999px;
  }
  .evt-confirm__day { font-size: 1rem; }
}

/* --- what to register for next --- */

.next-up {
  margin-top: var(--s-6); padding: var(--s-5);
  border: 1px dashed var(--border-strong); border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.next-up p { margin: 0; max-width: 60ch; }
.next-up .eyebrow { margin: 0 0 0.4rem; }
.next-up__go { margin-top: var(--s-4) !important; }

:root { --aud-mentors: #ffb84d; }
:root[data-skin="light"] { --aud-mentors: #b45309; }
.aud--mentors { --aud: var(--aud-mentors); }
.cal-chip--mentors { --c: var(--aud-mentors); }
.cal-filter__opt--mentors input { accent-color: var(--aud-mentors); }
.evt__cta { margin: 1rem 0 0; }
.evt .btn-sm { margin-top: 0; }
