/* ---------- Fonts ---------- */
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('fonts/PPNeueMontreal-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('fonts/PPNeueMontreal-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  --bg-base: #ffffff;
  --text-primary: #1c1c1c;
  --text-muted: #52525b;
  --card-placeholder: #ececec;

  --margin-main: 20px;
  --column-gap: 10px;
  --card-gap: 6px;
  --wrapper-pad-bottom: 40px;

  --label-lg: 16px;
  --body-font: 'PP Neue Montreal', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  color-scheme: light;
}

:root[data-theme='dark'] {
  --bg-base: #191919;
  --text-primary: #f2f2f2;
  --text-muted: #a1a1aa;
  --card-placeholder: #2c2c30;
  color-scheme: dark;
}

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

html, body { margin: 0; padding: 0; }
[hidden] { display: none !important; }

body {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: var(--body-font);
  font-size: var(--label-lg);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.01em;
  /* Crisp type */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
  font-feature-settings: 'kern' 1, 'liga' 1;
  font-synthesis: none;
  -webkit-text-size-adjust: 100%;
  transition: background-color 0.4s ease, color 0.4s ease;
}

p { margin: 0; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

/* ---------- Header ---------- */
.site-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--margin-main);
  flex: 0 0 auto;
}

.brand { max-width: 243px; }
.brand__link { white-space: nowrap; }
/* Tagline alternates between two lines: a clipped one-line window with a sliding track (main.js) */
.brand__tagline { height: 1.4em; overflow: hidden; }
.brand__swap { display: block; }
.brand__swap > span { display: block; white-space: nowrap; }
.brand__name { font-weight: 500; color: var(--text-primary); }
.brand__tagline { color: var(--text-muted); }

.nav {
  display: flex;
  align-items: center;
  gap: 12px;
}

.nav__item {
  color: var(--text-primary);
  white-space: nowrap;
}

/* ---------- Rolling text links (brand + nav) ----------
   Two copies of the label stacked in a clipped box; on hover each letter slides up one
   line, staggered left → right, so the second copy rolls in. Letters are split by main.js. */
.roll {
  position: relative;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: top;
}
.roll__text { display: block; }
.roll__word { display: inline-block; white-space: nowrap; }
.roll__text--clone { position: absolute; left: 0; top: 100%; }
.roll {
  --roll-step: 16ms;   /* per-letter stagger */
  --roll-dur: 0.55s;
}
.roll .char {
  display: inline-block;
  white-space: pre;
  transition: transform var(--roll-dur) cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: calc(var(--i) * var(--roll-step));
}
/* The brand name is 31 characters, so it gets a tighter stagger to finish in a similar time */
.brand__link.roll { --roll-step: 7ms; --roll-dur: 0.45s; }
.roll:hover .char,
.roll:focus-visible .char { transform: translateY(-100%); }
@media (hover: none) { .roll .char { transition: none; } }

.theme-toggle {
  position: relative;
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  color: var(--text-primary);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.theme-toggle__icon {
  grid-area: 1 / 1;
  width: 16px;
  height: 16px;
  transition: opacity 0.3s ease, transform 0.45s var(--ease-out);
}
.theme-toggle__icon--sun { opacity: 0; transform: rotate(-90deg) scale(0.6); }
:root[data-theme='dark'] .theme-toggle__icon--moon { opacity: 0; transform: rotate(90deg) scale(0.6); }
:root[data-theme='dark'] .theme-toggle__icon--sun { opacity: 1; transform: rotate(0deg) scale(1); }

/* ---------- Project cards ---------- */
.project-wrapper {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 var(--margin-main) var(--wrapper-pad-bottom);
}

.project-container {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--column-gap);
  width: 100%;
}

.project-card {
  flex: 1 0 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--card-gap);
  will-change: transform;
}

.project-card__media {
  position: relative;
  width: 100%;
  aspect-ratio: 6 / 8;
  border-radius: 4px;
  overflow: hidden;
  background: var(--card-placeholder);
}
.project-card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease-out);
}
/* Card hover effects: pointer devices only. On touch screens :hover sticks after a tap,
   which left cards dimmed/zoomed, so none of this applies there. */
@media (hover: hover) and (pointer: fine) {
  .project-card:hover .project-card__media img { transform: scale(1.03); }

  /* Dim every other card (image + text) to 50%, keep the hovered one at 100%.
     Only enabled once the intro has finished so the transition doesn't fight GSAP. */
  .intro-done .project-card { transition: opacity 0.4s ease; }
  .intro-done .project-container:has(.project-card:hover) .project-card:not(:hover) { opacity: 0.5; }
}

.project-card--draft { cursor: default; }

.project-card__name { font-weight: 500; color: var(--text-primary); }
.project-card__info { color: var(--text-muted); }
.project-card__row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.project-card__index { display: none; font-weight: 500; color: var(--text-primary); }

/* ---------- Project page ---------- */
.project-page {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--margin-main);
  align-content: start;
  padding: 0 var(--margin-main) var(--margin-main);
}

.project-image {
  position: relative;
  margin: 0; /* reset <figure> default */
  border-radius: 4px;
  overflow: hidden;
  background: var(--card-placeholder);
  grid-column: span 6;
}
.project-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Columns per row (aspect-ratio is set inline per image by main.js) */
.project-image--cols-1 { grid-column: span 6; }
.project-image--cols-2 { grid-column: span 3; }
.project-image--cols-3 { grid-column: span 2; }

/* Mobile: every image full width, one per row */
@media (max-width: 699px) {
  .project-page { gap: 12px; padding-bottom: 12px; }
  .project-image--cols-2,
  .project-image--cols-3 { grid-column: span 6; }
}

