/* ========================================
   FONT FACE
   ======================================== */
@font-face {
  font-family: 'Knowledge';
  font-weight: 300;
  font-style: normal;
  src: url("../typeface/Knowledge-Light.otf") format("opentype");
  font-display: swap;
}

@font-face {
  font-family: 'Knowledge';
  font-weight: 300;
  font-style: italic;
  src: url("../typeface/Knowledge-LightItalic.otf") format("opentype");
  font-display: swap;
}

@font-face {
  font-family: 'Knowledge';
  font-weight: 400;
  font-style: normal;
  src: url("../typeface/Knowledge-Regular.otf") format("opentype");
  font-display: swap;
}

@font-face {
  font-family: 'Knowledge';
  font-weight: 400;
  font-style: italic;
  src: url("../typeface/Knowledge-RegularItalic.otf") format("opentype");
  font-display: swap;
}

@font-face {
  font-family: 'Knowledge';
  font-weight: 700;
  font-style: normal;
  src: url("../typeface/Knowledge-Bold.otf") format("opentype");
  font-display: swap;
}

@font-face {
  font-family: 'Knowledge';
  font-weight: 700;
  font-style: italic;
  src: url("../typeface/Knowledge-BoldItalic.otf") format("opentype");
  font-display: swap;
}

/* ========================================
   ROOT VARIABLES
   ======================================== */
:root {
  /* Colors */
  --clr-black: #000;
  --clr-blue: #77C9F9;
  --clr-blue-dark: #518aab;
  --clr-green: #8CFC70;
  --clr-green-dark: #60ad4d;
  --clr-grey: #f1f1f1;
  --clr-grey-light: #f5f5f5;
  --clr-grey-lighter: #f0f0f0;
  --clr-grey-border: #e0e0e0;
  --clr-grey-text: #666;
  --clr-grey-text-light: #555;
  --clr-pink: #EC65BD;
  --clr-pink-dark: #944077;
  --clr-white: #fff;

  /* Typography Scale */
  --size-s: 1rem;
  --size-m: 1.4rem;
  --size-l: 2rem;
  --size-xl: 3rem;

  /* Font Weights */
  --fw-light: 300;
  --fw-regular: 400;
  --fw-bold: 700;

  /* Spacing Scale */
  --spacing-xs: 0.5rem;
  --spacing-s: 1rem;
  --spacing-m: 2rem;
  --spacing-l: 3rem;
  --spacing-xl: 4rem;
  --spacing-2xl: 6rem;
  --spacing-3xl: 8rem;
  --spacing-4xl: 10rem;
  --spacing-5xl: 14rem;

  /* Border Radius */
  --radius-xs: 0.2rem;
  --radius-s: 0.8rem;
  --radius-m: 3rem;

  /* Transitions */
  --transition-fast: 0.3s ease;
  --transition-fast-short: 0.2s ease;
  --transition-medium: 0.5s ease;
  --transition-slow: 0.6s ease;
}

/* ========================================
   GLOBAL RESETS
   ======================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  background: var(--clr-white);
  font-family: 'Knowledge', sans-serif;
  height: 100%;
  margin: 0;
  overflow: auto;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  hyphens: auto;
}

body {
  overflow-y: scroll;
  overflow-x: hidden;
}

:focus {
  outline: 4px solid #087FC4;
  outline-offset: 6px;
}

/* ========================================
   SELECTION
   ======================================== */

::selection {
  color: var(--clr-black);
  background: var(--clr-green);
}

/* ========================================
   TYPOGRAPHY
   ======================================== */
p,
.btn,
h2,
h3,
h4,
h5,
h6,
li,
b {
  font-weight: var(--fw-light);
  font-size: var(--size-m);
  line-height: 160%;
  overflow-wrap: break-word;
  hyphens: auto;
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: pretty;
}

p,
h1,
h2,
h3,
h4,
h5 {
  margin-block-start: 0;
}

h1,
header h1 {
  color: var(--clr-black);
  font-weight: bold;
  transition: color var(--transition-slow);
}

h2 {
  font-size: var(--size-xl);
  font-weight: var(--fw-bold);
}

h3 {
  font-size: var(--size-l);
  font-weight: var(--fw-bold);
  margin: 0;
  transition: color var(--transition-slow);
}

a {
  color: var(--clr-black);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.1em;
  text-underline-position: under;
  transition: background var(--transition-fast), color var(--transition-fast);
}

a:hover {
  background: var(--clr-grey);
  color: var(--clr-black);
}

/* ========================================
   UTILITY CLASSES
   ======================================== */
.no-break {
  white-space: nowrap;
}

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

.margin-top-xs {
  margin-block-start: var(--spacing-m);
}

.margin-top-l {
  margin-block-start: var(--spacing-4xl);
}

/* ========================================
   LAYOUT - HEADER
   ======================================== */
header {
  display: grid;
  gap: var(--spacing-m);
  grid-column: span 2;
  grid-row: span 2;
  grid-template-columns: repeat(2, 1fr);
  margin-block-end: 5rem;
  padding: 3rem var(--spacing-m);
}

/* Sticky header, shrinks on scroll (see header-scroll.js). Only h1/nav
   live inside header now (the intro paragraph is a separate, non-sticky
   sibling), so blending the whole element only ever affects them. */
header {
  position: sticky;
  top: 0;
  transition: padding var(--transition-fast), box-shadow var(--transition-fast);
  z-index: 100;
  padding: 1.4rem var(--spacing-m) 1rem var(--spacing-m);
  mix-blend-mode: difference;
  /* nav.js appends <nav> into header after the initial paint; without this
     reserved height the header renders h1-only first (short), then jumps
     taller once the 4-item nav list lands — a major CLS source on every
     page. Sized to fit the nav content so no shift occurs either way. */
  min-height: 8.8rem;
}

header,
header h1 {
  font-size: var(--size-m);
  transition: font-size var(--transition-fast);
}

header.scrolled,
header.scrolled h1 {
  font-size: var(--size-s);
}

header h1 > a {
  color: var(--clr-white);
  margin-block-end: 1.3rem;
  text-decoration: none;
}

header h1 > a:hover {
  background: none;
  color: var(--clr-white);
}

/* Intro blurb below the header: scrolls away normally, not sticky/blended */
.header_intro {
  margin-block: 0 var(--spacing-m);
  max-width: 50rem;
  padding-inline: var(--spacing-m);
}

/* Homepage "Apply now" button: unlike the footer's #emailBtn (nested inside
   an already-padded container), this sits directly in <body> with no
   padded wrapper, so it needs its own inset to line up with
   .header_intro's padding-inline above it. */
body#index > .btn {
  margin-inline-start: var(--spacing-m);
}

/* ========================================
   LAYOUT - NAVIGATION
   ======================================== */
nav ul {
  align-items: flex-end;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
}

nav ul li {
  display: block;
  font-size: var(--size-s);
  list-style-type: none;
  transition: font-size var(--transition-fast);
}

header.scrolled nav ul li {
  font-size: 0.75rem;
  line-height: 1rem;
}

nav ul li a {
  transition: background var(--transition-fast), color var(--transition-fast);
}

header nav ul li a {
  color: var(--clr-white);
}

header nav ul li a:hover {
  background: none;
  color: var(--clr-white);
}

header nav ul li a.nav-active {
  font-weight: var(--fw-bold);
  text-decoration: underline;
}

/* Positioned in JS (nav.js) to track .nav-active; kept outside <header>
   so it never gets swept into header's mix-blend-mode: difference. */
