@charset "UTF-8";
/* Sitewide mobile/desktop split — this is where the mega-menu collapses to
   the hamburger and grid layouts flip from stacked to multi-column. Route
   every "mobile starts here" media query through these instead of a literal
   @media (max-width: ...px), so the breakpoint can't drift to a stray value
   (768 is a deliberate secondary tablet tier layered on top of mobile via
   its own min-width: 768px queries, not a competing definition — leave
   those as-is). */
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, img, ins, kbd, q, s, samp,
small, strike, sub, sup, tt, var,
u, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, main {
  display: block;
}

body {
  line-height: 1;
}

ol, ul {
  list-style: none;
}

blockquote, q {
  quotes: none;
}

blockquote:before, blockquote:after,
q:before, q:after {
  content: "";
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition-duration: 0s !important;
  }
  [data-sal|=fade] {
    opacity: 1;
  }
  [data-sal|=slide], [data-sal|=zoom] {
    opacity: 1;
    transform: none;
  }
  [data-sal|=flip] {
    transform: none;
  }
}
* {
  box-sizing: border-box;
}

img, svg {
  max-width: 100%;
}

p, ul, ol {
  margin: 0 0 2em;
}

ul li {
  list-style: disc outside none;
  margin: 0 0 0.5em 2em;
}
ul li li {
  list-style-type: circle;
}
ul li li li {
  list-style-type: square;
}

ol li {
  list-style: decimal outside none;
  margin: 0 0 0.5em 2em;
}
ol li li {
  list-style-type: lower-alpha;
}
ol li li li {
  list-style-type: lower-roman;
}

li ul, li ol {
  margin-bottom: 0;
  margin-top: 0.5em;
}

b, strong {
  font-weight: bold;
}

i, em {
  font-style: italic;
}

select, input[type=text], input[type=email], input[type=tel], input[type=url], input[type=date], input[type=number], input[type=password], textarea {
  width: 100%;
}

input[type=text], input[type=email], input[type=tel], input[type=url], input[type=date], input[type=number], input[type=password], textarea {
  font: normal 14px/17px sans-serif;
  padding: 8px;
}

sub, sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sup {
  top: -0.5em;
}

sub {
  bottom: -0.25em;
}

/* Toggled on <html> by js.js while a full-viewport overlay (e.g. the
   Collaborator Bio overlay) is open, so the page underneath can't be
   scrolled behind it — without this the body stays scrollable the whole
   time the overlay sits on top of it. */
.no-scroll {
  overflow: hidden;
}

.visually-hidden {
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  overflow: hidden;
  position: absolute !important;
  width: 1px;
}

.centered, .aligncenter, .centred, .aligncentre, .center, .centre {
  text-align: center;
}

[data-sal] {
  transition-delay: 0s;
  transition-delay: var(--sal-delay, 0s);
  transition-duration: 1s;
  transition-duration: var(--sal-duration, 1s);
  transition-timing-function: ease-in-out;
  transition-timing-function: var(--sal-easing, ease-in-out);
}

[data-sal][data-sal-duration="200"] {
  transition-duration: 0.2s;
}

[data-sal][data-sal-duration="250"] {
  transition-duration: 0.25s;
}

[data-sal][data-sal-duration="300"] {
  transition-duration: 0.3s;
}

[data-sal][data-sal-duration="350"] {
  transition-duration: 0.35s;
}

[data-sal][data-sal-duration="400"] {
  transition-duration: 0.4s;
}

[data-sal][data-sal-duration="450"] {
  transition-duration: 0.45s;
}

[data-sal][data-sal-duration="500"] {
  transition-duration: 0.5s;
}

[data-sal][data-sal-duration="550"] {
  transition-duration: 0.55s;
}

[data-sal][data-sal-duration="600"] {
  transition-duration: 0.6s;
}

[data-sal][data-sal-duration="650"] {
  transition-duration: 0.65s;
}

[data-sal][data-sal-duration="700"] {
  transition-duration: 0.7s;
}

[data-sal][data-sal-duration="750"] {
  transition-duration: 0.75s;
}

[data-sal][data-sal-duration="800"] {
  transition-duration: 0.8s;
}

[data-sal][data-sal-duration="850"] {
  transition-duration: 0.85s;
}

[data-sal][data-sal-duration="900"] {
  transition-duration: 0.9s;
}

[data-sal][data-sal-duration="950"] {
  transition-duration: 0.95s;
}

[data-sal][data-sal-duration="1000"] {
  transition-duration: 1s;
}

[data-sal][data-sal-duration="1050"] {
  transition-duration: 1.05s;
}

[data-sal][data-sal-duration="1100"] {
  transition-duration: 1.1s;
}

[data-sal][data-sal-duration="1150"] {
  transition-duration: 1.15s;
}

[data-sal][data-sal-duration="1200"] {
  transition-duration: 1.2s;
}

[data-sal][data-sal-duration="1250"] {
  transition-duration: 1.25s;
}

[data-sal][data-sal-duration="1300"] {
  transition-duration: 1.3s;
}

[data-sal][data-sal-duration="1350"] {
  transition-duration: 1.35s;
}

[data-sal][data-sal-duration="1400"] {
  transition-duration: 1.4s;
}

[data-sal][data-sal-duration="1450"] {
  transition-duration: 1.45s;
}

[data-sal][data-sal-duration="1500"] {
  transition-duration: 1.5s;
}

[data-sal][data-sal-duration="1550"] {
  transition-duration: 1.55s;
}

[data-sal][data-sal-duration="1600"] {
  transition-duration: 1.6s;
}

[data-sal][data-sal-duration="1650"] {
  transition-duration: 1.65s;
}

[data-sal][data-sal-duration="1700"] {
  transition-duration: 1.7s;
}

[data-sal][data-sal-duration="1750"] {
  transition-duration: 1.75s;
}

[data-sal][data-sal-duration="1800"] {
  transition-duration: 1.8s;
}

[data-sal][data-sal-duration="1850"] {
  transition-duration: 1.85s;
}

[data-sal][data-sal-duration="1900"] {
  transition-duration: 1.9s;
}

[data-sal][data-sal-duration="1950"] {
  transition-duration: 1.95s;
}

[data-sal][data-sal-duration="2000"] {
  transition-duration: 2s;
}

[data-sal][data-sal-delay="50"] {
  transition-delay: 0.05s;
}

[data-sal][data-sal-delay="100"] {
  transition-delay: 0.1s;
}

[data-sal][data-sal-delay="150"] {
  transition-delay: 0.15s;
}

[data-sal][data-sal-delay="200"] {
  transition-delay: 0.2s;
}

[data-sal][data-sal-delay="250"] {
  transition-delay: 0.25s;
}

[data-sal][data-sal-delay="300"] {
  transition-delay: 0.3s;
}

[data-sal][data-sal-delay="350"] {
  transition-delay: 0.35s;
}

[data-sal][data-sal-delay="400"] {
  transition-delay: 0.4s;
}

[data-sal][data-sal-delay="450"] {
  transition-delay: 0.45s;
}

[data-sal][data-sal-delay="500"] {
  transition-delay: 0.5s;
}

[data-sal][data-sal-delay="550"] {
  transition-delay: 0.55s;
}

[data-sal][data-sal-delay="600"] {
  transition-delay: 0.6s;
}

[data-sal][data-sal-delay="650"] {
  transition-delay: 0.65s;
}

[data-sal][data-sal-delay="700"] {
  transition-delay: 0.7s;
}

[data-sal][data-sal-delay="750"] {
  transition-delay: 0.75s;
}

[data-sal][data-sal-delay="800"] {
  transition-delay: 0.8s;
}

[data-sal][data-sal-delay="850"] {
  transition-delay: 0.85s;
}

[data-sal][data-sal-delay="900"] {
  transition-delay: 0.9s;
}

[data-sal][data-sal-delay="950"] {
  transition-delay: 0.95s;
}

[data-sal][data-sal-delay="1000"] {
  transition-delay: 1s;
}

[data-sal][data-sal-easing=linear] {
  transition-timing-function: linear;
}

[data-sal][data-sal-easing=ease] {
  transition-timing-function: ease;
}

[data-sal][data-sal-easing=ease-in] {
  transition-timing-function: ease-in;
}

[data-sal][data-sal-easing=ease-out] {
  transition-timing-function: ease-out;
}

[data-sal][data-sal-easing=ease-in-out] {
  transition-timing-function: ease-in-out;
}

[data-sal][data-sal-easing=ease-in-cubic] {
  transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}

[data-sal][data-sal-easing=ease-out-cubic] {
  transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}

[data-sal][data-sal-easing=ease-in-out-cubic] {
  transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1);
}

[data-sal][data-sal-easing=ease-in-circ] {
  transition-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.335);
}

[data-sal][data-sal-easing=ease-out-circ] {
  transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
}

[data-sal][data-sal-easing=ease-in-out-circ] {
  transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}

[data-sal][data-sal-easing=ease-in-expo] {
  transition-timing-function: cubic-bezier(0.95, 0.05, 0.795, 0.035);
}

[data-sal][data-sal-easing=ease-out-expo] {
  transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
}

[data-sal][data-sal-easing=ease-in-out-expo] {
  transition-timing-function: cubic-bezier(1, 0, 0, 1);
}

