/* =========================================================================
   STYLE — reset, base, components.
   Tokens (tokens.css) and @font-face (fonts.css) load BEFORE this file.
   ========================================================================= */

/* ---------- Reset ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

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

body,
h1, h2, h3, h4, p, figure, blockquote, ul, ol,
dl, dt, dd {
  margin: 0;
}

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

a { color: inherit; text-decoration: none; }

/* ---------- Base ---------- */
body {
  background: var(--color-base);
  color: var(--color-text);
  font-family: var(--font-body);
  font-weight: var(--weight-regular);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Visible focus for keyboard users (accessibility). */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Centred content wrapper. */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: var(--page-padding);
}

/* Small reusable mono label, always in accent navy. */
.mono {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

/* =========================================================================
   NAV  (shared component, injected by js/nav.js)
   Default state: full-width pill flush at the top. Scrolled state: compact
   floating pill (toggled by js/motion.js adding .is-scrolled).
   ========================================================================= */
.nav {
  position: fixed;          /* stays sticky as the user scrolls */
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  padding: var(--space-sm) var(--page-padding) 0;
  transition: padding 0.4s var(--ease-soft);
}

.nav__pill {
  width: 100%;
  max-width: var(--max-width);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: 12px 16px 12px 20px;
  background: var(--color-base);
  border: var(--border-hairline);
  border-radius: 999px;
  /* Morph properties animate between default and compact states. */
  transition: max-width 0.4s var(--ease-soft),
              padding 0.4s var(--ease-soft),
              box-shadow 0.4s var(--ease-soft);
}

/* Compact floating pill on scroll. */
.nav.is-scrolled { padding-top: var(--space-sm); }

.nav.is-scrolled .nav__pill {
  max-width: 760px;
  padding: 10px 14px 10px 18px;
  box-shadow: 0 8px 30px rgba(11, 11, 11, 0.08);
}

.nav__logo {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(var(--space-sm), 2vw, var(--space-lg));
}

.nav__link {
  font-family: var(--font-body);
  font-weight: var(--weight-medium);
  font-size: var(--text-label);
  color: var(--color-text);
  transition: color 0.2s ease;
}

.nav__link:hover,
.nav__link.is-active { color: var(--color-accent); }

/* Mobile menu toggle — hidden on desktop, shown in the responsive pass. */
.nav__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 28px;
  height: 28px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}

.nav__toggle span {
  display: block;
  height: 1.5px;
  width: 20px;
  margin-inline: auto;
  background: var(--color-text);
  transition: transform 0.3s var(--ease-soft), opacity 0.2s ease;
}

/* =========================================================================
   HERO  (homepage)  — 100vh, oversized stacked title left, aside top-right.
   ========================================================================= */
.hero {
  min-height: 100vh;
  display: flex;
  align-items: center;
  position: relative;
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 46%);  /* intro left, venn right */
  align-items: center;
  gap: var(--space-2xl);
  width: 100%;
  padding-block: var(--space-3xl) var(--space-2xl);
  margin-top: var(--space-2xl);   /* nudge hero content below true centre */
}

.hero__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
}

.hero__title span { display: block; }   /* stack the lines */

