/* ============================================================
   Lucas Fernández — portfolio stylesheet
   0. Typeface (@font-face Satoshi)
   1. Tokens
   2. Reset
   3. Utilities (container, pills, ghost titles)
   4. Nav
   5. Hero
   6. Client marquee
   7. Selected Projects (scroll-scrubbed)
   8. About + Courses
   9. Contact / footer
   10. Desktop
   11. Motion preferences
   ============================================================ */

/* ---------- 0. Typeface ---------- */
@font-face {
  font-family: "Satoshi";
  src: url("../assets/fonts/Satoshi-Variable.woff2") format("woff2");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("../assets/fonts/Satoshi-VariableItalic.woff2") format("woff2");
  font-weight: 300 900;
  font-style: italic;
  font-display: swap;
}

/* ---------- 1. Tokens ---------- */
:root {
  /* Colour — the site is black end to end */
  --color-bg: #010101;
  /* one grey scale, lightest to darkest (contrast on --color-bg) */
  --color-text: #ffffff;       /* headings, links, buttons — 21:1 */
  --color-body: #d9d9d9;       /* running text, pills — 14:1 */
  --color-muted: #8c8c8c;      /* labels, meta, dates, notes — 6.3:1 */
  --color-ghost: #666666;      /* oversized decorative headings — 3.6:1 */
  --color-pill-bg: color-mix(in srgb, #ffffff 20%, transparent);
  --color-hairline: rgba(255, 255, 255, 0.16);
  --color-focus: #7f97ff;

  --font: "Satoshi", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --w-regular: 400;
  --w-medium: 500;
  --w-bold: 700;

  /* Fluid type scale (mobile -> desktop) */
  --text-display: clamp(2.5rem, 0.8rem + 7vw, 8rem);   /* 128px */
  --text-hero: clamp(2.5rem, 5vw, 5.625rem);   /* 72px — hero title + intro loader */
  --text-h2: clamp(2.25rem, 1rem + 5vw, 6.875rem);     /* 110px */
  --text-h3: clamp(1.75rem, 1rem + 3.4vw, 4rem);       /* 64px */
  --text-h4: clamp(1.25rem, 1rem + 1.2vw, 2rem);       /* 32px */
  /* rem = 12.8px (html is 80%), so px values below are the rendered size */
  --text-body-lg: clamp(1.25rem, 1.1rem + 0.35vw, 1.5rem);    /* 16 -> 19px — paragraphs */
  --text-hero-sm: clamp(1.25rem, 1.05rem + 0.4vw, 1.5625rem); /* 16 -> 20px — hero eyebrow + lead */
  --text-nav: clamp(1.172rem, 1.1rem + 0.1vw, 1.25rem);       /* 15 -> 16px — nav, buttons, UI lines */
  --text-pill: clamp(1.016rem, 0.95rem + 0.1vw, 1.094rem);    /* 13 -> 14px — labels, tags, chips, meta */

  --tracking-tight: -0.02em;

  --leading-tight: 1.05;
  --leading-snug: 1.2;
  --leading-ui: 1.4;           /* tags, chips, one-liners */
  --leading-body: 1.6;

  /* Spacing */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  /* larger steps grow with the viewport so desktop breathes like the Figma */
  --space-5: clamp(3rem, 2rem + 4vw, 5rem);
  --space-6: clamp(4rem, 2.25rem + 7vw, 8.5rem);
  --space-7: clamp(5.5rem, 2rem + 12vw, 14rem);
  --space-8: clamp(7rem, 1.5rem + 17vw, 20rem);

  --content-width: 1488px;
  --gutter: clamp(1.25rem, 6vw, 7.5rem);   /* 120px on desktop */
  --nav-h: 5rem;
  --radius-pill: 999px;
  --radius-card: 22px;   /* same corner as a .btn-pill--lg (44px tall) */

  /* Motion — one curve family shared by the intro loader and the hero */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);
  --hero-base: 0.15s;    /* when the hero entrance starts (pushed back by the loader) */
}

/* ---------- 2. Reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
}

html {
  font-size: 80%; /* scales every rem-based size (type + spacing tokens) down together */
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font);
  font-size: var(--text-body-lg);
  font-weight: var(--w-regular);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-synthesis: none;
  overflow-x: hidden;
}