[data-sal][data-sal-easing=ease-in-quad] {
  transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53);
}

[data-sal][data-sal-easing=ease-out-quad] {
  transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

[data-sal][data-sal-easing=ease-in-out-quad] {
  transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
}

[data-sal][data-sal-easing=ease-in-quart] {
  transition-timing-function: cubic-bezier(0.895, 0.03, 0.685, 0.22);
}

[data-sal][data-sal-easing=ease-out-quart] {
  transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}

[data-sal][data-sal-easing=ease-in-out-quart] {
  transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1);
}

[data-sal][data-sal-easing=ease-in-quint] {
  transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
}

[data-sal][data-sal-easing=ease-out-quint] {
  transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
}

[data-sal][data-sal-easing=ease-in-out-quint] {
  transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1);
}

[data-sal][data-sal-easing=ease-in-sine] {
  transition-timing-function: cubic-bezier(0.47, 0, 0.745, 0.715);
}

[data-sal][data-sal-easing=ease-out-sine] {
  transition-timing-function: cubic-bezier(0.39, 0.575, 0.565, 1);
}

[data-sal][data-sal-easing=ease-in-out-sine] {
  transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95);
}

[data-sal][data-sal-easing=ease-in-back] {
  transition-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
}

[data-sal][data-sal-easing=ease-out-back] {
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

[data-sal][data-sal-easing=ease-in-out-back] {
  transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

[data-sal|=fade] {
  opacity: 0;
  transition-property: opacity;
}

[data-sal|=fade].sal-animate, body.sal-disabled [data-sal|=fade] {
  opacity: 1;
}

[data-sal|=slide] {
  opacity: 0;
  transition-property: opacity, transform;
}

[data-sal=slide-up] {
  transform: translateY(20%);
}

[data-sal=slide-down] {
  transform: translateY(-20%);
}

[data-sal=slide-left] {
  transform: translateX(20%);
}

[data-sal=slide-right] {
  transform: translateX(-20%);
}

[data-sal|=slide].sal-animate, body.sal-disabled [data-sal|=slide] {
  opacity: 1;
  transform: none;
}

[data-sal|=zoom] {
  opacity: 0;
  transition-property: opacity, transform;
}

[data-sal=zoom-in] {
  transform: scale(0.5);
}

[data-sal=zoom-out] {
  transform: scale(1.1);
}

[data-sal|=zoom].sal-animate, body.sal-disabled [data-sal|=zoom] {
  opacity: 1;
  transform: none;
}

[data-sal|=flip] {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  transition-property: transform;
}

[data-sal=flip-left] {
  transform: perspective(2000px) rotateY(-91deg);
}

[data-sal=flip-right] {
  transform: perspective(2000px) rotateY(91deg);
}

[data-sal=flip-up] {
  transform: perspective(2000px) rotateX(-91deg);
}

[data-sal=flip-down] {
  transform: perspective(2000px) rotateX(91deg);
}

[data-sal|=flip].sal-animate, body.sal-disabled [data-sal|=flip] {
  transform: none;
}


:root {
  --color-black: #000000;
  --color-white: #ffffff;
  --color-river-blue: #1da9cc;
  --color-sun-yellow: #f5ca30;
  --color-grey: #666666;
  --font-display: 'benton-modern-display', Georgia, 'Times New Roman', serif;
  --font-body: 'univers-next-pro', Helvetica, Arial, sans-serif;
}

body {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.5;
  color: var(--color-black);
  background: var(--color-white);
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.01em;
  margin: 0 0 1em;
}

h1 {
  font-size: 74px;
  margin-top: 80px;
}

h2 {
  font-size: 48px;
}

h3 {
  font-family: var(--font-body);
  font-size: 32px;
  font-weight: 400;
}

h4 {
  font-family: var(--font-body);
  font-size: 24px;
  font-weight: 400;
}

@media (max-width: 1023px) {
  h1 {
    margin-top: 0;
    font-size: 54px;
  }
  h2 {
    font-size: 42px;
  }
  h3 {
    font-size: 30px;
  }
  h4 {
    font-size: 20px;
  }
}
p + h3 {
  margin-top: 60px;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.eyebrow {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

blockquote {
  font-family: var(--font-body);
  font-size: 32px;
  line-height: 1.3;
}

blockquote em, blockquote i {
  font-style: italic;
}

cite {
  font-family: var(--font-body);
  font-size: 32px;
  line-height: 1.3;
  font-style: normal;
}

cite em, cite i {
  font-style: italic;
}

@media (max-width: 1023px) {
  cite {
    font-size: 20px;
  }
}
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 40px;
  padding: 10px 20px;
  border: 2px solid var(--color-black);
  border-radius: 60px;
  background: var(--color-white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  line-height: 1;
  color: var(--color-black);
  white-space: nowrap;
  text-decoration: none;
  transition: border-color 0.2s ease;
}
.btn svg, .btn img {
  width: 17px;
  height: 16px;
  flex-shrink: 0;
}

.btn:hover,
.btn:focus-visible {
  border-color: var(--color-sun-yellow);
}

.btn--ghost {
  border-color: transparent;
}

.btn--accent {
  border-color: var(--color-river-blue);
  border-width: 3px;
}

.btn--lg {
  height: auto;
  padding: 10px 20px;
  font-size: 32px;
  font-weight: 400;
  line-height: 1.3;
}

/* Filled variant (e.g. "Page Shuffle" inside the mobile nav panel, Figma
   node 619-2623) — inverted colours, same border/hover behaviour as .btn. */
.btn--dark {
  background: var(--color-black);
  color: var(--color-white);
}

/* Category-colour highlight, set via --eco-colour by the ecosystem-filter JS. Used directly on links (e.g. mega-menu nav links) that aren't wrapped in a positioning element the way orbit-nav points are. */
.btn.is-highlighted {
  border-color: var(--eco-colour, var(--color-black));
}

.wrap {
  max-width: 1312px;
  margin-inline: auto;
  padding-inline: 24px;
}

@media (min-width: 1024px) {
  .wrap {
    padding-inline: 64px;
  }
}
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  width: 100%;
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-black);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 20px;
  padding-block: 30px;
}

.site-header__logo {
  margin-right: auto;
}
.site-header__logo img {
  display: block;
  width: 440px;
}

/* Below 1024px the logo fills whatever's left of the header row once the
   toggle button (fixed 39px + the row's 20px gap) is accounted for, instead
   of the desktop's fixed 440px — flex-grow does the "available width minus
   icon width" math instead of a computed max-width. */
@media (max-width: 1023px) {
  .site-header__inner {
    padding-block: 20px;
  }
  .site-header__logo {
    min-width: 0;
  }
  .site-header__logo img {
    width: 100%;
  }
}
/* Page Shuffle moves into the mobile nav panel (.mega-menu__shuffle) below
   1024px, so the sticky header itself only needs to fit the logo + toggle
   in that narrow width — hidden here, not removed from the header markup,
   so it still shows at desktop where the panel doesn't duplicate it. */
.site-header__shuffle {
  display: none;
}

@media (min-width: 1024px) {
  .site-header__shuffle {
    display: inline-flex;
  }
}
/* Hamburger-to-close morph: a centre bar plus ::before/::after bars offset
   above/below it. Opening fades the centre bar and rotates the other two
   into an X, entirely via transform/opacity transitions (no icon swap). */
.menu-toggle {
  background: var(--color-white);
  position: relative;
  flex-shrink: 0;
  width: 39px;
  height: 39px;
  padding: 0;
  border: 2px solid var(--color-black);
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 0.25s ease;
}
.menu-toggle:hover, .menu-toggle:active {
  border-color: var(--color-sun-yellow);
}

.menu-toggle__bar,
.menu-toggle__bar::before,
.menu-toggle__bar::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 17px;
  height: 2px;
  background: var(--color-black);
  transform: translate(-50%, -50%);
  transition: transform 0.25s ease, opacity 0.25s ease, background-color 0.25s ease;
}

.menu-toggle__bar::before {
  transform: translate(-50%, -50%) translateY(-5px);
}

.menu-toggle__bar::after {
  transform: translate(-50%, -50%) translateY(5px);
}

.menu-toggle[aria-expanded=true] .menu-toggle__bar {
  background: transparent;
}

.menu-toggle[aria-expanded=true] .menu-toggle__bar::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.menu-toggle[aria-expanded=true] .menu-toggle__bar::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* Primary nav mega-menu: docks directly beneath the sticky header via the
   --header-h custom property (set in JS, since the header's rendered height
   varies with viewport/content wrap and can't be known statically in CSS). */
.mega-menu {
  position: fixed;
  top: var(--header-h, 81px);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  overflow-y: auto;
  background: var(--color-white);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.25s ease, visibility 0.25s ease;
}

.mega-menu.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* No padding-block here: the sidebar's border-left (below) needs to reach
   from the panel's very top (right under the sticky header) to its very
   bottom (viewport edge), so the columns get their own vertical padding
   instead of it living on a shared ancestor. */
.mega-menu__inner {
  height: 100%;
}

.mega-menu .hero__grid {
  height: 100%;
  align-items: stretch;
}

.mega-menu .hero__ecosystem {
  padding-block: 60px;
}
.mega-menu .hero__ecosystem .hero__ecosystem-list {
  gap: 0.5em;
}

.mega-menu__links {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.mega-menu__links li {
  list-style: none;
  margin: 0;
}
.mega-menu__links {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  padding-block: 60px;
  margin-top: auto;
}

.mega-menu__shuffle {
  display: none;
}

/* Below 1024px the mega-menu sheds the desktop two-column/vertically-centred
   treatment for a plain top-down stack (Figma node 619-2623): nav links read
   as bare 30px text instead of ghost pill buttons, "Page Shuffle" appears
   inline as its own filled button, and the ecosystem pills wrap into rows
   instead of the desktop sidebar's single column. */
@media (max-width: 1023px) {
  .mega-menu .hero__grid {
    height: auto;
  }
  .mega-menu__links {
    margin-top: 0;
    padding-block: 40px 12px;
    gap: 20px;
  }
  /* Underline (in the matching Explore-pillar colour) replaces the
     desktop pill's border-color highlight, since these render as bare
     text on mobile — same mechanics as .eco-item/.eco-item.is-active,
     driven by the same [data-categories] JS (see js.js's "Orbit nav /
     explore-ecosystem colour hover"). */
  .mega-menu__links .btn {
    display: block;
    height: auto;
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 30px;
    line-height: 1.3;
    color: var(--color-black);
    text-decoration: underline;
    text-decoration-color: transparent;
    text-decoration-thickness: 3px;
    text-underline-offset: 0.15em;
    transition: text-decoration-color 0.2s ease;
  }
  .mega-menu__links .btn:hover,
  .mega-menu__links .btn:focus-visible {
    border-color: transparent;
  }
  .mega-menu__links .btn.is-highlighted {
    text-decoration-color: var(--eco-colour, currentColor);
  }
  /* justify-self: start keeps the button sized to its own content instead
     of stretching to the grid item's full column width (CSS Grid's default
     stretch behaviour applies regardless of the button's own inline-flex
     display). */
  .mega-menu__shuffle {
    display: inline-flex;
    justify-self: start;
    margin-bottom: 12px;
  }
  /* Full-viewport-width divider: the same negative-margin breakout as
     .text-slider (_content-blocks.scss), re-applying .wrap's own inline
     padding so the eyebrow/pills inside still line up with everything
     else instead of running edge-to-edge themselves. */
  .mega-menu .hero__ecosystem {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding-inline: 24px;
    padding-top: 32px;
    border-top: 1px solid var(--color-black);
  }
  .mega-menu .hero__ecosystem .hero__ecosystem-list {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 10px;
  }
}
.hero {
  padding: 0 60px;
  border-bottom: 1px solid var(--color-black);
}

.hero__grid {
  display: grid;
  gap: 40px;
  align-items: center;
}

.hero__ecosystem {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: 40px;
}

@media (min-width: 1024px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr) minmax(180px, 280px);
  }
  .hero__ecosystem {
    align-self: stretch;
    padding-left: 40px;
    border-left: 1px solid var(--color-black);
  }
}
.hero__ecosystem-list {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.hero__ecosystem-list li {
  list-style: none;
  margin: 0;
}
.hero__ecosystem-list {
  display: flex;
  flex-direction: column;
  gap: 1.5em;
}

.hero__ecosystem-list li {
  font-size: 32px;
  font-family: var(--font-body);
  line-height: 1.3;
}

/* --eco-colour is read by transitions (text-decoration-color here,
   border-color on .eco-item--pill below, plus the mobile mega-menu's nav
   link underline and .orbit-nav__point .btn in _orbit-nav.scss). An
   unregistered custom property is just a token stream, not a typed value,
   so a transition driven by var(--eco-colour, ...) never actually resolves
   in Chrome — it appears to hang at the fallback permanently. Registering
   it as a <color> makes it (and anything transitioning off it) animate
   normally. inherits MUST stay true: the orbit nav's JS sets --eco-colour
   on .orbit-nav__point itself, and its .btn child only sees that value by
   inheriting it (the .btn never gets --eco-colour set on it directly). */
@property --eco-colour {
  syntax: "<color>";
  inherits: true;
  initial-value: #000000;
}
.eco-item {
  all: unset;
  cursor: pointer;
  display: inline-block;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 3px;
  text-underline-offset: 0.15em;
  transition: text-decoration-color 0.2s ease;
}

.eco-item.is-active {
  text-decoration-color: var(--eco-colour, currentColor);
}

/* Pill-button variant (mega-menu sidebar) — same trigger/highlight behaviour
   as the plain-text .eco-item, styled like .btn instead of underlined text.
   Declared after .eco-item so its explicit values win the cascade without
   needing !important. */
.eco-item--pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 20px;
  border: 2px solid var(--color-black);
  border-radius: 60px;
  background: var(--color-white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  line-height: 1;
  color: var(--color-black);
  text-decoration: none;
  transition: border-color 0.2s ease;
}

/* No :hover rule here on purpose — the mega-menu's pills are click-only
   (see js.js's "Orbit nav / explore-ecosystem colour hover"), so a mouse
   hover shouldn't visually do anything. A stray :hover border-color rule
   previously left over from before that change was the actual cause of the
   "highlight breaks across a breakpoint resize" bug: resizing reflows the
   pill layout, which can leave a pill sitting under a now-stationary cursor
   in a browser-applied :hover state (browsers don't re-evaluate :hover
   until the next mousemove) with equal CSS specificity to .is-active,
   visually fighting the real active pill's colour. :focus-visible stays,
   since keyboard users still need a visible focus indicator and that
   pseudo-class doesn't trigger from mouse hover or click. */
.eco-item--pill:focus-visible {
  border-color: var(--color-sun-yellow);
}

.eco-item--pill.is-active {
  border-color: var(--eco-colour, var(--color-black));
}

/* X icon (click-to-remove hint), only shown once a pill is active — its
   own border already carries the highlight colour, so the icon just needs
   to read clearly against it via currentColor. Same two-pseudo-element
   rotate technique as .filter-dropdown__clear-icon. */
.eco-item__close {
  display: none;
  position: relative;
  flex-shrink: 0;
  width: 10px;
  height: 10px;
}

.eco-item__close::before,
.eco-item__close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
}

.eco-item__close::before {
  transform: rotate(45deg);
}

.eco-item__close::after {
  transform: rotate(-45deg);
}

.eco-item--pill.is-active .eco-item__close {
  display: block;
}

.eco-dots {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.eco-dots li {
  list-style: none;
  margin: 0;
}
.eco-dots {
  display: flex;
  gap: 10px;
  margin-top: 40px;
}

.eco-dot {
  appearance: none;
  -webkit-appearance: none;
  display: inline-block;
  width: 15px;
  height: 15px;
  padding: 0;
  margin: 0;
  cursor: pointer;
  border-radius: 50%;
  border: 1px solid var(--color-black);
  background: var(--color-black);
  transition: background-color 0.2s ease;
}

.eco-dot.is-active {
  background: var(--eco-colour, var(--color-black));
}

/* Page Entry hero: title + optional Page Menu (table field of {title, slug}
   rows, anchor-linked to matching Heading blocks' id in pageContent — see
   _partials/entry/heading.html). A sibling of the .section blocks below it,
   not a .section itself, matching the homepage .hero's shape so its own
   border-bottom is the divider (see "full-bleed section rule" convention). */
.page-hero {
  padding-block: 60px;
}

.page-hero__grid {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.page-hero__title {
  font-size: 48px;
  margin: 0;
}

@media (min-width: 768px) {
  .page-hero__title {
    font-size: 74px;
  }
}
.page-menu {
  align-self: flex-end;
  width: 100%;
}

@media (min-width: 1024px) {
  .page-menu {
    max-width: 646px;
  }
}
.page-menu__list {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.page-menu__list li {
  list-style: none;
  margin: 0;
}
.page-menu__list {
  border-bottom: 1px solid var(--color-black);
}

.page-menu__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-block: 1em;
  border-top: 1px solid var(--color-black);
  font-family: var(--font-body);
  font-size: 24px;
  line-height: 1.3;
  text-decoration: none;
}

@media (max-width: 1023px) {
  .page-menu__link {
    font-size: 20px;
  }
}
.page-menu__link:hover,
.page-menu__link:focus-visible {
  text-decoration: underline;
  text-decoration-color: var(--color-sun-yellow);
  text-decoration-thickness: 3px;
  text-underline-offset: 0.15em;
}

.section {
  padding-block: 60px;
}

@media (max-width: 1023px) {
  .section {
    padding-block: 40px;
  }
}
.section--shaded {
  background: #fbfbfb;
}

/* Discovery Corner (random Discovery Snippet entry) */
/* overflow: hidden establishes a block formatting context so the
   blockquote/cite's own margins render *inside* this box instead of
   collapsing through it — always on, not just while the "New Text" JS
   animates its height, so that toggling it wouldn't itself change the
   box's rendered size and cause a jump right as the height gets locked. */
.discovery-corner__quote {
  overflow: hidden;
}

.discovery-corner blockquote {
  font: 600 48px/130% var(--font-display);
  margin: 3em 0;
}

.discovery-corner cite {
  display: block;
  margin-bottom: 3em;
}

.discovery-corner__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 20px;
}

@media (max-width: 1023px) {
  .discovery-corner blockquote {
    font-size: 40px;
    margin: 1em 0;
  }
}
.site-footer {
  border-top: 1px solid var(--color-black);
  padding-block: 60px 40px;
}

.is-home .site-footer {
  border-top: none;
}

.site-footer a:not(.btn) {
  text-decoration: none;
}

.site-footer a:not(.btn):hover,
.site-footer a:not(.btn):focus-visible {
  text-decoration: underline;
  text-decoration-color: var(--color-sun-yellow);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.site-footer__columns {
  display: grid;
  gap: 40px;
  margin-bottom: 60px;
}
.site-footer__columns .btn {
  margin-top: 3em;
}

@media (min-width: 768px) {
  .site-footer__columns {
    grid-template-columns: repeat(4, 1fr);
  }
  .site-footer__column--wide {
    grid-column: span 2;
  }
}
.site-footer__columns h2 {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin-bottom: 2em;
}

.site-footer__sub-heading {
  margin-top: 2em;
}

.site-footer__columns ul {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.site-footer__columns ul li {
  list-style: none;
  margin: 0;
}
.site-footer__columns ul {
  display: flex;
  flex-direction: column;
  gap: 0.8em;
  margin-bottom: 3em;
}

.site-footer__mark {
  display: flex;
  justify-content: flex-end;
}

.site-footer__mark img {
  width: 48%;
  height: auto;
}

.site-footer__legal {
  font-size: 16px;
  width: 48%;
}

@media (max-width: 1023px) {
  .site-footer__nav {
    display: none;
  }
  .site-footer__mark img {
    margin-bottom: 60px;
    width: 100%;
  }
  .site-footer__legal {
    width: 100%;
  }
}
/*
	Ring of slowly-orbiting nav links. See the point-anchor technique notes
	kept alongside this component: a zero-size point rides the offset-path
	ellipse, the visible pill link is a centered child of that point. This
	keeps the path-follower unambiguous regardless of each link's label
	width, which is what a naive offset-anchor-on-the-box approach can't do
	without wobbling.
*/
.orbit-nav {
  position: relative;
  width: 100%;
  max-width: 810px;
  aspect-ratio: 809/500;
  margin-inline: auto;
  margin-block: 80px;
}

.orbit-nav__line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  transform: rotate(-20deg);
}

.orbit-nav__ring {
  position: absolute;
  inset: 0;
  transform: rotate(-20deg);
}

.orbit-nav__point {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  offset-path: ellipse(49.5% 49.5% at 50% 50%);
  offset-rotate: 0deg;
  animation: orbit-travel 90s linear infinite;
  animation-delay: calc(var(--i, 0) / var(--n, 1) * -90s);
}

@keyframes orbit-travel {
  to {
    offset-distance: 100%;
  }
}
.orbit-nav__point .btn {
  border-color: var(--color-white);
  position: absolute;
  transform: translate(-50%, -50%) rotate(20deg);
  transition: border-color 0.2s ease;
}
.orbit-nav__point .btn:hover {
  border-color: var(--color-black);
}

.orbit-nav__point.is-highlighted .btn {
  border-color: var(--eco-colour, var(--color-white));
}

/*
	Hover/focus pause is handled in JS (easing animation-playbackRate down to
	0 and back up, for a touch of inertia) rather than here via
	animation-play-state — that property is a hard, instant stop and would
	fight the JS tween if it were also toggled on :hover/:focus-within.
*/
@media (max-width: 1023px) {
  .hero {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .orbit-nav__point {
    animation: none;
  }
}
/* pageContent blocks all render concatenated inside one .page-content wrap
   (see _entry/page/pageEntry.html) rather than each getting its own .section,
   so there's no padding-block between them by default — grid/flex block
   types in particular (.text-lockup, .text-slider, .two-up-images,
   .image-carousel) establish their own formatting context and don't let a
   child's margin collapse through to space them from the next block. A
   bare-selector rule here covers every block type once, present and future,
   instead of adding a bottom margin to each block's own class. */
.page-content > * + * {
  margin-top: 60px;
}

/* Text-only blocks (Heading, Text, Pullquote) render as bare elements with no
   wrapping class — cap them to the same column width as a Text Lockup's own
   text side (1fr of a 1fr/1fr grid with a 40px gap, i.e. half the container
   minus half the gap) so they read as one consistent text column instead of
   spanning the full .wrap width like the grid-based blocks (Image, Two-Up
   Images, Text Slider, Image Carousel) do. */
@media (min-width: 1024px) {
  .page-content > h1,
  .page-content > h2,
  .page-content > h3,
  .page-content > h4,
  .page-content > h5,
  .page-content > h6,
  .page-content > .text-block,
  .page-content > ul,
  .page-content > ol,
  .page-content > blockquote,
  .page-content > cite {
    max-width: calc(50% - 20px);
  }
  /* Pullquote (blockquote + cite) is the one text-only block that sits in
     the right half of the column instead of the left, per Figma — margin-left:
     auto pushes it flush right within the already-capped half-width box. */
  .page-content > blockquote,
  .page-content > cite {
    margin-left: auto;
  }
}
/* Pullquote's own type treatment: smaller and lighter than the base
   blockquote/cite tags (which are also reused as-is by .discovery-corner's
   unrelated random-quote widget, so these overrides stay scoped under
   .page-content rather than changing the bare tags globally). */
.page-content > blockquote {
  font-size: 24px;
  line-height: 1.5;
  letter-spacing: 0.01em;
}

.page-content > cite {
  display: block;
  margin-top: 24px;
  font-size: 16px;
  color: var(--color-grey);
}

.page-content > cite::before {
  content: "— ";
}

/* All pageContent images share the same 40px corner radius, wherever they're
   rendered from (standalone Image, Two-Up Images, Image Carousel, Text
   Lockup) — targeting figure img here covers every case via the one shared
   _partials/entry/image.html partial, instead of a border-radius per block
   class. */
figure img {
  border-radius: 40px;
}

@media (max-width: 1023px) {
  figure img {
    border-radius: 20px;
  }
}
/* Text Lockup (pageContent block: image + text, placed left or right) */
.text-lockup {
  display: grid;
  gap: 40px;
}

@media (min-width: 1024px) {
  .text-lockup {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}
.text-lockup__image {
  order: 1;
  border-radius: 40px;
  overflow: hidden;
}

.text-lockup__image img {
  display: block;
  width: 100%;
  height: auto;
}

.text-lockup__content {
  order: 2;
}

.text-lockup--right .text-lockup__image {
  order: 2;
}

.text-lockup--right .text-lockup__content {
  order: 1;
}

/* Text Slider (pageContent block: tabbed set of Text Slide entries). Unlike
   the other blocks it keeps its own full-width divider + block padding
   (what every block got back when each was wrapped in its own .section) —
   so it breaks out of the shared .page-content wrap's max-width via the
   viewport-relative negative-margin trick, then re-establishes that same
   max-width/gutter for its own content via .wrap (reused, not reimplemented)
   on .text-slider__inner.

   Panels are managed by Swiper (loaded globally via CDN, same as the Image
   Carousel) rather than hand-rolled display:none/block toggling, so they're
   swipeable by touch at every width. The tabs (large clickable labels) are
   desktop-only — below 1024px they're hidden and the Swiper-generated
   pagination dots (.text-slider__dots doubles as the .swiper-pagination
   target) are the only direct-jump control, positioned above the panels by
   source order in .text-slider__nav. Bullet styling is the shared, unscoped
   .swiper-pagination-bullet rule (see Image Carousel below), so both
   components' dots already match. */
.text-slider {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-block: 60px;
  border-top: 1px solid var(--color-black);
  border-bottom: 1px solid var(--color-black);
}

.text-slider__inner {
  display: grid;
  gap: 24px;
}

.text-slider__nav {
  display: flex;
  flex-direction: column;
  gap: 20px;
  /* Below 1024px, .text-slider__tabs is hidden (see below) so .text-slider__nav
     is really just the dots row — order moves it after the swiper so the
     dots sit at the bottom of the whole component, not above the panels.
     Reset back to its natural (first) position at desktop, alongside the
     tabs. */
  order: 2;
}

.text-slider__tabs {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.text-slider__tabs li {
  list-style: none;
  margin: 0;
}
.text-slider__tabs {
  display: none;
  flex-direction: column;
  gap: 1.5em;
}

.text-slider__tab {
  all: unset;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 32px;
  line-height: 1.3;
  color: var(--color-black);
}

.text-slider__tab.is-active {
  text-decoration: underline;
  text-decoration-color: var(--color-sun-yellow);
  text-decoration-thickness: 3px;
  text-underline-offset: 0.15em;
}

.text-slider__dots {
  position: static;
  /* Swiper's base .swiper-pagination rule is text-align: center — override
     so the bullets (inline-block) line up with .text-slider__tab's left
     edge above them, instead of centering in the flex column's full
     stretched width. */
  text-align: left;
  --swiper-pagination-bullet-horizontal-gap: 5px;
}

.text-slider__swiper {
  /* Same nested-grid/flex intrinsic-sizing fix as .image-carousel__swiper
     below — this is the right-hand column of the same 1fr 1fr grid. */
  width: 100%;
  min-width: 0;
  order: 1;
}

/* Desktop overrides come last so they win the cascade over the mobile-first
   .text-slider__tabs { display: none } above, without needing extra
   specificity (an earlier attempt placed this media query above the base
   rules and the tabs never showed at any width — same-specificity rules
   resolve by source order, not by which one is inside a media query). */
@media (min-width: 1024px) {
  .text-slider__inner {
    grid-template-columns: 1fr 1fr;
    /* stretch (the grid default) rather than start — .text-slider__nav
       needs to match the swiper column's full height so its dots can be
       pinned to the bottom via justify-content below. */
    align-items: stretch;
  }
  .text-slider__tabs {
    display: flex;
  }
  .text-slider__nav {
    /* Back to its natural first-column position — the order:2 mobile
       reorder (dots below the swiper) doesn't apply once the tabs are
       visible again and nav/swiper sit side by side as columns. */
    order: 1;
    /* Pins the dots to the bottom of the stretched nav column — i.e. the
       bottom of the swiper container beside it — instead of sitting
       directly under the tabs with a fixed gap. */
    justify-content: space-between;
  }
  .text-slider__swiper {
    order: 2;
  }
}
/* Two-Up Images (pageContent block: a pair of side-by-side images) */
.two-up-images {
  display: grid;
  gap: 20px;
}

@media (min-width: 768px) {
  .two-up-images {
    grid-template-columns: 1fr 1fr;
  }
}
/* Image Carousel (pageContent block: a set of images with a caption column
   beside them — the "Books & Decks" layout in the Figma file — managed by
   Swiper, loaded globally via CDN in _layout.html, rather than a hand-rolled
   slider). Both the pagination dots and the caption column live outside the
   .swiper element itself (same out-of-swiper technique as .text-slider__dots
   below — Swiper's pagination.el just needs a reference to the node, not for
   it to be a descendant of the swiper root). Each image's own caption
   (CKEditor-purified HTML, see the Images volume's "Simple Text" field) is
   pre-rendered as its own panel and toggled via the same .is-active
   convention as .text-slider__panel — synced from Swiper's slideChange event
   in JS — instead of writing HTML into the DOM from JS.

   Plain source order — caption, swiper, dots — is what gives mobile its
   caption-above-image-above-dots stack for free (.image-carousel__inner has
   no explicit grid-template-columns below desktop, so it's just a single
   implicit column). Desktop then places all three by name via
   grid-template-areas rather than DOM order, putting the dots back directly
   under the image and the caption in its own side column.

   Matches .text-slider's own full-width divider + block padding treatment:
   breaks out of the shared .page-content wrap's max-width via the
   viewport-relative negative-margin trick, then re-establishes that same
   max-width/gutter for its own content via .wrap (reused, not reimplemented)
   on .image-carousel__inner. */
.image-carousel {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-block: 60px;
  border-top: 1px solid var(--color-black);
  border-bottom: 1px solid var(--color-black);
}

.image-carousel__inner {
  display: grid;
  gap: 40px;
}

@media (min-width: 1024px) {
  .image-carousel__inner {
    grid-template-columns: minmax(0, 1fr) minmax(220px, 368px);
    grid-template-areas: "swiper caption" "pagination caption";
    align-items: center;
  }
  .image-carousel__swiper {
    grid-area: swiper;
  }
  .image-carousel__pagination {
    grid-area: pagination;
  }
  .image-carousel__caption {
    grid-area: caption;
  }
}
.image-carousel__swiper {
  /* Grid items default to min-width:auto, so the .swiper-wrapper's flex
     children (each full-size image, before Swiper's JS sets an explicit
     pixel width per slide) blow the item — and Swiper's own clientWidth
     read — out to their combined intrinsic width instead of respecting
     the grid track. min-width:0 is the standard fix for a flex/grid
     child whose own content is itself a flex/grid container.

     min-width:0 alone still leaves this item's *own* width resolving via
     CSS Grid's "stretch" auto-sizing, which factors the item's max-content
     contribution (driven by those same unsized flex children) into the
     track-sizing algorithm before finally stretching it — an intermediate
     pass that occasionally hands Swiper's clientWidth read (on init) a
     garbage value well before the grid settles on the real track width.
     An explicit width:100% resolves this item's width from the grid
     track alone (a plain percentage), sidestepping that content-driven
     pass entirely so Swiper always measures the real column width. */
  width: 100%;
  min-width: 0;
}

.image-carousel__swiper img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 40px;
}

.image-carousel__pagination {
  position: static;
  display: flex;
  justify-content: center;
  --swiper-pagination-bullet-horizontal-gap: 5px;
}

.swiper-pagination-bullet {
  width: 15px;
  height: 15px;
  background: var(--color-black);
  border: 1px solid var(--color-black);
  opacity: 1;
}

.swiper-pagination-bullet-active {
  background: var(--color-sun-yellow);
  border-color: var(--color-black);
}

.image-carousel__caption-panel {
  display: none;
}

.image-carousel__caption-panel.is-active {
  display: block;
}

/* Accordion (pageContent block: a list of disclosure items, e.g. Sectors on
   the Services page). Each item toggles independently (not exclusive, unlike
   .text-slider's tabs) — the first is expanded by default, matching the
   Figma reference. border-top on every item plus one border-bottom on the
   container yields a divider both above and below each row without a
   separate divider element per gap. */
.accordion {
  border-bottom: 1px solid var(--color-black);
}

.accordion-item {
  border-top: 1px solid var(--color-black);
}

.accordion-item__header {
  all: unset;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
  width: 100%;
  box-sizing: border-box;
  padding-block: 30px;
  cursor: pointer;
}

.accordion-item__title {
  margin: 0;
}

.accordion-item__toggle {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-shrink: 0;
}

/* Plus-to-minus morph via transform/opacity on two bars, the same technique
   as .menu-toggle__bar's hamburger-to-X (no icon swap). */
.accordion-item__icon {
  position: relative;
  display: block;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
}

.accordion-item__icon::before,
.accordion-item__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--color-black);
  transform: translate(-50%, -50%);
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.accordion-item__icon::before {
  width: 30px;
  height: 2px;
}

.accordion-item__icon::after {
  width: 2px;
  height: 30px;
}

.accordion-item.is-active .accordion-item__icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
  opacity: 0;
}

.accordion-item__panel {
  display: none;
  padding: 40px 0;
  font-size: 20px;
  line-height: 1.5;
}

.accordion-item.is-active .accordion-item__panel {
  display: block;
  animation: text-slider-fade-in 0.25s ease;
}

@keyframes text-slider-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
/* Thumbnail Grid (pageContent block: a grid of square images with a caption
   underneath, e.g. Methods on the Services page). auto-fill/minmax instead
   of a fixed 4-column track so it reflows at narrower widths and with
   item counts other than four. */
.thumbnail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 40px;
}

.thumbnail-grid__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
  text-align: center;
}

.thumbnail-grid__image {
  display: block;
  width: 100%;
  aspect-ratio: 1/1;
  object-fit: cover;
  border-radius: 40px;
}

.thumbnail-grid__caption {
  font-family: var(--font-body);
  font-size: 24px;
}

/* Featured Entry (pageContent block: embeddedEntries — a related Project,
   Event, or Resource rendered as a rich two-column card, e.g. Featured
   Project on the Services page). Field availability differs per related
   entry's type (client/collaborators/category tags are Project-only), so
   the meta block markup itself is conditional in the template; the CSS here
   only lays out whichever rows are actually present. */
.featured-entry {
  display: grid;
  gap: 40px;
  padding-block: 40px;
  border-top: 1px solid var(--color-black);
  border-bottom: 1px solid var(--color-black);
}

@media (min-width: 1024px) {
  .featured-entry {
    grid-template-columns: minmax(0, 1fr) minmax(280px, 369px);
    align-items: start;
  }
}
.featured-entry__title {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 32px;
  line-height: 1.3;
}

.featured-entry__meta {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-top: 20px;
}

.featured-entry__meta-row .filter-group__label {
  margin-bottom: 0.25em;
  opacity: 0.7;
}

.featured-entry__meta-row p:last-child {
  font-size: 24px;
}

.featured-entry__description {
  margin-top: 20px;
  font-size: 20px;
  line-height: 1.5;
}

.featured-entry__content .filter-chips {
  margin-top: 20px;
}

.featured-entry__media {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 20px;
}

.featured-entry__read-more {
  font-family: var(--font-body);
  font-size: 24px;
  color: var(--color-black);
  opacity: 0.7;
  text-decoration: none;
}

.featured-entry__read-more:hover,
.featured-entry__read-more:focus-visible {
  text-decoration: underline;
}

.featured-entry__image {
  display: block;
  width: 100%;
  aspect-ratio: 1/1;
  object-fit: cover;
  border-radius: 40px;
}

/* Application (pageContent block: a funding/residency application listing —
   title, status badge, due date, requirements, and a CTA link, e.g. "2026
   Application" on the Community page). The entry type has no image field of
   its own — in the Figma reference the adjacent artwork belongs to the Text
   Lockup block above it — so this reads as a text block and caps to the same
   half-width column as bare headings/paragraphs on desktop (see
   .page-content > h1 etc. near the top of this file) rather than spanning
   the full .wrap width the way grid-based blocks do. Reuses
   .featured-entry__meta-row/__description from the Featured Entry block
   above for the due-date row and requirement/how-to-apply copy, since both
   are the same "label + value" shape. */
.application {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

@media (min-width: 1024px) {
  .application {
    max-width: calc(50% - 20px);
  }
}
.application__badge {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  height: 40px;
  padding: 10px 20px;
  border: 2px solid var(--color-sun-yellow);
  border-radius: 60px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  color: var(--color-black);
}

.application__title {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 32px;
  line-height: 1.3;
}

.application__cta {
  align-self: flex-start;
}

/* Collaborator Grid (pageContent block: every entry in the Collaborators
   channel, e.g. under "Collaborators" on the Community page). The entry type
   carries no fields of its own (see collaboratorGrid.html) — it's a query
   against the section, not per-block content, so there's nothing to bind to
   here beyond triggering the render. Paginated via Craft's native
   {% paginate %} (6 per page) rather than querying everything and hiding the
   overflow client-side — "Load More" is a real link to pageInfo.nextUrl. */
.collaborator-grid-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
}

/* Plain 2-column grid below desktop — the spacer stays display:none (next
   rule) here, since a real 2-up grid doesn't need one to fill a leftover
   slot the way the desktop 3-column layout does. Collapses to a single
   column only below 540px, a one-off breakpoint for this component alone
   (narrow phones where 2 headshots-per-row would get too cramped), not the
   sitewide mobile/desktop split — leave it a literal @media, not @include
   mobile. */
.collaborator-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 40px;
  width: 100%;
}

