/* ==========================================================================
   Greensnake — Programs
   --------------------------------------------------------------------------
   Same dark editorial ground as Science, so the two non-Home pages read as a
   pair. The page-head, facts, section-head and ticker all come from
   components.css; what is specific here is the pale "stage" panel and the
   programme card.
   ========================================================================== */

.programs {
  background: var(--green-900);
  background-image:
    radial-gradient(120% 60% at 84% -12%, rgba(120, 133, 8, 0.26), transparent 62%),
    radial-gradient(80% 45% at 8% 2%, rgba(19, 101, 196, 0.16), transparent 72%);
  background-repeat: no-repeat;
}

.programs .page-head__title {
  font-family: var(--font-ui);
  font-weight: 500;
  letter-spacing: -0.035em;
  max-width: 22ch;
}

.programs .facts b { font-size: 1.25rem; }

/* ==========================================================================
   Partners ticker
   --------------------------------------------------------------------------
   Every gap in this row is the SAME gap, and that is enforced twice over:

     1. Each mark is exported onto an identical 360x200 canvas, scaled by
        optical area rather than by bounding box (scripts note in the export).
        Matching bounding boxes was the original mistake — a wide wordmark and
        a tall roundel boxed to the same height carry different visual weight,
        so the space around them reads as different even when it is not.
     2. The cells are a fixed size with NO padding, and the only spacing is a
        single `gap`. Padding on the cell plus a variable logo width is what
        made the spacing drift in the first place.

   The track carries the same gap as each group, so the seam where the
   duplicated group begins is indistinguishable from any other gap.
   ========================================================================== */
.partners__ticker {
  --ticker-duration: 52s;
  --partner-gap: 72px;
  margin-top: var(--gap-head);
}

.partners__ticker .ticker__track { gap: var(--partner-gap); }
.partners__ticker .ticker__group { gap: var(--partner-gap); }

.partner {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  /* 1.8:1, matching the exported canvas exactly, so the image fills the cell
     with no letterboxing of its own. */
  width: clamp(190px, 17vw, 232px);
  height: clamp(106px, 9.5vw, 129px);
  padding: 0;
}

.partner__logo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Held back at rest so the row reads as a texture rather than six competing
     marks; the whole strip lifts when the pointer is anywhere on it. */
  /* The pale wordmarks were disappearing at 0.6 against the green. */
  opacity: 0.78;
  transition: opacity var(--t-slow) var(--ease-soft);
}
.ticker:hover .partner__logo { opacity: 1; }

/* ==========================================================================
   The stage
   --------------------------------------------------------------------------
   The pale slab is gone.

   Two attempts were made to soften it — a gradient, a green-tinted glow, a
   feathered edge — and both were treating a symptom. A large light rectangle
   on a dark green page is a foreign object no matter how its edges are
   handled: every other page on this site (Science, Community, FAQ, the legal
   pages) puts its content directly on the green, so Programs was the only one
   that looked like a different website.

   What replaces it is light rather than a surface: a soft radial pool behind
   the content, a hairline top edge that fades out at both ends, and the cards
   themselves carrying the elevation. Nothing is boxed, so nothing has an edge
   to disagree with the page.
   ========================================================================== */
.stage {
  position: relative;
  padding-bottom: var(--section-y);
}

.stage__panel {
  position: relative;
  padding-top: var(--space-9);
}

/* The pool of light. Wide, weak, and anchored above the content so it reads
   as the page being lit from the top rather than as a shape in its own
   right. */
.stage__panel::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -6% -12% auto;
  height: 70%;
  background:
    radial-gradient(58% 62% at 50% 12%, rgba(228, 254, 0, 0.09), transparent 68%),
    radial-gradient(78% 78% at 50% 0%, rgba(120, 133, 8, 0.16), transparent 72%);
  pointer-events: none;
}

/* A hairline that fades out at both ends instead of stopping — the one line
   that says "a new section starts here" without drawing a box. */
.stage__panel::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--on-dark-line) 18%, var(--on-dark-line) 82%, transparent);
  pointer-events: none;
}

.stage__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-8);
}

.stage__mark { width: 116px; height: auto; opacity: 0.5; }

.stage__label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.stage__lede { max-width: 46ch; }

.stage__h2 {
  margin: 0 0 var(--space-5);
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: clamp(1.875rem, 1.1rem + 3.2vw, 3.25rem);
  line-height: 1.06;
  letter-spacing: -0.04em;
  color: var(--ink);
  text-wrap: balance;
}

.stage__sub {
  margin: 0 0 var(--space-6);
  font-size: var(--step-small);
  line-height: 1.65;
  color: var(--ink-2);
}