/* Left column: title with catchphrase + contact rows stacked below it. */
.hero__intro {
  max-width: 440px;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.hero__intro .hero__title { margin-bottom: var(--space-xs); }

.hero__catch {
  color: var(--color-text-secondary);
  font-size: var(--text-body);
  line-height: var(--leading-snug);
}

/* Contact rows: mono label left, link right, hairline dividers between rows. */
.hero__contact {
  list-style: none;
  margin-top: var(--space-sm);
  padding: 0;
}

.hero__contact li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block: 10px;
  border-top: 0.5px solid var(--color-surface-dark, #DCDCD8);
}

.hero__contact li:last-child {
  border-bottom: 0.5px solid var(--color-surface-dark, #DCDCD8);
}

.hero__contact-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.hero__email {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

.hero__email:hover { text-decoration: underline; text-underline-offset: 3px; }

.hero__scroll-cue {
  position: absolute;
  left: var(--space-lg, 32px);
  bottom: var(--space-lg, 32px);
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-text-secondary);
  animation: hero-scroll-cue-bounce 2s ease-in-out infinite;
}

@keyframes hero-scroll-cue-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}

/* =========================================================================
   FEATURED WORK  — checkerboard, one 100vh panel per project.
   Alternating: text-left/photo-right  →  photo-left/text-right  → repeat.
   (Static for now. Scroll-snap is added in the motion phase.)
   ========================================================================= */
.work {
  border-top: var(--border-hairline);
}

.panel {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: var(--border-hairline);
}

/* Text tile. Project copy anchors to the BOTTOM of the tile. */
.panel__text {
  order: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-2xl) var(--page-padding);
  background: var(--color-base);
}

.panel__num {
  font-family: var(--font-mono);
  font-size: var(--text-mono-lg);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
  margin-bottom: var(--space-sm);
}

.panel__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-display);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
}

.panel__title a { transition: color 0.2s ease; }
.panel__title a:hover { color: var(--color-accent); }

.panel__body {
  margin-top: var(--space-lg);
  font-family: var(--font-body);
  font-size: var(--text-body);
  color: var(--color-text);
  line-height: 1.65;
  max-width: 480px;
}

.panel__desc {
  margin-top: var(--space-sm);
  max-width: 38ch;
  color: var(--color-text-secondary);
}

/* Photo tile. Solid surface placeholder until real assets land.
   overflow:hidden + inner element gives us the subtle hover scale. */
.panel__media {
  order: 2;
  position: relative;
  overflow: hidden;
  background: var(--color-surface);
}

.panel__media-link {
  display: block;
  width: 100%;
  height: 100%;
}

.panel__media-inner {
  width: 100%;
  height: 100%;
  min-height: 50vh;
  background: var(--color-surface);   /* placeholder fill (#E9E9E6) */
  transition: transform var(--dur-slow) var(--ease-soft);
}

.panel__media-link:hover .panel__media-inner { transform: scale(1.03); }

img.panel__media-inner {
  object-fit: cover;
  display: block;
}

/* Product renders shown in full — no crop. White fill blends with the
   renders' own white backgrounds. */
img.panel__media-inner--contain {
  object-fit: contain;
  background: #fff;
}

/* Reverse panels: photo left, text right. */
.panel--reverse .panel__text  { order: 2; }
.panel--reverse .panel__media { order: 1; }

/* =========================================================================
   HOMEPAGE GSAP SNAP
   body.is-home locks native scroll; .snap-container slides via gsap.to(y).
   Each .snap-panel is exactly 100vh so the translate offset is always a
   clean multiple of the viewport height.
   ========================================================================= */
body.is-home {
  overflow: hidden;
}

.snap-container {
  /* Sits at the top of the stacking context. GSAP animates translateY. */
  will-change: transform;
}

.snap-panel {
  height: 100vh;
  overflow: hidden;   /* clips content that would otherwise spill below 100vh */
}

/* =========================================================================
   PAGE STUB  — placeholder routes (Step 1 skeleton only).
   ========================================================================= */
.page-stub {
  min-height: 70vh;
  display: flex;
  align-items: center;
  padding-block: var(--space-3xl);
}

.page-stub h1 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-display);
}

.page-stub p {
  color: var(--color-text-secondary);
  margin-top: var(--space-sm);
}

/* =========================================================================
   CASE STUDY  — shared template for all four project pages.
   One set of classes; each page reuses the same structure with its own copy.
   Layout rhythm: padded .container sections interleaved with full-bleed media.
   ========================================================================= */

/* ---- Hero block (number, title, descriptor, metadata strip) ---- */
.cs-hero {
  /* Generous top padding clears the absolutely-positioned nav pill. */
  padding-top: clamp(120px, 16vh, 180px);
  padding-bottom: var(--space-xl);
}