/* Opaque page layer that slides over the fixed footer as you scroll to the end;
   its bottom edge is clipped into a curve that flexes with scroll speed (JS) */
#main {
  position: relative;
  z-index: 1;
  background: var(--color-bg);
  clip-path: var(--main-clip, none);
}

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

a {
  color: inherit;
}

h1, h2, h3 {
  font-weight: var(--w-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

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

/* ---------- 3. Utilities ---------- */
.container {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: 1.875rem;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--color-text);
  color: var(--color-bg);
  padding: var(--space-1) var(--space-2);
  border-radius: 0 0 8px 0;
}
.skip-link:focus {
  left: 0;
}

/* Oversized muted headings used across About / Courses */
.ghost-title {
  font-size: var(--text-h3);
  color: var(--color-ghost);
  letter-spacing: var(--tracking-tight);
}
.ghost-label {
  font-size: var(--text-h4);
  font-weight: var(--w-bold);
  color: var(--color-ghost);
  letter-spacing: var(--tracking-tight);
}

/* Pills (tags) */
.tag-list {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}
.tag-list li {
  background: var(--color-pill-bg);
  color: var(--color-body);
  border-radius: var(--radius-pill);
  padding: 0.3em 0.8em;
  font-size: var(--text-pill);
  font-weight: var(--w-medium);
  line-height: var(--leading-ui);
}

.btn-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-text);
  color: var(--color-bg);
  border-radius: var(--radius-pill);
  padding: 0.5rem 1.1rem;
  font-weight: var(--w-bold);
  text-decoration: none;
  transition: transform 0.18s ease, opacity 0.18s ease;
}
.btn-pill:hover {
  transform: translateY(-1px);
  opacity: 0.88;
}
/* secondary: outline on black */
.btn-pill--ghost {
  background: transparent;
  color: var(--color-text);
  border: none;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.45);
  font: inherit;
  font-weight: var(--w-bold);
  cursor: pointer;
}
.btn-pill--lg {
  padding: 0.85rem 2.25rem;
  font-size: var(--text-nav);
}


/* ---------- 4. Nav ---------- */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--color-bg) 82%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.site-nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--nav-h);
  gap: var(--space-2);
}
.site-nav__brand {
  font-size: var(--text-nav);
  font-weight: var(--w-bold);
  letter-spacing: var(--tracking-tight);
  text-decoration: none;
  white-space: nowrap;
}
/* "|" between the name and the page links — desktop only */
.site-nav__divider {
  display: none;
  font-size: var(--text-nav);
  font-weight: var(--w-bold);
}

.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0 10px;
  background: none;
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  cursor: pointer;
}
.nav-toggle__bar {
  height: 2px;
  background: var(--color-text);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.primary-nav {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: none;
  background: var(--color-bg);
  border-top: 1px solid var(--color-hairline);
}
.primary-nav.is-open {
  display: block;
}
.primary-nav ul {
  list-style: none;
  margin: 0;
  padding: var(--space-2) var(--gutter);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.primary-nav ul.primary-nav__actions {
  border-top: 1px solid var(--color-hairline);
  padding-bottom: var(--space-3);
}
.primary-nav a {
  font-size: var(--text-nav);
  font-weight: var(--w-bold);
  text-decoration: none;
}
.primary-nav a:not(.btn-pill):hover {
  opacity: 0.7;
}
.primary-nav .btn-pill {
  align-self: flex-start;
}

/* Digital/Physical and EN/ES: one shared toggle style. Each shows the state
   you're in: grey at rest, white on hover, a click switches to the other one. */
.nav-switch {
  display: inline-flex;
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--text-nav);
  font-weight: var(--w-bold);
  line-height: inherit;
  color: var(--color-muted);
  text-decoration: none;
  cursor: pointer;
  transition: color 0.18s ease;
}
.primary-nav a.nav-switch:hover,
.nav-switch:hover,
.nav-switch:focus-visible {
  color: var(--color-text);
  opacity: 1;
}


/* ---------- 5. Hero ---------- */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: calc(100svh - var(--nav-h));
  padding-block: var(--space-6);
  overflow: hidden;
}
.hero__vignette {
  position: absolute;
  inset: -20% -10%;
  z-index: -1;
  background: radial-gradient(
    60% 55% at 50% 45%,
    rgba(1, 1, 1, 0) 0%,
    rgba(1, 1, 1, 0.55) 62%,
    var(--color-bg) 100%
  );
}
.hero__inner {
  width: 100%;
}
.hero__eyebrow {
  color: var(--color-muted);
  font-size: var(--text-hero-sm);
  font-weight: var(--w-regular);
  line-height: var(--leading-ui);
  max-width: 60ch;
  margin-bottom: var(--space-3);
}
.hero__title {
  font-size: var(--text-hero);
  font-weight: var(--w-bold);
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  max-width: 14.5em; /* the Figma block: every landing title (EN/ES) breaks into 3 lines */
  margin-bottom: var(--space-4);
}
.hero__lead {
  color: var(--color-text);
  font-size: var(--text-hero-sm);
  font-weight: var(--w-medium);
  line-height: var(--leading-body);
  max-width: 47.5em; /* the Figma block (951px at 20px): both landing leads sit on 2 lines */
  margin-bottom: var(--space-4);
}

