/* ================================================================
   HUGO FILIPE COSTA — Design System v2
   Protocol Theory-inspired editorial aesthetic
   ================================================================

   TABLE OF CONTENTS
   ─────────────────
   01. Design Tokens
   02. Reset & Base
   03. Layout
   04. Navigation
   05. Hero
   06. Marquee
   07. Stats
   08. Projects
   09. About
   10. Experience
   11. Mentorship
   12. Other Projects / Archive
   13. Contact + Form
   14. Footer
   15. Utilities & Animations
   16. Responsive

   ================================================================ */


/* ================================================================
   01. DESIGN TOKENS
   ================================================================ */

:root {
  /* Colour */
  --bg:           #0c0c0c;
  --bg-1:         #111111;
  --bg-2:         #161616;
  --bg-3:         #1c1c1c;

  /* Contrast on --bg is matched to the light theme, step for step:
     16.8 / 11.4 / 8.0 / 6.1. --text-4 carries body copy (case card roles,
     footer, labels) so it has to clear AA on its own, not just look quiet. */
  --text:         #f0ede8;
  --text-2:       #c8c5bf;
  --text-3:       #a8a5a0;
  --text-4:       #938f89;
  --text-muted:   #fde3d2;

  --accent:       #ff6f03;
  --accent-dim:   rgba(255, 111, 3, 0.10);
  --accent-border:rgba(255, 111, 3, 0.22);
  /* Text sitting on a solid --accent fill (the primary button). White on
     this orange is 2.79:1, well under AA. --bg's near-black is 7.01:1. */
  --accent-ink:   var(--bg);

  --border:       rgba(255, 255, 255, 0.07);
  --border-2:     rgba(255, 255, 255, 0.13);

  /* Form status colours. Bright enough to read on --bg here; the light
     theme below uses darker shades of the same hue, since these values
     were previously hardcoded and fell to ~2:1 on a white background. */
  --success:      #7bcf72;
  --error:        #ff6b6b;

  /* Typography */
  --font:         'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display: 'Clash Display', 'Inter', -apple-system, sans-serif;
  --mono:         'JetBrains Mono', 'Fira Code', 'Courier New', monospace;

  /* Type scale */
  --text-xs:   0.6875rem;   /* 11px */
  --text-sm:   0.8125rem;   /* 13px */
  --text-base: 1rem;        /* 16px */
  --text-md:   1.125rem;    /* 18px */
  --text-lg:   1.375rem;    /* 22px */
  --text-xl:   1.75rem;     /* 28px */
  --text-2xl:  2.25rem;     /* 36px */
  --text-3xl:  3rem;        /* 48px */
  --text-4xl:  4.5rem;      /* 72px */
  --text-5xl:  7rem;        /* 112px */

  /* Layout */
  --container:   1160px;
  --gutter:      clamp(20px, 4vw, 48px);
  --nav-h:       88px;
  --radius-sm:   6px;
  --radius-md:   12px;
  --radius-lg:   20px;

  /* Case-card lift. Kept deliberately faint: the panel is the same
     colour as the page, so a hairline and the barest shadow are all
     that should separate them. */
  --case-border:       rgba(255, 255, 255, 0.055);
  --case-shadow:       0 8px 24px -20px rgba(0, 0, 0, 0.5);
  --case-shadow-hover: 0 14px 34px -24px rgba(0, 0, 0, 0.45);

  /* Motion */
  --ease:        cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast:    150ms;
  --dur-base:    260ms;
  --dur-slow:    420ms;
}

/* Light theme — same palette already proven on the case study pages,
   toggled via a `theme-light` class on <body> (see js/main.js). */
body.theme-light {
  --bg:           #ffffff;
  --bg-1:         #f6f6f7;
  --bg-2:         #eeeeef;
  --bg-3:         #e4e4e6;

  --text:         #14161a;
  --text-2:       #3a3d44;
  --text-3:       #55585f;
  --text-4:       #5f6368;
  --text-muted:   #347e4a;

  --accent:       #347e4a;
  --accent-dim:   rgba(52, 126, 74, 0.08);
  --accent-border:rgba(52, 126, 74, 0.25);
  --accent-ink:   #ffffff;

  --border:       rgba(0, 0, 0, 0.1);
  --border-2:     rgba(0, 0, 0, 0.16);

  --success:      #15803d;
  --error:        #dc2626;

  --case-border:       rgba(20, 22, 26, 0.055);
  --case-shadow:       0 8px 22px -18px rgba(20, 22, 26, 0.10);
  /* A light lift, not a dark drop shadow — bigger and softer than the
     resting state, but the alpha stays low so it reads as the card
     rising off the page rather than a shadow being cast onto it. */
  --case-shadow-hover: 0 24px 48px -20px rgba(20, 22, 26, 0.14);
}