@media (max-width: 540px) {
  .collaborator-grid {
    grid-template-columns: 1fr;
  }
}
.collaborator-grid__spacer {
  display: none;
}

/* Fixed 3-column grid at desktop, sized so the two visible headshots per row
   read as a third of the row each — the spacer div (see collaboratorGrid.html)
   fills the third slot and alternates sides per row via DOM order, so it only
   needs to occupy a track from here (min-width:0 keeps it from imposing a
   minimum track size like a real grid item would). */
@media (min-width: 1024px) {
  .collaborator-grid {
    grid-template-columns: repeat(3, 1fr);
  }
  .collaborator-grid__spacer {
    display: block;
    min-width: 0;
  }
}
.collaborator-grid__link {
  position: relative;
  display: block;
  aspect-ratio: 3/4;
}

/* Clips the headshot to the rounded thumbnail shape. Kept off
   .collaborator-grid__link itself (unlike before) so .collaborator-grid__cta
   — an absolutely-positioned sibling, not a child of this wrap — is free to
   render past the thumbnail's edge while cursor-following near a corner,
   instead of being clipped along with the image. */
.collaborator-grid__image-wrap {
  position: absolute;
  inset: 0;
  border-radius: 40px;
  overflow: hidden;
}

.collaborator-grid__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Read Bio only shows on hover/focus — the whole image is still the link,
   this is just the visible affordance for it (same technique as the sticky
   ecosystem hover, opacity/transform rather than a layout change). */