.hero__social {
  list-style: none;
  padding: 0;
  display: flex;
  gap: var(--space-2);
}
.hero__social a {
  display: inline-flex;
  transition: transform 0.18s ease, opacity 0.18s ease;
}
.hero__social img {
  width: clamp(44px, 3.4vw, 56px);
  height: auto;
}
.hero__social a:hover {
  transform: translateY(-2px);
  opacity: 0.85;
}

/* intro: every title word rises out of its own line mask (js/main.js splits
   the h1 into .word spans), then eyebrow, lead and social icons follow.
   Armed on every visit by html.hero-intro (set in the <head>); after the
   loader, --hero-base pushes the whole entrance back so it lands as the
   curtain lifts. Without JS nothing is hidden. */
.hero__title .word {
  display: inline-block;
  /* room for accents (Ó, É) and the comma tail inside the mask */
  padding-block: 0.12em;
  margin-block: -0.12em;
  overflow: clip;
  vertical-align: top;
}
.hero__title .word > span {
  display: inline-block;
}
.hero-intro .hero__title:not(:has(.word)) {
  opacity: 0; /* split pending: never flash the unsplit title */
}
.hero-intro .hero__title .word > span {
  transform: translateY(110%);
  animation: intro-word-in 1s var(--ease-out) forwards;
  animation-delay: calc(var(--hero-base) + var(--w, 0) * 0.045s);
}
.hero__title.is-static .word > span {
  transform: none;
  animation: none;
}
.hero-intro .hero [data-hero-step] {
  opacity: 0;
  transform: translateY(28px);
  animation: hero-step-in 0.9s var(--ease-out) forwards;
  animation-delay: calc(var(--hero-base) + var(--i, 0) * 0.14s);
}
@keyframes hero-step-in {
  to { opacity: 1; transform: none; }
}
@keyframes intro-word-in {
  to { transform: none; }
}

/* ---------- 5a. Intro loader ----------
   First landing of a session only (html.intro-loader, set in the <head>).
   ANOTHER [DESIGNER → PORTFOLIO] rolls like a slot, gets pushed down as
   JUST KIDDING! drops in from above, then the curtain lifts onto the hero.
   Same type size and left edge as the hero title, so the punchline reads
   as turning into the headline. js/main.js removes it when the lift ends,
   or right away on click / key / scroll. Timings live in the vars below. */