.cs-hero__num {
  font-family: var(--font-mono);
  font-size: var(--text-mono-lg);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

.cs-hero__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  margin-top: var(--space-sm);
}

.cs-hero__desc {
  margin-top: var(--space-sm);
  font-size: var(--text-mono-lg);
  color: var(--color-text-secondary);
  max-width: 48ch;
}

/* Metadata strip: Role · Context · Year · Type.
   Tiny General Sans labels (muted) over Space Mono values (navy, per the
   "mono is always accent" rule). */
.cs-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg) var(--space-2xl);
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: var(--border-hairline);
}

.cs-meta__item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cs-meta__label {
  font-family: var(--font-body);
  font-weight: var(--weight-medium);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.cs-meta__value {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

/* ---- Full-bleed hero image (16:9, edge to edge, no margin) ---- */
.cs-hero-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--color-surface);   /* placeholder fill (#E9E9E6) */
}

/* ---- Intro paragraph (the punchy "so what") ---- */
.cs-intro {
  max-width: 640px;
  font-size: var(--text-mono-lg);     /* slightly larger than body for emphasis */
  line-height: var(--leading-snug);
  padding-block: var(--space-2xl);
}

/* ---- Content blocks (alternating layouts) ---- */
.cs-blocks {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
  padding-bottom: var(--space-3xl);
}

.cs-block__label {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
  margin-bottom: var(--space-sm);
}

.cs-block__heading {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-heading);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
}

.cs-block__body {
  margin-top: var(--space-md);
  color: var(--color-text-secondary);
}

.cs-block__body + .cs-block__body { margin-top: var(--space-md); }

.cs-block__quote {
  margin-top: var(--space-lg);
  padding-left: var(--space-md);
  border-left: 2px solid var(--color-accent);
  font-style: italic;
  color: var(--color-text-secondary);
  font-size: var(--text-body);
}

/* Ensure real images inside cs-hero-media fill the container */
.cs-hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Detail image: contained within the content column, freeform ratio. */
.cs-img {
  display: block;
  width: 100%;
  background: var(--color-surface);   /* placeholder fill (#E9E9E6) */
}

/* Variant A — full-width: text above, full-column image below. */
.cs-block--full .cs-block__text { max-width: 720px; }
.cs-block--full .cs-img {
  margin-top: var(--space-xl);
  aspect-ratio: 16 / 9;
}

/* Variant B — split: text + image side by side. */
.cs-block--split,
.cs-block--split-reverse {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2xl);
  align-items: center;
}

.cs-block--split .cs-img,
.cs-block--split-reverse .cs-img { aspect-ratio: 4 / 3; }

/* Variant C — split reverse: image first (left), text right. */
.cs-block--split-reverse .cs-block__text  { order: 2; }
.cs-block--split-reverse .cs-block__media { order: 1; }

/* ---- Next project strip (minimal footer row) ---- */
.cs-next {
  display: block;
  border-top: var(--border-hairline);
}

.cs-next__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  padding-block: var(--space-2xl);
}

.cs-next__label {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
  margin-bottom: var(--space-xs);
}

.cs-next__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-display);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
  transition: color 0.2s ease;
}

.cs-next__arrow {
  font-family: var(--font-display);
  font-size: var(--text-display);
  color: var(--color-text);
  transition: transform var(--dur-slow) var(--ease-soft), color 0.2s ease;
}

.cs-next:hover .cs-next__title { color: var(--color-accent); }
.cs-next:hover .cs-next__arrow {
  color: var(--color-accent);
  transform: translateX(12px);
}

/* =========================================================================
   PROJECTS INDEX  — header + filter bar + two-column card grid.
   ========================================================================= */
.projects {
  /* Clear the absolutely-positioned nav pill. */
  padding-top: clamp(120px, 16vh, 180px);
  padding-bottom: var(--space-3xl);
}

