/* ============================================================
   Riverside South, Canary Wharf — public consultation
   Built to the Riverside South visual guidelines (August 2026).

   Palette : River depth / Soft Stone / Sunlight / Sea glass
   Type    : PT Serif Regular (headings and statements)
             Asta Sans Medium (subheadings) · Asta Sans Light (body)

   Every brand value is a custom property below.
   ============================================================ */

:root {
  /* --- Brand colours (visual guidelines, August 2026) ------- */
  --river:        #00494E;   /* main dark colour */
  --river-deep:   #003237;   /* darker shade, for layering */
  --stone:        #F7F7F7;   /* main light colour */
  --sunlight:     #FFE5B4;   /* accent, for details */
  --sea-glass:    #DDF3F2;   /* supporting, for details */
  --paper:        #FBF9F7;   /* warm off-white, alternating sections */

  /* Sunlight is unreadable as text on light grounds (1.15:1). This is the
     darkened sibling used for small accent text there — 5.5:1 on Soft Stone,
     5.1:1 on Sea glass, so it clears WCAG AA everywhere it is used. */
  --sunlight-deep: #8A5A12;

  /* --- Functional colours ---------------------------------- */
  --ink:          #00494E;                    /* headings on light  9.5:1 */
  --ink-body:     #24312F;                    /* body copy on light 12.3:1 */
  --ink-soft:     #4A5A58;                    /* secondary on light  6.6:1 */
  --on-dark:      #FFFFFF;                    /* on River depth     10.2:1 */
  --on-dark-soft: rgba(255, 255, 255, 0.78);  /* on River depth      6.9:1 */
  --hairline:       rgba(0, 73, 78, 0.16);
  --hairline-light: rgba(255, 255, 255, 0.22);

  /* --- Typography ------------------------------------------ */
  --font-heading: "PT Serif", Georgia, "Times New Roman", serif;
  --font-body:    "Asta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
                  Helvetica, Arial, sans-serif;

  --text-display: clamp(2.5rem, 1.6rem + 4vw, 4.5rem);
  --text-h2:      clamp(1.875rem, 1.35rem + 2.2vw, 3rem);
  --text-h3:      clamp(1.25rem, 1.1rem + 0.7vw, 1.5rem);
  --text-lead:    clamp(1.125rem, 1.02rem + 0.55vw, 1.4375rem);
  --text-body:    clamp(1.0625rem, 1.02rem + 0.2vw, 1.125rem);
  --text-small:   1rem;
  --text-kicker:  1rem;
  --text-caption: 0.9375rem;

  /* --- Layout ---------------------------------------------- */
  --container:        74rem;
  --container-narrow: 46rem;   /* reading measure, ~62ch */
  --gutter:        clamp(1.25rem, 5vw, 3.5rem);
  --space-section: clamp(3.75rem, 8vw, 7.5rem);
  --space-block:   clamp(2rem, 4vw, 3.5rem);
  --header-h:      clamp(4.5rem, 3.9rem + 2.4vw, 5.75rem);
  --nav-gap:       clamp(0.9rem, 1.9vw, 2.1rem);
  --radius:        6px;

  /* --- Motion ---------------------------------------------- */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
}

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

*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  background: var(--paper);
  color: var(--ink-body);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--text-body);
  line-height: 1.7;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
}

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

ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }

a { color: inherit; }

::selection { background: var(--sunlight); color: var(--river); }

:focus-visible { outline: 2px solid var(--river); outline-offset: 3px; }

.section--dark :focus-visible,
.site-header :focus-visible,
.mobile-nav :focus-visible,
.site-footer :focus-visible { outline-color: var(--sunlight); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: fixed;
  top: 0.75rem; left: 0.75rem;
  z-index: 100;
  padding: 0.75em 1.25em;
  background: var(--sunlight);
  color: var(--river);
  font-size: var(--text-small);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius);
  transform: translateY(calc(-100% - 1.5rem));
}

.skip-link:focus-visible { transform: none; }

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

.container {
  width: min(100% - 2 * var(--gutter), var(--container));
  margin-inline: auto;
}

.section { padding-block: var(--space-section); }

.section--stone  { background: var(--stone); }
.section--paper  { background: var(--paper); }
.section--glass  { background: var(--sea-glass); }
.section--dark   { background: var(--river); color: var(--on-dark); }
.section--dark p { color: var(--on-dark-soft); }

/* Centred introduction, but only once the lines are long enough for it to read
   as composition rather than as ragged copy. */
@media (min-width: 56rem) {
  .section--centred .section-head,
  .section--centred > .container > .prose { text-align: center; }

  .section--centred .section-head h2,
  .section--centred .lead,
  .section--centred > .container > .prose { margin-inline: auto; }

  .section--centred .hys__deadline { text-align: center; }
}