.intro {
  display: none;
}
.intro-loader {
  --hero-base: 3.3s;   /* the headline rises right where the punchline left */
  --intro-in: 0.2s;       /* ANOTHER DESIGNER rises */
  --intro-swap: 1.05s;    /* DESIGNER rolls up and out as PORTFOLIO rolls in */
  --intro-kid: 1.95s;     /* JUST KIDDING! drops in, pushing the line down */
  --intro-lift: 3.2s;     /* punchline exits up, curtain lifts */
  --intro-roll: 0.7s;     /* every swap moves as one, like a slot reel */
}
.intro-loader:not(.intro-done) {
  overflow: hidden; /* no scrolling the page underneath mid-joke */
}
.intro-loader .intro {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: grid;
  align-items: center;
  background: var(--color-bg);
  animation: intro-lift 0.95s var(--ease-in-out) var(--intro-lift) forwards;
}
.intro.is-skipped {
  animation: intro-fade 0.35s ease forwards;
}
.intro__stage {
  display: grid;
  font-size: min(var(--text-hero), 8vw);
  font-weight: var(--w-bold);
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: var(--color-text);
}
/* both lines share one grid cell so they swap in place */
.intro__line {
  grid-area: 1 / 1;
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.25em;
}
.intro__mask {
  display: inline-grid;
  padding-block: 0.12em;
  margin-block: -0.12em;
  overflow: clip;
}
.intro__word {
  grid-area: 1 / 1;
  display: inline-block;
  white-space: nowrap;
}
.intro__word--another {
  animation:
    intro-rise 0.8s var(--ease-out) var(--intro-in) both,
    intro-out-down var(--intro-roll) var(--ease-in-out) var(--intro-kid) forwards;
}
.intro__word--designer {
  animation:
    intro-rise 0.8s var(--ease-out) calc(var(--intro-in) + 0.08s) both,
    intro-out-up var(--intro-roll) var(--ease-in-out) var(--intro-swap) forwards;
}
.intro__word--portfolio {
  animation:
    intro-rise var(--intro-roll) var(--ease-in-out) var(--intro-swap) both,
    intro-out-down var(--intro-roll) var(--ease-in-out) var(--intro-kid) forwards;
}
.intro__word--kidding {
  animation:
    intro-drop var(--intro-roll) var(--ease-in-out) var(--intro-kid) both,
    intro-out-up 0.5s var(--ease-in-out) var(--intro-lift) forwards;
}
@keyframes intro-rise {
  from { transform: translateY(110%); }
  to { transform: none; }
}
@keyframes intro-drop {
  from { transform: translateY(-110%); font-weight: 700; }
  to { transform: none; font-weight: 900; }
}
@keyframes intro-out-up {
  to { transform: translateY(-110%); }
}
@keyframes intro-out-down {
  to { transform: translateY(110%); }
}
@keyframes intro-lift {
  to { clip-path: inset(0 0 100% 0); }
}
@keyframes intro-fade {
  to { opacity: 0; }
}

/* ---------- 6. Client marquee ---------- */
.marquee {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-6);
}
.marquee__viewport {
  display: flex;
  width: max-content;
  animation: marquee-scroll 32s linear infinite;
}
.marquee__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: clamp(3rem, 9vw, 8rem);
  padding-inline: clamp(1.5rem, 4.5vw, 4rem);
}
.marquee__track li {
  display: flex;
  align-items: center;
}
.marquee__track img {
  height: clamp(1.5rem, 1rem + 1.2vw, 2rem);
  width: auto;
  opacity: 0.75;
}
.marquee__track li:nth-child(2) img {  /* STG is a tall badge — give it more height */
  height: clamp(2.25rem, 1.5rem + 2vw, 3.25rem);
}
.marquee__fade {
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(4rem, 20vw, 20rem);
  z-index: 2;
  pointer-events: none;
}
.marquee__fade--left {
  left: 0;
  background: linear-gradient(to right, var(--color-bg) 12%, rgba(1, 1, 1, 0) 100%);
}
.marquee__fade--right {
  right: 0;
  background: linear-gradient(to left, var(--color-bg) 12%, rgba(1, 1, 1, 0) 100%);
}
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ---------- 7. Selected Projects (scroll-linked reveal) ---------- */
.sp {
  /* local tokens updated by JS from scroll progress (0 -> 1) */
  --sp-bg: #ffffff;
  --sp-ghost: #4f4f4f;
  --sp-title-x: 0vw;
  --sp-ink: #0b0b0b;
  --sp-muted: #4a4a4a;
  --sp-hairline: rgba(0, 0, 0, 0.22);
  position: relative;
  overflow: hidden;
  background: var(--sp-bg);
  padding-block: var(--space-8) var(--space-7);
}
.sp.is-scrubbed {
  --sp-bg: #010101;
}
.sp__stage {
  width: 100%;
}
.sp__title {
  font-size: var(--text-display);
  color: var(--sp-ghost);
  text-transform: none;
  transform: translate3d(var(--sp-title-x), 0, 0);
  will-change: transform;
  margin-bottom: var(--space-6);
}
.projects-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-3);
}
/* each card fades + rises as it scrolls into view; JS staggers a batch
   of cards that enter together (ScrollTrigger.batch style) */