.nav-active-dot {
  background: var(--clr-black);
  border-radius: 50%;
  height: 0.4rem;
  width: 0.4rem;
  pointer-events: none;
  position: fixed;
  transform: translateY(-50%);
  z-index: 101;
}

/* ========================================
   LAYOUT - MOBILE BURGER MENU
   Hidden above the mobile breakpoint (see RESPONSIVE - MOBILE below,
   which shows .nav-burger and hides the in-header <nav>).
   ======================================== */
.nav-burger {
  align-items: flex-end;
  background: none;
  border: none;
  cursor: pointer;
  display: none;
  flex-direction: column;
  gap: 5px;
  height: 2rem;
  padding: 0;
  width: 2rem;
  z-index: 102;
}

.nav-burger span {
  background: var(--clr-white);
  border-radius: 1px;
  display: block;
  height: 2px;
  transition: transform var(--transition-fast), opacity var(--transition-fast), width var(--transition-fast);
  width: 100%;
}

.nav-burger span:nth-child(2) {
  width: 70%;
}

.nav-burger.is-open span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
  width: 100%;
}

.nav-burger.is-open span:nth-child(2) {
  opacity: 0;
}

.nav-burger.is-open span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
  width: 100%;
}

/* Rendered as a sibling of <header> in document.body (see nav.js) rather
   than inside it, so its background renders normally instead of being
   swept into header's mix-blend-mode: difference. */
.mobile-nav-panel {
  background: var(--clr-black);
  display: none;
  inset: 0;
  overflow-y: auto;
  padding: 6rem var(--spacing-m) var(--spacing-m);
  position: fixed;
  z-index: 150;
}

/* Toggled by header-scroll.js alongside header.scrolled. Semi-transparent
   with a backdrop blur so the page content stays dimly visible (frosted
   glass) behind the open nav, instead of the solid fill used at the top of
   the page. Matches header.scrolled's white/black treatment, so the link
   color is flipped to black below too. */
.mobile-nav-panel.scrolled {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.mobile-nav-panel.scrolled a {
  color: var(--clr-black);
}

.mobile-nav-panel.is-open {
  display: block;
}

.mobile-nav-panel ul {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-m);
  margin: 0;
  padding: 0;
}

.mobile-nav-panel li {
  list-style-type: none;
}

.mobile-nav-panel a {
  color: var(--clr-white);
  font-size: var(--size-m);
  font-weight: var(--fw-bold);
  text-decoration: none;
}

.mobile-nav-panel a:hover,
.mobile-nav-panel a.nav-active {
  text-decoration: underline;
}

body.nav-open {
  overflow: hidden;
}

/* Header creates its own stacking context (position: sticky + z-index),
   so .nav-burger's z-index only ranks it within that context — without
   this, the full-screen .mobile-nav-panel (z-index: 150) buries the
   header, and the open/X burger disappears behind it. */
body.nav-open header {
  z-index: 200;
}

#projectNav {
    display: grid;
    gap: var(--spacing-s);
    grid-template-columns: repeat(4, 1fr);
    margin: var(--spacing-xl);
}

.projectNavButton {
    width: -webkit-fill-available;
    border: 1px solid black;
    border-radius: 9999rem;
    display: inline-flex;
    align-items: center;       /* center vertically */
    justify-content: center;   /* center horizontally */
    text-align: center;        /* center text */
    padding: 1rem 1.3rem;
}

.projectNavButtonPrev {
    grid-column: 3 / span 1;}

.projectNavButtonNext {
    grid-column: 4 / span 1;}

a.projectNavButton:hover {
    cursor: pointer;
}

/* ========================================
   COMPONENTS - PROJECT GRID
   ======================================== */
#projectGrid {
  display: grid;
  /* Matches padding-inline below, so the gap between thumbnails equals the
     grid's left/right margin. */
  gap: var(--spacing-m);
  grid-template-columns: repeat(3, 1fr);
  padding-inline: var(--spacing-m);
  width: 100%;
  /* Empty until script-homepage.js/script-cohort.js fetch projects.json and
     render into it — reserving space for the first viewport's worth of
     cards keeps that population from shifting everything below it. */
  min-height: 50vh;
}

#projectGrid img {
  aspect-ratio: 16/9;
  display: block;
  width: 100%;
  border-radius: var(--radius-s);
  transition: transform var(--transition-medium), opacity var(--transition-fast);
}

#projectGrid a {
  position: relative;
  text-decoration: none;
  z-index: 1;
  transition: background var(--transition-fast);
}

#projectGrid a:hover {
  background: none;
}

#projectGrid a:hover img {
  opacity: 0.1;
  transform: scale(1.07);
}

#projectGrid > a > div {
  align-items: center;
  display: flex;
  justify-content: left;
  left: 45%;
  position: absolute;
  text-align: left;
  top: 25%;
  transform: translate(-50%, -50%);
  width: 85%;
  z-index: -1;
}

#projectGrid > * {
  background: none;
  color: var(--clr-black);
  font-size: var(--size-s);
  line-height: 160%;
}

#projectGrid p {
  font-size: var(--size-s);
  font-weight: var(--fw-bold);
}

#projectGrid h2 {
  font-size: var(--size-m);
  font-weight: var(--fw-bold);
  grid-column: 1 / -1;
  margin-block: var(--spacing-m) 0;
  transition: color var(--transition-fast);
}

#projectGrid h2::before {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-inline-end: var(--spacing-xs);
  border-radius: 50%;
  vertical-align: middle;
  transition: background-color var(--transition-fast);
}

#projectGrid h3 {
  font-weight: var(--fw-bold);
  grid-column: 1 / -1;
  margin-block-start: 3rem;
  transition: color var(--transition-fast);
}

/* Cohort Colors */
.cohort-arabic::before {
  background-color: var(--clr-pink);
}

.cohort-sea::before {
  background-color: var(--clr-blue);
}

.cohort-latin::before,
.cohort-other::before {
  background-color: var(--clr-green);
}

.cohort-indigenous::before {
  background: linear-gradient(45deg, var(--clr-pink) 50%, var(--clr-green) 50%);
}

.cohort-asian::before {
  background: radial-gradient(circle at center, var(--clr-pink) 35%, var(--clr-blue) 36%);
}

/* ========================================
   COMPONENTS - LECTURERS
   ======================================== */
.lecturers, .contributors {
  grid-column: 2 / span 2;
}

.lecturer_image {
  grid-column: 1 / span 2;
}

.lecturer_image img {
  width: 100%;
  object-fit: cover;
  display: block;
  transition: opacity var(--transition-fast), transform var(--transition-medium);
}

.lecturer_image img:hover {
  opacity: 0.9;
  transform: scale(1.02);
}

.workshop_instructors, .resources-contributors {
  grid-column: 3 / span 1;
}

.script_advisors {
  grid-column: 4 / span 1;
}

.workshop_instructors ul,
.script_advisors ul, .resources-contributors ul {
  padding: 0;
  margin: 0;
}

.workshop_instructors ul li,
.script_advisors ul li, .resources-contributors ul li {
  list-style-type: none;
}

.workshop_instructors li:last-child {
  margin-block-end: var(--spacing-s);
}

.workshop_instructors ul h3,
.script_advisors ul h3, .resources-contributors ul h3 {
  margin: 0;
}

/* ========================================
   COMPONENTS - PROJECT PAGE
   ======================================== */
article {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  padding-inline: var(--spacing-m);
  width: 100%;
}

figure {
  grid-column: 1 / -1;
  margin: var(--spacing-s) 0;
}