/* A touch wider than the standard lead: centred, the shorter measure left it
   looking like a narrow column adrift in the section. */
#have-your-say .lead { max-width: 42ch; }

#journey .section-head { margin-bottom: calc(var(--space-block) + 1rem); }

#team .section-head h2 { max-width: none; }

@media (min-width: 56rem) {
  #team .section-head h2 { white-space: nowrap; }
}


/* ------------------------------------------------------------ type */

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.15;
  text-wrap: balance;
  color: var(--ink);
}

.section--dark h1,
.section--dark h2,
.section--dark h3 { color: var(--on-dark); }

.lead {
  font-size: var(--text-lead);
  line-height: 1.55;
  max-width: 34ch;
  font-weight: 500;
  font-family: var(--font-body);
  color: var(--ink);
}

.section--dark .lead { color: var(--on-dark); }

.prose { max-width: var(--container-narrow); }
.prose p + p { margin-top: 1.1em; }

.measure { max-width: 62ch; }

/* Section head — heading block.
   Every one sits on the same left grid edge. */

.section-head {
  margin-bottom: var(--space-block);
}

.section-head h2 { font-size: var(--text-h2); max-width: 22ch; }

.section--centred .section-head h2 {
  margin-inline: auto;
  text-align: center;
}

.section-head .lead { margin-top: 1.25rem; }

/* Placeholders awaiting confirmed content stay visibly unresolved. */
.tbc {
  background: transparent;
  color: var(--sunlight-deep);
  border: 1px dashed currentColor;
  border-radius: 3px;
  padding: 0.05em 0.45em;
  font-size: 1em;
  font-weight: 500;
  white-space: nowrap;
}

.section--dark .tbc { color: var(--sunlight); }

/* ------------------------------------------------------------ buttons */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85em 1.6em;
  /* Explicit, or <button> picks up the UA's opaque `buttonface` grey and the
     ghost variants end up as white text on #EFEFEF. */
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 200ms var(--ease-out),
              color 200ms var(--ease-out),
              border-color 200ms var(--ease-out);
}

.btn__icon { width: 1.15em; height: 1.15em; flex: none; }

.btn--primary { background: var(--sunlight); color: var(--river); }
.btn--ghost-light { border-color: var(--hairline-light); color: var(--on-dark); }
.btn--ghost { border-color: var(--river); color: var(--river); }

@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover      { background: #FFF2DA; }
  .btn--ghost-light:hover  { background: rgba(255, 255, 255, 0.1); border-color: var(--sunlight); }
  .btn--ghost:hover        { background: var(--river); color: var(--on-dark); }
}

/* A CTA whose destination does not exist yet is a real disabled button,
   never a link that pretends to go somewhere. */
.btn:disabled {
  background: transparent;
  color: var(--on-dark-soft);
  border: 1px dashed var(--hairline-light);
  cursor: not-allowed;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: 2rem;
}

/* ------------------------------------------------------------ header */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  background: rgba(0, 73, 78, 0.94);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--on-dark);
}

.site-header__inner {
  position: relative;
  width: min(100% - 2 * var(--gutter), var(--container));
  margin-inline: auto;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: flex-end;   /* only the toggle sits here on small screens */
  gap: 1.5rem;
}

/* The docked type sizes live here so CSS stays in charge of them; the script
   reads them off these nodes and scales the h1 to match. */
.site-header__metric {
  position: absolute;
  width: 0; height: 0;
  overflow: hidden;
  visibility: hidden;
  font-family: var(--font-heading);
  font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.6rem);
}

/* Uniform scaling would leave the place line below reading size once docked.
   This is the size it holds there instead. */
.site-header__metric--place { font-size: 13px; }

/* Equal side columns, so the middle column is dead centre of the container
   however wide either pair of links happens to be. */
.site-nav {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  transform: translateX(var(--nav-shift, 0px));
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--nav-gap);
  list-style: none;
  padding: 0;
}

.site-nav__list--start { justify-content: flex-end; }
.site-nav__list--end   { justify-content: flex-start; }

/* One plain gap at rest. The script keeps --nav-gap-w wider than whatever the
   climbing title currently measures, so the pairs are always already clear of
   it rather than parting as it arrives. */
.site-nav__gap {
  width: calc(var(--nav-gap) + var(--nav-gap-w, 0px));
}

.site-nav a {
  display: block;
  font-size: 1rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-decoration: none;
  padding-block: 0.4em;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: border-color 180ms ease, color 180ms ease;
}

.site-nav a:hover,
.site-nav a.is-active { border-bottom-color: var(--sunlight); color: var(--sunlight); }