/* ---- Header: title left, meta + filter right ---- */
.projects-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-lg);
  padding-bottom: var(--space-lg);
  border-bottom: var(--border-hairline);
}

.projects-header__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
}

.projects-header__side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-md);
  text-align: right;
}

.projects-header__meta {
  display: flex;
  gap: var(--space-lg);
}

/* Filter bar */
.filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
}

.filter__btn {
  font-family: var(--font-body);
  font-weight: var(--weight-medium);
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color 0.2s ease;
}

.filter__btn:hover { color: var(--color-text); }

.filter__btn.is-active { color: var(--color-accent); }

/* ---- Card grid (two columns, scales gracefully) ---- */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
  margin-top: var(--space-2xl);
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--color-base);
  border: var(--border-hairline);
  transition: background-color 0.25s ease;
}

.card:hover { background: var(--color-hover); }   /* subtle background shift */

/* Thumbnail: fixed height, object-fit cover, number overlaid top-left. */
.card__media {
  position: relative;
  height: clamp(220px, 26vw, 320px);
  overflow: hidden;
  background: var(--color-surface);
}

.card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--color-surface);   /* placeholder fill (#E9E9E6) */
}

/* Keep the top of the artwork in frame (e.g. banner text). */
.card__img--top { object-position: center top; }

/* Product renders shown in full — no crop. */
.card__img--contain {
  object-fit: contain;
  background: #fff;
}

.card__num {
  position: absolute;
  top: var(--space-md);
  left: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-mono-lg);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

.card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--space-lg);
}

.card__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-heading);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
}

.card__desc {
  margin-top: var(--space-xs);
  color: var(--color-text-secondary);
}

.card__footer {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

.card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  list-style: none;
  padding: 0;
}

.card__tags li {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

/* Arrow: hidden until the card is hovered/focused. */
.card__arrow {
  font-family: var(--font-display);
  font-size: var(--text-heading);
  line-height: 1;
  color: var(--color-text);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 0.2s ease, transform 0.2s var(--ease-soft);
}

.card:hover .card__arrow,
.card:focus-visible .card__arrow {
  opacity: 1;
  transform: translateX(0);
}

/* =========================================================================
   ABOUT
   ========================================================================= */
/* Full-bleed portrait at top (nav sits over it, like the homepage hero). */
.about-portrait {
  width: 100%;
  height: clamp(320px, 60vh, 640px);
  overflow: hidden;
}

.about-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  display: block;
}

.about-intro {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-2xl);
  align-items: start;
  padding-top: calc(var(--space-3xl) + 48px);
  padding-bottom: var(--space-3xl);
}

.about-intro__content { min-width: 0; }

/* Opening statement, larger and set in the display face. */
.about-intro__lead {
  max-width: 18ch;
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-display);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-xl);
}

.about-intro__body { max-width: 560px; }

.about-intro__body p { color: var(--color-text-secondary); }
.about-intro__body p + p { margin-top: var(--space-md); }

.about-intro__image {
  width: clamp(220px, 28vw, 380px);
  flex-shrink: 0;
}

.about-intro__image img {
  width: 100%;
  height: auto;
  display: block;
  object-fit: cover;
}

/* Skills / education strip — highlights only, not a full CV. */
.about-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2xl);
  padding-block: var(--space-2xl);
  border-top: var(--border-hairline);
}

.about-strip__label {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
  margin-bottom: var(--space-md);
}

.about-strip__list { list-style: none; padding: 0; }

.about-strip__list li { padding-block: var(--space-xs); }
.about-strip__list li + li { border-top: var(--border-hairline); }

.about-strip__list small {
  display: block;
  font-size: var(--text-mono);
  color: var(--color-text-secondary);
}

/* =========================================================================
   CONTACT
   ========================================================================= */
.contact {
  padding-top: clamp(140px, 24vh, 280px);
  padding-bottom: var(--space-3xl);
}