figure img {
  display: block;
  width: 100%;
  height: auto;
  margin-inline: auto;
  border-radius: var(--radius-xs);
  transition: opacity var(--transition-fast), transform var(--transition-medium);
}

figure img:hover {
  opacity: 0.95;
  transform: scale(1.01);
}

figcaption {
  color: var(--clr-black);
  display: grid;
  font-size: var(--size-s);
  font-weight: var(--fw-light);
  grid-column: 1 / -1;
  grid-template-columns: repeat(9, 1fr);
  line-height: 170%;
  margin-block: var(--spacing-s) var(--spacing-xl);
  text-align: left;
  width: 100%;
}

figcaption span {
  grid-column: 4 / 8;
}

article h2,
article > p {
  grid-column: 2 / span 4;
  margin-block-end: var(--spacing-xs);
}

/* A lone paragraph sitting directly between two project images. */
article > figure + p:has(+ figure) {
  margin: var(--spacing-l) 0;
}

/* First/last paragraph of a run of several between two project images. */
article > figure + p:has(+ p) {
  margin-top: var(--spacing-l);
}

article > p + p:has(+ figure) {
  margin-bottom: var(--spacing-l);
}

/* The first paragraph trailing after the article's last project image. */
article > figure:last-of-type + p {
  margin-top: var(--spacing-l);
}

article h2 {
  font-size: var(--size-xl);
  font-weight: var(--fw-bold);
  margin-block: 0 var(--spacing-s);
  /* #project_title starts empty in the static HTML and is filled in by
     project-data.js after a fetch — with no reserved height, a genuinely
     empty block element collapses to 0px (no line box), then jumps to its
     full text height once the title lands, shoving every image and
     paragraph below it down. Reserving one line-height matches all but one
     of the titles in projects.json exactly (checked against every current
     project); a title long enough to wrap to two lines (currently just
     zahra-ahmed's) still shifts by one line instead of two. */
  min-height: calc(var(--size-xl) * 1.6);
  transition: color var(--transition-fast);
}

article ul {
  display: grid;
  grid-column: 2 / -2;
  font-size: var(--size-m);
  font-weight: var(--fw-light);
}

article ul li:first-child {
  padding-block-start: var(--spacing-xs);
}

/* A <ul> styled to read like a table (year | event) without being one. */
.timeline {
  /* Left/right edges of the <ul> itself already line up with the rest of
     the page via article ul's grid-column (both desktop and the ≤600px
     override) — it's the browser's default 40px list padding pushing each
     <li> in past that edge that misaligns the visible content. */
  padding-inline-start: 0;
}

.timeline li {
  display: grid;
  grid-template-columns: 5rem 1fr;
  gap: var(--spacing-s);
  padding-block: var(--spacing-s);
}

.timeline li:first-child {
  padding-block-start: var(--spacing-s);
}

.timeline-year {
  font-weight: var(--fw-regular);
}

main h3 {
  grid-column: 2 / span 4;
  transition: color var(--transition-fast);
  margin-top: var(--spacing-m);
}

/* ========================================
   COMPONENTS - ABOUT SECTION
   ======================================== */
section {
  display: grid;
  gap: var(--spacing-m);
  grid-template-columns: repeat(4, 1fr);
  margin-block: var(--spacing-xl);
  padding-inline: var(--spacing-m);
  width: 100%;
}

section h3 {
  font-size: var(--size-m);
  grid-column: 3 / span 2;
  margin-block: 1.8rem var(--spacing-s);
  transition: color var(--transition-fast);
}

section > p {
  grid-column: 3 / span 2;
  font-size: var(--size-m);
}

section figure {
  align-items: center;
  display: flex;
  justify-content: center;
  margin-block: var(--spacing-m);
  perspective: 1000px;
  position: relative;
}

section figure img {
  aspect-ratio: 1;
  border: 2px solid var(--clr-green);
  border-radius: 50%;
  box-shadow: 6px 6px 0 var(--clr-green);
  height: auto;
  position: relative;
  transition: transform var(--transition-slow),
    box-shadow var(--transition-fast),
    border-color var(--transition-fast);
  transform-style: preserve-3d;
  width: 200px;
}

.designer_bio {
  font-size: var(--size-m);
}

/* Shown below the social links list (About section) when a project's
   scholar_elp/scholar_typeafrika flag is true (see project-data.js). */
.scholar-logo {
  display: block;
  grid-column: 3 / span 2;
  margin-block-start: var(--spacing-s);
}

/* "ELP/Type Afrika Scholar" label after student_location (see
   project-data.js). Inherits the surrounding p's light (300) weight, which
   now has a matching Knowledge-LightItalic.otf face declared above. */
.scholar-label {
  font-style: italic;
}

/* ========================================
   COMPONENTS - SOCIAL LINKS
   ======================================== */
ul.module_social {
  display: flex;
  grid-column: 3 / span 2;
  padding: 0;
  margin: 0;
}

ul.module_social li {
  list-style: none;
  margin-inline-end: var(--spacing-s);
}

ul.module_social li a {
  transition: background var(--transition-fast), color var(--transition-fast);
}

ul.module_social li::after {
  color: var(--clr-green);
  content: "⬤";
  padding-inline-start: var(--spacing-s);
  vertical-align: middle;
  transition: color var(--transition-fast);
}

ul.module_social li:last-child::after {
  content: "";
}

/* ========================================
   COMPONENTS - FOOTER
   ======================================== */
footer {
  display: grid;
  gap: var(--spacing-m);
  grid-template-columns: repeat(2, 1fr);
  margin-block: var(--spacing-xl) 3rem;
  padding: 3rem;
}

footer > .credits_kbi,
footer > .credits_contributors {
  padding-inline-end: 3rem;
  margin-block-end: 3rem;
}

.credits_kbi {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-s);
  width: 100%;
}

.credits_kbi img {
  display: block;
  margin-block-end: 3rem;
  transition: opacity var(--transition-fast), transform var(--transition-medium);
}

.credits_kbi img:hover {
  opacity: 0.8;
  transform: scale(1.02);
}

.credits_collaborators {
  display: flex;
  align-items: center;
  gap: var(--spacing-m);
}

.credits_collaborators img {
  margin-block-end: 0;
}

footer > div > h3 {
  display: block;
  font-size: var(--size-s);
  font-weight: var(--fw-bold);
  margin-block: 1.5rem 0.2rem;
  transition: color var(--transition-fast);
}

footer > div > p {
  font-size: var(--size-s);
  font-weight: var(--fw-light);
  margin-block-end: 0.8rem;
  line-height: 160%;
}

footer a {
  transition: background var(--transition-fast), color var(--transition-fast);
}

.credits_contributors p a::before {
  content: "⬤";
  color: var(--dot-color, var(--clr-pink));
  display: inline-block;
  padding-inline-end: var(--spacing-xs);
  text-decoration: none;
  vertical-align: middle;
  transition: color var(--transition-fast);
}

/* ========================================
   COMPONENTS - BUTTON
   ======================================== */
.btn,
#emailBtn {
  background: var(--clr-pink);
  border: none;
  border-radius: var(--radius-m);
  color: var(--clr-white);
  display: inline-block;
  font-family: 'Knowledge', sans-serif;
  font-size: x-large;
  font-weight: var(--fw-bold);
  margin-block: 0.4rem var(--spacing-m);
  min-height: 48px;
  min-width: fit-content;
  padding: var(--spacing-xs) var(--spacing-m);
  text-decoration: none;
  transition: background var(--transition-fast), 
              color var(--transition-fast), 
              transform var(--transition-fast);
  cursor: pointer;
  align-content: center;
}