body {
  transition: background-color var(--dur-base) var(--ease), color var(--dur-base) var(--ease);
}


/* ================================================================
   02. RESET & BASE
   ================================================================ */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--text-base);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { cursor: pointer; border: none; background: none; font: inherit; }
ul, ol { list-style: none; }

::selection { background: var(--accent); color: #fff; }

::-webkit-scrollbar { width: 3px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 2px; }


/* ================================================================
   03. LAYOUT
   ================================================================ */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Dot grid for the tinted sections — the hero's lattice at the same
   16px pitch and 1px dot, but drawn as a CSS gradient rather than a
   second canvas, so it costs nothing to run. Deliberately low contrast:
   white dots on the light theme, black on the dark, reading as paper
   texture rather than as a pattern competing with the content. */
:root            { --dot: rgba(0, 0, 0, 0.55); }
body.theme-light { --dot: rgba(255, 255, 255, 0.9); }

.dot-grid {
  background-image: radial-gradient(circle, var(--dot) 1px, transparent 1px);
  background-size: 16px 16px;
}

/* Section label — mono code-block style */
.code-label {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--accent-border);
  padding: 3px 10px;
  border-radius: 3px;
  margin-bottom: 28px;
}

/* Section header row — ↘ Title pattern */
.section-header {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 16px;
}

.section-arrow {
  font-size: var(--text-xl);
  color: var(--accent);
  line-height: 1;
}

.section-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3.5vw, var(--text-3xl));
  font-weight: 300;
  color: var(--text);
  letter-spacing: -0.01em;
  line-height: 1.15;
}

/* Kept as a spacer, not a rule — section titles carry their own weight
   without a line under them. Retains the vertical rhythm the headings
   were built around. */
.section-divider {
  width: 100%;
  height: 0;
  margin-bottom: 56px;
}


/* ================================================================
   04. NAVIGATION
   ================================================================ */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  height: var(--nav-h);
  border-bottom: 1px solid transparent;
  /* background, blur & border-color driven progressively by JS */
}

.nav > .container {
  height: 100%;
}

.nav__inner {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Logo */
.nav__logo img {
  height: 28px;
  width: auto;
}

/* Logo ships as solid white — invert for light theme */
body.theme-light .nav__logo img { filter: invert(1); }

/* Desktop links */
.nav__links {
  display: flex;
  align-items: center;
  gap: 36px;
  list-style: none;
}

.nav__links a {
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  color: var(--text-3);
  position: relative;
  transition: color var(--dur-fast) var(--ease);
}

.nav__links a::after {
  content: '';
  position: absolute;
  bottom: -3px; left: 0; right: 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease);
}

.nav__links a:hover        { color: var(--text); }
.nav__links a:hover::after { transform: scaleX(1); }

/* Keyboard/click feedback — replaces the browser's default focus
   rectangle with something that matches each nav's own hover state. */
.nav__links a:focus-visible {
  outline: none;
  color: var(--text);
}
.nav__links a:focus-visible::after { transform: scaleX(1); }

.nav__mobile a:focus-visible {
  outline: none;
  color: var(--accent);
}

/* Current-page indicator. Covers both mechanisms used across the site:
   .is-current on same-page anchor links styled by hand (case-study
   pages linking back to a homepage section), and aria-current="page"
   on links to an actual separate page (Writing, from blog.html and
   every article under blog/). */
.nav__links a.is-current,
.nav__links a[aria-current="page"],
.nav__mobile a.is-current,
.nav__mobile a[aria-current="page"] {
  color: var(--text-4);
  opacity: 0.55;
}
.nav__links a.is-current::after,
.nav__links a[aria-current="page"]::after {
  display: none;
}

/* Hamburger */
.nav__hamburger {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: 6px;
}

.nav__hamburger span {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--text);
  transition: transform var(--dur-base) var(--ease),
              opacity var(--dur-fast) var(--ease);
}

.nav__hamburger.active span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav__hamburger.active span:nth-child(2) { opacity: 0; transform: scaleX(0); }
.nav__hamburger.active span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* Mobile drawer */
.nav__mobile {
  display: none;
  position: fixed;
  inset: 0;
  top: var(--nav-h);
  background: var(--bg);
  z-index: 99;
  padding: 40px var(--gutter);
  flex-direction: column;
  gap: 0;
}

.nav__mobile.open { display: flex; }

.nav__mobile a {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 300;
  color: var(--text);
  border-bottom: 1px solid var(--border);
  padding-block: 22px;
  transition: color var(--dur-fast);
}

.nav__mobile a:first-child { border-top: 1px solid var(--border); }
.nav__mobile a:hover       { color: var(--accent); }


/* ================================================================
   05. HERO
   ================================================================ */

