:root {
  --ink: #111617;
  --text: #253031;
  /* --muted and --teal are darkened just enough to clear WCAG AA (4.5:1) on
     --wash, not only on --paper: the previous values measured 4.37 and 4.32 on
     the wash sections, which is where the 10-13px micro-copy lives. */
  --muted: #636f6f;
  --paper: #fcfdfb;
  --wash: #edf7f3;
  --line: #dfe6e3;
  --teal: #12768b;
  --green: #38b887;
  --yellow: #edb419;
  --coral: #f16d70;

  /* Type scale ------------------------------------------------------------
     Two families of size: a small set of display sizes for headings, and a
     micro-label size used by the mono eyebrows, card codes and fineprint.
     Body copy never goes below --fs-sm: the cards previously set 11-13px,
     which is below a comfortable reading size, especially on a phone. */
  --fs-2xs: 11px;                          /* micro-labels (was 10px) */
  --fs-xs: 13px;                           /* dense list text */
  --fs-sm: 14px;                           /* minimum body copy */
  --fs-md: 16px;
  --fs-lg: 20px;
  --fs-xl: 28px;
  --fs-hero: clamp(50px, 5.8vw, 84px);     /* home hero headline */
  --fs-page: clamp(30px, 4.4vw, 64px);     /* sub-page hero headline */
  --fs-h2: clamp(35px, 4vw, 61px);         /* section headings */
  --fs-footer: clamp(39px, 4.5vw, 67px);   /* footer heading */

  /* Longest comfortable line for prose (about 65 characters) */
  --measure: 65ch;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Instrument Sans', Arial, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
  /* was transition: all, which also animated outline/outline-offset and made
     focus rings fade in; only the properties that actually change on hover */
  transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}

.site {
  max-width: 100%;
  margin: 0;
  background: var(--paper);
  /* Previously overflow: hidden, which silently clipped overflowing content
     (cut-off leadership cards, 320px headlines) instead of surfacing it.
     Every overflow source has been fixed, so layout bugs now show up as a
     scrollbar rather than as content the visitor can never reach. */
}

.nav {
  /* positioning context for the mobile dropdown, which is absolutely placed */
  position: relative;
  height: 78px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 38px;
  gap: 24px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.navlinks {
  display: flex;
  align-items: center;
  gap: 33px;
  font-size: var(--fs-xs);
}

.navlinks a {
  padding: 29px 0 25px;
  border-top: 4px solid transparent;
}

.navlinks a.active,
.navlinks a:hover {
  border-color: var(--teal);
}

.navlinks a:last-child {
  color: var(--teal);
}

.menu {
  display: none;
  border: 0;
  background: transparent;
  font-size: 23px;
}

.hero {
  min-height: 470px;
  padding: 72px 7.3% 56px;
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  align-items: center;
  gap: 8%;
  position: relative;
}

/* The home hero sits flush against the .compute visualization strip by design */
#home {
  padding-bottom: 0;
}

/* Sub-page heroes (About, Core Areas, Partners, Contact).
   The heading size is a fluid clamp here rather than an inline style: an
   inline font-size could not be overridden by the small-screen rules, which
   locked these headings at 40px and overflowed 320px viewports. */
.hero.page-hero {
  /* 300px rather than 340: on the shorter sub-page heroes the extra 40px was
     just empty space at the top of the page */
  min-height: 300px;
}

