/* Kerb project site.
   Design system: "Signal at the kerb" (light-communication) merged with
   "Kerbline" (street cross-section) and an adaptive chrome layer.
   The site behaves like a well-designed eHMI: it brightens before it moves.
   Plain CSS, no JS. All ratios verified WCAG AA+ (most AAA).

   Discipline budgets (acceptance criteria, keep these when editing):
   - At rest, at most two full-brightness #00C2FF elements per viewport:
     the fixed top strip plus one contextual element (the hero light band,
     or the lead researcher's plate). Everything else rests dim and only
     brightens on hover or focus.
   - Exactly one crossing divider per page.
   - Tactile-dot texture on one surface only, never under body text.
   - Remove every cyan band (here and in the inline SVGs) and a
     conventional, fully working academic page must remain; the print
     stylesheet below neutralises all of them for the greyscale test. */

:root {
  --ground: #F7F5F2;        /* footpath: warm concrete, low glare. */
  --surface: #FFFFFF;       /* cards, header */
  --ink: #1A1C1F;           /* asphalt. text: 15.69:1 on ground */
  --muted: #4F5358;         /* 7.12:1 on ground */
  --link: #005E86;          /* 6.55:1 on ground */
  --link-strong: #003D5C;   /* hover text: 10.59:1 */
  --band: #00C2FF;          /* the eHMI light band. never text on light. */
  --band-dim: #BFE9FA;      /* an unlit LED. decorative only */
  --hairline: #DEDAD4;      /* concrete edges. decorative only */
  --dusk: #0E1B22;          /* the road at dusk (footer) */
  --dusk-text: #F7F5F2;     /* 16.10:1 on dusk */
  --dusk-link: #7FDFFF;     /* 11.60:1 on dusk */
  --dusk-muted: #B9CCD6;    /* 10.57:1 on dusk */
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
}

/* the site adapts to its context, like the vehicles it studies */
@media (prefers-color-scheme: dark) {
  :root {
    --ground: #12161A;
    --surface: #1A2026;
    --ink: #E8EBEE;         /* 15.19:1 on ground */
    --muted: #9FA9B2;       /* 7.61:1 */
    --link: #5FD0FF;        /* 10.35:1 */
    --link-strong: #9ADFFF; /* 12.44:1 */
    --band-dim: #1E4A5E;
    --hairline: #2A3138;
  }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 5rem; }

body {
  margin: 0;
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--ground);
  -webkit-text-size-adjust: 100%;
}

/* the strip: a fixed 3px light band along the top of the page,
   one lit segment, the rest resting dim */
body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 60;
  background: linear-gradient(90deg,
    var(--band-dim) 0 28%, var(--band) 34% 52%, var(--band-dim) 58% 100%);
}

/* type */
h1, h2, h3 { line-height: 1.15; letter-spacing: -0.01em; }
h1 {
  font-size: clamp(2rem, 1rem + 4.5vw, 3.1rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.08;
  margin: 0 0 1rem;
}
h2 { font-size: 1.6rem; font-weight: 700; margin: 0 0 1.25rem; }
h3 { font-size: 1.15rem; font-weight: 650; margin: 0 0 0.5rem; }
p { margin: 0 0 1rem; }

/* section marker: the strip sampled at each section boundary.
   the lit segment uses the dark signal ink, not full-brightness cyan,
   so markers stay inside the lit-band budget */
h2::before {
  content: "";
  display: block;
  width: 40px;
  height: 3px;
  border-radius: 999px;
  margin-bottom: 0.75rem;
  background: linear-gradient(90deg, var(--link) 0 45%, var(--band-dim) 45% 100%);
}

.kicker {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--link);
  margin: 0 0 0.75rem;
}

.mono { font-family: var(--mono); font-size: 0.8125rem; }

/* links speak the signal grammar: brighten before anything moves */
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 160ms ease-out, text-decoration-color 160ms ease-out,
    text-decoration-thickness 160ms ease-out;
}
a:hover {
  color: var(--link-strong);
  text-decoration-thickness: 3px;
  text-decoration-color: var(--band);
}
a:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--ground);
  padding: 0.6rem 1rem;
  z-index: 70;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.wrap {
  max-width: 66rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

/* header: white bar under the strip.
   static on phones (a wrapped nav would eat the viewport), sticky from 40rem */
.site-header {
  position: static;
  z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  padding: 0.8rem 0;
}
@media (min-width: 40rem) {
  .site-header { position: sticky; top: 3px; }
}
.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.5rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--ink);
  text-decoration: none;
}
.brand svg { display: block; }
.grant-id { color: var(--muted); display: none; }
@media (min-width: 48rem) { .grant-id { display: inline; } }
.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  margin-left: auto;
}
.site-nav a {
  font-size: 0.95rem;
  color: var(--ink);
  text-decoration: none;
  padding: 0.45rem 0;
}
.site-nav a:hover { color: var(--link-strong); text-decoration: underline;
  text-decoration-thickness: 3px; text-decoration-color: var(--band); }