#emailBtn:hover,
.btn:hover {
  background: var(--clr-pink-dark);
  color: var(--clr-white);
  transform: translateY(-2px);
}

#emailBtn:active,
.btn:active {
  transform: translateY(0);
}

/* ========================================
   SCROLL ANIMATIONS
   ======================================== */
@supports (animation-timeline: view()) {
  /* Fade-in on scroll */
  figure,
  article > p,
  section > p,
  footer > div {
    animation: fadeInUp 0.8s ease-out both;
    animation-timeline: view();
    animation-range: entry 0% cover 20%;
  }

  /* Images fade and scale on scroll */
  figure img,
  .lecturer_image img,
  section figure img {
    animation: fadeInScale 0.8s ease-out both;
    animation-timeline: view();
    animation-range: entry 0% cover 20%;
  }

  /* Headings fade in on scroll */
  article h2,
  section h3,
  #projectGrid h2 {
    animation: fadeInDown 0.8s ease-out both;
    animation-timeline: view();
    animation-range: entry 0% cover 20%;
  }

  /* Grid items stagger on scroll */
  #projectGrid a {
    animation: fadeInUp 0.8s ease-out both;
    animation-timeline: view();
    animation-range: entry 0% cover 25%;
  }

  /* Lazy load project cards with stagger */
  #projectGrid a:nth-child(1) { animation-delay: 0s; }
  #projectGrid a:nth-child(2) { animation-delay: 0.1s; }
  #projectGrid a:nth-child(3) { animation-delay: 0.2s; }
  #projectGrid a:nth-child(4) { animation-delay: 0.3s; }
  #projectGrid a:nth-child(5) { animation-delay: 0.4s; }
  #projectGrid a:nth-child(6) { animation-delay: 0.5s; }
}

/* ========================================
   KEYFRAME ANIMATIONS
   ======================================== */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeInScale {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* ========================================
   FALLBACK - Safari & Older Browsers
   ======================================== */
@supports not (animation-timeline: view()) {
  /* Safari fallback: instant load without animations */
  figure,
  article > p,
  section > p,
  footer > div,
  figure img,
  .lecturer_image img,
  section figure img,
  article h2,
  section h3,
  #projectGrid h2,
  #projectGrid a {
    opacity: 1;
    transform: none;
    animation: none;
  }

  /* Maintain hover effects on Safari */
  #projectGrid img {
    transition: transform var(--transition-medium), opacity var(--transition-fast);
  }

  #projectGrid img:hover {
    opacity: 0.1;
    transform: scale(1.07);
  }

  figure img:hover {
    opacity: 0.95;
    transform: scale(1.01);
  }

  .lecturer_image img:hover {
    opacity: 0.9;
    transform: scale(1.02);
  }

  .credits_kbi img:hover, .credits_kbi a:hover {
    opacity: 0.8;
    transform: scale(1.02);
    background: none!important;
  }

  section figure:hover img {
    border-color: var(--clr-blue);
    box-shadow: 6px 6px 0 var(--clr-blue);
    transform: rotateY(360deg);
  }
}

/* ========================================
   SCROLL BEHAVIOR
   ======================================== */
html {
  scroll-behavior: smooth;
}

/* ========================================
   RESPONSIVE - MOBILE (max-width: 600px)
   ======================================== */
@media (max-width: 600px) {
  :root {
    --size-s: 0.8rem;
    --size-m: 1.2rem;
    --size-l: 1.8rem;
    --size-xl: 2.5rem;
  }

  header {
    grid-template-columns: 1fr auto;
    align-items: center;
    padding: 1.3rem var(--spacing-s) 1rem var(--spacing-s);
    gap: var(--spacing-s);
    margin-block-end: var(--spacing-m);
    grid-column: span 1;
    grid-row: span 1;
    /* Nav is hidden here (burger button instead, see below) — the header
       stays content-sized rather than reserving the desktop nav height. */
    min-height: auto;
  }

  .header_intro {
    padding-inline: var(--spacing-s);
  }

  /* Difference blend mode only works against page content showing through
     an unfilled header (see the LAYOUT - HEADER comment above) — once
     scrolled, swap to a normal frosted panel (matching
     .mobile-nav-panel.scrolled) instead of diffing this background too.
     Needs its own text/icon color flip below, since the base header styles
     assume a dark/blended backdrop. */
  header.scrolled {
    mix-blend-mode: normal;
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }

  header.scrolled h1 > a,
  header.scrolled h1 > a:hover {
    color: var(--clr-black);
  }

  header.scrolled .nav-burger span {
    background: var(--clr-black);
  }

  /* While the mobile nav is open, header sits above .mobile-nav-panel
     (z-index bump below) and both are semi-transparent + blurred in the
     scrolled state — stacking header's own copy on top double-blurs that
     strip. Drop it here so the panel's background/blur shows through
     header instead; text/icon colors stay black to match. */
  body.nav-open header.scrolled {
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  header > nav {
    display: none;
  }

  .nav-burger {
    display: flex;
  }

  .nav-active-dot {
    display: none;
  }

  .mobile-nav-panel {
    padding-inline: var(--spacing-s);
  }

  #projectGrid {
    grid-template-columns: 1fr;
    gap: var(--spacing-s);
    padding-inline: var(--spacing-s);
  }

  #projectGrid h2,
  #projectGrid h3,
  #projectGrid a {
    grid-column: 1 / -1;
  }

  article {
    grid-template-columns: 1fr;
    padding-inline: var(--spacing-s);
  }

  article h2,
  article > p,
  article ul,
  figcaption {
    grid-column: 1 / -1;
  }

  figure {
    grid-column: 1 / -1;
    /* Grid items don't collapse margins, so an end-only margin gives exactly
       one gap between stacked images — sized to match article's left/right
       padding-inline above, so the gap between images equals the page's
       side margins. */
    margin: 0 0 var(--spacing-s) 0;
  }

  figcaption {
    grid-template-columns: 1fr;
    margin-block: var(--spacing-xs) var(--spacing-s);
  }

  figcaption span {
    grid-column: 1 / -1;
  }

  main h3 {
    grid-column: 1 / -1;
  }

  section {
    grid-template-columns: 1fr;
    padding-inline: var(--spacing-s);
    gap: var(--spacing-s);
    margin-block: var(--spacing-m);
  }

  section figure {
    grid-column: 1 / -1;
  }

  section h3,
  section > p,
  ul.module_social,
  section > .scholar-logo {
    grid-column: 1 / -1;
  }

  ul.module_social {
    flex-wrap: wrap;
    gap: var(--spacing-xs);
  }

  #projectNav {
    grid-template-columns: 1fr;
    gap: 8px;
    margin: var(--spacing-s);
  }

  .projectNavButtonPrev,
  .projectNavButtonNext {
    grid-column: 1 / -1;
  }

  .lecturers {
    grid-column: 1 / -1;
  }

  .lecturer_image {
    grid-column: 1 / -1;
  }

  .workshop_instructors {
    grid-column: 1 / -1;
  }

  .script_advisors {
    grid-column: 1 / -1;
  }

  footer {
    grid-template-columns: 1fr;
    gap: var(--spacing-s);
    padding: var(--spacing-m) var(--spacing-s);
    margin-block: var(--spacing-m) var(--spacing-s);
  }

  footer > .credits_kbi,
  footer > .credits_contributors {
    padding: 0;
    margin-block-end: var(--spacing-m);
  }

  .credits_kbi img {
    width: 10rem;
    /* The width/height HTML attributes on these logos (set for CLS) act as
       low-priority presentational hints for both properties. Overriding
       width here without also overriding height left the old fixed height
       in place, stretching each logo to the new, narrower width. */
    height: auto;
    margin-inline-end: var(--spacing-s);
    margin-block-end: var(--spacing-s);
  }

  .credits_collaborators img {
    /* Scaled down by the same ratio as the credits_kbi logos above
       (10rem / 300px native width) so both groups shrink proportionally. */
    width: 3.6rem;
    height: auto;
    margin-block-end: 0;
  }
}