.hero {
  min-height: 85svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: var(--nav-h);
  padding-bottom: 96px;
  position: relative;
  overflow: hidden;
  background-color: var(--bg);
  background-image: linear-gradient(to bottom, transparent 40%, var(--bg) 100%);
  background-size: 100% 100%;
}

/* Interactive dot grid — canvas-rendered so it can scatter away from the cursor.
   Sits below the veil and content, same layer the old static dot pattern used.
   .section-dots is the same treatment reused on other sections (e.g.
   #ai-projects) so their background reads as one continuous grid with
   the hero's. */
.hero__dots,
.section-dots {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  pointer-events: none;
}

/* Gradient veil over video */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to bottom, rgba(12,12,12,0.4) 0%, transparent 40%, rgba(12,12,12,0.85) 100%),
    radial-gradient(ellipse 65% 55% at 60% 30%, rgba(255,111,3,0.06), transparent 65%);
}

body.theme-light .hero::before {
  background:
    linear-gradient(to bottom, rgba(255,255,255,0.55) 0%, transparent 40%, rgba(255,255,255,0.92) 100%),
    radial-gradient(ellipse 65% 55% at 60% 30%, rgba(52,126,74,0.05), transparent 65%);
}

.hero > .container {
  position: relative;
  z-index: 2;
}

.hero__content {
  max-width: 820px;
  margin-top: 70px;
}

.hero__title {
  font-family: var(--font-display);
  font-size: clamp(52px, 8.5vw, 120px);
  font-weight: 300;
  line-height: 1.03;
  letter-spacing: -0.03em;
  color: var(--text);
  margin-bottom: 28px;
}

.hero__title em {
  font-style: normal;
  color: var(--text-muted);
}

.hero__sub {
  font-size: clamp(var(--text-base), 1.4vw, var(--text-md));
  color: var(--text-3);
  line-height: 1.7;
  max-width: 540px;
  margin-bottom: 40px;
}

.hero__sub strong { color: var(--text-2); font-weight: 500; }

.hero__cta-row {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

/* Buttons */
.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.03em;
  padding: 11px 24px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  border: 1px solid var(--accent);
  transition: background var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.btn-primary:hover {
  background: transparent;
  color: var(--accent);
}

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.03em;
  padding: 11px 24px;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-3);
  border: 1px solid var(--border-2);
  transition: border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.btn-ghost:hover {
  border-color: var(--text-3);
  color: var(--text);
}

.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  padding: 9px 20px;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-3);
  border: 1px solid var(--border-2);
  transition: border-color var(--dur-base), color var(--dur-base);
}

.btn-outline:hover {
  border-color: var(--text-4);
  color: var(--text);
}


/* ================================================================
   06. MARQUEE
   ================================================================ */

.marquee-wrap {
  overflow: hidden;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding-block: 14px;
  background: var(--bg-1);
}

.marquee-track {
  display: flex;
  gap: 0;
  width: max-content;
  animation: marquee 28s linear infinite;
}

.marquee-track:hover { animation-play-state: paused; }

.marquee-item {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  white-space: nowrap;
  padding-inline: 20px;
}

.marquee-item .dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.6;
  display: inline-block;
}


/* ================================================================
   07. STATS
   ================================================================ */

.stats {
  padding-block: 80px;
}

.stats__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* Cells sit on the page colour — the 1px grid gaps supply the ruling,
   so a fill on top of that only muddied it. */
.stat {
  background: var(--bg);
  padding: 36px 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.stat__number {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 5vw, var(--text-4xl));
  font-weight: 300;
  color: var(--text);
  line-height: 1;
  letter-spacing: -0.02em;
}

.stat__desc {
  font-size: var(--text-sm);
  color: var(--text-3);
  line-height: 1.55;
}


/* ================================================================
   08. PROJECTS
   ================================================================ */

.projects {
  padding-block: 96px;
  background: var(--bg);
}

/* Sits on the page colour like every other section — the dot grid and
   the cards' own fill are enough to set it apart without a band. Same
   interactive canvas dot grid as the hero (.section-dots), so the two
   backgrounds read as one continuous treatment. */
#ai-projects {
  background-color: var(--bg);
  position: relative;
  overflow: hidden;
  /* More room than the shared .projects 96px -- the section right after
     it (Experience) switches to a visibly different background, so the
     transition needs more breathing room than a same-colour handoff
     does. Kept symmetric: top and bottom always match. */
  padding-block: 160px;
}

/* Fades the dot grid to the page colour at the top and bottom edges
   of the section (var(--bg), so it fades to white in the light theme
   and to transparent-into-dark in the dark theme) instead of cutting
   the pattern off hard. */
#ai-projects::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom,
    var(--bg) 0%,
    transparent 15%,
    transparent 85%,
    var(--bg) 100%);
}