/* Bleed tab — a yellow bookmark pinned to the top-right, running off the
   right edge of the viewport. Sits above the header bar. */

.hys-tab {
  position: fixed;
  z-index: 51;
  top: calc(var(--header-h) / 2);
  right: 0;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  background: var(--sunlight);
  color: var(--river);
  font-size: 1.125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
  padding: 0.75em 2rem 0.75em 1.15em;
  border-radius: var(--radius) 0 0 var(--radius);
  box-shadow: 0 8px 24px rgba(0, 20, 22, 0.28);
  transition: padding-right 180ms ease, background-color 180ms ease;
}

.hys-tab__icon { width: 1.1em; height: 1.1em; flex: none; }

@media (hover: hover) {
  .hys-tab:hover { padding-right: 2.6rem; background: #FFEFCF; }
}

/* Mobile navigation */

.nav-toggle {
  display: none;
  position: relative;
  width: 2.75rem; height: 2.75rem;
  border: 1px solid var(--hairline-light);
  border-radius: var(--radius);
  background: transparent;
  font: inherit;
  cursor: pointer;
}

.nav-toggle__line {
  position: absolute;
  left: 0.7rem; right: 0.7rem;
  height: 2px;
  background: var(--on-dark);
  transition: transform 220ms var(--ease-out);
}

.nav-toggle__line:nth-child(1) { top: calc(50% - 4px); }
.nav-toggle__line:nth-child(2) { top: calc(50% + 3px); }

.nav-toggle[aria-expanded="true"] .nav-toggle__line:nth-child(1) { transform: translateY(3.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__line:nth-child(2) { transform: translateY(-3.5px) rotate(-45deg); }

.mobile-nav {
  display: none;
  position: fixed;
  z-index: 49;              /* under the header, over the page */
  top: var(--header-h);
  left: 0; right: 0; bottom: 0;
  overflow-y: auto;
  background: var(--river);
  color: var(--on-dark);
  padding: 1rem var(--gutter) 2.5rem;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 220ms var(--ease-out), transform 220ms var(--ease-out);
}

.mobile-nav.is-open { opacity: 1; transform: none; }

.mobile-nav__list { list-style: none; padding: 0; }

.mobile-nav a {
  display: block;
  padding: 1rem 0.25rem;
  font-size: 1.0625rem;
  font-weight: 400;
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-light);
}

.mobile-nav a.site-nav__cta { color: var(--sunlight); }

@media (max-width: 63.99rem) {
  .site-nav   { display: none; }
  .hys-tab    { display: none; }   /* the hamburger owns the right edge here */
  .nav-toggle { display: block; }
  .mobile-nav { display: block; }
  .mobile-nav[hidden] { display: none; }
}

body.nav-open { overflow: hidden; }

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

.hero {
  background: var(--river);
  color: var(--on-dark);
  padding-top: calc(var(--header-h) + clamp(2.5rem, 6vw, 4.5rem));
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* The h1 is the only title on the page: it shrinks and climbs into the header
   instead of being duplicated there. The wrapper holds its space open so the
   hero does not jump when the h1 leaves the flow at the end of the climb. */

.hero__titlewrap { display: flow-root; }

.hero__title {
  position: relative;
  z-index: 55;               /* over the header bar it lands on */
  font-size: var(--text-display);
  color: var(--on-dark);
  text-align: center;
  width: fit-content;
  max-width: min(22ch, 100%);
  margin-inline: auto;
  transform-origin: top center;
}

.js .hero__title { will-change: transform; }

/* Final resting state — handed to the browser as a fixed element so the
   docked title cannot jitter against momentum scrolling. */
.hero__title.is-docked {
  position: fixed;
  top: var(--dock-top, 0px);
  left: var(--dock-left, 0px);
  margin: 0;
  transform-origin: top left;   /* left/top already carry the docked position */
}

/* Scaled rather than resized, so growing it cannot disturb the h1's box and
   the geometry the climb is measured from. */
.hero__place {
  display: block;
  transform: scale(var(--place-boost, 1));
  transform-origin: top center;
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.9rem + 0.4vw, 1.125rem);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sunlight);
  margin-top: 0.9rem;
}

.hero__figure { margin-top: clamp(2rem, 4vw, 3rem); }

.hero__figure img {
  width: 100%;
  height: clamp(15rem, 42vw, 30rem);
  object-fit: cover;
  object-position: center 62%;
  border-radius: var(--radius);
}

.hero__body {
  display: grid;
  gap: clamp(1.75rem, 3.5vw, 3rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}

.hero__statement {
  font-family: var(--font-body);
  font-size: var(--text-lead);
  font-weight: 400;
  line-height: 1.45;
  color: var(--on-dark);
}

.hero__note p + p { margin-top: 1em; }

.hero__cta { margin-top: clamp(1.5rem, 3vw, 2.25rem); }
.hero__cta .btn-row { margin-top: 0; flex-direction: column; align-items: flex-start; }

@media (min-width: 56rem) {
  .hero__body {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    align-items: start;
  }
  .hero__cta .btn-row { flex-direction: row; align-items: center; }
}

/* ------------------------------------------------------------ figures */

.figure { margin: 0; }

.figure__link {
  display: block;
  color: inherit;
  text-decoration: none;
  cursor: zoom-in;
  border-radius: var(--radius);
}

.figure img { width: 100%; border-radius: var(--radius); }

.figure--framed img {
  background: #FFFFFF;
  border: 1px solid var(--hairline);
  padding: clamp(0.5rem, 1.5vw, 1.25rem);
}

.figure figcaption {
  margin-top: 0.9rem;
  font-size: var(--text-caption);
  line-height: 1.5;
  color: var(--ink-soft);
  border-top: 1px solid var(--hairline);
  padding-top: 0.7rem;
}

.section--dark .figure figcaption {
  color: var(--on-dark-soft);
  border-top-color: var(--hairline-light);
}

.figure-pair {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin-top: var(--space-block);
}

/* The source photographs have different proportions; a shared frame keeps the
   two captions on one baseline instead of stepping down the page. */
.figure-pair .figure img {
  /* The matched site-photo frame is 15% taller than the previous crop. */
  aspect-ratio: 16 / 12.42;
  object-fit: cover;
}

/* Plans and paired sketches share a widescreen composition, unlike the two
   site photographs above. Keep their native framing and matching baselines. */
.figure-pair--landscape .figure img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.figure-pair--flush { margin-top: 0; }

/* The planning diagram and aerial share one frame so their relationship can
   be read through a direct cross-fade rather than a lateral slide. Without JS
   the figures remain a straightforward vertical pair. */
.comparison-slider {
  margin-top: var(--space-block);
}

html.js .comparison-slider__stage {
  position: relative;
  display: grid;
}

html.js .comparison-slider__slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity 650ms var(--ease-in-out),
              visibility 0s linear 650ms;
}

html.js .comparison-slider__slide.is-active {
  z-index: 1;
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

/* The aerial is resampled onto the plan's exact 2000 x 1116 pixel grid
   (future-hq-office-aligned.jpg), so the same crop lands both images on the
   same ground. Any replacement slide must be registered the same way. */
.comparison-slider__slide img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.comparison-slider__controls[hidden] { display: none; }

.comparison-slider__controls {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.comparison-slider__arrow {
  position: absolute;
  top: 45%;
  width: clamp(2.75rem, 5vw, 3.25rem);
  height: clamp(2.75rem, 5vw, 3.25rem);
  padding: 0;
  transform: translateY(-50%);
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 50%;
  background: rgba(0, 73, 78, 0.84);
  color: var(--on-dark);
  cursor: pointer;
  pointer-events: auto;
  transition: background-color 200ms var(--ease-out),
              color 200ms var(--ease-out);
}

.comparison-slider__arrow--prev { left: clamp(0.75rem, 2vw, 1.25rem); }
.comparison-slider__arrow--next { right: clamp(0.75rem, 2vw, 1.25rem); }

.comparison-slider__arrow svg {
  width: 1.35rem;
  height: 1.35rem;
  vertical-align: middle;
}

.comparison-slider__arrow path {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.comparison-slider__arrow:focus-visible {
  outline-color: var(--river);
  outline-offset: 3px;
}

@media (hover: hover) and (pointer: fine) {
  .comparison-slider__arrow:hover {
    background: var(--sunlight);
    color: var(--river);
  }
}

/* ------------------------------------------------------------ lightbox */

body.lightbox-open { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: rgba(0, 50, 55, 0.92);
}

.lightbox[hidden] { display: none; }

.lightbox__figure {
  width: min(100%, 92rem);
  max-height: 100%;
  margin: 0;
}

.lightbox__image {
  width: auto;
  max-width: 100%;
  max-height: calc(100vh - 2 * var(--gutter));
  margin-inline: auto;
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: 0 1.5rem 5rem rgba(0, 20, 22, 0.35);
}

.lightbox__close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--hairline-light);
  border-radius: var(--radius);
  background: rgba(0, 73, 78, 0.4);
  color: var(--on-dark);
  font: inherit;
  cursor: pointer;
}

.lightbox__close span,
.lightbox__close span::after {
  position: absolute;
  top: 50%;
  left: 0.72rem;
  right: 0.72rem;
  height: 2px;
  background: currentColor;
  content: "";
}

.lightbox__close span { transform: translateY(-50%) rotate(45deg); }
.lightbox__close span::after { left: 0; right: 0; transform: rotate(90deg); }

@media (min-width: 48rem) {
  .figure-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.figure-stack {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  margin-top: var(--space-block);
}

/* ------------------------------------------------------------ numbered issue list */

/* The heading and introduction read side by side with the numbered points once
   there is room for both to keep a comfortable measure. The list is a child of
   the same grid as the heading, so the two start on the same line. */

@media (min-width: 64rem) {
  .site-intro {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto;
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    row-gap: 0;
    align-items: start;
  }

  .site-intro__main { display: contents; }

  .site-intro .section-head {
    grid-column: 1 / -1;
    grid-row: 1;
    width: 100%;
    margin-bottom: clamp(2rem, 4vw, 3rem);
    text-align: center;
  }

  .site-intro .prose {
    grid-column: 1;
    grid-row: 2;
  }

  .site-intro .section-head h2,
  .site-intro .section-head .lead {
    margin-inline: auto;
  }

  .site-intro .section-head h2 {
    max-width: 60rem;
    margin-inline: 0;
    text-align: left;
  }
  .site-intro .section-head .lead { max-width: 42ch; }

  /* The list shares the paragraph row, so its first and last rules align with
     the first and last lines of the copy beside it. */
  .site-intro .issues {
    grid-column: 2;
    grid-row: 2;
    margin-top: 0;
    align-self: end;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }

  .site-intro .issues__item:first-child { border-top: 0; }
}

/* Points at the list it introduces: across on two columns, down when stacked. */
.deliver-arrow {
  width: 1.5em;
  height: 1.5em;
  vertical-align: -0.45em;
  margin-left: 0.15em;
  color: var(--sunlight-deep);
  transform: rotate(90deg);
}

@media (min-width: 64rem) {
  .deliver-arrow { transform: none; }
}

.issues[role="list"] {
  list-style: none;
  padding: 0.5rem clamp(1rem, 2.5vw, 1.5rem);
  margin-top: var(--space-block);
  background: var(--sunlight);
  border-radius: var(--radius);
}

.issues__item {
  display: grid;
  gap: 0.5rem 1.5rem;
  border-top: 1px solid var(--hairline);
  padding-block: 0.9rem;
}

.issues__num {
  font-size: calc(var(--text-small) * 1.2);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.12em;
  color: var(--sunlight-deep);
}

.issues__text { max-width: 58ch; margin: 0; font-weight: 400; }

@media (min-width: 44rem) {
  .issues__item { grid-template-columns: 4rem minmax(0, 1fr); }
}

/* ------------------------------------------------------------ ambitions (icon list) */

.ambitions {
  display: grid;
  gap: clamp(1.75rem, 3vw, 2.5rem);
  list-style: none;
  padding: 0;
  margin-top: var(--space-block);
}

.ambitions__item {
  padding-top: 0;
}

.ambitions__icon {
  width: clamp(6rem, 12vw, 8.75rem);
  height: auto;
  margin-bottom: 1.1rem;
}

.ambitions__title {
  font-family: var(--font-body);
  font-size: var(--text-h3);
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}

.ambitions__text {
  margin-top: 0.6rem;
  font-size: var(--text-small);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 34ch;
}

@media (min-width: 44rem) {
  .ambitions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 68rem) {
  .ambitions { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ------------------------------------------------------------ timeline */

.timeline-scroller {
  position: relative;
  /* Narrowest a milestone may become once four of them no longer fit. */
  --timeline-col-min: 10.5rem;
  --timeline-gap: clamp(1.25rem, 2.2vw, 2.25rem);
  /* Room either side for the current step's card, which sits proud of its
     column and would otherwise be clipped by the scroller. */
  --timeline-pad: 1.5rem;
}

.timeline {
  --timeline-line: 3px;
  --timeline-dot: 0.8rem;
  --timeline-bg: var(--sea-glass);
  position: relative;
  display: grid;
  gap: 2.5rem;
  list-style: none;
  padding: 0;
  margin-top: var(--space-block);
}

/* One unbroken rule for the whole run, in the ink, weight and rounded ends of
   the ambition icons rather than the page's hairline. Stacked, it runs down
   the side of the steps; in three columns it runs across the top of them. */
.timeline::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--timeline-dot) / 2 - var(--timeline-line) / 2);
  width: var(--timeline-line);
  border-radius: 999px;
  background: var(--ink);
}

.timeline__step {
  position: relative;
  padding-left: 2.25rem;
}

.timeline__step--current {
  z-index: 1;
}

.timeline__step--current::after {
  content: "";
  position: absolute;
  top: -1.1rem;
  right: -1.25rem;
  bottom: -1.1rem;
  left: 1.65rem;
  z-index: 0;
  background: #FFFFFF;
  border-radius: var(--radius);
}

.timeline__step--current > * {
  position: relative;
  z-index: 1;
}

.timeline__step--current .timeline__date::before {
  content: "";
  position: absolute;
  top: 0.28rem;
  left: -1.45rem;
  z-index: -1;
  width: 0;
  height: 0;
  border-top: 0.42rem solid transparent;
  border-right: 0.85rem solid #FFFFFF;
  border-bottom: 0.42rem solid transparent;
}

/* Drawn like the icons too: dark outline, light fill, accent for the step
   we are on. */
.timeline__step::before {
  content: "";
  position: absolute;
  top: 0.4rem; left: 0;
  width: var(--timeline-dot); height: var(--timeline-dot);
  border-radius: 50%;
  background: var(--stone);
  border: 2px solid var(--ink);
  z-index: 1;
}

.timeline__step--current::before {
  background: var(--sunlight);
  z-index: 2;
}

.timeline__step:last-child::after {
  content: "";
  position: absolute;
  top: calc(0.4rem + var(--timeline-dot));
  bottom: 0;
  left: calc(var(--timeline-dot) / 2 - var(--timeline-line) / 2);
  width: calc(var(--timeline-line) + 4px);
  background: var(--timeline-bg);
  border-left: var(--timeline-line) dotted var(--ink);
  z-index: 0;
}

.timeline__date {
  font-family: var(--font-body);
  font-size: calc(var(--text-body) * 1.1);
  font-weight: 600;
  color: var(--ink);
}

.timeline__desc {
  margin-top: 0.5rem;
  font-size: var(--text-small);
  color: var(--ink-soft);
  max-width: 32ch;
}

.timeline__now {
  display: inline-block;
  justify-self: start;
  align-self: start;
  margin-top: 1rem;
  padding: 0.35em 0.85em;
  border-radius: var(--radius);
  background: var(--sunlight);
  color: var(--river);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  animation: timeline-pulse 1.8s var(--ease-in-out) infinite;
  transform-origin: center;
}

@keyframes timeline-pulse {
  0%, 100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(138, 90, 18, 0.36);
  }
  50% {
    transform: scale(1.04);
    box-shadow: 0 0 0 0.5rem rgba(138, 90, 18, 0);
  }
}

@media (min-width: 44rem) {
  /* The whole run on one line: five equal columns that shrink to
     --timeline-col, past which the viewport scrolls sideways instead. */
  /* Qualified so the padding outranks the `ol[role="list"]` reset. */
  .timeline-scroller .timeline {
    /* Four milestones to a screenful: wide enough to read comfortably, with
       the fifth just past the edge so the arrows always have somewhere to go.
       Measured against the viewport, which is the query container. */
    --timeline-col: max(var(--timeline-col-min),
                        calc((100cqw - 2 * var(--timeline-pad)
                              - 3 * var(--timeline-gap)) / 4));
    grid-template-columns: repeat(5, var(--timeline-col));
    /* Date, description, then the "we are here" pill. The five steps share
       these rows, so a date that wraps to two lines still leaves every
       description starting on the same line as its neighbours. */
    grid-template-rows: auto auto auto;
    column-gap: var(--timeline-gap);
    row-gap: 0;
    padding-inline: var(--timeline-pad);
    min-width: calc(5 * var(--timeline-col) + 4 * var(--timeline-gap)
                    + 2 * var(--timeline-pad));
  }

  .timeline__viewport {
    overflow-x: auto;
    container-type: inline-size;
    /* Clear air for the current step's card, the pill's pulse and the reveal
       lift, given back as negative margin so the section spacing is unchanged. */
    padding-block: 1.5rem;
    margin-block: -1.5rem;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--timeline-pad);
  }

  .timeline__viewport::-webkit-scrollbar { display: none; }

  .timeline__step { scroll-snap-align: start; }

  /* The rule runs dot to dot, so it starts inside the scroll padding. */
  .timeline::before {
    top: 0; bottom: auto;
    left: var(--timeline-pad); right: var(--timeline-pad);
    width: auto; height: var(--timeline-line);
  }

  .timeline__step {
    grid-row: span 3;
    display: grid;
    grid-template-rows: subgrid;
    align-content: start;
    padding-left: 0;
    padding-top: 1.75rem;
  }

  /* Centred on the rule it sits on. */
  .timeline__step::before { top: calc((var(--timeline-line) - var(--timeline-dot)) / 2); }

  .timeline__step--current::after {
    top: 1.25rem;
    right: -1.25rem;
    bottom: -1.1rem;
    left: -1.25rem;
  }

  .timeline__step--current .timeline__date::before {
    top: -1.75rem;
    left: -0.35rem;
    border-top: 0;
    border-right: 0.75rem solid transparent;
    border-bottom: 1.25rem solid #FFFFFF;
    border-left: 0.75rem solid transparent;
  }

  .timeline__step:last-child::after {
    top: 0;
    right: calc(-1 * var(--timeline-pad));
    bottom: auto;
    left: var(--timeline-dot);
    width: auto;
    height: calc(var(--timeline-line) + 4px);
    border-left: 0;
    border-top: var(--timeline-line) dotted var(--ink);
  }
}