/* ========================================
   MAP PAGE STYLES
   ======================================== */
.kpi-stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--spacing-2xl);
  margin-block: var(--spacing-xl) 0;
  padding-inline: var(--spacing-m);
}

.kpi-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.kpi-number {
  font-size: var(--size-xl);
  font-weight: var(--fw-bold);
  line-height: 1;
}

.kpi-label {
  margin-block-start: var(--spacing-xs);
  font-size: var(--size-s);
  color: var(--clr-text-primary);
}

@media (max-width: 768px) {
  .kpi-stats {
    gap: var(--spacing-xl);
  }
}

@media (max-width: 480px) {
  .kpi-stats {
    gap: var(--spacing-m);
  }
}

.map-container {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--clr-white);
    margin: var(--spacing-xl) 0 -8px 0;
}

.map-container .world-map {
  height: 100%;
  width: auto;
  max-width: 100%;
  display: block;
}

#n_woplycdp {
  display: block;
  height: auto;
  contain: content;
}

#n_woplycdp .country {
  stroke: var(--clr-black);
  stroke-width: 0.8px;
  fill: var(--clr-white);
  stroke-linejoin: round;
}

#n_woplycdp .country.project-country.cohort-sea,
#n_woplycdp .country.cohort-sea {
  fill: var(--clr-blue);
}

#n_woplycdp .country.project-country.cohort-sea:hover,
#n_woplycdp .country.cohort-sea:hover,
#n_woplycdp .cohort-sea.hovered {
  fill: var(--clr-blue-dark);
}

/* A country with only unpublished students (no entry in projects.json) in
   a cohort — same fill as a published country in that cohort, brightened,
   so it reads as a distinct, lighter-weight signal on the map. Hover keeps
   the same brightness so it never gets fully as dark/certain-looking as a
   published country's hover state. */
#n_woplycdp .country.project-country.cohort-sea-unpublished,
#n_woplycdp .country.cohort-sea-unpublished {
  fill: var(--clr-blue);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-sea-unpublished:hover,
#n_woplycdp .country.cohort-sea-unpublished:hover,
#n_woplycdp .cohort-sea-unpublished.hovered {
  fill: var(--clr-blue-dark);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-arabic,
#n_woplycdp .country.cohort-arabic {
  fill: var(--clr-pink);
}

#n_woplycdp .country.project-country.cohort-arabic:hover,
#n_woplycdp .country.cohort-arabic:hover,
#n_woplycdp .cohort-arabic.hovered {
  fill: var(--clr-pink-dark);
}

#n_woplycdp .country.project-country.cohort-arabic-unpublished,
#n_woplycdp .country.cohort-arabic-unpublished {
  fill: var(--clr-pink);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-arabic-unpublished:hover,
#n_woplycdp .country.cohort-arabic-unpublished:hover,
#n_woplycdp .cohort-arabic-unpublished.hovered {
  fill: var(--clr-pink-dark);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-latin,
#n_woplycdp .country.cohort-latin {
  fill: var(--clr-green);
}

#n_woplycdp .country.project-country.cohort-latin:hover,
#n_woplycdp .country.cohort-latin:hover,
#n_woplycdp .cohort-latin.hovered {
  fill: var(--clr-green-dark);
}

#n_woplycdp .country.project-country.cohort-latin-unpublished,
#n_woplycdp .country.cohort-latin-unpublished {
  fill: var(--clr-green);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-latin-unpublished:hover,
#n_woplycdp .country.cohort-latin-unpublished:hover,
#n_woplycdp .cohort-latin-unpublished.hovered {
  fill: var(--clr-green-dark);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-indigenous,
#n_woplycdp .country.cohort-indigenous {
  fill: url(#indigenous-stripes);
}

/* A pattern fill can't be swapped for a "darker" fill value the way a solid
   color can (there's no second, darker pattern def to switch to) — darken
   the rendered pattern itself instead, matching the ~30% darkening the
   solid-color cohorts get between their base/:hover custom properties. */
#n_woplycdp .country.project-country.cohort-indigenous:hover,
#n_woplycdp .country.cohort-indigenous:hover,
#n_woplycdp .cohort-indigenous.hovered {
  fill: url(#indigenous-stripes);
  filter: brightness(0.7);
}

#n_woplycdp .country.project-country.cohort-indigenous-unpublished,
#n_woplycdp .country.cohort-indigenous-unpublished {
  fill: url(#indigenous-stripes);
  filter: brightness(1.3);
}

/* 1.3 (unpublished base) × 0.7 (the published pattern's hover-darken
   factor) — stays lighter than a published country's hover at every point,
   not just at rest. */
#n_woplycdp .country.project-country.cohort-indigenous-unpublished:hover,
#n_woplycdp .country.cohort-indigenous-unpublished:hover,
#n_woplycdp .cohort-indigenous-unpublished.hovered {
  fill: url(#indigenous-stripes);
  filter: brightness(0.91);
}

#n_woplycdp .country.project-country.cohort-asian,
#n_woplycdp .country.cohort-asian {
  fill: url(#asian-scripts-dots);
}

#n_woplycdp .country.project-country.cohort-asian:hover,
#n_woplycdp .country.cohort-asian:hover,
#n_woplycdp .cohort-asian.hovered {
  fill: url(#asian-scripts-dots);
  filter: brightness(0.7);
}

#n_woplycdp .country.project-country.cohort-asian-unpublished,
#n_woplycdp .country.cohort-asian-unpublished {
  fill: url(#asian-scripts-dots);
  filter: brightness(1.3);
}

#n_woplycdp .country.project-country.cohort-asian-unpublished:hover,
#n_woplycdp .country.cohort-asian-unpublished:hover,
#n_woplycdp .cohort-asian-unpublished.hovered {
  fill: url(#asian-scripts-dots);
  filter: brightness(0.91);
}

#n_woplycdp .country.project-country.split-country {
  fill: transparent;
}

#n_woplycdp .country.project-country.split-country:hover {
  fill: transparent;
}

.country-tooltip {
  position: fixed;
  background: var(--clr-white);
  border: 1px solid var(--clr-black);
  border-radius: var(--radius-xs);
  padding: 0.8rem var(--spacing-s);
  font-size: var(--size-s);
  font-weight: var(--fw-regular);
  line-height: 1.6;
  pointer-events: none;
  z-index: 1000;
}

.country-tooltip a {
  color: var(--clr-black);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
  transition: color var(--transition-fast-short);
  pointer-events: auto;
  cursor: pointer;
}

.tooltip-cohort {
  font-size: 0.85rem;
  font-weight: var(--fw-light);
  color: var(--clr-grey-text-light);
  margin-top: var(--radius-xs);
}

.tooltip-location {
  font-size: 0.85rem;
  font-weight: var(--fw-light);
  color: var(--clr-grey-text);
  margin-top: var(--spacing-xs);
}