#ai-projects .container {
  position: relative;
  z-index: 2;
}

.projects__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 0;
}

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

/* ── Case cards ──────────────────────────────────────────
   One project per row, full width. Text leads, image follows on a
   tinted field. No card chrome: the type and the generous spacing do
   the separating, so nothing competes with the work itself. */
.cases {
  display: flex;
  flex-direction: column;
  gap: 104px;
}

.case-card {
  display: block;
  position: relative;
  color: inherit;
}


.case-card__title {
  transition: color var(--dur-base) var(--ease);
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 3vw, 5rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 0.95;
  color: var(--text);
  margin-bottom: 18px;
}

/* Sits directly below the role description and shares its left edge,
   rather than floating up beside the title. */
.case-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.case-card__tag {
  font-family: var(--font-display);
  font-size: 0.75rem;
  letter-spacing: 0;
  text-transform: capitalize;
  color: var(--text-mid);
  border: 1px solid var(--border);
  padding: 4px 12px;
  border-radius: 999px;
  white-space: nowrap;
}

.case-card__role {
  font-size: var(--text-md);
  color: var(--text-4);
  line-height: 1.5;
  max-width: 52ch;
  margin-bottom: 16px;
}


/* The tint is the project's own colour, kept faint so the screenshot
   sits on a field rather than inside a coloured box. */
/* Capped height so a tall screenshot can't run away with the page.
   The preview fills the panel edge to edge and is anchored to the top,
   so the crop takes from the bottom, where screenshots carry the least.
   The hairline and soft shadow are what lift this panel off the page —
   the card around it carries no chrome at all. */
.case-card__media {
  margin-top: 48px;
  height: clamp(260px, 32vw, 450px);
  border: 1px solid var(--case-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--case-shadow);
  overflow: hidden;
  /* Surface is overridable per card: a preview drawn on white needs a
     white panel in both themes, or it floats on a dark field. */
  background: var(--case-surface, var(--bg));
  transition: box-shadow var(--dur-slow) var(--ease),
              border-color var(--dur-base) var(--ease);
}

.case-card:hover .case-card__media {
  box-shadow: var(--case-shadow-hover);
}

/* Diagram previews read better centred with the panel showing through
   than scaled up to fill it. The breathing room is per-card, since how
   much a preview wants depends on how dense it is. */
.case-card__media--inset {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--inset-pad, clamp(20px, 4vw, 56px));
}

.case-card__media--inset .case-card__img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
}

.case-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Hover is carried by the shadow alone — the preview itself is left
   exactly as it is, so nothing about the work shifts under the cursor.
   The title doesn't recolour either: each card sits on its own brand
   colour below it, and the shared accent would clash against some of
   them (a green title over Screenloop's blue, for instance). */


@media (prefers-reduced-motion: reduce) {
  .case-card__img { transition: none; }
}

@media (max-width: 768px) {
  .cases { gap: 72px; }
  .case-card__media { margin-top: 32px; }
}


/* Project card */
/* Sits on the page colour — the hairline alone defines the card, so
   it reads as a frame rather than a filled tile. */
.project-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: border-color var(--dur-base) var(--ease),
              transform var(--dur-slow) var(--ease);
}

.project-card:hover {
  border-color: var(--border-2);
  transform: translateY(-2px);
}

/* Modifier: image-forward vertical card (Selected Projects) — the
   thumb row and body row are forced to equal height so the thumbnail
   never dwarfs the text underneath it. */
.project-card--media {
  padding: 0;
  overflow: hidden;
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 0;
}

.project-card--media:hover { transform: translateY(-4px); }

.project-card__thumb {
  position: relative;
  overflow: hidden;
  background: var(--bg-2);
}

.project-card__thumb::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 90% 70% at 50% 32%, color-mix(in srgb, var(--card-accent, var(--accent)) 24%, transparent), transparent 72%);
  pointer-events: none;
}

/* One-off: thumb has a plain white background — skip the accent tint so it stays true white */
.project-card__thumb--flat::after {
  display: none;
}

/* Theme-aware shade, layered above the image (z-index 2 > image's 1):
   dark overlay in dark mode, light overlay in light mode. Fades away
   on hover to reveal the image at full clarity. */
.project-card__thumb::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.22);
  transition: opacity var(--dur-slow) var(--ease);
}

body.theme-light .project-card__thumb::before { background: rgba(255, 255, 255, 0.14); }

.project-card:hover .project-card__thumb::before { opacity: 0; }

.project-card__img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: block;
  transition: transform var(--dur-slow) var(--ease);
}

.project-card__thumb--cover .project-card__img {
  object-fit: cover;
  object-position: top center;
}

.project-card__thumb--contain .project-card__img {
  object-fit: contain;
  padding: 2%;
}