/* ---------- sign-up ----------
   A dark pill on the dark page, lifted by a hairline rather than by being a
   different colour. It brightens as you focus it, which is the only moment it
   needs to stand out. */
.signup {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  max-width: 440px;
  padding: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 0 0 1px var(--on-dark-line);
  transition: box-shadow var(--t-slow) var(--ease-soft),
              background var(--t-slow) var(--ease-soft);
}
.signup:focus-within {
  background: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1.5px var(--lime), 0 0 0 4px rgba(228, 254, 0, 0.12);
}

.signup__input {
  flex: 1 1 180px;
  min-width: 0;
  height: 44px;
  padding-inline: 20px;
  border: 0;
  background: none;
  color: var(--on-dark);
  font-family: var(--font-ui);
  font-size: var(--step-small);
  letter-spacing: -0.01em;
}
.signup__input:focus { outline: none; }
.signup__input::placeholder { color: var(--on-dark-3); }
.signup__input:user-invalid { color: #ff9b8f; }

.signup__submit { flex: none; }

.signup__note {
  flex: 1 0 100%;
  margin: 0;
  padding: 0 20px;
  font-family: var(--font-mono);
  font-size: var(--step-micro);
  letter-spacing: 0.04em;
  color: var(--on-dark-3);
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--t-slow) var(--ease-soft), padding var(--t-slow) var(--ease-soft);
}
.signup__note:not(:empty) { max-height: 4em; padding-block: var(--space-2) 6px; }
.signup[data-state="error"] .signup__note { color: #ff9b8f; }
.signup[data-state="done"] .signup__note { color: var(--lime); }

/* ==========================================================================
   Programme grid
   ========================================================================== */
.stage__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: var(--space-6);
  margin-top: var(--gap-block);
}

/* ==========================================================================
   Programme card
   --------------------------------------------------------------------------
   A dark card on the pale panel — the inversion is deliberate. These are the
   one thing on the page you are meant to act on, and on a light ground a
   dark card is the strongest object available without adding a colour.
   ========================================================================== */
.pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: var(--radius-lg);
  /* The same elevated surface the Community person cards use — one card
     treatment across the site rather than one per page. */
  background: rgba(255, 255, 255, 0.035);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--on-dark-line);
  transition: transform var(--t-slow) var(--ease-soft),
              box-shadow var(--t-slow) var(--ease-soft);

  /* Back to the dark ramp for the card's own contents. */
  --ink: var(--on-dark);
  --ink-2: var(--on-dark-2);
  --ink-3: var(--on-dark-3);
  --hairline: var(--on-dark-line);
  --accent: var(--lime);
  --btn-ring: var(--lime);
}
.pcard:hover {
  transform: translateY(-4px);
  box-shadow: inset 0 0 0 1px rgba(228, 254, 0, 0.32), 0 24px 50px -30px rgba(0, 0, 0, 0.8);
}

.pcard__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.3);
}

.pcard__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.82;
  transition: opacity var(--t-slow) var(--ease-soft),
              transform 760ms var(--ease-soft);
}
.pcard:hover .pcard__img { opacity: 1; transform: scale(1.04); }

/* the cover fades into the card body rather than ending on a hard line */
.pcard__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(2, 31, 17, 0.96) 2%, rgba(2, 31, 17, 0) 52%);
  pointer-events: none;
}

.pcard__badge {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 1;
  padding: 5px 11px;
  border-radius: var(--radius-xs);
  background: var(--yellow);
  color: var(--green-900);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.pcard__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-5);
}

.pcard__title {
  margin: 0;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.25;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-wrap: balance;
}

.pcard__subtitle {
  margin: -4px 0 0;
  font-size: var(--step-small);
  line-height: 1.4;
  color: var(--ink-3);
}

.pcard__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px var(--space-3);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step-micro);
  letter-spacing: 0.02em;
  color: var(--accent);
}

.pcard__where { display: inline-flex; align-items: center; gap: 5px; }
.pcard__where svg { width: 12px; height: 12px; flex: none; }

.pcard__when { color: var(--ink-3); }
.pcard__when::before { content: "· "; }

.pcard__text {
  margin: 0;
  font-size: var(--step-small);
  line-height: 1.6;
  color: var(--ink-2);
}

.pcard__actions {
  display: grid;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-5);
}
.pcard__actions .btn { justify-content: space-between; }

/* ==========================================================================
   Responsive
   ========================================================================== */
/* Phone layout lives in styles/mobile.css — the panel has no border-radius
   to adjust any more, and the rest was duplicating what that file sets. */
@media (max-width: 560px) {
  .programs .facts b { font-size: 1.125rem; }
}