.collaborator-grid__cta {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.2s ease;
  /* Now that this can render outside the thumbnail's own box (see
     .collaborator-grid__image-wrap above), it must never be the hit-tested
     element itself: since it tracks the cursor 1:1, the pointer would
     always be "over" it, and because it's a descendant of the link it
     would keep :hover — and thus itself — active indefinitely, even long
     after the cursor has left the thumbnail. Pointer-events stay on the
     link/image beneath it, which is the real, correctly-bounded hover and
     click target. */
  pointer-events: none;
}

.collaborator-grid__link:hover .collaborator-grid__cta,
.collaborator-grid__link:focus-visible .collaborator-grid__cta {
  opacity: 1;
}

/* Desktop only (js.js gates .is-following-cursor to the same 1024px
   breakpoint via matchMedia, this rule is the belt-and-braces backstop):
   while the pointer is over the headshot, the pill tracks it instead of
   sitting fixed in the centre — --cursor-x/--cursor-y are set to a
   position local to .collaborator-grid__link (position: relative), not
   the viewport, since every grid item tracks its own cursor position
   independently. Falls back to the centred 50%/50% above for
   :focus-visible, which has no cursor position to follow. No transition
   on top/left, same reasoning as the bio overlay's close button — 1:1
   tracking reads right, eased tracking reads laggy. */
