:root {
  --cream: #F5F4ED;
  --oxblood: #6A1500;
  --black: #050505;

  /* Driven by JS. --s: continuous video shrink, --p: colour flip, --q: scatter */
  --s: 0;
  --p: 0;
  --q: 0;

  /* Light page from the start (no black phase). Text starts cream over the
     full-bleed video and the nav quickly flips to oxblood as the cream bg shows
     through (driven in main.js). */
  --nav-color: var(--cream);
  --page-bg: var(--cream);
}

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

html { scroll-behavior: auto; }

body {
  background: var(--page-bg);
  color: var(--oxblood);
  font-family: "neue-haas-grotesk-display", "Neue Haas Grotesk Display Pro",
               "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8125rem; /* 13px */
  font-feature-settings: "kern" 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* ======================= NAV ======================= */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  padding: 44px 50px 0;
  color: var(--nav-color);
  mix-blend-mode: normal;
}

.nav__logo { display: inline-block; line-height: 0; color: var(--nav-color); }
.nav__logo svg { width: 47px; height: auto; display: block; }
.nav__logo svg path { fill: currentColor; transition: fill .1s linear; }

.nav__center {
  grid-column: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  justify-self: center;
  padding-top: 4px;
  font-family: "neue-haas-grotesk-display", "Neue Haas Grotesk Display Pro",
               "Helvetica Neue", Arial, sans-serif;
  font-size: 0.75rem; /* 12px */
  line-height: 1.09;
  text-transform: uppercase;
  white-space: nowrap;
}
.nav__eyebrow { font-weight: 700; }
.nav__rule { width: 16px; height: 1px; background: currentColor; display: inline-block; }
.nav__date { font-weight: 700; }
.nav__venue {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 500;
}

.nav__menu {
  grid-column: 3;
  justify-self: end;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  font-family: "neue-haas-grotesk-display", "Neue Haas Grotesk Display Pro",
               "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8125rem; /* 13px */
  line-height: 0.9;
  font-weight: 700;
  text-transform: uppercase;
}
.nav__menu a { color: inherit; text-decoration: none; transition: opacity .2s ease; }
.nav__menu a:hover { opacity: .55; }

/* ======================= HERO ======================= */
/* Tall stage: phase 1 = full-bleed -> card, phase 2 = clips scatter around it */
.hero { position: relative; height: 260vh; }

.hero__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* One continuous shrink driven by --s (full-bleed -> final card). Radius fades
   in with --p so the rounding appears as the background flips to cream. */
.hero__media {
  --w: calc(100vw - (100vw - 46vw) * var(--s));
  --h: calc(100vh - (100vh - 58vh) * var(--s));
  --r: calc(20px * var(--p));
  position: relative;
  z-index: 10;
  width: var(--w);
  height: var(--h);
  border-radius: var(--r);
  overflow: hidden;
  transform: translateY(var(--mshift, 0px)); /* light exit rise, driven by JS */
  will-change: width, height, transform;
}

.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* turns black & white as it scatters (frame 3) */
  filter: grayscale(var(--q));
}

/* Scattered clips (small, no blur) revealed around the same hero video in phase 2.
   Depth (0..1) drives size, stacking and parallax speed only. */
.clip {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  aspect-ratio: 3 / 4;
  border-radius: 3px;
  overflow: hidden;
  opacity: 0; /* JS reveals + parallaxes in phase 2 */
  /* far clips behind the hero video, near clips in front */
  z-index: calc(4 + 30 * var(--depth));
  transform: translate(-50%, -50%) translateY(var(--shift, 0px));
  will-change: transform, opacity;
  box-shadow: 0 12px 26px rgba(10, 4, 0, calc(.14 * var(--depth)));
}
.clip video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.hero__caption {
  position: absolute;
  /* Above the video (z-index:10) so the text is actually visible, not painted
     behind it. Position, alignment and colour are all driven by JS across the
     hero scroll (the CAP_* knobs in main.js): it starts bottom-left over the
     full-bleed video, left-aligned and cream (matching Web Design/1.jpg), and
     lands centred just below the resolved card, centre-aligned and oxblood, at
     the first snap stop. It then rides the SAME --mshift as the video, so the
     two leave together instead of the text fading out first. */
  left: var(--cap-x, 12.8%);
  top: var(--cap-y, 81%);
  max-width: 320px;
  z-index: 20;
  transform: translate(var(--cap-tx, 0%), -50%) translateY(var(--mshift, 0px));
  text-align: var(--cap-align, left);
  color: var(--cap-color, var(--cream));
  font-weight: 700;
  font-size: 14px;
  line-height: 1.14;
  text-transform: uppercase;
  pointer-events: none;
  will-change: transform, color;
}