/* ------------------------------------------------------------ timeline controls
   Only shown once JS has measured the row overflowing its viewport. */

.timeline-scroller.is-scrollable .timeline__viewport {
  cursor: grab;
  /* The edge you can still scroll towards fades into the section, so a cut-off
     milestone reads as more to come rather than as a mistake. The ends stay
     hard so the first and last steps are never dimmed. */
  --fade-start: 0px;
  --fade-end: 0px;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-start),
                      #000 calc(100% - var(--fade-end)), transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-start),
                      #000 calc(100% - var(--fade-end)), transparent 100%);
}

.timeline-scroller.is-scrollable:not(.is-at-start) .timeline__viewport { --fade-start: 2.5rem; }
.timeline-scroller.is-scrollable:not(.is-at-end)   .timeline__viewport { --fade-end: 2.5rem; }

.timeline-scroller.is-scrollable .timeline__viewport.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  user-select: none;
}

.timeline__controls[hidden] { display: none; }

.timeline__controls {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 2rem;
}

.timeline__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: var(--stone);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 200ms var(--ease-out),
              color 200ms var(--ease-out),
              opacity 200ms var(--ease-out);
}

.timeline__arrow:hover { background: var(--sunlight); }

.timeline__arrow:disabled {
  opacity: 0.35;
  cursor: default;
  background: var(--stone);
}