.contact__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
}

.contact__line {
  max-width: 42ch;
  margin-top: var(--space-md);
  font-size: var(--text-mono-lg);
  color: var(--color-text-secondary);
}

.contact__links {
  list-style: none;
  padding: 0;
  margin-top: var(--space-2xl);
  border-top: var(--border-hairline);
}

.contact__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
  padding-block: var(--space-lg);
  border-bottom: var(--border-hairline);
}

.contact__link-label {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
  flex-shrink: 0;
}

.contact__link-value {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-heading);
  letter-spacing: -0.01em;
  text-align: right;
  transition: color 0.2s ease;
}

.contact__link:hover .contact__link-value { color: var(--color-accent); }

/* =========================================================================
   PLAYGROUND  — masonry grid (CSS multi-column). Sketchbook feel, no
   enforced uniformity; each tile carries its own aspect ratio.
   ========================================================================= */
.playground {
  padding-top: clamp(120px, 16vh, 180px);
  padding-bottom: var(--space-3xl);
}

.playground-header__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  max-width: 16ch;
}

.masonry {
  columns: 3;
  column-gap: var(--space-lg);
  margin-top: var(--space-2xl);
}

.masonry__item {
  break-inside: avoid;
  margin-bottom: var(--space-2xl);
}

.masonry__media {
  width: 100%;
  background: var(--color-surface);   /* placeholder fill (#E9E9E6) */
  margin-bottom: var(--space-md);
}

/* Varied tile ratios — the "no enforced uniformity" sketchbook feel. */
.masonry__media--tall   { aspect-ratio: 3 / 4; }
.masonry__media--wide   { aspect-ratio: 4 / 3; }
.masonry__media--square { aspect-ratio: 1 / 1; }
.masonry__media--phone  { aspect-ratio: 9 / 16; }   /* app screenshots */

/* Tiles with a real visual: the link wraps the whole card, the image fills
   the media box and gets the same slow hover scale as homepage panels. */
.masonry__link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.masonry__media { overflow: hidden; }

.masonry__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
  transition: transform var(--dur-slow) var(--ease-soft);
}

.masonry__link:hover .masonry__media img { transform: scale(1.03); }
.masonry__link:hover .masonry__title { color: var(--color-accent); }

.masonry__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-heading);
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
}

.masonry__note {
  margin-top: var(--space-xs);
  color: var(--color-text-secondary);
}

/* =========================================================================
   ENGINES  — "3 engines" Venn diagram page (standalone for now; designed to
   drop into the homepage later). Circles are HTML so the type stays crisp
   and each engine can become interactive in the motion phase; the outer
   flow loop is an SVG sharing the container's 760×700 coordinate space.
   ========================================================================= */
.engines {
  padding-top: clamp(120px, 16vh, 180px);
  padding-bottom: var(--space-3xl);
}

.engines-header__kicker {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: var(--space-sm);
}

.engines-header__title {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
}

.engines-header__lede {
  margin-top: var(--space-md);
  max-width: 560px;
  color: var(--color-text-secondary);
  line-height: var(--leading-body);
}

/* ---------- Diagram container: 760×700 coordinate space ---------- */
.engines-venn {
  position: relative;
  max-width: 760px;
  margin: var(--space-2xl) auto 0;
  aspect-ratio: 760 / 700;
}

.engines-venn__loop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--color-text-secondary);
}

/* Dotted construction-line style for the loop arcs. Scoped to the <g> so
   the arrowhead paths inside <defs>/<marker> stay solid. */
.engines-venn__loop g path {
  stroke-dasharray: 2 5;
  stroke-linecap: round;
}

/* ---------- The three circles ---------- */
/* Each circle is 320/760 of the container wide and carries its own muted
   tint; multiply lets the fills genuinely mix where the circles overlap. */
.engine {
  position: absolute;
  width: 42.105%;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  mix-blend-mode: multiply;
  container-type: inline-size;             /* type scales with the circle */
}