/* Each line is its own row, as drawn. Without this the spans run inline and
   re-wrap to the block width, collapsing the three lines into two. */
.hero__cap-line { display: block; }

.hero__scrollcue {
  position: absolute;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  opacity: var(--p);
  transition: opacity .2s ease;
}
.hero__pill {
  display: block;
  width: 34px;
  height: 6px;
  border-radius: 6px;
  background: var(--oxblood);
  opacity: .5;
}

/* ======================= WORKS / PROJECTS SLIDER ======================= */
.works {
  position: relative;
  min-height: 100vh;
  background: var(--cream);
  color: var(--oxblood);
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
  padding: 8vh 0 0;
  /* Pull the section up into the hero's sticky trailing so the resolved video
     card hands off directly to the projects instead of scrolling through an
     empty viewport first.
       hero is 260vh, so its scroll range is 160vh
       stop 1 (video resolved) = HERO_STOP 0.42 x 160vh = 67.2vh
       this margin puts .works at 260 - 91 = 169vh
     which is 1.8vh below the fold at stop 1 (just out of sight) and means the
     projects start rising the moment you scroll off it. Anything less negative
     re-opens a band of empty cream between the two. */
  margin-top: -91vh;
}

.works__viewport {
  position: relative;
  width: 100%;
  height: 34vh;
}

/* All projects sit across the screen as a centered strip. The active project is
   always re-ordered into the middle slot (see main.js), with the rest wrapping
   out symmetrically on either side. */
.works__track {
  position: absolute;
  inset: 0;
}

/* Each item is absolutely centred, then pushed to its slot with an animated
   translateX (--x) driven by main.js. Because every slide shares the same
   origin and only its transform changes, a change of active makes the whole row
   glide one slot instead of snapping. --sc grows the centre item. */
.work {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Height is definite; aspect-ratio derives the width so the 4:5 source is
     never cropped. Size changes come from --sc so they never reflow. */
  height: 15vh;
  width: auto;
  aspect-ratio: 4 / 5;
  cursor: pointer;
  transform: translate(-50%, -50%) translateX(var(--x, 0px)) scale(var(--sc, 1));
  transform-origin: center center;
  transition:
    transform 1.6s cubic-bezier(.33, 0, .2, 1),
    opacity 1.3s cubic-bezier(.33, 0, .2, 1),
    filter 1.6s cubic-bezier(.33, 0, .2, 1);
  will-change: transform, opacity, filter;
}
.work img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 10px;
  box-shadow: 2px 5px 5px rgba(20, 6, 0, .12);
}

/* Edge gradients fading the outer projects into the cream bg. Sit ABOVE the
   slides (which JS gives z-index up to 20) so the fade actually covers them;
   stay below the nav (z-index 50). */
.works__fade {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 26vw;
  pointer-events: none;
  z-index: 30;
}
.works__fade--left {
  left: 0;
  background: linear-gradient(90deg, var(--cream) 30%, rgba(245, 244, 237, 0) 100%);
}
.works__fade--right {
  right: 0;
  background: linear-gradient(270deg, var(--cream) 30%, rgba(245, 244, 237, 0) 100%);
}

/* Center caption under the active slide */
.works__caption {
  text-align: center;
  margin-top: 3.5vh;
  text-transform: uppercase;
  font-size: 0.75rem;
  line-height: 1.5;
  min-height: 5.5em;
  transition: opacity .5s ease;
}
.works__caption .wc-title { font-weight: 700; margin-bottom: 1.2em; }
.works__caption .wc-line { display: block; font-weight: 500; }
.works__caption.is-fading { opacity: 0; }

/* Bottom-left index. A 2-column grid so every year aligns in its own column,
   independent of name length. Bold throughout; the active row is full oxblood
   while the rest are a muted tint. */