/* ------------------------------------------------------------ project team */

/* Nine members, so three to a row makes three even rows. Two to a row on
   small screens leaves one over; the rows wrap and centre, keeping that odd
   plate on the section's axis instead of stranded left. */
.team {
  --team-cols: 2;
  --team-gap: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--team-gap);
  list-style: none;
  padding: 0;
  margin-top: calc(var(--space-block) + 1rem);
}

.team__item {
  flex: 0 0 calc((100% - (var(--team-cols) - 1) * var(--team-gap)) / var(--team-cols));
  min-width: 0;
}

@media (min-width: 56rem) {
  .team { --team-cols: 3; }
}

/* The plate keeps every logo on white, whatever the section behind it, and
   gives the row a common baseline however different the marks are. */
.team__logo {
  display: grid;
  place-items: center;
  height: 7rem;
  padding: 1rem 1.25rem;
  margin-bottom: 0.9rem;
  background: #FFFFFF;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}

/* Every mark is drawn at a different proportion and weight, so one shared
   size cap makes the long wordmarks shout and the compact marks vanish.
   Each logo is instead given a share of its plate, tuned by eye so the ink
   on every plate carries about the same optical mass.

   The share is a plain number, used twice: once against the plate width, so
   the balance survives every column width, and once against a fixed ceiling,
   so the marks never grow past a set size. Without that ceiling the wide
   three-up plates on a desktop, and the two-up plates on a tablet, would blow
   the whole set up. */
.team__logo img {
  width: calc(var(--logo-share) * 100% * var(--logo-scale, 1.15));
  max-width: calc(var(--logo-share) * 14.5rem);
  height: auto;
  object-fit: contain;
}

/* Two to a row the plates are narrow and short, so the marks are let out a
   little to stop them floating in the middle of all that white. */
@media (min-width: 56rem) {
  .team__logo img { --logo-scale: 1; }
}

.team__logo--cwg      { --logo-share: 0.28; }  /* stacked mark, balanced with the wider wordmarks */
.team__logo--cwg img  { filter: brightness(0) saturate(100%) opacity(0.72); }
.team__logo--jpmc     { --logo-share: 0.62; }  /* long, heavy serif wordmark */
.team__logo--adamson  { --logo-share: 0.52; }
.team__logo--foster   { --logo-share: 0.82; }  /* widest mark, but light in height */
.team__logo--fieldops { --logo-share: 0.70; }  /* ultra-bold, so held back a little */
.team__logo--arup     { --logo-share: 0.44; }  /* solid black serif capitals */
.team__logo--steer    { --logo-share: 0.42; }  /* heavy rounded sans */
.team__logo--dp9      { --logo-share: 0.38; }
.team__logo--lowick   { --logo-share: 0.35; }  /* light serif, stacked two lines */

.team__name { display: block; font-weight: 500; color: var(--ink); }

.team__role {
  display: block;
  margin-top: 0.15rem;
  font-size: var(--text-small);
  line-height: 1.5;
  color: var(--ink-soft);
}

/* ------------------------------------------------------------ have your say */

.hys__grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  margin-top: var(--space-block);
}