/* Centres form an equilateral triangle around the container midpoint. */
.engine--bd { left: 28.947%; top: 8%;      background: rgba(30, 58, 95, 0.14); }   /* navy — top   (380, 216) */
.engine--id { left: 13.684%; top: 36.714%; background: rgba(166, 92, 51, 0.13); }  /* clay — left  (264, 417) */
.engine--ai { left: 44.211%; top: 36.714%; background: rgba(116, 134, 108, 0.16); }/* sage — right (496, 417) */

/* Text sits toward the outer edge of each circle, clear of the overlaps.
   The two lower blocks centre on the same optical line (55% of the circle),
   mirrored left/right, so they read as a matched pair. */
.engine__text {
  position: absolute;
  width: 68%;
  text-align: center;
  transform: translateX(-50%);
}

.engine--bd .engine__text { left: 50%; top: 25%; }
.engine--id .engine__text { left: 42%; top: 55%; width: 46%; transform: translate(-50%, -50%); } /* narrower so the label wraps */
.engine--ai .engine__text { left: 58%; top: 55%; transform: translate(-50%, -50%); }

.engine__label {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: clamp(1rem, 0.8rem + 0.9vw, 1.375rem);   /* fallback: 16 → 22px */
  font-size: clamp(0.9rem, 6.9cqw, 1.375rem);         /* ~7% of circle width */
  line-height: var(--leading-snug);
  letter-spacing: -0.01em;
}

.engine__skills {
  list-style: none;
  padding: 0;
  margin-top: var(--space-xs);
  color: var(--color-text-secondary);
  font-size: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); /* fallback: 12 → 14px */
  font-size: clamp(0.72rem, 4.4cqw, 0.875rem);          /* ~4.4% of circle width */
  line-height: 1.5;
}

/* ---------- The RE core — round white badge over the mixing tints ---------- */
/* Fixed equal width/height keeps it a true circle at every viewport. */
.engines-venn__core {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 58px;
  height: 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-base);
  border: var(--border-hairline);
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: var(--text-mono-lg);
  letter-spacing: var(--tracking-mono);
  color: var(--color-accent);
}

/* ---------- Arrow down to the Solution endpoint ---------- */
.engines-flow {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  margin-top: var(--space-md);
}

.engines-flow__arrow { color: var(--color-text-secondary); }

.engines-flow__pill {
  border: 1px solid var(--color-text);
  border-radius: 8px;
  padding: 10px 56px;
  font-size: var(--text-label);
  letter-spacing: 0.02em;
}

/* ---------- Hero variant (homepage) ---------- */
/* Compact venn for the hero's right column: same circles, labels + RE core
   only — no loop, no skills. The container is a tight box around the
   circles (568×537 in the 760×700 space), so there's no dead margin. */
.engines-venn--hero {
  margin: 0;
  max-width: 560px;
  aspect-ratio: 568 / 537;
}

.engines-venn--hero .engine { width: 56.338%; }          /* 320 / 568 */
.engines-venn--hero .engine--bd { left: 21.83%; top: 1.49%; }
.engines-venn--hero .engine--id { left: 1.41%;  top: 38.92%; }
.engines-venn--hero .engine--ai { left: 42.25%; top: 38.92%; }

/* No skills list in the hero, so each label sits at its circle's centre;
   the narrow width wraps two-word labels to two lines like the wireframe. */
.engines-venn--hero .engine .engine__text {
  left: 50%;
  top: 50%;
  width: 52%;
  transform: translate(-50%, -50%);
}

.engines-venn--hero .engines-venn__core { top: 56.24%; } /* Venn centroid */

/* ---------- Small screens: vertical chain of overlapping circles ---------- */
/* The triangular Venn gets too cramped below ~600px, so the circles stack
   into a vertical chain (still overlapping) and the loop + core hide. */