.works__index {
  position: absolute;
  left: 50px;
  bottom: 44px;
  list-style: none;
  display: grid;
  grid-template-columns: auto auto;
  column-gap: 2.4em;
  row-gap: 0.12em;
  font-size: 0.8125rem; /* 13px */
  line-height: 1.15;
  font-weight: 700;
  text-transform: uppercase;
}
/* Each row's name + year become cells of the shared grid so columns align. */
.works__index li { display: contents; cursor: pointer; }
.works__index .wi-name,
.works__index .wi-year {
  color: var(--oxblood);
  opacity: .38;
  transition: opacity .4s ease;
}
.works__index li:hover .wi-name,
.works__index li:hover .wi-year { opacity: .6; }
.works__index li.is-active .wi-name,
.works__index li.is-active .wi-year { opacity: 1; }

/* ======================= ABOUT / STUDIO ======================= */
/* One full panel, laid out per Web Design/6.jpg: portrait + credit links on the
   left, statement + justified bio on the right, footer centred at the bottom.
   Both columns hang off the same 50px gutters the nav uses; the gap down the
   middle is intentional dead space. */
.about {
  position: relative;
  min-height: 100vh;
  background: var(--cream);
  color: var(--oxblood);
  display: flex;
  flex-direction: column;
  /* Top padding keeps the statement clear of the fixed nav, which runs to about
     118px (44px offset + five 13px rows). The px floor matters on short screens:
     8vh alone is only 72px at 900px tall, which the nav would overlap.
     The side gutters live on the children, not here, so .footer can carry its
     own and stay self-contained on pages that have no .about wrapper. */
  padding: max(130px, 8vh) 0 0;
}

.about__inner {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 6vw;
  /* "safe" centres only while there is room; once the copy is taller than the
     panel it falls back to start-alignment instead of overflowing upward behind
     the nav. */
  align-content: safe center;
  padding: 0 50px;
}

/* LEFT: the credit links tuck against the portrait's bottom-right corner.
   align-self keeps the column at its content height so the portrait tops out
   level with the statement opposite it, rather than being stretched and pushed
   to the bottom of the row. */
.about__left {
  align-self: start;
  display: flex;
  align-items: flex-end;
  gap: 30px;
}

/* Height is definite and aspect-ratio derives the width, so the 2:3 source
   (bio.jpg is 734x1100) is never cropped or stretched. */
.about__portrait {
  flex: none;
  height: 39vh;
  width: auto;
  aspect-ratio: 2 / 3;
}
.about__portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 10px; /* matches the works slider images */
}

.about__links {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.6em;
  padding-bottom: 0.25em;
}
.about__link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
}
.about__link-icon { display: inline-flex; line-height: 0; }
/* The rule sits under the label only, clear of the arrow icon, as drawn. */
.about__link-text {
  font-size: 0.8rem; /* set explicitly, not fluid like the rest of the panel */
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid currentColor;
  padding-bottom: 3px;
}

/* RIGHT: statement and bio share the right gutter; the bio runs in a narrower
   measure than the statement above it. */
.about__right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
/* Type in this panel is fluid rather than fixed px. The design frame is drawn at
   a 2048px viewport, so each size is expressed as the vw it occupies there (e.g.
   the statement is 28px at 2048 = 1.37vw) and clamped so it stays readable on
   small screens and keeps growing on large ones. Pinning these to px made the
   whole panel read ~11% small on a 2272px display. */
.about__title {
  text-align: right;
  font-weight: 500;
  font-size: 1.9rem; /* set explicitly, not fluid like the rest of the panel */
  line-height: 1.22;
  letter-spacing: -0.01em;
  margin-bottom: 3.2vh;
}
.about__bio {
  width: 74%;
  font-weight: 500;
  font-size: 15px; /* set explicitly, not fluid like the rest of the panel */
  line-height: 1.2;
  text-align: justify;
}
.about__bio p + p { margin-top: 1.1em; }

/* ======================= COLLECTION PAGE ======================= */
/* Per temp/Frame 96.jpg. This page is the TEMPLATE every other collection page
   is built from, so the row types below are meant to be reused, not one-offs.
   Two column widths, both centred and both taken from the 2048px design frame:
   the caption row is wider (1602/2048) than the image column (1326/2048) so the
   medium and year hang outside the photos.
   Note there are no oxblood mats behind the photos. Earlier revisions framed
   every image in a red plate; the design does not, so the photo IS the plate. */