.project-card {
  position: relative;
  opacity: 0;
  transform: translateY(42px);
  transition: opacity 0.7s ease, transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform, opacity;
}
.project-card.is-in {
  opacity: 1;
  transform: none;
}
.project-card__link {
  display: block;
  text-decoration: none;
  color: var(--color-text);
}

/* custom "View" pill that follows the pointer over a project card,
   replacing the native cursor (js/main.js sets cursor:none on hover) */
.cursor-view {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 300;
  pointer-events: none;
  background: var(--color-text);
  color: var(--color-bg);
  border-radius: var(--radius-pill);
  padding: 0.7rem 1.5rem;
  font-weight: var(--w-bold);
  font-size: var(--text-pill);
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.6);
  transition: opacity 0.18s ease, transform 0.18s ease;
  will-change: transform, opacity;
}
.cursor-view.is-active {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.project-card__media {
  position: relative;
  margin: 0;
  border-radius: var(--radius-card);
  aspect-ratio: 11 / 10;
  overflow: hidden;
  background: #1a1a1a;
}
.project-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.project-card__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: clamp(1.25rem, 3vw, 2.5rem);
  background: linear-gradient(to top, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.15) 55%, rgba(0, 0, 0, 0) 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.project-card__link:hover .project-card__overlay,
.project-card__link:focus-visible .project-card__overlay {
  opacity: 1;
}
.project-card__overlay .tag-list li {
  background: rgba(255, 255, 255, 0.22);
  color: var(--color-text);
  backdrop-filter: blur(2px);
}

/* two blocks inside Selected Projects: Digital products, Physical products */
.work-group + .work-group {
  margin-top: var(--space-7);
}
.work-group__title {
  font-size: var(--text-h4);
  font-weight: var(--w-bold);
  color: var(--sp-ghost);
  letter-spacing: var(--tracking-tight);
  margin-bottom: var(--space-4);
}
.work-group__intro {
  color: var(--sp-muted);
  font-size: var(--text-body-lg);
  line-height: var(--leading-body);
  max-width: 52ch;
  margin-top: calc(var(--space-2) - var(--space-4));
  margin-bottom: var(--space-4);
}

/* name, one-liner and outcome chips under each project image */
.project-card__body {
  display: grid;
  gap: var(--space-1);
  padding-top: var(--space-2);
  color: var(--sp-ink);
}
.project-card__name {
  font-size: var(--text-h4);
  font-weight: var(--w-bold);
  letter-spacing: var(--tracking-tight);
  text-transform: none;
}
.project-card__line {
  color: var(--sp-muted);
  font-size: var(--text-nav);
  line-height: var(--leading-ui);
  max-width: 44ch;
}
.chip-list {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.35rem;
}
.chip-list li {
  border-radius: var(--radius-pill);
  box-shadow: inset 0 0 0 1px var(--sp-hairline);
  color: var(--sp-ink);
  padding: 0.2em 0.75em;
  font-size: var(--text-pill);
  font-weight: var(--w-medium);
  line-height: var(--leading-ui);
}

/* ---------- 8. About + Courses ---------- */
.about {
  padding-block: var(--space-7) var(--space-8);
}
.about__title {
  font-size: var(--text-h2);
  color: var(--color-ghost);
  margin-bottom: var(--space-6);
}
.about__grid {
  display: grid;
  gap: var(--space-5);
}
.about__body p {
  color: var(--color-body);
  max-width: 60ch;
}
.about__body p + p {
  margin-top: var(--space-3);
}
.about__aside {
  display: grid;
  gap: var(--space-4);
}
.about__group h3 {
  margin-bottom: var(--space-2);
}

.courses {
  margin-top: var(--space-7);
}
.courses h2 {
  margin-bottom: var(--space-6);
}
.courses__list {
  display: grid;
  gap: var(--space-5);
}
.course-row,
.cv-row {
  display: grid;
  gap: var(--space-2);
}
.course-row__cat {
  font-size: var(--text-h4);
}
.course-row ul {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  color: var(--color-body);
}

/* ---------- 8b. Case study pages (work/*.html) ---------- */
.case-study__back,
.case-study__next {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  color: var(--color-body);
  font-weight: var(--w-medium);
  text-decoration: none;
}
.case-study__back:hover,
.case-study__next:hover {
  opacity: 0.75;
}

.case-study__head {
  padding-block: var(--space-6) var(--space-5);
}
.case-study__title {
  font-size: var(--text-h3);
  font-weight: var(--w-bold);
  letter-spacing: var(--tracking-tight);
  margin-top: var(--space-2);
}
.case-study__subtitle {
  color: var(--color-body);
  font-size: var(--text-body-lg);
  max-width: 60ch;
  margin-top: var(--space-3);
}
.case-study__meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}
.case-study__meta dt {
  font-size: var(--text-pill);
  color: var(--color-muted);
  font-weight: var(--w-medium);
}
.case-study__meta dd {
  margin: 0;
  font-weight: var(--w-medium);
}
.case-study__note {
  color: var(--color-muted);
  font-size: var(--text-pill);
  max-width: 60ch;
  margin-top: var(--space-3);
}