/* One-off nudge: shift the crop right — stays full-bleed cover, no gaps */
.project-card__thumb--cover .project-card__img--adjust {
  object-position: calc(50% + 110px) center;
}

/* One-off nudge: shift the crop left so the sidebar nav stays in frame */
.project-card__thumb--cover .project-card__img--left {
  object-position: left top;
}

.project-card:hover .project-card__img { transform: scale(1.045); }

.project-card__body {
  padding: 26px 26px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1;
  border-top: 1px solid var(--border);
}


.project-card__name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 300;
  color: var(--text);
  line-height: 1.2;
}

.project-card__desc {
  font-size: var(--text-sm);
  color: var(--text-3);
  line-height: 1.65;
  flex: 1;
}

/* Same outlined control as the case cards, the hero and the
   masterclass, so every "view" action reads as one component.
   `align-self: flex-start` stops it stretching the full card width. */
.project-card__link {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.03em;
  color: var(--text-3);
  padding: 11px 24px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--border-2);
  margin-top: auto;
  transition: border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.project-card:hover .project-card__link {
  color: var(--text);
  border-color: var(--text-3);
}


/* ================================================================
   09. ABOUT
   ================================================================ */

.about {
  padding-block: 96px;
}

.about__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: start;
}

.about__lede {
  font-family: var(--font-display);
  font-size: clamp(var(--text-lg), 2vw, var(--text-xl));
  font-weight: 400;
  color: var(--text);
  line-height: 1.4;
  letter-spacing: -0.005em;
  max-width: 720px;
  margin-bottom: 20px;
}

.about__text {
  font-size: var(--text-md);
  color: var(--text-3);
  line-height: 1.75;
  margin-bottom: 20px;
  max-width: 720px;
}

.about__text strong { color: var(--text-2); font-weight: 500; }

/* Design Mentorship column inside Leading & Coaching: image leads,
   copy follows at the same typographic scale as the lede/text beside it. */
.leading__mentorship .mentorship__card {
  max-width: 400px;
  margin: 0 0 24px;
}

.leading__mentorship .about__lede { margin-top: 0; }

.about__lists {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  gap: 36px;
}

.about__lists > div {
  border-top: 1px solid var(--border);
  padding-top: 20px;
}

.about__list-title {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
  display: block;
}

.about__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  list-style: none;
}

.about__list li {
  font-size: var(--text-sm);
  color: var(--text-3);
  padding-left: 18px;
  position: relative;
}

.about__list li::before {
  content: '→';
  position: absolute;
  left: 0;
  color: var(--text-4);
  font-size: 0.65rem;
  top: 1px;
}


/* ================================================================
   10. EXPERIENCE
   ================================================================ */

.experience {
  padding-block: 96px;
  background: var(--bg-1);
}

.experience__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 0;
}

/* Download CV + Go back sit on one line, Go back always last (rightmost). */
.experience__header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.timeline-item {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 40px;
  padding-block: 36px;
}

/* Rules separate roles, they don't frame the list — so no line above
   the first entry or below the last. */
.timeline-item + .timeline-item { border-top: 1px solid var(--border); }

.timeline-item__period {
  padding-top: 4px;
  flex-shrink: 0;
}

.timeline-item__period span {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-4);
  display: block;
}

.timeline-item__role {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 300;
  color: var(--text);
  margin-bottom: 4px;
  line-height: 1.2;
}

.timeline-item__company {
  font-size: var(--text-sm);
  color: var(--text-3);
  margin-bottom: 4px;
}

.timeline-item__company a {
  color: var(--accent);
  text-decoration: none;
}

.timeline-item__company a:hover {
  text-decoration: underline;
}

.timeline-item__scope {
  font-size: var(--text-sm);
  color: var(--text-4);
  line-height: 1.5;
  margin-bottom: 16px;
}

.timeline-item__bullets {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.timeline-item__bullets li {
  font-size: var(--text-sm);
  color: var(--text-3);
  line-height: 1.65;
  padding-left: 18px;
  position: relative;
}

.timeline-item__bullets li::before {
  content: '—';
  position: absolute;
  left: 0;
  color: var(--text-3);
  font-size: 0.65rem;
  top: 2px;
}


/* ================================================================
   11. MENTORSHIP
   ================================================================ */

.mentorship {
  padding-block: 96px;
}

.mentorship__inner {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 64px;
  align-items: center;
}

.mentorship__title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3vw, var(--text-3xl));
  font-weight: 300;
  color: var(--text);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin-bottom: 20px;
}

.mentorship__text {
  font-size: var(--text-base);
  color: var(--text-3);
  line-height: 1.75;
  margin-bottom: 28px;
}