/* WCAG 1.4.10 (Reflow): tables are exempt from the no-horizontal-scroll
   requirement since they need 2D layout to convey relationships, but the
   scroll region itself still needs to be keyboard-operable (2.1.1) and
   identifiable (4.1.2) — hence tabindex="0" + role="region" + aria-label
   on the wrapper in the HTML, not just overflow-x here. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%;
}

.projects-table {
  display: table;
  border-collapse: collapse;
  margin: 0 0 var(--spacing-3xl) 0;
  padding: 0 var(--spacing-m);
  box-sizing: border-box;
  /* Overridden with hardcoded (not var(--size-s)) sizes here and at each
     breakpoint below, shrinking toward ~0.7rem — the practical floor for
     readable body text — rather than sharing the site-wide token. */
  font-size: 0.85rem;
  font-family: inherit;
}

.projects-table thead {
  background-color: var(--clr-grey-light);
  border-bottom: 1px solid var(--clr-black);
  border-top: 1px solid var(--clr-black);
}

.projects-table th {
  padding: 0;
  text-align: left;
  font-weight: var(--fw-bold);
  border-right: 1px solid var(--clr-grey-border);
  /* Prevent wrapping so the table's rendered width reflects its real
     content width — narrower viewports then scroll (via .table-scroll)
     instead of squeezing/wrapping cell text into unreadable columns. */
  white-space: nowrap;
}

.sort-btn {
  display: flex;
  align-items: center;
  gap: 0.4em;
  width: 100%;
  padding: var(--spacing-s);
  border: none;
  background: none;
  font: inherit;
  font-weight: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  /* Contains the .visually-hidden "Cohort" label inside (position: absolute,
     no positioned ancestor otherwise) — without this, its containing block
     falls back to the page's initial containing block instead of this
     button's normal-flow position. body is its own independent scroll
     container on this site (see the "window scroll events never fire"
     gotcha), so anything anchored to the initial containing block instead
     doesn't scroll with body's content — it ended up rendering ~500px below
     the visible page, forcing <html> itself to become independently
     scrollable to reach it. That showed up as: scroll body to the bottom,
     hit what looks like the end of the page, then further scroll input
     starts moving <html> instead and the page seems to keep going. */
  position: relative;
}

.sort-btn:hover,
.sort-btn:focus-visible {
  background-color: var(--clr-grey-lighter);
}

.sort-btn:focus-visible {
  outline: 2px solid var(--clr-black);
  outline-offset: -2px;
}

.sort-icon {
  display: inline-flex;
  align-items: center;
  font-size: 0.7rem;
  line-height: 1;
}

.sort-icon::after {
  content: '';
  display: inline-block;
  width: 0.6rem;
}

th[aria-sort="ascending"] .sort-icon::after {
  content: '▲';
}

th[aria-sort="descending"] .sort-icon::after {
  content: '▼';
}

.projects-table th:last-child {
  border-right: none;
}

.projects-table th:last-child .sort-btn {
  justify-content: flex-end;
  padding-right: 2rem;
}

.projects-table tbody tr {
  border-bottom: 1px solid var(--clr-grey-border);
  cursor: pointer;
  transition: background-color var(--transition-fast-short);
}

.projects-table tbody tr:hover {
  background-color: var(--clr-grey-lighter);
}

.projects-table td {
  padding: var(--spacing-s);
  border-right: 1px solid var(--clr-grey-border);
  white-space: nowrap;
}

.projects-table td:last-child {
  border-right: none;
  text-align: right;
  padding-right: 2rem;
}

.cohort-circle,
.projects-table th:first-child {
  font-size: 2rem;
  line-height: 0.9;
}

.cohort-circle-split {
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  vertical-align: middle;
  background: linear-gradient(-45deg, var(--clr-pink) 50%, var(--clr-green) 50%);
}

.cohort-circle-dots {
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  vertical-align: middle;
  background: radial-gradient(circle at center, var(--clr-pink) 35%, var(--clr-blue) 36%);
}

@media (max-width: 1024px) {
  .projects-table {
    margin: 0 0 var(--spacing-3xl) 0;
    font-size: 0.8rem;
  }

  .projects-table th .sort-btn,
  .projects-table td {
    padding: 0.75rem var(--spacing-xs);
  }

  .cohort-circle {
    font-size: 1.5rem;
  }
}

@media (max-width: 768px) {
  .projects-table {
    margin: 0 0 var(--spacing-3xl) 0;
    font-size: 0.75rem;
  }

  .projects-table th .sort-btn,
  .projects-table td {
    padding: 0.6rem 0.4rem;
  }

  .cohort-circle {
    font-size: 1.3rem;
  }

  .map-container {
    margin: var(--spacing-xl) 0 -8px 0;
  }
}

@media (max-width: 480px) {
  .projects-table {
    margin: 0 0 6rem 0;
    font-size: 0.7rem;
    border-collapse: separate;
    border-spacing: 0;
  }

  .projects-table th,
  .projects-table td {
    border-right: none;
    border-bottom: 1px solid var(--clr-grey-border);
  }

  .projects-table th .sort-btn,
  .projects-table td {
    padding: var(--spacing-xs) 0.3rem;
  }

  .projects-table th {
    border-bottom: 2px solid var(--clr-black);
  }

  .projects-table tbody tr:hover {
    background-color: var(--clr-grey-light);
  }

  .cohort-circle {
    font-size: 1.1rem;
  }

  .map-container {
    margin: var(--spacing-xl) 0 -8px 0;
  }
}

@media (orientation: portrait) {
  .map-container {
    position: relative;
    overflow: hidden;
    display: block;
    background: var(--clr-white);
    margin: var(--spacing-2xl) 0;
    /* Reserve the box in the map's rotated (portrait) proportions —
       1080/1920, i.e. the SVG's 1920x1080 viewBox with width/height
       swapped — so the rotated map below fills it exactly instead of the
       container being sized from the pre-rotation landscape box (which
       previously left it narrower than 100% wide once rotated). */
    width: 100%;
    aspect-ratio: 1080 / 1920;
  }

  /* #n_woplycdp is included (not just .world-map) because the base
     "#n_woplycdp { height: auto }" rule is an ID selector — it would
     otherwise win over a class-only selector here regardless of source
     order and silently break this sizing. */
  .map-container #n_woplycdp.world-map {
    position: absolute;
    top: 50%;
    left: 50%;
    width: auto;
    /* 1080/1920 again: this pre-rotation height becomes the map's visual
       width (100% of the container) once rotated 90°. */
    height: 56.25%;
    max-width: none;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  .projects-table {
    font-size: 0.7rem;
    margin: var(--spacing-2xl) var(--spacing-s);
    padding: 0 var(--spacing-s);
  }

  .projects-table th,
  .projects-table td {
    padding: 0.75rem var(--spacing-xs);
  }
}

/* ========================================
   RESOURCES LAYOUT
   ======================================== */
.resources-wrapper {
  display: grid;
  grid-template-columns: 1fr 350px;
  gap: var(--spacing-5xl);
  max-width: 100%;
  margin: 0 auto;
  padding: 3rem var(--spacing-m);
}

main#resourcesContainer {
  grid-column: 1;
  min-width: 0;
}

/* ========================================
   RESOURCES TABLE
   ======================================== */