.hero.page-hero h1 {
  font-size: var(--fs-page);
  line-height: 0.98;
  max-width: 720px;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.tag {
  color: var(--teal);
  font: var(--fs-2xs) 'DM Mono', monospace;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 19px;
  display: inline-block; /* Forces the background width to hug the text exactly */
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0% 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size 0.3s ease;
  padding-bottom: 2px; /* Small gap between text and underline */
}

.tag:before {
  content: '// ';
  color: var(--coral);
}

.tag:hover {
  background-size: 100% 1px;
}

/* Same eyebrow on a dark surface (footer, contact page) */
.tag-on-dark {
  color: #8ce0ba;
}

h1 {
  font-size: var(--fs-hero);
  line-height: 0.94;
  letter-spacing: -0.02em;
  margin: 0;
  /* The headline used hard <br> breaks for a three-line lockup, but the 620px
     cap meant "Turning data into" broke early and rendered as five lines with
     "into" orphaned on its own everywhere above 800px. Balancing lets the
     browser choose the break points at every width instead. */
  text-wrap: balance;
}

.accent {
  color: var(--teal);
}

.hero-copy {
  padding-top: 2px;
}

.hero-copy > p {
  font-size: clamp(19px, 1.9vw, 27px);
  line-height: 1.27;
  letter-spacing: normal;
  margin: 0;
  max-width: 485px;
}

.compute {
  height: 280px;
  margin-top: 56px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  position: relative;
  overflow: hidden;
  background: 
    linear-gradient(90deg, rgba(19, 126, 149, .04) 1px, transparent 1px),
    linear-gradient(rgba(19, 126, 149, .04) 1px, transparent 1px);
  background-size: 52px 52px;
}

.compute-label {
  position: absolute;
  top: 16px;
  left: 7.3%;
  z-index: 2;
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: var(--muted);
  letter-spacing: 0.05em;
}

.compute-label b {
  color: var(--teal);
  font-weight: 500;
}

.nodes {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* preserveAspectRatio="xMidYMid slice" keeps the nodes circular at every
     width by cropping instead of squashing: the viewBox was stretched when the
     strip was wider or narrower than 1440px, which turned every circle into an
     ellipse (0.58x at 834px, 1.33x at 1920px). */
}

.nodes line {
  stroke: #b7ceca;
  stroke-width: 1;
}

.nodes .hot {
  stroke: var(--green);
  stroke-width: 2;
}

.nodes circle {
  fill: #b8c7c5;
}

.nodes .n1 { fill: var(--teal); }
.nodes .n2 { fill: var(--green); }
.nodes .n3 { fill: var(--yellow); }
.nodes .n4 { fill: var(--coral); }

.trajectory {
  fill: none;
  stroke: var(--teal);
  stroke-width: 2;
  stroke-dasharray: 4 5;
  opacity: .7;
  animation: dash 10s linear infinite;
}

@keyframes dash {
  to { stroke-dashoffset: -180; }
}

.data-chip {
  position: absolute;
  right: 7.3%;
  bottom: 18px;
  background: var(--ink);
  color: #fff;
  padding: 12px 15px;
  font: var(--fs-2xs) 'DM Mono', monospace;
  line-height: 1.6;
}

.data-chip b {
  color: #87e1bf;
}

section {
  padding: 92px 7.3%;
  border-bottom: 1px solid var(--line);
}

.section-top {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 50px;
  margin-bottom: 52px;
  align-items: end;
}

.section-top h2 {
  font-size: var(--fs-h2);
  line-height: 0.98;
  letter-spacing: -0.015em;
  margin: 0;
}

.section-top p {
  font-size: 17px;
  line-height: 1.5;
  color: var(--text);
  max-width: 510px;
  margin: 0 0 0 auto;
}

.section-top p em {
  font-style: normal;
  color: var(--teal);
}

.metrics {
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.metric {
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 22px;
  min-height: 200px;
}

.metric {
  /* code at the top, heading and copy anchored to the bottom */
  display: flex;
  flex-direction: column;
}

.metric .card-code {
  letter-spacing: 0.04em;
}

.metric h3 {
  font-size: var(--fs-sm);
  margin: auto 0 7px;
  letter-spacing: normal;
}

.metric h3:before {
  content: '▰';
  color: var(--yellow);
  font-size: var(--fs-2xs);
  margin-right: 8px;
}

.metric p {
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--muted);
  margin: 0;
}

.research {
  background: var(--wash);
}

.viz-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.viz-card {
  background: var(--paper);
  border: 1px solid var(--line);
  min-height: 400px;
  padding: 22px;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.viz-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 25px 50px rgba(29, 80, 63, 0.08);
}

.card-code {
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: var(--teal);
}

.viz-card h3 {
  font-size: clamp(23px, 2.3vw, 35px);
  letter-spacing: -0.01em;
  line-height: 1.02;
  margin: 16px 0 10px;
  max-width: 360px;
}

.viz-card p {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
  max-width: 38ch;
}

.chart {
  height: 200px;
  border-bottom: 1px solid var(--line);
  border-left: 1px solid var(--line);
  background: 
    linear-gradient(rgba(19, 126, 149, .075) 1px, transparent 1px),
    linear-gradient(90deg, rgba(19, 126, 149, .075) 1px, transparent 1px);
  background-size: 100% 42px, 55px 100%;
  margin-top: auto;
  margin-bottom: 24px;
}

.bars {
  display: flex;
  align-items: end;
  gap: 9px;
  height: 100%;
  padding: 0 18px;
}

.bars i {
  width: 12%;
  background: var(--teal);
  opacity: .9;
  transition: height 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.viz-card:hover .bars i:nth-child(1) { height: 22%; }
.viz-card:hover .bars i:nth-child(2) { height: 35%; }
.viz-card:hover .bars i:nth-child(3) { height: 50%; }
.viz-card:hover .bars i:nth-child(4) { height: 64%; }
.viz-card:hover .bars i:nth-child(5) { height: 71%; }
.viz-card:hover .bars i:nth-child(6) { height: 86%; }
.viz-card:hover .bars i:nth-child(7) { height: 95%; }

.bars i:nth-child(2) { height: 35%; background: var(--green); }
.bars i:nth-child(3) { height: 71%; background: var(--yellow); }
.bars i:nth-child(4) { height: 50%; background: var(--coral); }
.bars i:nth-child(5) { height: 86%; background: var(--teal); }
.bars i:nth-child(6) { height: 64%; background: var(--green); }
.bars i:nth-child(7) { height: 92%; background: var(--yellow); }

.matrix {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-top: auto;
  margin-bottom: 24px;
}

.matrix i {
  aspect-ratio: 1;
  background: #ebefec;
}

.matrix i:nth-child(2n) { background: #93d4c0; }
.matrix i:nth-child(3n) { background: #f9d466; }
.matrix i:nth-child(5n) { background: #ec9691; }
.matrix i:nth-child(7n) { background: #66a5b6; }

@keyframes matrixShuffle {
  0%, 100% { background: #93d4c0; }
  25% { background: #f9d466; }
  50% { background: #ec9691; }
  75% { background: #66a5b6; }
}
.viz-card:hover .matrix i {
  animation: matrixShuffle 2s infinite;
  /* per-cell animation-delay is set inline in HTML to avoid the 7-column
     nth-child period lining up into a uniform vertical stripe */
}

.network-mini {
  width: 100%;
  height: 200px;
  margin-top: auto;
  margin-bottom: 24px;
}

@keyframes flowData {
  to { stroke-dashoffset: -20; }
}
@keyframes pulseNode {
  50% { transform: scale(1.3); opacity: 0.7; }
}
.network-mini line {
  stroke: #b7ceca;
  stroke-dasharray: 4;
  stroke-width: 1.2;
}
.viz-card:hover .network-mini line {
  animation: flowData 0.8s linear infinite;
  stroke: var(--teal);
}
.viz-card:hover .net-nodes circle {
  transform-origin: center;
  transform-box: fill-box;
  animation: pulseNode 1.5s ease-in-out infinite;
}
.viz-card:hover .net-nodes circle:nth-child(odd) { animation-delay: -0.5s; }

.net-nodes circle {
  fill: var(--teal);
}

.net-nodes circle:nth-of-type(2n) { fill: var(--green); }
.net-nodes circle:nth-of-type(3n) { fill: var(--yellow); }
.net-nodes circle:nth-of-type(5n) { fill: var(--coral); }
.net-nodes circle:first-child { fill: var(--coral); }

/* Geospatial / remote-sensing radar visualization — always alive, intensifies on hover */
/* Sized by hand: at 200px the radar plot was drawing smaller than the other
   five method illustrations because the SVG is height-constrained here (its
   viewBox is 250x220, so a 200px-tall box scaled the whole plot to about 0.91).
   At 246px the plot renders ~279x246 and reads at the same weight as its
   neighbours. margin-bottom is 4px rather than 24px for the same reason. */
.geo-mini {
  width: 100%;
  height: 246px;
  margin-top: auto;
  margin-bottom: 4px;
}

.geo-ring {
  fill: none;
  stroke: var(--teal);
  stroke-width: 1.5;
  transition: stroke-opacity 0.4s ease;
}

/* concentric rings fade outward, the way a radar plot reads */
.geo-r1 { stroke-opacity: 0.55; }
.geo-r2 { stroke-opacity: 0.35; }
.geo-r3 { stroke-opacity: 0.22; }

.viz-card:hover .geo-ring {
  stroke-opacity: 0.75;
}

/* marks the rotation centre, so the sweep reads as turning around it */
.geo-centre {
  fill: var(--teal);
}

.geo-sweep {
  transform-origin: 125px 110px;
  transform-box: view-box;
  opacity: 0.65;
  animation: geoSweep 7s linear infinite;
  transition: opacity 0.3s ease;
}

.geo-wedge {
  fill: var(--teal);
  opacity: 0.13;
}

.geo-sweep-line {
  stroke: var(--teal);
  stroke-width: 2.5;
}

.viz-card:hover .geo-sweep {
  opacity: 1;
  animation-duration: 2.4s;
}

@keyframes geoSweep {
  to { transform: rotate(360deg); }
}

.geo-dot {
  fill: var(--coral);
  transform-box: fill-box;
  transform-origin: center;
  animation: geoPulse 3.4s ease-in-out infinite;
}

/* a paper-coloured ring lifts each dot off the rings it sits on */
.geo-dot {
  stroke: var(--paper);
  stroke-width: 1.5;
}

.dot-a { fill: var(--coral); }
.dot-b { fill: var(--yellow); animation-delay: -0.6s; }
.dot-c { fill: var(--green); animation-delay: -1.2s; }
.dot-d { fill: var(--teal); animation-delay: -1.8s; }

@keyframes geoPulse {
  0%, 100% { opacity: 0.3; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.4); }
}

.viz-card:hover .geo-dot {
  animation-duration: 1.5s;
}

/* Time-series / forecasting visualization — line always visible, pulses continuously */
.wave-mini {
  width: 100%;
  height: 200px;
  margin-top: auto;
  margin-bottom: 24px;
  overflow: visible;
}

.wave-path {
  fill: none;
  stroke: var(--green);
  stroke-width: 2.5;
  transition: stroke 0.3s ease, filter 0.3s ease;
}

.viz-card:hover .wave-path {
  stroke: var(--teal);
  filter: drop-shadow(0 0 5px rgba(19, 126, 149, 0.45));
}

.wave-dot {
  fill: var(--coral);
  transform-box: fill-box;
  transform-origin: center;
  animation: wavePulse 2.6s ease-in-out infinite;
}

.wave-dot-1 { animation-delay: -0.6s; }
.wave-dot-2 { fill: var(--yellow); animation-delay: -1.2s; }
.wave-dot-end { fill: var(--teal); animation-delay: -1.8s; }

@keyframes wavePulse {
  0%, 100% { opacity: 0.55; transform: scale(0.9); }
  50% { opacity: 1; transform: scale(1.5); }
}

.viz-card:hover .wave-dot {
  animation-duration: 1.2s;
}

/* Business intelligence / radial KPI visualization — arcs grow further on hover */
.radial-mini {
  width: 100%;
  height: 200px;
  margin-top: auto;
  margin-bottom: 24px;
}

.radial-track {
  fill: none;
  stroke: #dfe6e3;
  stroke-width: 10;
}

.radial-arc {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  transition: stroke-dashoffset 1s cubic-bezier(0.4, 0, 0.2, 1);
}

.radial-arc.arc1 { stroke: var(--teal); stroke-dasharray: 439.8; stroke-dashoffset: 308; }
.radial-arc.arc2 { stroke: var(--green); stroke-dasharray: 326.7; stroke-dashoffset: 229; }
.radial-arc.arc3 { stroke: var(--coral); stroke-dasharray: 213.6; stroke-dashoffset: 150; }

.viz-card:hover .radial-arc.arc1 { stroke-dashoffset: 88; }
.viz-card:hover .radial-arc.arc2 { stroke-dashoffset: 82; }
.viz-card:hover .radial-arc.arc3 { stroke-dashoffset: 32; }

.publication-list {
  border-top: 1px solid var(--line);
}

.pub {
  display: grid;
  grid-template-columns: 85px 1.1fr 1fr 44px;
  gap: 20px;
  align-items: center;
  padding: 24px 0;
  border-bottom: 1px solid var(--line);
}

.pub small {
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: var(--teal);
}

.pub h3 {
  font-size: 19px;
  letter-spacing: normal;
  margin: 0;
}

.pub p {
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
  margin: 0;
}

.pub a {
  color: var(--teal);
  font-size: 20px;
  transition: transform 0.2s ease;
  /* the row's only control: give it a 44px tall hit area, not a 20px glyph */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
}

.pub:hover a {
  transform: translateX(5px);
}

.callout {
  margin-top: 45px;
  background: var(--ink);
  color: #fff;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 50px;
  padding: 40px;
}

.callout h3 {
  font-size: 31px;
  letter-spacing: -0.02em;
  line-height: 1.03;
  margin: 0;
}

.callout p {
  font-size: 14px;
  line-height: 1.5;
  color: #c4d5cf;
  margin: 0;
}

.callout a {
  color: #8ce0ba;
  display: inline-block;
  padding: 7px 0;
  font-size: var(--fs-xs);
  font-weight: 700;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0% 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size 0.3s ease;
}

.callout a:hover {
  background-size: 100% 1px;
}

footer {
  background: #17211f;
  color: #fff;
  padding: 60px 7.3% 25px;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.25fr .8fr .8fr .95fr;
  gap: 45px;
}

.footer-grid h2 {
  font-size: var(--fs-footer);
  line-height: 0.95;
  letter-spacing: -0.02em;
  margin: 11px 0 20px;
}

.footer-grid p {
  color: #bed0c9;
  max-width: 470px;
  font-size: 15px;
  line-height: 1.55;
}

.footer-grid h3 {
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: #7fd4af;
  letter-spacing: 0.1em;
  margin: 5px 0 17px;
  text-transform: uppercase;
  font-weight: bold;
}

.footer-grid ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer-grid li {
  font-size: var(--fs-xs);
  color: #d7e1dc;
  line-height: 1.6;
}

.footer-grid a {
  color: #d7e1dc;
  /* inline-block + padding gives the link a tappable box (WCAG 2.5.8 asks for
     24x24 minimum); these were 15px tall, which is hard to hit on a phone */
  display: inline-block;
  padding: 4px 0;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0% 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size 0.3s ease, color 0.2s ease;
}

.footer-grid a:hover {
  color: #8ce0ba;
  background-size: 100% 1px;
}

.hero-cta {
  display: inline-block;
  margin-top: 36px;
  padding: 15px 26px;
  background: var(--ink);
  color: #fff;
  font: var(--fs-2xs) 'DM Mono', monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.hero-cta:hover {
  background: var(--teal);
}

.mail-btn {
  display: inline-block;
  margin-top: 8px;
  padding: 6px 11px;
  border: 1px solid var(--line);
  color: var(--teal);
  font: 12px 'DM Mono', monospace;
  letter-spacing: 0.04em;
}

.mail-btn:hover {
  background: var(--teal);
  color: #fff;
  border-color: var(--teal);
}

.mail-btn.on-dark {
  border-color: #3d514b;
  color: #8ce0ba;
}

.mail-btn.on-dark:hover {
  background: #8ce0ba;
  color: #17211f;
  border-color: #8ce0ba;
}

/* Contact page: dark navbar + footer-style dark green surface for hero + content */
.nav.dark {
  background: #17211f;
  border-color: #3d514b;
  color: #fff;
}

.nav.dark .navlinks a {
  color: #fff;
}

.nav.dark .navlinks a.active,
.nav.dark .navlinks a:hover {
  border-color: #8ce0ba;
}

.nav.dark .navlinks a:last-child {
  color: #8ce0ba;
}

.nav.dark .menu {
  color: #fff;
}

/* Mobile dropdown menu must also switch to the dark panel on the contact page,
   otherwise .nav.dark's white link text lands on the default white dropdown
   background and disappears. */
.nav.dark .navlinks {
  background: #17211f;
  border-color: #3d514b;
}

.contact-dark {
  background: #17211f;
}

.contact-dark .hero .tag {
  color: #8ce0ba;
}

.contact-dark .hero h1 {
  color: #fff;
}

.contact-dark .hero-copy p {
  color: #c4d5cf;
}

.contact-dark .pillar-grid,
.contact-dark .pillar {
  border-color: #3d514b;
}

.contact-dark .pillar h3 {
  color: #fff;
}

.contact-dark .pillar p {
  color: #c4d5cf;
}

.contact-dark section {
  border-bottom: none;
}

.footer-seals {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
}

.footer-seals img {
  height: 44px;
  width: auto;
  display: block;
}

.fineprint a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  /* 14px of text needs padding to reach a 24px tap target */
  display: inline-block;
  padding: 5px 0;
}

.fineprint {
  border-top: 1px solid #3d514b;
  margin-top: 57px;
  padding-top: 18px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px 28px;
  color: #9cb1a8;
  font: var(--fs-2xs) 'DM Mono', monospace;
}

/* Keep the legal link pair on one line (breaking between "Privacy notice ·" and
   "Accessibility" read as a mistake). The copyright and the university line are
   free to wrap — they need to at 320px. */
.fineprint > span:last-child {
  white-space: nowrap;
}

/* Responsive Overrides */

/* Brand lockup (navbar logomark) */
.brand img {
  height: 34px;
  width: auto;
  display: block;
}

/* About: institutional logo lockup.
   Two columns: the seals on the left, the explanation on the right, so the copy
   lines up with the second column used by .section-top instead of hugging the
   CICT seal. */
.institutional-lockup {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 50px;
  align-items: center;
  padding: 40px 7.3%;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.lockup-seals {
  display: flex;
  align-items: center;
  gap: 48px;
  flex-wrap: wrap;
}

/* Same 510px measure and right-aligned placement as .section-top p, so the
   copy starts at exactly the same x as every other second-column block. */
.lockup-copy {
  width: 100%;
  max-width: 510px;
  justify-self: end;
}

.institutional-lockup figure {
  margin: 0;
  text-align: center;
}

.institutional-lockup img {
  height: 72px;
  width: auto;
  object-fit: contain;
}

.institutional-lockup h2 {
  font-size: 15px;
  margin: 0 0 8px;
}

.institutional-lockup p {
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.6;
  margin: 0;
}

.institutional-lockup figcaption {
  margin-top: 10px;
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  max-width: 180px;
}

/* About: mission/vision/values/goals cards */
.pillar-grid {
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.pillar {
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 32px;
}

.pillar h3 {
  font-size: 15px;
  margin: 0 0 12px;
}

.pillar h3:before {
  content: '▰';
  color: var(--yellow);
  font-size: var(--fs-2xs);
  margin-right: 8px;
}

.pillar p, .pillar ol {
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
  padding-left: 0;
  max-width: var(--measure);
}

/* Links inside body copy (404 page, FAQ answers) need a tappable box too;
   symmetric padding keeps the text baseline where it was */
.pillar p a,
.faq p a {
  display: inline-block;
  padding: 4px 0;
}

.pillar ol {
  padding-left: 18px;
}

.pillar ol li {
  margin-bottom: 6px;
}

/* Leadership cards */
.leader-grid {
  display: grid;
  /* Two across on desktop. The single-column collapse happens at 720px, which
     is where the card's contents would otherwise start to clip — a fixed
     2-column track used to clip the second card between 481px and ~700px,
     silently, because .site hid the overflow. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  /* No horizontal padding: .leader-grid sits inside a <section> that already
     applies 7.3%, which aligned the cards 90px right of the heading above them. */
  padding: 0 0 20px;
}

.leader-card {
  border: 1px solid var(--line);
  background: var(--paper);
  display: grid;
  grid-template-columns: minmax(88px, 140px) 1fr;
  align-items: center;
  gap: 20px;
  padding: 22px;
}

.leader-card img {
  width: 100%;
  /* height: auto is required: the width/height attributes on the <img> (added
     to reserve space and avoid layout shift) become fixed dimensions as soon
     as CSS sets a width, which would stretch the photo to 650px tall */
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--line);
}

.leader-card h3 {
  font-size: 19px;
  line-height: 1.15;
  margin: 0 0 6px;
  text-wrap: balance;
}

.leader-card p {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--muted);
  margin: 0 0 4px;
  max-width: 42ch;
}

/* Researcher grid */
.team-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 18px;
  /* Inside a padded <section> — see .leader-grid */
  padding: 30px 0 60px;
}

.team-card {
  text-align: center;
}

.team-photo {
  position: relative;
  margin-bottom: 10px;
}

.team-card img {
  width: 100%;
  height: auto;   /* see .leader-card img */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--line);
  display: block;
}

.team-photo .mail-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  margin-top: 0;
  padding: 6px 9px;
  font-size: 13px;
  background: var(--paper);
  border-color: var(--line);
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.team-card:hover .mail-btn {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* .team-photo .mail-btn sets the background at higher specificity than
   .mail-btn:hover, so hovering the chip itself left it paper-white while
   .mail-btn:hover turned the glyph white — the ✉ disappeared. Restore the
   intended hover state at a specificity that wins here. */
.team-photo .mail-btn:hover {
  background: var(--teal);
  color: #fff;
  border-color: var(--teal);
}

.team-card h3 {
  font-size: var(--fs-sm);
  margin: 0;
  letter-spacing: normal;
  font-weight: 500;
}

/* Core area page cards */
.area-block {
  border-top: 1px solid var(--line);
  padding: 48px 7.3%;
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 40px;
}

.area-block:nth-child(odd) {
  background: var(--wash);
}

.area-block h2 {
  font-size: clamp(26px, 2.6vw, 38px);
  letter-spacing: -0.01em;
  line-height: 1.05;
  margin: 10px 0 0;
}

.area-block .body p {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  max-width: 620px;
  margin: 0 0 14px;
}

.area-block .body p.muted {
  color: var(--muted);
  font-size: var(--fs-sm);
}

/* Partner directory */
.partner-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  padding: 30px 7.3% 60px;
}

.partner-card {
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.partner-card img {
  height: 48px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  align-self: flex-start;
}

.partner-card h3 {
  font-size: 17px;
  margin: 0;
}

.partner-card p {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
  flex-grow: 1;
}

.partner-card a {
  font: var(--fs-2xs) 'DM Mono', monospace;
  color: var(--teal);
  font-weight: 500;
  letter-spacing: 0.04em;
  align-self: flex-start;
  padding: 6px 0;
}

/* The diagram is decorative: once the strip is short the caption competes with
   the artwork, so the visible label carries the message on its own. */

/* ==========================================================================
   Reduced motion
   The hero diagram dash, the geo sweep, the matrix shuffle and the pulsing
   dots all start automatically and loop indefinitely, which is both a
   vestibular-trigger risk and a WCAG 2.2.2 concern (no mechanism to pause).
   Visitors who ask their OS for less motion now get static artwork, with the
   hover transitions collapsed to effectively instant rather than removed
   (end states are unchanged, so nothing disappears).
   ========================================================================== */

/* ==========================================================================
   Screen-reader-only utility
   Some sections deliberately have no visible heading (the hero introduces
   them), but the document outline still needs one so that heading navigation
   does not jump from h1 straight to h3.
   ========================================================================== */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Keyboard focus
   The stylesheet had 33 :hover rules and no focus rules: keyboard users got
   only the browser default ring, and none of the hover affordances (nav tab
   underline, row arrow shift, card lift) had a keyboard equivalent.
   ========================================================================== */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
  border-radius: 2px;
}

.nav.dark :where(a, button):focus-visible,
.contact-dark :where(a, button):focus-visible,
footer :where(a, button):focus-visible {
  outline-color: #8ce0ba;
}

/* Skip link: the nav carries five links before the content on every page, so
   keyboard users need a way past it. It is off-screen until focused. */
.skip-link {
  position: absolute;
  top: -3.5rem;
  left: 12px;
  z-index: 100;
  padding: 12px 18px;
  background: var(--ink);
  color: #fff;
  font: var(--fs-2xs) 'DM Mono', monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 12px;
}

/* <main> only needs a programmatic focus target, never a tab stop */
main:focus {
  outline: none;
}


/* ==========================================================================
   FAQ rows (faq.html)
   Question in the first column, answer in the second, matching the .pub row
   pattern used on the home page. The answers are plain prose so that an answer
   engine can lift them verbatim.
   ========================================================================== */
.faq-list {
  border-top: 1px solid var(--line);
}

.faq {
  display: grid;
  grid-template-columns: minmax(0, 24ch) minmax(0, 1fr);
  gap: 24px 40px;
  padding: 26px 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}

.faq h3 {
  font-size: var(--fs-lg);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

.faq p {
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--text);
  margin: 0;
  max-width: var(--measure);
}

/* ==========================================================================
   Responsive
   Every breakpoint lives here, after all base rules, ordered widest-first.
   Previously these overrides were spread across four blocks in three places
   in the file — two of them duplicated — which is what allowed "the base rule
   silently won and the mobile layout never applied" bugs to hide.
   ========================================================================== */

/* Touch devices never fire :hover, so the mail chip on each researcher photo
   has to be permanently visible there. */
@media (hover: none) {
  .team-photo .mail-btn {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }
}

@media (max-width: 1024px) {
  .section-top {
    gap: 24px;
  }
  .leader-card {
    grid-template-columns: 100px 1fr;
  }
  .area-block {
    grid-template-columns: 1fr;
  }
  .team-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 900px) {
  .institutional-lockup {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .lockup-copy {
    justify-self: start;
  }
  .faq {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .metrics,
  .viz-grid,
  .partner-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .pillar-grid {
    grid-template-columns: 1fr;
  }
  .team-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 800px) {
  .nav {
    padding: 0 20px;
  }
  .menu {
    display: block;
  }
  .navlinks {
    display: none;
    position: absolute;
    z-index: 10;
    /* top: 100% of the 78px bar; an absolute 85px left a 7px strip of page
       content showing through between the bar and the panel */
    top: 100%;
    left: 0;
    right: 0;
    background: var(--paper);
    padding: 12px 20px;
    flex-direction: column;
    align-items: flex-start;
    border-bottom: 1px solid var(--line);
  }
  .navlinks.open {
    display: flex;
  }
  .navlinks a {
    padding: 9px 0;
    /* the 4px top border is a desktop tab indicator; on mobile the current page
       is marked with colour and weight instead */
    border: 0;
  }
  .navlinks a.active,
  .navlinks a:hover {
    color: var(--teal);
    font-weight: 700;
  }
  .hero,
  .section-top,
  .callout {
    grid-template-columns: 1fr;
  }
  .hero {
    padding: 55px 28px 40px;
    gap: 30px;
  }
  .compute-label {
    left: 28px;
  }
  .data-chip {
    right: 28px;
  }
  section {
    padding: 65px 28px;
  }
  .section-top p {
    margin: 0;
  }
  .pub {
    grid-template-columns: 60px 1fr 44px;
    align-items: start;
  }
  .pub small {
    grid-column: 1;
    grid-row: 1 / 3;
  }
  .pub h3 {
    grid-column: 2;
    grid-row: 1;
  }
  .pub p {
    grid-column: 2;
    grid-row: 2;
    display: block;
  }
  .pub a {
    grid-column: 3;
    grid-row: 1 / 3;
    align-self: center;
  }
  .fineprint {
    flex-direction: column;
  }
  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
  .footer-grid > div:first-child {
    grid-column: span 2;
  }
  .footer-seals {
    margin-top: 14px;
  }
}

/* The leadership card needs ~280px of text column; below this it would clip */
@media (max-width: 720px) {
  .leader-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .metrics,
  .viz-grid,
  .partner-grid {
    grid-template-columns: 1fr;
  }
}

/* Once the diagram strip is short the caption competes with the artwork, so
   the visible label carries the message on its own. */
@media (max-width: 600px) {
  .compute-label-aside,
  .data-chip {
    display: none;
  }
}

@media (max-width: 480px) {
  h1 {
    font-size: clamp(36px, 10vw, 48px);
  }
  .compute {
    height: 220px;
  }
  .callout {
    padding: 27px;
  }
  .pub {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .pub small,
  .pub h3,
  .pub p,
  .pub a {
    grid-column: auto;
    grid-row: auto;
  }
  .footer-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .footer-grid > div:first-child {
    grid-column: auto;
  }
  .viz-card {
    min-height: 440px;
  }
  .geo-mini {
    height: 240px;
  }
  .leader-card {
    grid-template-columns: 1fr;
  }
  .leader-card img {
    max-width: 200px;
    margin: 0 auto;
  }
  .team-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 420px) {
  .team-grid {
    grid-template-columns: 1fr;
  }
  .team-card {
    max-width: 280px;
    margin: 0 auto;
  }
}


@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Print
   Institutional pages get printed and filed: drop the chrome and the
   decorative illustrations, keep the text black on white, and expose the
   destination of every link.
   ========================================================================== */
@media print {
  .nav,
  .menu,
  .skip-link,
  .compute,
  .viz-grid,
  .footer-seals,
  .location-marker {
    display: none;
  }

  html {
    scroll-behavior: auto;
  }

  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
  }

  .site,
  .research,
  .contact-dark,
  .area-block,
  footer {
    background: #fff;
    color: #000;
  }

  h1 { font-size: 20pt; }
  h2 { font-size: 15pt; }
  h3 { font-size: 12pt; }

  section,
  .area-block,
  .institutional-lockup {
    padding: 0 0 10pt;
    border: 0;
    break-inside: avoid;
  }

  .hero {
    min-height: 0;
    padding: 0 0 10pt;
    display: block;
  }

  a {
    color: #000;
    text-decoration: underline;
  }

  /* show where a link goes when the page is on paper */
  a[href^="http"]::after,
  a[href^="mailto"]::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    color: #333;
    text-decoration: none;
    word-break: break-all;
  }

  .footer-grid h3,
  .footer-grid li,
  .footer-grid p,
  .footer-grid a,
  .fineprint,
  .fineprint a,
  .pillar p,
  .pillar ol,
  .metric p,
  .faq p,
  .leader-card p,
  .partner-card p,
  .viz-card p {
    color: #000;
  }

  footer {
    border-top: 1pt solid #000;
  }
}