.mentorship__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.03em;
  padding: 11px 24px;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-3);
  border: 1px solid var(--border-2);
  transition: border-color var(--dur-base), color var(--dur-base);
}

.mentorship__btn:hover {
  border-color: var(--text-3);
  color: var(--text);
}

/* Capped rather than filling its grid column — at full width the card
   outweighed the copy sitting beside it. */
.mentorship__card {
  display: block;
  max-width: 400px;
  margin-left: auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  transition: border-color var(--dur-base);
}

.mentorship__card:hover { border-color: var(--border-2); }

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

/* The masterclass card is a poster only, and isn't a link — no hover lift. */
.mentorship__card--static { cursor: default; }

/* Event details sit with the copy rather than on the poster. Laid out
   as a wrapping row so three short pairs read as one band instead of a
   tall stack pushing the buttons down. */
.mentorship__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 44px;
  margin: 0 0 28px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}

.mentorship__meta dt {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  margin-bottom: 6px;
}

.mentorship__meta dd {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-2);
}

@media (max-width: 480px) {
  .mentorship__meta { gap: 18px 28px; }
}

.mentorship__card-platform {
  display: block;
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  padding: 13px 18px;
  border-top: 1px solid var(--border);
  background: var(--bg-1);
}


/* ================================================================
   12. OTHER PROJECTS / ARCHIVE
   ================================================================ */

.other-projects {
  padding-block: 96px;
  background-color: var(--bg-1);
}

/* Speaking is pulled out of the page's own dark/light cycle and pinned to
   a plain white band, whatever theme the rest of the page is in right
   now -- same token values as the light theme, scoped to this section so
   its cards/links/borders stay legible regardless. */
.speaking-band {
  background-color: #ffffff;
  --bg:            #ffffff;
  --bg-1:          #f6f6f7;
  --bg-2:          #eeeeef;
  --text:          #14161a;
  --text-2:        #3a3d44;
  --text-3:        #55585f;
  --text-4:        #5f6368;
  --accent:        #347e4a;
  --accent-dim:    rgba(52, 126, 74, 0.08);
  --accent-border: rgba(52, 126, 74, 0.25);
  --border:        rgba(0, 0, 0, 0.1);
  --border-2:      rgba(0, 0, 0, 0.16);
}

.other-projects__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin-bottom: 48px;
}

/* Other card */
.other-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: border-color var(--dur-base) var(--ease);
}

.other-card:hover { border-color: var(--border-2); }

.other-card__meta {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.other-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 300;
  color: var(--text);
  line-height: 1.25;
}

.other-card__desc {
  font-size: var(--text-sm);
  color: var(--text-3);
  line-height: 1.65;
  flex: 1;
}

/* Same outlined control as the project cards, so every "view" action
   across the site reads as one component. */
.other-card__link {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.03em;
  color: var(--text-3);
  padding: 11px 24px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--border-2);
  margin-top: 4px;
  transition: border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.other-card__link:hover {
  color: var(--text);
  border-color: var(--text-3);
}

/* Archive list */
.other-projects__archive {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.archive-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding-block: 24px;
}

/* Separators between entries only — the list isn't boxed in. */
.archive-card + .archive-card { border-top: 1px solid var(--border); }

.archive-card__meta {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
  display: block;
}

.archive-card__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 400;
  color: var(--text);
  line-height: 1.25;
}

.archive-card__desc {
  font-size: var(--text-sm);
  color: var(--text-3);
  line-height: 1.65;
  margin-bottom: 4px;
  width: 100%;
  max-width: 680px;
}

/* Entries with two CTAs (e.g. a masterclass + a facilitator profile)
   sit side by side instead of stacking. */
.archive-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 4px;
  width: 100%;
}


/* ================================================================
   13. CONTACT + FORM
   ================================================================ */

.contact {
  padding-block: 96px;
}

.contact__headline {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 6vw, var(--text-5xl));
  font-weight: 300;
  color: var(--text);
  line-height: 1.05;
  letter-spacing: -0.025em;
  margin-bottom: 72px;
  max-width: 860px;
}

.contact__headline em {
  font-style: normal;
  color: var(--text-muted);
}

.contact__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: start;
}

/* Channels */
.contact__channels {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 28px;
}

.contact__channel {
  display: grid;
  grid-template-columns: 110px 1fr 20px;
  align-items: center;
  gap: 20px;
  padding-block: 18px;
  transition: opacity var(--dur-fast);
}

.contact__channel + .contact__channel { border-top: 1px solid var(--border); }
.contact__channel:hover                { opacity: 0.7; }

.contact__channel-label {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-4);
}

.contact__channel-value {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 300;
  color: var(--text);
}

.contact__channel-arrow {
  color: var(--accent);
  font-size: 1.1rem;
}