@media (min-width: 1024px) {
  .collaborator-grid__cta.is-following-cursor {
    top: var(--cursor-y, 50%);
    left: var(--cursor-x, 50%);
  }
}
.collaborator-grid__name {
  margin: 20px 0 5px;
  font-family: var(--font-body);
  font-size: 24px;
}

.collaborator-grid__field {
  font-size: 24px;
  margin-bottom: 20px;
  opacity: 0.7;
}

/* Collaborator Bio. Shared between the standalone /collaborators/{slug} page
   (_entry/collaborator.html, the source of truth) and the quick-view overlay
   below, which fetches that same page over AJAX and injects the
   [data-collaborator-bio] fragment — see the "Collaborator Bio overlay"
   block in js.js. */
.collaborator-bio {
  padding-block: 40px;
}

.collaborator-bio__pronouns {
  opacity: 0.7;
  font-weight: 400;
}

.collaborator-bio__text {
  margin-top: 40px;
  max-width: 646px;
  font-size: 20px;
  line-height: 1.5;
}

.collaborator-bio__links {
  display: flex;
  gap: 20px;
  margin-top: 40px;
}

/* Collaborator Bio overlay ("Read Bio" quick view). Unlike .mega-menu (which
   docks below the sticky header via var(--header-h) so it never covers the
   nav), this overlay spans the full viewport including the header — its
   z-index (110) beats .site-header's (100), so the header's own translucent
   backdrop-filter gets blurred further by this overlay's backdrop, same as
   the rest of the page behind it. The panel is a text-only quick view — the
   Figma reference shows the collaborator's photo bleeding through the
   blurred backdrop instead of repeating it in the panel, so
   .collaborator-bio__media (the headshot) is suppressed here rather than
   forking the bio markup. */