/* hero: the footpath, with a faint tactile-paving corner (one surface only) */
.hero {
  position: relative;
  padding: 4.5rem 0 4rem;
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  display: none;
  background-image: radial-gradient(circle,
    rgb(26 28 31 / 0.10) 1.5px, transparent 1.6px);
  background-size: 20px 20px;
  -webkit-mask-image: linear-gradient(215deg, #000 0 22%, transparent 55%);
  mask-image: linear-gradient(215deg, #000 0 22%, transparent 55%);
  pointer-events: none;
}
/* dots appear only beside the hero figure, never under stacked body text */
@media (min-width: 56rem) { .hero::before { display: block; } }
@media (prefers-color-scheme: dark) {
  .hero::before {
    background-image: radial-gradient(circle,
      rgb(232 235 238 / 0.10) 1.5px, transparent 1.6px);
  }
}
.hero .wrap {
  position: relative;
  display: grid;
  gap: 2.5rem;
  align-items: center;
}
@media (min-width: 56rem) {
  .hero .wrap { grid-template-columns: 1.2fr 0.8fr; }
}
.hero .lede {
  font-size: 1.2rem;
  line-height: 1.55;
  color: var(--muted);
  max-width: 34em;
  margin-bottom: 1.75rem;
}
/* shown at every size: stacks under the text on small screens,
   capped and centred so it stays modest on phones */
.hero-figure {
  display: block;
  max-width: 26rem;
  margin: 0 auto;
}
@media (min-width: 56rem) {
  .hero-figure { max-width: none; margin: 0; }
}
.hero-figure svg { width: 100%; height: auto; }
/* the shuttle cutout floats on the page ground, no panel */
.hero-figure img {
  display: block;
  width: 100%;
  height: auto;
}

/* buttons: a resting light strip that fills before the button lifts */
.cta-row { display: flex; flex-wrap: wrap; gap: 0.8rem; }
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1.2rem;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  border-radius: 2px;
  transition: box-shadow 160ms ease-out, transform 160ms ease-out 60ms,
    color 160ms ease-out, background-color 160ms ease-out;
}
.btn-primary {
  background: var(--ink);
  color: var(--surface);
}
.btn-primary:hover, .btn-primary:focus-visible {
  box-shadow: inset 0 -4px 0 var(--band);
  transform: translateY(-1px);
}
@media (prefers-color-scheme: dark) {
  .btn-primary { background: var(--surface); color: var(--ink); }
}
.btn-secondary {
  border: 1px solid var(--link);
  color: var(--link);
  background: transparent;
}
.btn-secondary:hover, .btn-secondary:focus-visible {
  color: var(--link-strong);
  border-color: var(--link-strong);
  box-shadow: inset 0 -3px 0 var(--band);
}
.btn:focus-visible { outline: 3px solid var(--link); outline-offset: 3px; }

/* sections */
section { padding: 3.5rem 0; }
.standfirst { color: var(--muted); max-width: 46em; margin-top: -0.5rem; }

/* news: a maintenance log for the street. dates in a chainage rail */
.log { list-style: none; margin: 0; padding: 0; }
.log li {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.1rem 1.5rem;
  padding: 1rem 0;
  border-top: 1px dashed var(--hairline);
}
.log li:last-child { border-bottom: 1px dashed var(--hairline); }
@media (min-width: 40rem) {
  .log li { grid-template-columns: 7.5rem 1fr; }
}
.log time, .log .rail {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  padding-top: 0.2rem;
}
.log p { margin: 0; }

/* research cards: static surfaces (they do not signal because they do not act) */
.card-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 40rem) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 56rem) { .card-grid { grid-template-columns: repeat(3, 1fr); } }
.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-top: 3px solid var(--band-dim);
  border-radius: 2px;
  padding: 1.5rem;
}
.card p { color: var(--muted); margin: 0; font-size: 0.98rem; }