/* ---------- About page ----------
   12-column grid (10px gutters, same as the homepage cards), anchored to the bottom.
   Portrait = cols 1–2 · eyebrows = cols 5–6 · text = cols 7–11 (as in the Figma grid). */
.about {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 40px var(--margin-main) 96px;
}
.about__grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: auto auto auto auto;
  column-gap: var(--column-gap);
  row-gap: 64px;
  align-items: start;
}

.about__portrait {
  grid-column: 1 / 3;
  grid-row: 1 / 5;
  aspect-ratio: 6 / 8;
  border-radius: 4px;
  overflow: hidden;
  background: var(--card-placeholder);
}
.about__portrait img { width: 100%; height: 100%; object-fit: cover; }

.about__eyebrow {
  grid-column: 5 / 7;
  font-weight: 500;
  font-size: 18px;
  line-height: 1.5;
  color: var(--text-primary);
}
.about__lead,
.about__list,
.about__links { grid-column: 7 / 12; }

.about__lead {
  max-width: 62ch;   /* keep measure comfortable on very wide screens */
  font-weight: 500;
  font-size: 18px;
  line-height: 1.5;
  color: var(--text-primary);
}

.about__list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-weight: 500;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-primary);
}

/* Social links — label + Lucide arrow-up-right (20px, 5px gap) */
.about__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  font-weight: 500;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-primary);
}
.about__link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.about__link-icon {
  width: 20px;
  height: 20px;
  flex: none;
  transition: transform 0.4s var(--ease-out);
}
.about__link:hover .about__link-icon { transform: translate(2px, -2px); }

/* Line-reveal masks (spans are injected by main.js, removed again after the intro) */
.about .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em;   /* room for descenders inside the mask */
  margin-bottom: -0.08em;
}
.about .line > span { display: block; }

/* Pre-animation: hide until JS is ready (JS removes this) */
.is-loading .about__portrait,
.is-loading .about__eyebrow,
.is-loading .about__lead,
.is-loading .about__list li,
.is-loading .about__links li { opacity: 0; }

@media (max-width: 1199px) {
  .about__portrait { grid-column: 1 / 4; }
  .about__eyebrow  { grid-column: 5 / 7; }
  .about__lead, .about__list, .about__links { grid-column: 7 / 13; }
}

@media (max-width: 899px) {
  .about { justify-content: flex-start; padding-top: 3rem; padding-bottom: 40px; }   /* 3rem from the nav */
  .about__grid { row-gap: 12px; }
  .about__portrait { grid-column: 1 / 7; grid-row: auto; margin-bottom: 36px; }        /* half the screen width */
  .about__eyebrow, .about__lead, .about__list, .about__links { grid-column: 1 / 13; }
  .about__list { margin-bottom: 0; }
  .about__eyebrow--services, .about__eyebrow--links { margin-top: 36px; }
}

/* ---------- Page transition helpers ---------- */
/* The floating image that travels between the card and the project hero */
.flip-clone {
  position: fixed;
  z-index: 50;
  border-radius: 4px;
  overflow: hidden;
  pointer-events: none;
  will-change: top, left, width, height;
}
.flip-clone img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  backface-visibility: hidden;
}
/* While a transition runs, hand opacity control to GSAP */
.is-transitioning .project-card { transition: none; }
.is-transitioning .project-container:has(.project-card:hover) .project-card:not(:hover) { opacity: 1; }
.is-transitioning .project-card:hover .project-card__media img { transform: none; }

/* Pre-animation state: hide until JS positions the cards (JS removes this) */
.is-loading .brand > *,
.is-loading .nav > *,
.is-loading .project-card { opacity: 0; }

/* Homepage only: cards start below the viewport during the intro — stop that creating a scrollbar */
html.lock-scroll { overflow: hidden; }

/* ---------- Responsive: 2-col grid below 1200px ---------- */
@media (max-width: 1199px) {
  .project-wrapper {
    justify-content: flex-start;
    padding-top: 0;
  }
  .project-container {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 24px;
    align-items: start;
  }
  .project-card { flex: none; }
}

/* =====================================================================================
   MOBILE CAROUSEL (< 700px)
   One swipeable row: first card centred, next card peeking in from the right, with an
   "01." index above each card. To go back to the stacked 2-column grid on mobile, delete
   this whole block (down to the closing "END MOBILE CAROUSEL" line). Nothing else depends on it.
   ===================================================================================== */
@media (max-width: 699px) {
  .project-wrapper {
    justify-content: flex-start;
    padding: 2rem var(--margin-main);   /* 2rem safe zone above and below the row */
  }
  .project-container {
    display: flex;                      /* override the 2-col grid */
    justify-content: flex-start;        /* NOT center: centring an overflowing row hides its start */
    gap: var(--column-gap);
    align-items: flex-start;
    align-self: stretch;                /* fill the wrapper's width (it centres children by default) */
    width: auto;
    min-width: 0;
    margin: auto calc(-1 * var(--margin-main));         /* auto = vertically centred, but never overflows the safe zone */
    padding: 0 calc((100vw - var(--card-w)) / 2);       /* centres the first (and last) card */
    --card-w: calc(90vw - 6px);         /* neighbours peek in by ~12px on a 375px phone */
    overflow-x: auto;
    overflow-y: visible;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .project-container::-webkit-scrollbar { display: none; }
  .project-card {
    flex: 0 0 var(--card-w);
    scroll-snap-align: center;
  }
  .project-card__media { aspect-ratio: 4 / 5; }
  .project-card__index { display: block; }

  /* During the intro the cards fly in from below the viewport — let them show outside the row */
  html:not(.intro-done) .project-container { overflow: visible; }
}
/* END MOBILE CAROUSEL */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