.collaborator-bio-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 110;
  visibility: hidden;
  pointer-events: none;
  /* Only visibility lives on the container now — the backdrop, panel and
     close button each animate themselves (see below) so the blur can land
     before the panel slides in. Hiding is delayed to the longest closing
     transition (the panel's 0.3s) so nothing gets cut off mid-animation;
     opening flips visibility instantly via the .is-open override below. */
  transition: visibility 0s linear 0.3s;
}

.collaborator-bio-overlay.is-open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

.collaborator-bio-overlay__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.collaborator-bio-overlay.is-open .collaborator-bio-overlay__backdrop {
  opacity: 1;
}

.collaborator-bio-overlay__panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(100%, 767px);
  overflow-y: auto;
  /* Without this, scrolling to the top/bottom of the panel's own content
     chains to the page behind it (still scrollable underneath the fixed
     overlay — see the body lock in js.js) instead of stopping dead, which
     reads as "the overlay itself doesn't scroll, the background does". */
  overscroll-behavior: contain;
  background: var(--color-white);
  border-left: 1px solid var(--color-black);
  padding: 60px;
  transform: translateX(100%);
  /* No delay here — this is the closing transition (slides out as soon as
     .is-open is removed). The opening delay lives on the .is-open rule
     below, so the backdrop's blur is visible first. */
  transition: transform 0.3s ease;
}

.collaborator-bio-overlay.is-open .collaborator-bio-overlay__panel {
  transform: translateX(0);
  transition-delay: 0.15s;
}

/* Floats to the left of the white panel, over the blurred backdrop, rather
   than sitting inline with the bio content — per the Figma quick-view spec.
   It's a sibling of .collaborator-bio-overlay__panel (not nested inside it)
   so the panel's own overflow-y: auto doesn't clip it once positioned
   outside the panel's box. Fades in on the same delay as the panel, so it
   appears together with it rather than with the backdrop. */