/* toolkit component furniture: a numbered tag and a publications slot */
.tag {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  display: block;
  margin-bottom: 0.5rem;
}
.card .pubs {
  margin-top: 1rem;
  padding-top: 0.75rem;
  border-top: 1px dashed var(--hairline);
  font-size: 0.9rem;
}
.card .pubs ul { list-style: none; margin: 0; padding: 0; }
.card .pubs li { margin-bottom: 0.35rem; }

/* the crossing: used exactly once, where we invite people in */
.crossing {
  height: 8px;
  background: repeating-linear-gradient(90deg,
    rgb(26 28 31 / 0.12) 0 40px, transparent 40px 72px);
  margin-bottom: 3.5rem;
}
@media (prefers-color-scheme: dark) {
  .crossing {
    background: repeating-linear-gradient(90deg,
      rgb(232 235 238 / 0.14) 0 40px, transparent 40px 72px);
  }
}

/* featured workshop card: linked, so it signals. the band fills, then it lifts */
.feature {
  position: relative;
  display: block;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-top: 3px solid var(--band-dim);
  border-radius: 2px;
  padding: 1.75rem;
  background-image: linear-gradient(90deg, var(--band), var(--band));
  background-repeat: no-repeat;
  background-size: 0% 3px;
  background-position: top left;
  transition: background-size 160ms ease-out, transform 160ms ease-out 60ms;
}
.feature:hover, .feature:focus-within {
  background-size: 100% 3px;
  transform: translateY(-2px);
}
.feature h3 { font-size: 1.35rem; margin-bottom: 0.75rem; }
.feature h3 a { color: var(--ink); text-decoration: none; }
.feature h3 a::after { content: ""; position: absolute; inset: 0; }
.feature h3 a:focus-visible { outline: none; }
/* ring for keyboard focus only; :focus-within fallback for engines without :has() */
.feature:has(a:focus-visible) { outline: 3px solid var(--link); outline-offset: 3px; }
@supports not selector(:has(*)) {
  .feature:focus-within { outline: 3px solid var(--link); outline-offset: 3px; }
}
.feature p { margin-bottom: 0.5rem; }
.feature .go {
  color: var(--link);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
/* a feature card with no link yet: no approach signal, no link-coloured go text */
.feature-static:hover, .feature-static:focus-within {
  background-size: 0% 3px;
  transform: none;
}
.feature-static .go { color: var(--muted); font-weight: 500; }
.status {
  display: inline-block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0.1rem 0.75rem;
  margin-bottom: 0.9rem;
}

/* publications ledger: same rail as the news log */
.pub-empty { color: var(--muted); margin: 0; }

/* people: monogram plates, each lit at its own phase */
.people-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(2, 1fr);
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 48rem) { .people-grid { grid-template-columns: repeat(4, 1fr); } }
.person { font-size: 0.95rem; }
.plate {
  width: 64px;
  height: 64px;
  border-radius: 2px;
  background-color: var(--ink);
  background-image: linear-gradient(90deg, var(--band-dim), var(--band-dim));
  background-repeat: no-repeat;
  background-size: 40% 3px;
  background-position: 0% 100%;
  color: var(--ground);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.25rem;
  margin-bottom: 0.6rem;
}
@media (prefers-color-scheme: dark) { .plate { color: var(--dusk); } }
/* the signal currently sits with the lead researcher: the one lit plate */
.person:first-child .plate {
  background-image: linear-gradient(90deg, var(--band), var(--band));
}

/* photo plates: the portrait fills the square and the band sits on top.
   larger than monogram plates, fluid so they fit narrow grid columns */
.plate.photo {
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 192px;
  height: auto;
  aspect-ratio: 1 / 1;
}
.plate.photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.plate.photo::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 40%;
  height: 4px;
  background: var(--band-dim);
}
.person:first-child .plate.photo::after { background: var(--band); }
.person:nth-child(2) .plate { background-position: 14% 100%; }
.person:nth-child(3) .plate { background-position: 29% 100%; }
.person:nth-child(4) .plate { background-position: 43% 100%; }
.person:nth-child(5) .plate { background-position: 57% 100%; }
.person:nth-child(6) .plate { background-position: 71% 100%; }
.person:nth-child(7) .plate { background-position: 86% 100%; }
.person:nth-child(8) .plate { background-position: 100% 100%; }
.person .name { font-weight: 650; display: block; }
.person .role { color: var(--muted); }