/* summary block at the top of a case: problem / what I did / results */
.case-summary {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-hairline);
}
.case-summary__label {
  font-size: var(--text-pill);
  font-weight: var(--w-medium);
  color: var(--color-muted);
  margin-bottom: var(--space-2);
}
.case-summary__item p {
  font-size: var(--text-body-lg);
  line-height: var(--leading-body);
  max-width: 52ch;
}
.case-summary__results {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.case-summary__results li {
  position: relative;
  padding-left: 1.25rem;
  line-height: var(--leading-body);
  max-width: 60ch;
}
.case-summary__results li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #4ade80;
}

/* grid of module thumbnails inside a case section */
.case-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  gap: var(--space-3);
}
.case-grid img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 4px;
}

/* every direct child of a case-study section gets breathing room from the
   one before it — covers heading → text, text block → image, image → text,
   without having to special-case each combination (the reset zeroes all
   default margins, see section 2) */
.section > * + * {
  margin-top: 2rem;
}
/* .container.about__body (not just .about__body) targets case-study pages
   only — the homepage's own .about__body has no .container class, since
   it's already nested in one — so this can't touch the homepage's spacing.
   Needs the compound selector to out-specificity .about__body p + p above. */
.container.about__body > * + * {
  margin-top: 2rem;
}

.case-study__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 4px;
}
.case-study__media figcaption {
  margin-top: var(--space-1);
  font-size: var(--text-pill);
  color: var(--color-muted);
}

.case-study__next {
  justify-content: flex-end;
  text-align: right;
}
.case-study__next-wrap {
  padding-block: var(--space-5) var(--space-7);
}

.ghost-label + .tag-list {
  margin-top: 2rem;
}

/* ---------- 8c. Resume CV (resume/*.html) ---------- */
.cv-actions {
  margin-top: var(--space-4);
}

.cv-body {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-4) var(--space-5);
}
.cv-prose p,
.cv-text,
.cv-list li,
.cv-edu li {
  color: var(--color-body);
}
.cv-prose p {
  max-width: 60ch;
}
.cv-prose p + p {
  margin-top: var(--space-3);
}
.cv-block + .cv-block {
  margin-top: var(--space-4);
}
.cv-block__title {
  font-size: var(--text-body-lg);
  margin-bottom: var(--space-2);
}

.cv-job + .cv-job {
  margin-top: var(--space-5);
}
.cv-job__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem var(--space-3);
}
.cv-job__role {
  font-size: var(--text-body-lg);
  line-height: var(--leading-snug);
}
.cv-job__date {
  color: var(--color-muted);
  font-size: var(--text-pill);
  font-weight: var(--w-medium);
  white-space: nowrap;
}
/* client inside one job (TechShare, SalesQL under Webake) */
.cv-job__client {
  font-size: var(--text-nav);
  font-weight: var(--w-bold);
  color: var(--color-text);
  margin-top: var(--space-3);
}
.cv-job__client + .cv-list {
  margin-top: var(--space-1);
}
.cv-list {
  padding-left: 1.1em;
  margin-top: var(--space-2);
  max-width: 70ch;
}
.cv-list li + li {
  margin-top: var(--space-1);
}
.cv-list li::marker {
  color: var(--color-ghost);
}
.cv-list strong,
.cv-edu strong {
  color: var(--color-text);
}
.cv-edu {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}
.cv-edu + .cv-block {
  margin-top: var(--space-4);
}