.collaborator-bio-overlay__close {
  position: absolute;
  top: 50%;
  right: min(100%, 767px);
  transform: translateY(-50%);
  margin-right: 40px;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.collaborator-bio-overlay.is-open .collaborator-bio-overlay__close {
  opacity: 1;
  transition-delay: 0.15s;
}

/* Desktop only (js.js gates .is-following-cursor to the same 1024px
   breakpoint via matchMedia, this rule is the belt-and-braces backstop):
   once the overlay is open, the close button abandons its static spot
   beside the panel and tracks the cursor instead, repositioned every
   mousemove via the --cursor-x/--cursor-y custom properties. No transition
   on top/left — cursor-follow reads as laggy the moment it isn't a 1:1
   tracking. */
@media (min-width: 1024px) {
  .collaborator-bio-overlay__close.is-following-cursor {
    position: fixed;
    top: var(--cursor-y, 50%);
    left: var(--cursor-x, 50%);
    right: auto;
    margin-right: 0;
    /* Offset left of the cursor point (rather than centred under it) so
       the pointer doesn't sit directly over "Close Bio" — the cursor
       rides just off the button's right edge instead. */
    transform: translate(-90%, -50%);
    /* .collaborator-bio-overlay__panel is a later, z-index:auto sibling
       within the same z-index:110 stacking context, so DOM order alone
       would paint the panel over the button once cursor-tracking moves
       it across the panel's own box — bump it above without needing a
       z-index on the overlay's other children. */
    z-index: 1;
  }
  /* Following the cursor everywhere means it inevitably trails across the
     Instagram/Website links too — as a real click target sitting above
     everything, it was stealing those clicks (a blanket pointer-events:
     none on the button fixed that but also broke "click the follow
     button to close" for the rest of the bio, since most of the panel
     has no click-to-close handler of its own underneath). js.js toggles
     this class via a real mouseenter/mouseleave on .collaborator-bio__links
     (not the throttled cursor-follow mousemove loop), so the button gets
     out of the way only where it would otherwise cover a real link —
     everywhere else in the panel it stays the click target it was always
     meant to be. transition: none overrides the base rule's opacity fade
     — a button that lingers, semi-visible and sitting right on top of the
     link you're trying to click, for a fifth of a second reads as broken,
     not smooth, so this has to be an instant cut rather than a fade. */
  .collaborator-bio-overlay__close.is-following-cursor.is-over-links {
    opacity: 0;
    pointer-events: none;
    transition: none;
  }
}
/* Mobile: the overlay docks below the sticky header (same var(--header-h)
   technique as .mega-menu) instead of spanning the full viewport, and drops
   below the header in the stacking order (z-index 90, matching
   .mega-menu's) rather than blurring over top of it. The close button moves
   onto the panel itself as a circular icon-only control (top right, X drawn
   from two crossed bars like .menu-toggle's) since there's no room to float
   it in the margin beside the panel at this width; its label is kept for
   screen readers via the same clip-rect technique as .visually-hidden. */
@media (max-width: 1023px) {
  .collaborator-bio-overlay {
    top: var(--header-h, 81px);
    z-index: 90;
  }
  .collaborator-bio-overlay__panel {
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border-left: 0;
    padding: 80px 20px 40px;
  }
  .collaborator-bio-overlay .collaborator-bio__header .entry-card__meta {
    margin-bottom: 0;
  }
  .collaborator-bio-overlay__close {
    position: absolute;
    top: 20px;
    right: 20px;
    left: auto;
    bottom: auto;
    margin-right: 0;
    transform: none;
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 50%;
    z-index: 1;
  }
  .collaborator-bio-overlay__close-label {
    clip: rect(1px, 1px, 1px, 1px);
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
  }
  .collaborator-bio-overlay__close::before,
  .collaborator-bio-overlay__close::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 16px;
    height: 2px;
    background: var(--color-black);
  }
  .collaborator-bio-overlay__close::before {
    transform: translate(-50%, -50%) rotate(45deg);
  }
  .collaborator-bio-overlay__close::after {
    transform: translate(-50%, -50%) rotate(-45deg);
  }
}
.collaborator-bio-overlay .collaborator-bio {
  padding-block: 0;
}

.collaborator-bio-overlay .collaborator-bio__media {
  display: none;
}

/* The injected fragment is [data-collaborator-bio]'s innerHTML, so this
   content div (not .collaborator-bio, which isn't part of that innerHTML)
   is the actual flex container for the overlay's header/text/links —
   stretched to the panel's full height so .collaborator-bio__links can be
   pinned to the bottom via margin-top: auto, per the Figma spec. On short
   viewports where the content already overflows (panel scrolls), the links
   just follow the text with no extra gap, since there's no leftover space
   for auto to consume. */
.collaborator-bio-overlay__content {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.collaborator-bio-overlay .collaborator-bio__links {
  margin-top: auto;
  padding-top: 40px;
}

/* The overlay's name/pronouns/field-of-work block sits at a much smaller
   scale than the standalone page's h1 (which uses the site's 74px display
   serif) — the Figma quick-view spec sets this as 24px body-font regular,
   with pronouns and field of work in #666, so it's overridden here rather
   than changing the shared h1/.entry-card__meta styles used elsewhere. */
.collaborator-bio-overlay .collaborator-bio__header h1 {
  margin: 0;
  font-family: var(--font-body);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.3;
}

.collaborator-bio-overlay .collaborator-bio__pronouns {
  opacity: 1;
  color: var(--color-grey);
}

.collaborator-bio-overlay .collaborator-bio__header .entry-card__meta {
  margin-top: 5px;
  font-size: 24px;
  opacity: 1;
  color: var(--color-grey);
}

/* Contact Blocks (pageContent block: the "General Inquiries / Work with Us /
   Customer Service / Book a Meeting" grid on the Contact page). A Matrix of
   Contact Block entries (title, optional email, optional Link — rendered
   .btn like Link Button) laid out 2-up like Two-Up Images. border-top per
   block (not the container) gives a divider above the first row and between
   rows but not after the last, the same technique as .accordion-item. */
.contact-blocks {
  display: grid;
  gap: 20px 40px;
}

@media (min-width: 768px) {
  .contact-blocks {
    grid-template-columns: 1fr 1fr;
  }
}
.contact-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  border-top: 1px solid var(--color-black);
  padding-top: 30px;
}

.contact-block > h3 {
  margin-bottom: 0;
}

.contact-block__email {
  font-family: var(--font-body);
  font-size: 24px;
  text-decoration: none;
}

.contact-block__email:hover,
.contact-block__email:focus-visible, .contact-block__title-link:hover,
.contact-block__title-link:focus-visible {
  text-decoration-color: var(--color-sun-yellow);
  text-decoration-line: underline;
}

.contact-block__title-link {
  text-decoration: none;
}

/* Embed Code (pageContent block: raw third-party embed HTML pasted in by an
   editor, e.g. a Google Maps iframe on the Contact page — trusted CMS
   content, not user input, hence |raw in embedCode.html). iframe/embed sizing
   is whatever the pasted snippet specifies, so cap it to the column and let
   it keep its own aspect ratio rather than assuming one. */
.embed-code iframe,
.embed-code embed {
  max-width: 100%;
  border: 0;
  border-radius: 40px;
}

@media (max-width: 1023px) {
  .embed-code iframe, .embed-code embed {
    border-radius: 20px;
  }
}
.page-intro {
  max-width: 60ch;
  margin-bottom: 20px;
}

.filter-groups {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.filter-group__label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin-bottom: 0.5em;
}

.filter-chips {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.filter-chips li {
  list-style: none;
  margin: 0;
}
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 20px;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 10px 20px;
  border: 2px solid var(--color-black);
  border-radius: 60px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-black);
  text-decoration: none;
  transition: border-color 0.2s ease;
}

.filter-chip:hover,
.filter-chip:focus-visible {
  border-color: var(--color-sun-yellow);
}

.filter-chip.is-active {
  background: var(--color-black);
  color: var(--color-white);
}

.entry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 40px;
  margin-block: 40px;
}

.entry-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.entry-card__link {
  display: flex;
  flex-direction: column;
  gap: 12px;
  color: inherit;
  text-decoration: none;
}

.entry-card__image {
  display: block;
  width: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  border-radius: 24px;
}

.entry-card__title {
  font-size: 24px;
}

.entry-card__summary {
  font-size: 16px;
}

.entry-card__meta {
  font-family: var(--font-body);
  font-size: 14px;
  opacity: 0.7;
}

/* Pagination (Figma: Projects/Resources/Events listings, bottom of page).
   A 3-column grid rather than flex space-between — Previous/Next differ in
   width, and only a grid's two independent 1fr tracks keep .pagination__pages
   visually centered in the row regardless of that width difference; flex
   space-between would instead center it relative to the leftover space
   between the two side items, which isn't the same thing whenever they're
   unequal widths. */
.pagination {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px;
  margin-top: 40px;
  font-family: var(--font-body);
}

.pagination__prev,
.pagination__next {
  font-size: 28px;
  line-height: 1.3;
  color: var(--color-black);
  text-decoration: none;
  transition: color 0.2s ease;
}

.pagination__prev:hover,
.pagination__prev:focus-visible,
.pagination__next:hover,
.pagination__next:focus-visible {
  color: var(--color-sun-yellow);
}

.pagination__next {
  justify-self: end;
}

.pagination__prev.is-disabled,
.pagination__next.is-disabled {
  color: var(--color-grey);
}

.pagination__pages {
  display: flex;
  align-items: center;
  justify-self: center;
  gap: 20px;
}

.pagination__page,
.pagination__ellipsis {
  font-size: 20px;
  line-height: 1.5;
  color: var(--color-grey);
}

a.pagination__page {
  text-decoration: none;
  transition: color 0.2s ease;
}

a.pagination__page:hover,
a.pagination__page:focus-visible {
  color: var(--color-black);
}

.pagination__page.is-active {
  color: var(--color-black);
  font-weight: 700;
}

@media (max-width: 1023px) {
  .pagination__prev,
  .pagination__next {
    font-size: 18px;
  }
  .pagination__pages {
    gap: 12px;
  }
  .pagination__page,
  .pagination__ellipsis {
    font-size: 16px;
  }
}
/* Row-based listing (Projects, Resources — Figma: filter dropdowns + a
   full-width row list, distinct from the .entry-grid card layout used by
   Events). Shared across sections via filterDropdown.html/sortDropdown.html
   and listRowItem-style partials so the look stays identical without
   duplicating the CSS per section. <details>/<summary> gives the dropdown
   disclosure behaviour for free, no JS. Chevron and X icons are drawn with
   CSS (border/rotate), the same technique as .accordion-item__icon's
   plus-to-minus morph and .menu-toggle__bar's hamburger-to-X — no icon font
   is loaded on this site. */