.resources-category-grid {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.resources-category-grid h2 {
  font-size: var(--size-l);
  font-weight: var(--fw-bold);
  margin: 5rem 0 0 0;
}

.resources-subcategory {
  grid-column: span 1;
}

.resources-subcategory h3 {
  font-size: var(--size-m);
  margin-bottom: 1.2rem;
  font-weight: var(--fw-bold);
  color: var(--clr-black);
}

.resources-nested-subcategory {
  margin-bottom: var(--spacing-xl);
}

.resources-nested-subcategory h4 {
  display: inline-block;
  font-size: var(--size-s);
  margin-bottom: var(--spacing-s);
  font-weight: var(--fw-bold);
  color: var(--clr-black);
  border-bottom: 2px solid var(--clr-black);
}

.resources-list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.resources-item {
  padding: 0;
  border-radius: 0;
  transition: none;
}

/* Filter Sidebar */
.resources-filter-sidebar {
  position: sticky;
  top: var(--spacing-m);
  padding: var(--spacing-2xl) var(--spacing-m) var(--spacing-m) var(--spacing-m);
  border-radius: var(--radius-s);
  height: fit-content;
  max-height: calc(100vh - var(--spacing-m) * 2);
  overflow-y: auto;
  grid-column: 2;
}

.resources-filter-sidebar h3 {
  font-size: var(--size-m);
  margin-bottom: var(--spacing-m);
  font-weight: var(--fw-bold);
  color: var(--clr-black);
  margin-top: 0;
}

.resources-filter-sections {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-m);
}

.resources-filter-section {
  width: 100%;
}

.resources-filter-section-title {
  font-family: 'Knowledge', sans-serif;
  font-size: var(--size-s);
  font-weight: var(--fw-regular);
  color: var(--clr-black);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  width: 100%;
  text-align: left;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: color var(--transition-fast-short);
  margin-bottom: var(--spacing-s);
}

.resources-filter-section-title::after {
  content: '›';
  font-size: 1.2rem;
  transition: transform var(--transition-fast-short);
}

.resources-filter-section.collapsed .resources-filter-section-title::after {
  transform: rotate(-90deg);
}

.resources-filter-section-title:hover {
  color: var(--clr-black);
}

.resources-filter-checkbox-container {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-m);
}

.resources-filter-checkbox-label {
  display: flex;
  align-items: center;
  gap: var(--spacing-s);
  cursor: pointer;
  font-size: var(--size-s);
  color: var(--clr-black);
  font-weight: var(--fw-regular);
  transition: color var(--transition-fast-short);
  padding: var(--spacing-xs) 0;
  min-height: 44px;
}

.resources-filter-checkbox-label:hover {
  color: var(--clr-black);
  font-weight: var(--fw-bold);
  text-decoration: underline;
}

/* Topics Container (Links instead of checkboxes) */
.resources-filter-topics-container {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-m);
}

.resources-filter-topic-link {
  color: var(--clr-black);
  text-decoration: none;
  font-size: var(--size-s);
  font-weight: var(--fw-regular);
  transition: color var(--transition-fast-short);
  padding: var(--spacing-xs) 0 var(--spacing-xs) var(--spacing-s);
  min-height: 44px;
  display: flex;
  align-items: center;
  cursor: pointer;
  line-height: 1.5;
}

.resources-filter-topic-link:hover {
  color: var(--clr-black);
  font-weight: var(--fw-bold);
  background: none;
  text-decoration: underline;
}

.resources-filter-checkbox {
  cursor: pointer;
  accent-color: var(--clr-black);
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  transition: opacity var(--transition-fast-short);
}

.resources-filter-clear-all {
  width: 100%;
  padding: var(--spacing-s) var(--spacing-m);
  background-color: var(--clr-white);
  border: 2px solid var(--clr-black);
  border-radius: var(--radius-m);
  font-size: var(--size-s);
  font-weight: var(--fw-bold);
  font-family: 'Knowledge', sans-serif;
  cursor: pointer;
  transition: all var(--transition-fast-short);
  font-weight: var(--fw-bold);
  color: var(--clr-black);
  margin-top: var(--spacing-m);
  min-height: 44px;
  text-align: center;
}

.resources-filter-clear-all:hover {
  border-color: var(--clr-pink-dark);
  color: var(--clr-white);
  background-color: var(--clr-pink);
  font-weight: var(--fw-bold);
  transition: all var(--transition-fast-short);
}



.resources-title-link {
  display: contents;
  font-weight: var(--fw-regular);
  color: var(--clr-black);
  text-decoration: none;
  transition: color var(--transition-fast-short);
  margin-bottom: var(--spacing-s);
  font-size: var(--size-s);
}

.resources-title-link:hover {
  color: var(--clr-black);
  background: none;
  font-weight: var(--fw-bold);
    border-bottom: 1px solid black;

}

.resources-description {
  color: var(--clr-grey-text);
  font-size: var(--size-s);
  font-weight: var(--fw-regular);
  line-height: 1.5;
  margin-top: 0.2rem;
}

.resources-date {
  margin-top: 0;
}

.resources-meta {
  color: var(--clr-black);
  font-size: var(--size-s);
  font-weight: var(--fw-regular);
  margin-top: var(--spacing-xs);
  line-height: 1.5;
}

/* Mobile Optimizations for Resources Page */

/* Tablets and below (max 1200px) - Single column layout */
@media (max-width: 1200px) {
  .resources-wrapper {
    grid-template-columns: 1fr;
    gap: var(--spacing-m);
    padding: var(--spacing-xl) var(--spacing-m);
  }

  .resources-filter-sidebar {
    grid-column: 1;
    position: static;
    max-height: none;
    overflow-y: visible;
    padding: 0;
    border-radius: 0;
    background-color: var(--clr-white);
    border-top: 1px solid var(--clr-grey-border);
    padding-top: var(--spacing-xl);
    margin-top: var(--spacing-xl);
  }
}

/* Landscape tablet (max 1024px) */
@media (max-width: 1024px) {
  .resources-wrapper {
    gap: var(--spacing-m);
  }

  .resources-filter-sidebar {
    max-height: calc(100vh - var(--spacing-m) * 3);
  }

  .resources-filter-sidebar h3 {
    font-size: var(--size-s);
    margin-bottom: var(--spacing-s);
  }

  .resources-filter-sections {
    gap: var(--spacing-s);
  }

  .resources-filter-section-title {
    font-size: 0.95rem;
    padding: var(--spacing-xs);
    margin-bottom: var(--spacing-xs);
  }

  .resources-filter-checkbox-label {
    font-size: 0.9rem;
    gap: var(--spacing-xs);
    min-height: 40px;
  }

  .resources-filter-topic-link {
    font-size: 0.9rem;
    min-height: 40px;
  }

  .resources-filter-clear-all {
    font-size: 0.9rem;
    padding: var(--spacing-xs) var(--spacing-s);
  }
}

/* Tablet portrait (max 768px) */
@media (max-width: 768px) {
  .resources-wrapper {
    gap: var(--spacing-xl);
    padding: var(--spacing-xl) var(--spacing-m);
  }

  .resources-filter-sidebar h3 {
    font-size: var(--size-m);
    margin-bottom: var(--spacing-m);
  }

  .resources-filter-sections {
    gap: var(--spacing-m);
  }

  .resources-filter-section-title {
    font-size: var(--size-s);
    padding: 0;
    margin-bottom: var(--spacing-s);
  }

  .resources-filter-checkbox-container {
    gap: var(--spacing-m);
  }

  .resources-filter-checkbox-label {
    gap: var(--spacing-s);
    min-height: 44px;
    font-size: var(--size-s);
  }

  .resources-filter-topic-link {
    min-height: 44px;
    font-size: var(--size-s);
  }

  .resources-filter-clear-all {
    font-size: var(--size-s);
    padding: var(--spacing-s) var(--spacing-m);
    margin-top: var(--spacing-xl);
  }

  .resources-category-grid {
    gap: var(--spacing-m);
  }

  .resources-category-grid h2 {
    font-size: var(--size-l);
    margin-bottom: 0.8rem;
    margin-top: var(--spacing-m);
  }

  .resources-category-grid h3 {
    font-size: var(--size-m);
    margin-bottom: var(--spacing-xs);
    margin-top: var(--spacing-s);
  }

  .resources-list {
    gap: 1rem;
  }

  .resources-item {
    margin-bottom: 1rem;
  }
}