/* Contact form */
.contact__form {
  display: flex;
  flex-direction: column;
  gap: 24px;
  margin-top: 28px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form-group label {
  font-family: var(--mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
}

.form-group input,
.form-group textarea {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  font-family: var(--font);
  font-size: var(--text-sm);
  color: var(--text);
  outline: none;
  transition: border-color var(--dur-base);
  resize: none;
  width: 100%;
}

.form-group input::placeholder,
.form-group textarea::placeholder {
  color: var(--text-4);
}

.form-group input:focus,
.form-group textarea:focus {
  border-color: var(--accent);
}

.form-group textarea {
  min-height: 140px;
}

.form-message {
  font-size: var(--text-sm);
  color: var(--text-3);
  min-height: 20px;
}

.form-message.success { color: var(--success); }
.form-message.error   { color: var(--error); }

.form-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  padding: 13px 28px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  border: 1px solid var(--accent);
  cursor: pointer;
  transition: background var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
  align-self: flex-start;
}

.form-submit:hover {
  background: transparent;
  color: var(--accent);
}


/* ================================================================
   14. FOOTER
   ================================================================ */

footer {
  background: var(--bg);
  padding-block: 28px;
}

.footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.footer__copy {
  font-family: var(--font);
  font-size: var(--text-xs);
  color: var(--text-4);
}


/* ================================================================
   14b. SHOWCASE
   ================================================================ */

@keyframes showcase-crossfade {
  0%    { opacity: 0; }
  12%   { opacity: 1; }
  28%   { opacity: 1; }
  44%   { opacity: 0; }
  100%  { opacity: 0; }
}

.showcase {
  width: 100%;
  overflow: hidden;
  margin-top: 192px;
  margin-bottom: 192px;
}

.showcase__stage {
  position: relative;
  width: 100%;
  height: 700px;
}

.showcase__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  opacity: 0;
  filter: brightness(0.78);
  will-change: opacity;
  animation: showcase-crossfade 30s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}

/* Stagger: each image offset by 10s (30s ÷ 3), shifted so the fade's
   opacity plateau (now centred at 20% of the cycle) lands on the 0/10/20s marks. */
.showcase__img--1 { animation-delay:  -6s; }
.showcase__img--2 { animation-delay: -26s; }
.showcase__img--3 { animation-delay: -16s; }

/* Dark fade + dense dot grid overlay */
.showcase__stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.38);
}

/* Light theme: lighten the strip so it doesn't read as a jarring dark
   band against the rest of the (now white) page. */
body.theme-light .showcase__img { filter: brightness(0.92); }
body.theme-light .showcase__stage::after { background: rgba(0, 0, 0, 0.2); }

@media (max-width: 768px) {
  .showcase__stage { height: 520px; }
}

@media (max-width: 480px) {
  .showcase__stage { height: 320px; }
}

/* Bento grid variant — a random subset of the showcase pool, reshuffled
   each page load by js/main.js. Overrides the crossfade layout above
   when JS swaps in .showcase__stage--bento.

   "Justified" layout: every column holds one 4:3 tile and one 3:4
   tile. Those ratios sum to the same height in every column (0.75 +
   1.333 of the column width), so the row bottom-aligns on its own
   while each tile keeps a locked aspect ratio — landscape media only
   ever sits in a 4:3 cell, portrait only in a 3:4 cell. Height is
   therefore derived from the column width, not set explicitly. */
.showcase__stage--bento {
  height: auto;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 12px;
  padding: 12px;
  box-sizing: border-box;
  background: transparent;
}

.showcase__stage--bento::after { display: none; }

.showcase__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.showcase__tile {
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  width: 100%;
  background: var(--bg-2);
}

.showcase__tile--wide { aspect-ratio: 4 / 3; }
.showcase__tile--tall { aspect-ratio: 3 / 4; }

/* Entrance sweep — tiles start hidden and rise in once the strip
   scrolls into view, one at a time along the same diagonal order
   (--reveal-i, set per tile in js/main.js) that later drives the
   rotation. Stays hidden indefinitely if JS never adds is-visible
   (see the IntersectionObserver fallback in main.js). */
.showcase__tile {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 900ms var(--ease),
              transform 900ms var(--ease);
  transition-delay: calc(var(--reveal-i, 0) * 130ms);
}