.filter-dropdown-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px;
  margin-bottom: 40px;
}

.filter-dropdown {
  position: relative;
  flex: 1 1 0;
  min-width: 220px;
  max-width: 368px;
}

.filter-dropdown__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  box-sizing: border-box;
  list-style: none;
  padding: 16px 24px;
  border: 3px solid #d9d9d9;
  border-radius: 60px;
  background: var(--color-white);
  font-family: var(--font-body);
  font-size: 20px;
  color: rgba(0, 0, 0, 0.6);
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.filter-dropdown__trigger::-webkit-details-marker {
  display: none;
}

.filter-dropdown__trigger:hover,
.filter-dropdown__trigger:focus-visible,
.filter-dropdown[open] > .filter-dropdown__trigger {
  border-color: var(--color-black);
}

.filter-dropdown__icon {
  position: relative;
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}

.filter-dropdown[open] .filter-dropdown__icon {
  transform: rotate(225deg);
}

.filter-dropdown__panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 5;
  width: 100%;
  box-sizing: border-box;
  padding: 24px;
  border: 2px solid var(--color-grey);
  border-radius: 40px;
  background: var(--color-white);
}

.filter-dropdown__clear {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  font-family: var(--font-body);
  font-size: 20px;
  color: var(--color-grey);
  text-decoration: none;
}

.filter-dropdown__clear:hover,
.filter-dropdown__clear:focus-visible {
  color: var(--color-black);
}

.filter-dropdown__clear-icon {
  position: relative;
  flex-shrink: 0;
  width: 12px;
  height: 12px;
}

.filter-dropdown__clear-icon::before,
.filter-dropdown__clear-icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
}

.filter-dropdown__clear-icon::before {
  transform: rotate(45deg);
}

.filter-dropdown__clear-icon::after {
  transform: rotate(-45deg);
}

.filter-dropdown__options {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.filter-dropdown__options li {
  list-style: none;
  margin: 0;
}
.filter-dropdown__options {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.filter-dropdown__option {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-body);
  font-size: 20px;
  color: var(--color-grey);
  text-decoration: none;
}

.filter-dropdown__option:hover,
.filter-dropdown__option:focus-visible {
  color: var(--color-black);
}

.filter-dropdown__option.is-active {
  color: var(--color-black);
}

.filter-dropdown__radio {
  position: relative;
  flex-shrink: 0;
  width: 17px;
  height: 17px;
  border: 1px solid var(--color-black);
  border-radius: 50%;
}

.filter-dropdown__option.is-active .filter-dropdown__radio::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--color-black);
}

.filter-dropdown-bar__clear {
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-grey);
  text-decoration: none;
}

.filter-dropdown-bar__clear:hover,
.filter-dropdown-bar__clear:focus-visible {
  color: var(--color-black);
}

/* border-top on the container plus border-bottom on every row yields a
   divider above the first row, between each row, and after the last —
   same technique as .accordion / .accordion-item. */
.list-rows {
  border-top: 1px solid var(--color-black);
}
.list-rows > p {
  padding: 40px 0;
}

.list-row {
  display: flex;
  justify-content: space-between;
  gap: 60px;
  padding-block: 40px;
  border-bottom: 1px solid var(--color-black);
}
.list-row .eyebrow {
  color: var(--color-grey);
}

.list-row__content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: auto;
  max-width: 646px;
}

.list-row__title a {
  text-decoration: none;
}

.list-row__side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 20px;
  flex-shrink: 0;
}

.list-row__read-more {
  font-family: var(--font-body);
  font-size: 28px;
  color: var(--color-grey);
  text-decoration: none;
}

.list-row__read-more:hover,
.list-row__read-more:focus-visible {
  color: var(--color-black);
}

/* Arrow only shows on mobile, where the link becomes a standard .btn-style
   button (see the @include mobile query below) — desktop keeps the plain
   text-link treatment. */
.list-row__read-more .btn__arrow {
  display: none;
}

.list-row__meta {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.list-row__meta-item dd {
  font-family: var(--font-body);
  font-size: 24px;
  margin-top: 4px;
}

.list-row__summary {
  font-size: 20px;
  letter-spacing: 0.01em;
}

.list-row__tags {
  list-style: none outside none;
  margin: 0;
  padding: 0;
}
.list-row__tags li {
  list-style: none;
  margin: 0;
}
.list-row__tags {
  display: flex;
  flex-wrap: wrap;
  margin-top: auto;
  gap: 10px;
}

.list-row__tag {
  display: inline-flex;
  align-items: center;
  padding: 10px 16px;
  border: 2px solid var(--color-sun-yellow);
  border-radius: 60px;
  background: var(--color-white);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-black);
  text-decoration: none;
  transition: background-color 0.2s ease;
}

a.list-row__tag:hover,
a.list-row__tag:focus-visible {
  background: var(--color-sun-yellow);
}

.list-row__thumb {
  display: block;
  flex-shrink: 0;
  width: 369px;
  height: 369px;
  border-radius: 40px;
  overflow: hidden;
}

.list-row__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 1023px) {
  .list-row__meta-item dd {
    font-size: 20px;
  }
  .list-row {
    flex-direction: column;
    gap: 24px;
  }
  /* .list-row__content and .list-row__side step out of the way (display:
     contents) so their children become direct flex items of .list-row
     itself — the only way to move the category pills (nested in
     .list-row__content) past the thumbnail (nested in .list-row__side) via
     flex `order`, without duplicating markup per breakpoint. */
  .list-row__content,
  .list-row__side {
    display: contents;
  }
  .list-row__title {
    order: 1;
  }
  .list-row__meta {
    order: 2;
  }
  .list-row__summary {
    order: 3;
  }
  /* Standard button treatment (same spec as .btn) + left alignment, with
     the arrow icon (hidden by default above) switched back on. */
  .list-row__read-more {
    order: 4;
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 10px 20px;
    border: 2px solid var(--color-black);
    border-radius: 60px;
    background: var(--color-white);
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
    color: var(--color-black);
  }
  .list-row__read-more:hover,
  .list-row__read-more:focus-visible {
    border-color: var(--color-sun-yellow);
  }
  .list-row__read-more .btn__arrow {
    display: block;
  }
  .list-row__thumb {
    order: 5;
    width: 100%;
    height: auto;
    aspect-ratio: 1/1;
  }
  .list-row__tags {
    order: 6;
    margin-top: 0;
  }
  /* Filter menus go full width and stack (each .filter-dropdown and the
     clear-all link lands on its own line, in DOM order, for free via
     flex-direction: column). The dropdown panel drops position: absolute
     so it opens as a normal block flowing below the trigger instead of
     overlaying the content underneath. */
  .filter-dropdown-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-dropdown {
    width: 100%;
    max-width: none;
  }
  .filter-dropdown__panel {
    position: static;
    width: 100%;
    margin-top: 8px;
  }
}
.detail-header {
  padding-block: 40px;
}

/* Project title reads smaller than the site's default h1 and stays capped
   to a half-width column, matching Figma node 603-5955 (48px vs. the
   default 74px, and half the .wrap width rather than spanning it). */
.detail-header h1 {
  max-width: calc(50% - 20px);
  font-size: 48px;
}

@media (max-width: 1023px) {
  .detail-header h1 {
    font-size: 40px;
    max-width: none;
  }
}
.detail-header .filter-chips {
  margin-top: 20px;
}

.detail-image {
  display: block;
  width: 100%;
  max-width: 900px;
  border-radius: 40px;
  margin-top: 20px;
}

/* Project/Resource detail header: Year/Client(or Author)/Collaborator(s)
   meta list on the left, category tags on the right (Figma node 603-5955). */
.detail-header__grid {
  display: grid;
  gap: 40px;
  margin-top: 40px;
}

@media (min-width: 1024px) {
  .detail-header__grid {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}
.detail-meta {
  margin: 0;
  border-bottom: 1px solid var(--color-black);
}

.detail-meta__row {
  display: grid;
  grid-template-columns: 202px 1fr;
  gap: 20px;
  padding-block: 24px;
  border-top: 1px solid var(--color-black);
  font-family: var(--font-body);
  font-size: 24px;
}

@media (max-width: 1023px) {
  .detail-meta__row {
    font-size: 20px;
    padding-block: 20px;
  }
}
.detail-meta__row dt {
  color: var(--color-grey);
}

.detail-meta__row dd {
  margin: 0;
}

.detail-meta__line {
  display: block;
}

.detail-header__tags {
  align-self: start;
}

.detail-pagination__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.detail-pagination__link {
  font-family: var(--font-body);
  font-size: 28px;
  text-decoration: none;
}

.detail-pagination__link--prev {
  color: var(--color-grey);
}

.detail-pagination__link--next {
  color: var(--color-black);
}

.detail-pagination__link:hover,
.detail-pagination__link:focus-visible {
  text-decoration: underline;
}

* {
  scroll-behavior: smooth;
  scroll-margin-top: 120px;
}