/* Three panels: two abreast while there is only room for two, with the odd one
   filling its row rather than leaving a hole, then three abreast. */
@media (min-width: 56rem) {
  .hys__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hys__grid > :last-child { grid-column: 1 / -1; }
}

@media (min-width: 72rem) {
  .hys__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hys__grid > :last-child { grid-column: auto; }
}

.hys__panel {
  border: 1px solid var(--hairline-light);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.hys__panel--action,
.hys__panel--contact {
  display: flex;
  flex-direction: column;
}

.hys__panel--action .btn-row,
.hys__panel--contact .contact {
  margin-top: auto;
}

.hys__venue-action .btn,
.hys__panel--action .btn {
  width: 100%;
  justify-content: center;
  line-height: 1.2;
}

.hys__panel-title {
  font-family: var(--font-body);
  font-size: var(--text-kicker);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sunlight);
  margin-bottom: 1.25rem;
}

.hys__when {
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--on-dark);
  line-height: 1.5;
  margin-top: 1.25rem;
}

.hys__detail {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.hys__detail + .hys__detail { margin-top: 0.9rem; }

.hys__detail .contact__icon {
  width: 2rem;
  height: 2rem;
}

.hys__detail .contact__icon svg { width: 0.95rem; height: 0.95rem; }

.hys__time { color: var(--sunlight); }

.hys__venue {
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 500;
  line-height: 1.5;
  font-style: normal;
  margin-top: 1rem;
  color: var(--on-dark-soft);
}

.hys__venue-action { margin-top: 1.5rem; }

.hys__note {
  margin-top: 1.25rem;
  font-size: var(--text-small);
  color: var(--on-dark-soft);
}

.hys__deadline {
  margin-top: var(--space-block);
  border-top: 1px solid var(--hairline-light);
  padding-top: 1.5rem;
  font-size: var(--text-lead);
  font-weight: 400;
  color: var(--on-dark);
}

.hys__deadline strong { color: var(--sunlight); font-weight: 500; }

/* Contact list */

.contact { list-style: none; padding: 0; margin-top: 1.75rem; display: grid; gap: 0.9rem; }

.contact li { display: flex; align-items: center; gap: 0.85rem; }

.contact__icon {
  width: 2.25rem; height: 2.25rem;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--hairline-light);
  border-radius: 50%;
  color: var(--sunlight);
}