/* schedule table (workshop pages) */
.schedule {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}
.schedule th {
  text-align: left;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted);
  padding: 0.5rem 1rem 0.5rem 0;
  border-bottom: 2px solid var(--ink);
}
.schedule td {
  padding: 0.6rem 1rem 0.6rem 0;
  border-bottom: 1px dashed var(--hairline);
  vertical-align: top;
}
.schedule .t {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
}
.schedule .break-row td { color: var(--muted); }

/* organiser list (workshop pages): plate, name, then the bio */
.org-list { list-style: none; margin: 1.5rem 0 0; padding: 0; }
.org-list li {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 0.4rem 1.25rem;
  padding: 1.25rem 0;
  border-top: 1px dashed var(--hairline);
}
.org-list .plate { margin-bottom: 0; }
.org-list .who { align-self: center; }
.org-list .who .name { font-weight: 650; display: block; }
.org-list .who .role { color: var(--muted); font-size: 0.95rem; }
.org-list .bio {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--muted);
  font-size: 0.98rem;
}
@media (min-width: 48rem) {
  .org-list .bio { grid-column: 2; margin-top: -0.25rem; }
}

/* footer: the page ends footpath, kerb, road */
.kerb-edge {
  height: 8px;
  background: var(--hairline);
  border-top: 2px solid var(--band);
  margin-top: 3.5rem;
}
.site-footer {
  background: var(--dusk);
  color: var(--dusk-text);
  padding: 3rem 0 3.5rem;
  background-image: linear-gradient(180deg, rgb(0 194 255 / 0.10), transparent 24px);
  font-size: 0.95rem;
}
.site-footer a { color: var(--dusk-link); }
.site-footer a:hover { color: var(--dusk-text); text-decoration-color: var(--band); }
.site-footer a:focus-visible { outline-color: var(--band); }
.site-footer .cols {
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) { .site-footer .cols { grid-template-columns: 1.2fr 1fr; } }
.site-footer h2 { margin: 0 0 0.5rem; font-size: 1rem; }
.site-footer h2::before { display: none; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 0.4rem; }
.centreline {
  height: 4px;
  background: repeating-linear-gradient(90deg,
    rgb(247 245 242 / 0.35) 0 48px, transparent 48px 96px);
  margin: 2rem 0;
}
.site-footer .fine { color: var(--dusk-muted); margin-bottom: 0.6rem; }

/* adaptive chrome: contrast preference hardens every dim or textured element */
@media (prefers-contrast: more) {
  body::before { background: var(--band); }
  h2::before { background: var(--band); }
  .hero::before { display: none; }
  .crossing { background: repeating-linear-gradient(90deg,
    var(--ink) 0 40px, transparent 40px 72px); }
  .log li { border-top-style: solid; border-top-color: var(--ink); }
  .log li:last-child { border-bottom-style: solid; border-bottom-color: var(--ink); }
  .schedule td { border-bottom-style: solid; border-bottom-color: var(--ink); }
  .org-list li { border-top-style: solid; border-top-color: var(--ink); }
  .card .pubs { border-top-style: solid; border-top-color: var(--ink); }
  .card, .feature { border-color: var(--ink); border-top-color: var(--band); }
  .status { border-color: var(--ink); color: var(--ink); }
  .site-footer { background-image: none; }
  .site-header { border-bottom-color: var(--ink); }
  .kerb-edge { background: var(--ink); }
}

/* reduced motion: the luminance change stays, the movement goes.
   colour is the signal; motion was only ever the consequence */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: 0.001ms !important; }
  .btn-primary:hover, .btn-primary:focus-visible,
  .feature:hover, .feature:focus-within { transform: none; }
}

/* the greyscale print test: on paper this must read as a plain academic page */
@media print {
  body::before, .hero::before, .crossing, .kerb-edge, .centreline { display: none; }
  body { background: #fff; color: #000; }
  .site-header { position: static; }
  .site-footer { background: #fff; color: #000; }
  .site-footer a { color: #000; }
  .feature, .card { border-color: #000; box-shadow: none;
    background-image: none; border-top-color: #000; }
  .btn { background: none; color: #000; box-shadow: none; border: 1px solid #000; }
  .plate { background: none; color: #000; border: 1px solid #000; }
  [fill="#00C2FF"] { fill: #000; }
  [stroke="#00C2FF"] { stroke: #000; }
  h2::before { background: #000; }
}