@media (max-width: 600px) {
  .engines-venn {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .engines-venn__loop,
  .engines-venn__core { display: none; }

  .engine {
    position: static;
    width: min(72vw, 300px);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .engine + .engine { margin-top: -14%; }   /* keep the circles linked */

  /* .engine .engine__text matches the specificity of the per-circle
     desktop offsets above so the stacked layout wins on small screens. */
  .engine .engine__text {
    position: static;
    transform: none;
    width: auto;
    padding: 0 14%;
  }
}

/* =========================================================================
   RESPONSIVE  — minimal collapse so nothing breaks on small screens.
   (A full responsive pass is a later build step.)
   ========================================================================= */
@media (max-width: 768px) {
  .hero__inner {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }

  /* The hero is a fixed 100vh snap panel — the venn doesn't fit under the
     intro on small screens, so it lives on /engines.html only there. */
  .hero__venn { display: none; }

  .nav__links { gap: var(--space-sm); }

  /* Stack each checkerboard panel: text above, media below. */
  .panel,
  .panel--reverse {
    grid-template-columns: 1fr;
    min-height: auto;
  }

  .panel__text,
  .panel--reverse .panel__text { order: 1; padding-block: var(--space-xl); }

  .panel__media,
  .panel--reverse .panel__media { order: 2; }

  .panel__media-inner { min-height: 56vw; }

  /* Case study: split blocks stack to a single column. */
  .cs-block--split,
  .cs-block--split-reverse {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }

  /* When stacked, keep image below text for the reverse variant too. */
  .cs-block--split-reverse .cs-block__text  { order: 1; }
  .cs-block--split-reverse .cs-block__media { order: 2; }

  .cs-next__title,
  .cs-next__arrow { font-size: var(--text-heading); }

  /* Projects index: single-column grid, header stacks to the left. */
  .projects-grid { grid-template-columns: 1fr; }

  .projects-header__side {
    align-items: flex-start;
    text-align: left;
  }

  /* About: skills/education strip stacks. */
  .about-strip {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
}

/* ---- Masonry column reductions ---- */
@media (max-width: 960px) {
  .masonry { columns: 2; }
}

@media (max-width: 600px) {
  .masonry { columns: 1; }
}

/* =========================================================================
   MOBILE NAV  — hamburger toggle + collapsible menu.
   Below 640px the inline links are replaced by a toggle that drops the
   links down inside the pill.
   ========================================================================= */
@media (max-width: 640px) {
  /* gap:0 so the collapsed links row adds no height; open spacing comes from
     the links' own padding-top. */
  .nav__pill { flex-wrap: wrap; gap: 0; border-radius: 22px; }

  .nav.is-scrolled .nav__pill { border-radius: 22px; }

  .nav__logo  { order: 1; }
  .nav__toggle { display: flex; order: 2; }

  .nav__links {
    order: 3;
    flex-basis: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-sm);
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.3s var(--ease-soft),
                opacity 0.2s ease,
                padding 0.3s var(--ease-soft);
  }

  .nav__links.is-open {
    max-height: 320px;
    opacity: 1;
    padding-top: var(--space-md);
  }

  /* Hamburger → X when open. */
  .nav__toggle.is-open span:first-child { transform: translateY(2.75px) rotate(45deg); }
  .nav__toggle.is-open span:last-child  { transform: translateY(-2.75px) rotate(-45deg); }
}

/* =========================================================================
   SMALL-SCREEN POLISH  — title sizing and row stacking below 600px.
   ========================================================================= */
@media (max-width: 600px) {
  .hero__title,
  .cs-hero__title,
  .contact__title,
  .projects-header__title,
  .playground-header__title {
    font-size: clamp(2rem, 8.5vw, 2.5rem);
  }

  /* Contact rows: stack label over value, left-aligned. */
  .contact__link {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
  }

  .contact__link-value {
    text-align: left;
    font-size: var(--text-heading);
    overflow-wrap: anywhere;
  }
}