.collection {
  --col-w: 64.75%;
  --head-w: 78.2%;
  /* Must be a LENGTH, not a percentage: a percentage row-gap resolves against
     the container's own (auto) height, which is circular. */
  --gap: 1.9vw;
  /* Top clears the fixed nav (~130px); bottom is the 207px gap to the footer
     rule in the design, as a share of the 2048px frame. */
  padding: 160px 0 10.1%;
}

/* Pages that are cream from the very top need the nav in oxblood immediately.
   index.html leaves this alone: there main.js drives --nav-color from cream to
   oxblood as the hero video resolves. */
body.page-cream { --nav-color: var(--oxblood); }

.collection__head {
  width: var(--head-w);
  margin: 0 auto 33px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 4vw;
}
/* The piece info: installation type (left), size (under the title), date and
   location (right). All four are ONE typographic voice, so they share a single
   rule. Keep it that way. They previously drifted to two different opacities,
   which read as an accident rather than a hierarchy. The title is the only
   thing in the header that is allowed to look different. */
.collection__medium,
.collection__meta,
.collection__dims {
  font-size: 0.9rem; /* 14.4px */
  font-weight: 600;
  line-height: 1.09;
  color: rgba(106, 21, 0, 0.64);
}
.collection__medium,
.collection__meta { flex: none; }
.collection__meta { text-align: right; }

/* Title block: the work name with its size directly under it. Wrapping the two
   means the flex row still centres them as a single unit. */
.collection__titles { flex: 1; text-align: center; }
.collection__title {
  font-size: 1.5rem; /* 24px */
  font-weight: 400;
  line-height: 1.09;
  color: var(--oxblood);
}
.collection__dims { margin-top: 11px; }

/* The image column. A plain vertical stack: every row is either a full-width
   photo or a split (text + photo), so no grid is needed. */
.collection__body {
  width: var(--col-w);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* No mat, no crop, no fixed aspect ratio: the photo fills the width it is given
   and keeps its own proportions. width/height on the <img> reserve the space so
   the page does not jump as images load. */
.plate { margin: 0; }
.plate img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
}

/* The text row: copy on the left, a detail shot on the right.
   Two equal halves. The row's height is set by the COPY alone, because the photo
   is taken out of flow (below) and so can never be the thing that makes the row
   tall. That is what keeps the detail shot bounded by the copy instead of
   towering over it.
   --min-media is the floor under that: short copy would otherwise shrink the
   photo to a thumbnail, so the row never gets shorter than this and the photo
   never smaller. Raise it to make the detail shot bigger everywhere. */