/* closing question */
.cv-cta {
  padding-block: var(--space-6) var(--space-7);
}
.cv-cta__title {
  font-size: var(--text-h2);
  max-width: 14ch;
}
.cv-cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
/* the "No" that runs away (js/main.js → escapeButton): slides while chased,
   springs a little when it jumps to a new spot or heads home */
.cv-escape {
  position: relative;
  z-index: 2;
  background: var(--color-bg); /* opaque, so it reads cleanly when it flees over the title */
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
.cv-escape.is-jumping {
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.cv-escape:hover {
  opacity: 1;
}

/* ---------- 9. Contact / footer (fixed, revealed from underneath) ---------- */
.site-footer {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 0;
  isolation: isolate;
  max-height: 100svh;
  overflow: auto;
  display: flex;
  align-items: center;
  padding-block: clamp(2.5rem, 8vh, var(--space-6));
  color: var(--color-text);
}
/* the SVG path is the footer surface; its top edge bounces on reveal */
.site-footer__wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
  z-index: -2;
  pointer-events: none;
}
.site-footer__path {
  will-change: d;
}
/* grey ambient glow + grain (exported from Figma) */
.site-footer__glow {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center bottom;
  z-index: -1;
  pointer-events: none;
  user-select: none;
}
.site-footer__inner {
  width: 100%;
}
.site-footer__title {
  font-size: var(--text-h3);
  text-transform: none;
}
.site-footer__lead {
  color: var(--color-body);
  margin-top: var(--space-1);
  margin-bottom: var(--space-4);
}
.site-footer__links {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.site-footer__links a {
  font-size: var(--text-nav);
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: opacity 0.15s ease;
}
.site-footer__links a:hover {
  opacity: 0.65;
}
.site-footer__legal {
  margin-top: var(--space-4);
  color: var(--color-body);
  font-size: var(--text-nav);
}

/* pushes the document tall enough to scroll the content off the fixed footer;
   height set by JS to the footer's real height */
.footer-spacer {
  width: 100%;
}


/* ---------- 10. Desktop ---------- */
@media (min-width: 64rem) {
  .nav-toggle { display: none; }
  .site-nav__inner {
    justify-content: flex-start;
    gap: clamp(1.5rem, 3vw, 3rem);
  }
  .site-nav__divider { display: block; }
  .primary-nav {
    position: static;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: none;
    border: none;
  }
  .primary-nav ul {
    flex-direction: row;
    align-items: center;
    gap: clamp(1.5rem, 3vw, 3rem);
    padding: 0;
  }
  .primary-nav ul.primary-nav__actions {
    border-top: none;
    padding-bottom: 0;
  }
  .nav-switch { align-self: auto; }
  .primary-nav .btn-pill { align-self: auto; }


  .about__grid {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
  }
  .about__body p { font-size: var(--text-body-lg); }

  .projects-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
  }

  .case-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-6);
  }
  .case-summary__item--wide {
    grid-column: 1 / -1;
  }
  .case-summary__item--wide .case-summary__results {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-5);
  }

  .course-row,
  .cv-row {
    grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: start;
  }
}

@media (min-width: 90rem) {
  .projects-grid { gap: 80px; }
}

/* ---------- 11. Motion preferences ---------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .marquee__viewport { animation: none; flex-wrap: wrap; justify-content: center; }
  .marquee__track[aria-hidden="true"] { display: none; }
  .sp__title { transform: none; transition: none; }
  .project-card { opacity: 1; transform: none; transition: none; }
  .btn-pill:hover, .hero__social a:hover { transform: none; }
  .hero-intro .hero [data-hero-step] { opacity: 1; transform: none; animation: none; }
  .hero-intro .hero__title .word > span { transform: none; animation: none; }
  .intro { display: none !important; }
  .cv-escape, .cv-escape.is-jumping { transition: none; }
}

/* Visually hidden but available to assistive tech */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