/* Mobile landscape (max 667px) */
@media (max-width: 667px) {
  .resources-wrapper {
    display: flex;
    padding: 0;
    gap: 0;
    flex-direction: column;
  }

  main#resourcesContainer {
    padding: var(--spacing-m) var(--spacing-s);
    padding-top: 0;
    order: 2;
    grid-column: unset;
  }

  .resources-filter-sidebar {
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    background-color: var(--clr-white);
    border-bottom: 1px solid var(--clr-grey-border);
    padding: 0;
    margin: 0;
    border-radius: 0;
    border-top: none;
    max-height: none;
    overflow-y: visible;
    margin-top: 0;
    order: 1;
    width: 100%;
    grid-column: unset;
  }

  .resources-filter-sidebar h3 {
    font-size: 1rem;
    padding: var(--spacing-s);
    margin-bottom: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
  }

  .resources-filter-sidebar h3::after {
    content: '🔍';
    font-size: 1.2rem;
    font-weight: bold;
  }

  .resources-filter-sidebar.expanded h3::after {
    content: '✕';
  }

  .resources-filter-sections {
    gap: 0.75rem;
    padding: 0 var(--spacing-s) var(--spacing-s) var(--spacing-s);
    display: none;
    flex-direction: column;
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .resources-filter-sidebar.expanded .resources-filter-sections {
    display: flex;
  }

  body.filter-expanded {
    overflow: hidden;
  }

  .resources-category-grid {
    gap: var(--spacing-s);
  }

  .resources-category-grid h2 {
    font-size: 1.5rem;
    margin-bottom: 0.6rem;
    margin-top: var(--spacing-s);
  }

  .resources-list {
    gap: 0.75rem;
  }

  .resources-item {
    margin-bottom: 0.75rem;
    padding: 0;
  }

  .resources-filter-section-title {
    font-size: 0.95rem;
  }

  .resources-filter-checkbox-label {
    font-size: 0.9rem;
    min-height: 40px;
  }

  .resources-filter-topic-link {
    font-size: 0.9rem;
    min-height: 40px;
    padding-left: var(--spacing-s);
  }
}

/* Mobile portrait (max 480px) */
@media (max-width: 480px) {
  .resources-wrapper {
    display: flex;
    padding: 0;
    gap: 0;
    flex-direction: column;
  }

  main#resourcesContainer {
    padding: var(--spacing-m) var(--spacing-s);
    padding-top: 0;
    order: 2;
    grid-column: unset;
  }

  .resources-filter-sidebar {
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    background-color: var(--clr-white);
    border-bottom: 1px solid var(--clr-grey-border);
    padding: 0;
    margin: 0;
    border-radius: 0;
    border-top: none;
    max-height: none;
    overflow-y: visible;
    margin-top: 0;
    order: 1;
    grid-column: unset;
  }

  .resources-filter-sidebar h3 {
    font-size: 1.1rem;
    margin-bottom: 0;
    padding: var(--spacing-s) var(--spacing-s);
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
  }

  .resources-filter-sidebar h3::after {
    content: '🔍';
    font-size: 1.2rem;
    font-weight: bold;
  }

  .resources-filter-sidebar.expanded h3::after {
    content: '✕';
  }

  .resources-filter-sections {
    gap: var(--spacing-s);
    padding: var(--spacing-s);
    padding-top: 0;
    display: none;
  }

  .resources-filter-sidebar.expanded .resources-filter-sections {
    display: flex;
  }

  .resources-filter-section-title {
    font-size: 0.9rem;
    padding: var(--spacing-xs);
    margin-bottom: var(--spacing-xs);
  }

  .resources-filter-section-title::after {
    font-size: 1rem;
  }

  .resources-filter-checkbox-container,
  .resources-filter-topics-container {
    gap: var(--spacing-m);
  }

  .resources-filter-checkbox-label,
  .resources-filter-topic-link {
    gap: var(--spacing-s);
    font-size: 0.9rem;
    min-height: 44px;
    padding: var(--spacing-xs) 0;
    padding-left: var(--spacing-s);
  }

  .resources-filter-checkbox {
    width: 16px;
    height: 16px;
  }

  .resources-filter-clear-all {
    font-size: 0.9rem;
    padding: var(--spacing-s) var(--spacing-m);
    margin-top: var(--spacing-m);
    width: 100%;
  }

  .resources-category-grid {
    gap: var(--spacing-s);
  }

  .resources-category-grid h2 {
    font-size: 1.3rem;
    margin-bottom: 0.6rem;
    margin-top: var(--spacing-m);
  }

  .resources-category-grid h3 {
    font-size: 1.1rem;
  }

  .resources-category-grid h4 {
    font-size: 1rem;
  }

  .resources-nested-subcategory {
    margin-bottom: var(--spacing-m);
  }

  .resources-title-link {
    font-size: var(--size-s);
  }

  .resources-description,
  .resources-date {
    font-size: 0.85rem;
  }

  .resources-list {
    gap: 0.6rem;
  }

  .resources-item {
    margin-bottom: 0.6rem;
    padding: 0;
  }
}

/* Small mobile phones (max 360px) */
@media (max-width: 360px) {
  .resources-wrapper {
    padding: 0;
  }

  main#resourcesContainer {
    padding-inline: var(--spacing-xs);
  }

  .resources-filter-sections {
    padding-inline: var(--spacing-xs);
  }

  .resources-filter-sidebar h3 {
    font-size: 1rem;
  }

  .resources-category-grid h2 {
    font-size: 1.1rem;
  }

  .resources-category-grid h3 {
    font-size: 0.95rem;
  }

  .resources-filter-checkbox-label,
  .resources-filter-topic-link {
    font-size: 0.85rem;
  }

  .resources-title-link {
    font-size: 0.9rem;
  }
}

/* Landscape adjustments for small screens */
@media (max-height: 600px) {
  .resources-filter-sidebar {
    max-height: calc(100vh - 20px);
    overflow-y: auto;
  }

  .resources-filter-section-title {
    padding: var(--spacing-xs);
  }
}

/* High-resolution devices (for performance optimization) */
@media (min-device-pixel-ratio: 2) {
  .resources-filter-checkbox {
    accent-color: var(--clr-black);
  }
}

/* Touch device optimizations */
@media (hover: none) {
  .resources-filter-checkbox-label:active,
  .resources-filter-topic-link:active {
    background-color: var(--clr-grey-lighter);
    border-radius: var(--radius-xs);
  }

  .resources-filter-section-title:active {
    background-color: var(--clr-grey-lighter);
    border-radius: var(--radius-xs);
  }

  .resources-filter-clear-all:active {
    opacity: 0.8;
  }
}

/* Reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
  .resources-filter-checkbox-label,
  .resources-filter-topic-link,
  .resources-filter-section-title,
  .resources-filter-clear-all {
    transition: none;
  }

  .resources-filter-section-title::after {
    transition: none;
  }
}

/* Print styles */
@media print {
  .resources-filter-sidebar {
    display: none;
  }

  .resources-wrapper {
    grid-template-columns: 1fr;
  }

  .resources-category-grid {
    page-break-inside: avoid;
  }
}