.collection__split {
  --measure: 78%;
  --min-media: 450px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--gap);
  align-items: stretch;
  min-height: var(--min-media);
}
.collection__text {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Centred within its own half, per the design. */
.collection__text p {
  max-width: var(--measure);
  text-align: center;
  font-size: 0.875rem; /* 14px */
  font-weight: 600;
  line-height: 1.5;
  color: rgba(106, 21, 0, 0.78);
}

/* The photo is absolutely positioned so it contributes NO intrinsic height to
   the grid row: the copy (or --min-media) sets the height, never the photo.
   Sizing is max-height/max-width with both dimensions auto, NOT height: 100%.
   That hands the browser the replaced-element rule, which shrinks the photo to
   fit whichever bound is tighter while keeping its ratio, so the element box
   always matches the photo exactly. object-fit would instead letterbox inside a
   fixed box and leave the 10px radius floating off the image's real corners.
   Pinned right so it stays flush with the full-width rows above and below. */
.collection__split .plate {
  position: relative;
}
.collection__split .plate img {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}

/* ============ FOOTER (bottom of the about/studio panel) ============ */
/* Self-contained: carries its own gutters and its own positioning context, so
   it drops into any page (about panel, collection page) without needing a
   wrapper. Markup lives in footer.js — edit it there, not per page. */
.footer {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 50px 6vh;
}

/* Sits between the brand mark and the contact block, which is its DOM order, so
   it just flows normally. */
.footer__rule {
  width: 26.7%;
  height: 1px;
  background: currentColor;
  opacity: .5;
  margin-top: 2.4vh;
}

.footer__brand { display: flex; align-items: center; gap: 14px; }
/* logo.svg is authored in oxblood, so it needs no recolouring here. */
.footer__logo {
  width: 47px;
  height: 23px;
  background: url(assets/logo.svg) no-repeat center / contain;
}
.footer__divider { width: 1px; height: 22px; background: currentColor; opacity: .55; }
.footer__ig { color: inherit; display: inline-flex; transition: opacity .2s ease; }
.footer__ig:hover { opacity: .6; }

.footer__label {
  margin-top: 2.6vh;
  font-size: 0.8125rem; /* 13px, matching the nav menu items */
  font-weight: 700;
  text-transform: uppercase;
}
.footer__email {
  margin-top: 0.55em;
  color: inherit;
  font-weight: 600;
  font-size: 0.85rem; /* set explicitly, not fluid like the rest of the panel */
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Credits sit in the panel's bottom-right corner, outside the centred stack. */
.footer__meta {
  position: absolute;
  right: 50px;
  bottom: 3vh;
  display: flex;
  gap: 2.6em;
  font-size: 11px; /* set explicitly, not fluid like the rest of the panel */
  font-weight: 700;
  text-transform: uppercase;
}

/* Below 1250px the split row has no room to sit side by side, so the copy and
   its detail shot stack. The photo goes back into normal flow here: out of flow
   it had no height of its own, which only works while the copy beside it is
   setting the row height. Must stay ABOVE the 720px block so that one wins. */
@media (max-width: 1250px) {
  .collection__split {
    /* Stacked, the copy's cell is the full image column, so a percentage here
       is a share of the big full-width photo above it. 80% is what Yasin asked
       for. The photo keeps its own --media-w: the two are no longer competing
       for one row, so they no longer need to match. */
    --measure: 80%;
    --media-w: 62%;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--gap);
    /* The floor is a side-by-side concern only. Stacked, the photo is sized by
       width and is already large, and a 450px row would just add dead space. */
    min-height: 0;
  }
  .collection__split .plate {
    position: static;
    display: flex;
    justify-content: center;
  }
  .collection__split .plate img {
    position: static;
    transform: none;
    width: var(--media-w);
    height: auto;
    max-width: var(--media-w);
    max-height: none;
  }
}

@media (max-width: 720px) {
  .nav { padding: 22px 22px 0; grid-template-columns: 1fr auto; }
  .nav__center { display: none; }
  .nav__menu { grid-column: 2; }
  .hero__media { --w: calc(100vw - (100vw - 88vw) * var(--p)); }
  .hero__caption { font-size: 12px; max-width: 74vw; }

  /* About stacks: portrait, then its links, then statement + bio full width.
     Nothing is justified at this measure — the word gaps get ugly. */
  .about { padding: 0; }
  .about__inner {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 4vh;
    padding: 14vh 22px 6vh;
  }
  .footer { padding: 0 22px 6vh; }

  /* Collection: single column, full-bleed within the 22px gutters. The caption
     row stacks so the long medium/location strings stop colliding. */
  .collection { --col-w: auto; --head-w: auto; padding: 120px 0 14%; }
  .collection__head {
    margin: 0 22px 22px;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .collection__titles { text-align: left; }
  .collection__title { font-size: 1.25rem; }
  .collection__dims { margin-top: 6px; }
  .collection__meta { text-align: left; }
  .collection__body { margin: 0 22px; gap: 10px; }
  /* The split collapses: text above its detail shot, and the copy goes
     full-width and left-aligned so it stops reading as a narrow ribbon. */
  .collection__split {
    --measure: 100%;
    --media-w: 100%;
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }
  .collection__text p { text-align: left; }
  .about__left { flex-direction: column; align-items: flex-start; gap: 18px; }
  .about__portrait { height: 34vh; }
  .about__links { padding-bottom: 0; }
  .about__right { align-items: stretch; }
  .about__title { text-align: left; font-size: 18px; margin-bottom: 2.4vh; }
  .about__bio { width: 100%; text-align: left; }

  .footer__rule { width: 70%; }
  .footer__meta {
    position: static;
    justify-content: center;
    margin-top: 3vh;
    gap: 1.6em;
  }
}