.showcase__stage--bento.is-visible .showcase__tile {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .showcase__tile {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Full-page capture: ~3.8x taller than its 3:4 cell, so cropping it
   leaves a meaningless sliver. It pans its own length once, reading as
   a slow scroll, then hands over to the next image. The 63% travel is
   the overflow beyond the cell, held just short of the bottom edge so
   no gap can appear. */
/* Descendant selector is deliberate: it has to outrank the
   `.showcase__tile img` cover rule above, otherwise the capture gets
   locked to the cell height and there's nothing left to pan. */
.showcase__tile .showcase__scroll {
  width: 100%;
  height: auto;
  object-fit: initial;
  display: block;
  /* Movement only — no opacity anywhere. Fading in meant fading up out
     of the empty cell, which reads as a flash of white before the
     picture lands. The image is simply present and then travels.
     `both` holds the opening frame while the animation waits on the
     image's real dimensions. */
  animation: showcase-pan 16s cubic-bezier(0.45, 0, 0.55, 1) 0.35s 1 both;
}

/* Distance comes from --pan-travel, measured per image in js/main.js
   against its own overflow. The fallback is deliberately shy: better a
   short pan than one that drags empty space into the cell. */
@keyframes showcase-pan {
  from { transform: translateY(0); }
  to   { transform: translateY(var(--pan-travel, -40%)); }
}

@media (prefers-reduced-motion: reduce) {
  .showcase__tile .showcase__scroll { animation: none; }
}

.showcase__tile img,
.showcase__tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.showcase__tile--top img,
.showcase__tile--top video { object-position: top; }

/* Theme-aware shade: dark overlay in dark mode, light overlay in
   light mode — replaces raw brightness filtering so the tone matches
   the surrounding page instead of just flattening the photo. */
.showcase__tile::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.3);
}

body.theme-light .showcase__tile::after { background: rgba(255, 255, 255, 0.16); }

/* Responsive: js/main.js drops a column at each breakpoint (4 → 3 → 2)
   rather than reshaping tiles, so the aspect ratios hold at every size.
   Stage height follows from the column width, so these rules only need
   to tune the gutters. */
@media (max-width: 900px) {
  .showcase__stage--bento {
    gap: 10px;
    padding: 10px;
  }
  .showcase__col { gap: 10px; }
}

@media (max-width: 480px) {
  .showcase__stage--bento {
    gap: 8px;
    padding: 8px;
  }
  .showcase__col { gap: 8px; }
  .showcase__tile { border-radius: 10px; }
}

/* ================================================================
   15. UTILITIES & ANIMATIONS
   ================================================================ */

/* Reveal on scroll */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
}

.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

/* Staggered children */
.stagger > .reveal:nth-child(1)  { transition-delay: 0ms; }
.stagger > .reveal:nth-child(2)  { transition-delay: 80ms; }
.stagger > .reveal:nth-child(3)  { transition-delay: 160ms; }
.stagger > .reveal:nth-child(4)  { transition-delay: 240ms; }
.stagger > .reveal:nth-child(5)  { transition-delay: 320ms; }
.stagger > .reveal:nth-child(6)  { transition-delay: 400ms; }

/* Keyframes */
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes pulse {
  0%, 100% { opacity: 1;   transform: scale(1);   }
  50%       { opacity: 0.3; transform: scale(0.65); }
}

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


/* ================================================================
   16. RESPONSIVE
   ================================================================ */

@media (max-width: 1024px) {
  .about__inner     { grid-template-columns: 1fr; gap: 48px; }
  .about__lists     { grid-template-columns: 1fr; }
  .mentorship__inner{ grid-template-columns: 1fr; }
  .mentorship__card { margin-left: 0; margin-right: auto; }
  .contact__inner   { grid-template-columns: 1fr; gap: 48px; }
}

@media (max-width: 900px) {
  .stats__grid    { grid-template-columns: repeat(2, 1fr); }
  .projects__grid { grid-template-columns: repeat(2, 1fr); }
  .other-projects__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  :root { --nav-h: 70px; }

  .nav__links     { display: none; }
  .nav__hamburger { display: flex; }

  .hero__title  { font-size: clamp(40px, 10.5vw, 72px); }
  .hero         { padding-bottom: 64px; }

  .stats    { padding-block: 56px; }
  .projects,
  .about,
  .experience,
  .mentorship,
  .other-projects,
  .contact  { padding-block: 72px; }
  #ai-projects { padding-block: 112px; }

  .stats__grid    { grid-template-columns: repeat(2, 1fr); }
  .projects__grid { grid-template-columns: 1fr; }

  .timeline-item {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .other-projects__grid { grid-template-columns: 1fr; }

  .contact__channel {
    grid-template-columns: 90px 1fr 20px;
    gap: 14px;
  }

  .contact__channel-value { font-size: var(--text-base); }

  .footer__inner { flex-direction: column; align-items: flex-start; gap: 12px; }

  .experience__header { flex-direction: column; gap: 16px; }
}

@media (max-width: 480px) {
  .hero__title { font-size: clamp(36px, 11vw, 54px); }
  .stats__grid { grid-template-columns: 1fr 1fr; }
  .contact__headline { font-size: clamp(var(--text-2xl), 8vw, var(--text-3xl)); }
}