.contact__icon svg { width: 1.05rem; height: 1.05rem; }

/* inline-block + padding so the email and phone clear a ~44px tap target */
.contact a {
  display: inline-block;
  padding-block: 0.4rem;
  color: var(--on-dark);
  text-decoration-color: var(--hairline-light);
  text-underline-offset: 0.2em;
}
.contact a:hover { color: var(--sunlight); }

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

.site-footer {
  background: var(--river-deep);
  color: var(--on-dark-soft);
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
  font-size: var(--text-small);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem 2rem;
}

.site-footer__brand {
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 400;
  color: var(--on-dark);
}

.site-footer__brand span {
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.9rem + 0.4vw, 1.125rem);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sunlight);
}

.site-footer a { color: var(--on-dark); text-underline-offset: 0.2em; }
.site-footer a:hover { color: var(--sunlight); }

/* ------------------------------------------------------------ entrance reveals
   .reveal is only hidden once JS has added .js to <html>, so everything
   stays visible when JavaScript does not run. */

html.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 640ms var(--ease-out), transform 640ms var(--ease-out);
}

html.js .reveal.is-visible { opacity: 1; transform: none; }

html.js .reveal-group .reveal:nth-child(2) { transition-delay: 60ms; }
html.js .reveal-group .reveal:nth-child(3) { transition-delay: 120ms; }
html.js .reveal-group .reveal:nth-child(4) { transition-delay: 180ms; }
html.js .reveal-group .reveal:nth-child(5) { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  html.js .reveal { transform: none; transition: opacity 300ms ease; }
  html.js .comparison-slider__slide { transition: none; }
  .nav-toggle__line, .mobile-nav { transition: none; }
  .timeline__now { animation: none; }
  * , *::before, *::after { animation-duration: 0.01ms !important; }
}
