/* ==========================================================================
   PROJECT — archive grid + single case study
   ========================================================================== */

/* ============================================================ ARCHIVE ===== */
.archive__head { max-width: 62ch; margin-bottom: clamp(28px, 4vw, 52px); }
.archive__head h1 { margin-top: var(--sp-sm); }
.archive__lede {
  margin-top: var(--sp-md);
  color: var(--ink-light);
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
}

.archive__toolbar {
  position: sticky;
  top: var(--nav-h);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-md);
  margin-bottom: var(--sp-xl);
  padding-block: var(--sp-md);
  background: linear-gradient(var(--base) 78%, transparent);
}
.archive__toolbar .filters { flex: 1; min-width: 0; }
.archive__count {
  font-size: var(--fs-xs);
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.pf-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 26px);
}
@media (max-width: 1100px) { .pf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .pf-grid { grid-template-columns: minmax(0, 1fr); } }

.pf-card .card__body { gap: var(--sp-xs); }
.pf-card .card__title { font-size: var(--fs-lg); }
.pf-card .card__text  { font-size: var(--fs-sm); line-height: 1.55; }
.pf-card .chip { font-size: var(--fs-3xs); }

/* client-only work is marked, never hidden — it reads as depth */
.pf-card .card__flag {
  position: absolute;
  top: var(--sp-sm); left: var(--sp-sm);
  z-index: 2;
}

@media (max-width: 900px) {
  .archive__toolbar { position: static; background: none; }
}

/* ============================================================== SINGLE ==== */
.case { background: var(--void); color: var(--on-dark); }

/* hero */
.case__hero { position: relative; background: var(--void); overflow: hidden; }
.case__hero-media { position: relative; aspect-ratio: 21 / 9; }
.case__hero-media img { width: 100%; height: 100%; object-fit: cover; }
.case__hero-media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(3, 5, 4, .72) 0%, rgba(3, 5, 4, .18) 42%, rgba(3, 5, 4, .92) 100%);
}
.case__hero-inner {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--sp-md);
  padding-block: var(--sp-2xl);
}
.case__title { color: #fff; max-width: 18ch; }
.case__tagline {
  max-width: 52ch;
  color: var(--on-dark-mute);
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
}
.case__chips { margin-top: var(--sp-xs); }

@media (max-width: 760px) {
  .case__hero-media { aspect-ratio: 4 / 3; }
  .case__hero-inner { padding-block: var(--sp-lg); }
}

/* sticky rail */
/* The rail used to be `minmax(0,1fr) minmax(0,2.1fr)` as an inline style, so a
   TOC holding as little as one link was taking a third of the page and the
   gallery was squeezed into ~880px. It is a fixed, narrow column now and the
   case body takes everything else. */
.case__layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}
@media (max-width: 900px) {
  .case__layout { grid-template-columns: minmax(0, 1fr); }
  .case__rail  { position: static; }
}

.case__rail {
  position: sticky;
  top: calc(var(--nav-h) + var(--sp-lg));
  align-self: start;
}
.case__rail-title {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--copper-hot);
  margin-bottom: var(--sp-md);
}
.case__toc { display: grid; gap: 2px; }
.case__toc a {
  display: block;
  padding: var(--sp-xs) var(--sp-sm);
  color: var(--on-dark-mute);
  font-size: var(--fs-sm);
  text-decoration: none;
  border-left: 2px solid var(--on-dark-line);
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.case__toc a:hover { color: #fff; border-color: var(--copper-hot); }
.case__toc a.is-active { color: #fff; border-color: var(--copper); font-weight: 600; }

.case__body { padding-block: var(--sp-3xl); }
.case__block + .case__block { margin-top: var(--sp-4xl); }
.case__h2 {
  color: #fff;
  font-size: var(--fs-2xl);
  margin-bottom: var(--sp-md);
  scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

/* the three-beat case study structure */
.beat { display: grid; gap: var(--sp-md); }
.beat + .beat { margin-top: var(--sp-xl); }
.beat__label {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
  font-size: var(--fs-3xs);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--copper-hot);
}
.beat__label::after { content: ""; flex: 1; height: 1px; background: var(--on-dark-line); }
.beat__text { color: var(--on-dark-mute); max-width: var(--measure); line-height: var(--lh-loose); }
.beat__text strong { color: #fff; font-weight: 600; }

/* Design details.
   These stack rather than sit side by side. They used to be a 1.1fr / .9fr
   split, but the gallery then made TWO more columns inside that .9fr - so a
   board photo landed around 225px wide and a schematic sheet got the same
   narrow column. The gallery is the visual payload of a case study; it gets
   the full measure. The spec table is reference material and reads fine at a
   shorter line length, so it is capped instead. */
.case__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
}

.case__panel {
  background: var(--graphite);
  border: 1px solid var(--on-dark-line);
  padding: clamp(20px, 2.4vw, 32px);
  clip-path: var(--clip);
}

/* The panel is full width now the section is single-column, so the rows pair
   up two-across instead of leaving half the panel empty. */
@media (min-width: 900px) {
  .case__panel .spec tbody {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(28px, 3.5vw, 56px);
  }
  .case__panel .spec tr { display: block; }
  .case__panel .spec th,
  .case__panel .spec td {
    display: block;
    border: 0;
    padding: 0;
  }
  /* Readability: the labels were 10px muted caps over a 90ch value, which is
     the worst of both - the value ran the full panel width while the label it
     belongs to was hard to find. Bigger label, measured value, more air. */
  /* `width: auto` is load-bearing. The ACF label sub-field carries
     `width => 35%`, which ACF emits as an inline style on every <th> - that
     capped the label at a third of the track and wrapped "Onboard 5 V
     regulation" onto two lines inside a cell wide enough for one. */
  .case__panel .spec th {
    width: auto !important;
    font-family: var(--font-display);
    font-size: var(--fs-md);
    font-weight: 700;
    letter-spacing: -0.01em;
    text-transform: none;   /* the data is already sentence case */
    color: #fff;
    padding-bottom: 6px;
    text-wrap: balance;
  }
  .case__panel .spec td {
    padding-bottom: var(--sp-lg);
    font-size: var(--fs-sm);
    line-height: 1.65;
    color: var(--on-dark-mute);
    max-width: 46ch;
  }
  .case__panel .spec tr {
    padding-bottom: var(--sp-sm);
    border-bottom: 1px solid var(--on-dark-line);
    margin-bottom: var(--sp-md);
  }
  .case__panel .spec tr:nth-last-child(-n+2) { border-bottom: 0; margin-bottom: 0; }
}

/* gallery on dark */
.case .gallery img { background: var(--surface); border-color: transparent; }
.gallery-grid {
  display: grid;
  gap: clamp(16px, 2vw, 28px);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
/* Every image renders at the same grid size. Schematic sheets used to be
   full-bleed at ~3x, which broke the rhythm of the grid - the lightbox is what
   makes them inspectable instead. */
.gallery-grid > figure { margin: 0; min-width: 0; }
.gallery-grid figcaption {
  margin-top: var(--sp-xs);
  font-size: var(--fs-3xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.gallery-grid img {
  width: 100%; height: auto;
  background: var(--surface);
  clip-path: var(--clip-sm);
  transition: clip-path var(--t-base) var(--ease);
}
.gallery-grid a:hover img { clip-path: var(--clip); }
@media (max-width: 760px) {
  .gallery-grid { grid-template-columns: minmax(0, 1fr); }
}

/* video */
.case__video { margin-top: var(--sp-xl); }
.case__video video {
  width: 100%;
  background: #000;
  clip-path: var(--clip);
}
.case__video figcaption {
  margin-top: var(--sp-sm);
  font-size: var(--fs-3xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}

/* CTA strip */
.case__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-lg);
  justify-content: space-between;
  padding: clamp(24px, 3vw, 44px);
  background: var(--graphite);
  border: 1px solid var(--on-dark-line);
  border-left: 3px solid var(--copper);
  clip-path: var(--clip);
}
.case__cta h2 { color: #fff; font-size: var(--fs-2xl); }
.case__cta p { color: var(--on-dark-mute); margin-top: var(--sp-xs); max-width: 48ch; }

/* prev / next */
.case__nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-md);
  margin-top: var(--sp-3xl);
  padding-top: var(--sp-2xl);
}

/* "EXPLORE MORE" sits between two rules - one above, one below - so the label
   reads as a divider rather than a floating caption, and the block balances
   against the CTA above it. The nav's own border-top was removed for this. */
.case__nav-title {
  display: flex;
  align-items: center;
  gap: var(--sp-md);
  margin: 0 0 var(--sp-xl);
}
.case__nav-title::before,
.case__nav-title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--on-dark-line);
}
.case__nav-title {
  grid-column: 1 / -1;
  font-size: var(--fs-3xs);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--on-dark-mute);
  margin: 0 0 var(--sp-2) ;
}
.case__nav-link .label i { font-size: 1.1em; margin-inline: 2px; }
/* Backed by the neighbouring project's featured image (--nav-bg), with a
   scrim so the title stays legible over any artwork. */
.case__nav-link {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--sp-3xs);
  /* 16:9 so the featured image (which is 16:9) fills the card instead of being
     cropped to a letterbox strip by background-size: cover. */
  aspect-ratio: 16 / 9;
  min-height: 230px;
  padding: var(--sp-lg);
  border: 1px solid var(--on-dark-line);
  color: var(--on-dark-mute);
  text-decoration: none;
  clip-path: var(--clip-sm);
  overflow: hidden;
  isolation: isolate;
  background-color: var(--graphite);
  background-image: var(--nav-bg);
  background-size: cover;
  background-position: center;
  transition: border-color var(--t-base) var(--ease), color var(--t-base) var(--ease);
}
.case__nav-link::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgba(3, 5, 4, .97) 0%, rgba(3, 5, 4, .88) 38%, rgba(3, 5, 4, .55) 100%);
  opacity: .94;
  transition: opacity var(--t-base) var(--ease);
}
.case__nav-link:hover { border-color: var(--copper-edge); color: #fff; }
.case__nav-link:hover::before { opacity: .74; }
.case__nav-link b {
  position: relative;
  color: #fff;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.9vw, 1.75rem);
  font-weight: 700;
  line-height: 1.15;
}
.case__nav-link .label {
  position: relative;
  font-size: var(--fs-3xs);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.case__nav-link--next { text-align: right; align-items: flex-end; }

/* A copper rule under the title, drawn out on hover. */
.case__nav-link b::after {
  content: "";
  display: block;
  width: 34px;
  height: 2px;
  margin-top: 10px;
  background: var(--copper);
  transition: width var(--t-base) var(--ease);
}
.case__nav-link--next b::after { margin-left: auto; }
.case__nav-link:hover b::after { width: 72px; }
.case__nav-link.is-empty { visibility: hidden; }
@media (max-width: 640px) { .case__nav { grid-template-columns: minmax(0, 1fr); } }

/* light sections inside a dark page */
.case .is-light { background: var(--surface); color: var(--ink); }

/* ---------------------------------------------------------------
   Lightbox - full-size image viewer for the case-study gallery.
   --------------------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 56px);
  background: rgba(3, 5, 4, .94);
  backdrop-filter: blur(4px);
}
.lightbox.is-open { display: flex; }

.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  background: var(--surface);
  box-shadow: 0 24px 80px rgba(0, 0, 0, .6);
}

.lightbox__cap {
  position: absolute;
  left: 50%;
  bottom: clamp(14px, 3vw, 28px);
  transform: translateX(-50%);
  margin: 0;
  max-width: 90vw;
  text-align: center;
  font-size: var(--fs-3xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}

.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border: 1px solid var(--on-dark-line);
  background: rgba(18, 22, 20, .9);
  color: #fff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: var(--copper); color: #fff; }

.lightbox__close { top: clamp(12px, 2vw, 24px); right: clamp(12px, 2vw, 24px); }
.lightbox__nav--prev { left: clamp(8px, 2vw, 24px);  top: 50%; transform: translateY(-50%); }
.lightbox__nav--next { right: clamp(8px, 2vw, 24px); top: 50%; transform: translateY(-50%); }

/* The grid image is a thumbnail now - say so. */
.gallery-grid a[data-lightbox] { cursor: zoom-in; display: block; }
.gallery-grid a[data-lightbox] img { transition: clip-path var(--t-base) var(--ease), opacity var(--t-base) var(--ease); }
.gallery-grid a[data-lightbox]:hover img { opacity: .86; }

/* download chip gets an icon */
.chip--file { display: inline-flex; align-items: center; gap: 8px; }
.chip--file i { font-size: 1.05em; line-height: 1; }

/* The beats carry the board: prose left, artwork right on both. The brief gets
   the featured shot, "What we did" gets the hover shot. Static - no crossfade. */
.case__beat {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 3vw, 48px);
  align-items: center;
}
@media (min-width: 1000px) {
  .case__beat {
    grid-template-columns: minmax(0, 1fr) clamp(360px, 42%, 600px);
  }
}
.case__beat .case__h2 { margin-bottom: var(--sp-md); }
.case__beat .prose { max-width: 62ch; }

.case__beat-media {
  position: relative;
  margin: 0;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  clip-path: var(--clip);
  background: var(--graphite);
}
.case__beat-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (max-width: 999px) {
  .case__beat-media { margin-top: var(--sp-md); }
}

/* "What we did" runs long, so its artwork matches the copy height exactly
   instead of sitting in a fixed 4:3 box with dead space above and below. */
.case__beat--fill { align-items: stretch; }
.case__beat-media--fill {
  aspect-ratio: auto;
  height: 100%;
  min-height: 320px;
  background-color: var(--graphite);
  background-image: var(--beat-bg);
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}
@media (max-width: 999px) {
  .case__beat-media--fill { min-height: 260px; }
}
/* Design summary: heading outside the panel, so it matches the other section
   headings instead of reading as a table caption inside the box. */
.case__specs .case__h2 { margin-bottom: var(--sp-lg); }
.case__specs .case__panel { margin: 0; }

/* ------------------------------------------------------------------ video --
   A poster frame (the project's own hero shot) plus a real play button. The
   native control strip is present but sits behind the overlay until play, so the
   card reads as a deliberate click target rather than a grey browser rectangle. */
.case__video { margin: 0 0 var(--sp-xl); }
.case__video-frame {
  position: relative;
  overflow: hidden;
  clip-path: var(--clip);
  background: var(--graphite);
}
.case__video-frame video {
  display: block;
  width: 100%;
  object-fit: cover;
  background: var(--graphite);
}
.case__video-play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 76px;
  height: 76px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, .38);
  border-radius: 50%;
  background: rgba(222, 73, 22, .92);
  color: #fff;
  font-size: 30px;
  line-height: 0;
  padding-left: 5px;
  cursor: pointer;
  box-shadow: 0 10px 34px rgba(0, 0, 0, .5);
  transition: transform var(--t-base) var(--ease), background var(--t-base) var(--ease),
              opacity var(--t-base) var(--ease);
}
.case__video-play::before {
  content: "";
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  border: 1px solid rgba(222, 73, 22, .55);
  animation: pcr-pulse 2.4s var(--ease) infinite;
}
/* While playing it shrinks into the corner rather than hiding - the native
   control bar is gone, so this button is the only way to pause. */
.case__video-frame.is-playing .case__video-play {
  inset: auto 14px 14px auto;
  margin: 0;
  width: 48px;
  height: 48px;
  font-size: 20px;
  padding-left: 0;
  background: rgba(3, 5, 4, .72);
  border-color: rgba(255, 255, 255, .28);
  opacity: .55;
}
.case__video-frame.is-playing .case__video-play::before { display: none; }
.case__video-frame.is-playing:hover .case__video-play,
.case__video-frame.is-playing .case__video-play:hover { opacity: 1; }
.case__video-play:hover { transform: scale(1.07); background: var(--copper-hot); opacity: 1; }

@keyframes pcr-pulse {
  0%   { transform: scale(.9);  opacity: .8; }
  70%  { transform: scale(1.25); opacity: 0; }
  100% { transform: scale(1.25); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .case__video-play::before { animation: none; }
}
@media (max-width: 640px) {
  .case__video-play { width: 60px; height: 60px; font-size: 24px; }
}

/* The projects archive / category head is not a `.section`, so it never picked
   up the fixed-header offset that `.pcr-inner .section:first-child` reserves -
   which put the "Projects" <h1> behind the fixed nav. */
.pcr-archive-head {
  position: relative;
  padding-top: calc(var(--pcr-nav-offset) + var(--sp-2xl));
  padding-bottom: var(--sp-2xl);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--base) 0%, var(--surface) 100%);
  overflow: hidden;
}
.pcr-archive-head::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 40%;
  height: 100%;
  background: radial-gradient(60% 80% at 100% 0%, rgba(222, 73, 22, .10), transparent 70%);
  pointer-events: none;
}
.pcr-archive-head .shell {
  position: relative;
  z-index: 1;
}
.pcr-archive-head .crumbs {
  color: var(--ink-light);
}
.pcr-archive-head .crumbs a {
  color: var(--ink-light);
}
.pcr-archive-head .crumbs a:hover {
  color: var(--copper);
}
.pcr-archive-head .crumbs [aria-current] {
  color: var(--ink);
  font-weight: 600;
}
.pcr-archive-head .crumbs__sep {
  color: var(--support);
}
.pcr-archive-head .shell > h1 {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  line-height: 1.05;
  margin: var(--sp-sm) 0 var(--sp-md);
  letter-spacing: var(--ls-display);
}
.pcr-archive-head .pf-lede {
  max-width: 72ch;
  color: var(--ink-light);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}

/* ==========================================================================
   SINGLE PROJECT - MOBILE TOC + PREV/NEXT OVERFLOW

   1. The rail was left `position: sticky` on a phone. The media query that
      reset it to `static` sat ABOVE the base `.case__rail` rule, so the later
      declaration won on source order and the rail floated over the first
      section - the TOC links printed on top of "The brief" and its copy.
      This block is deliberately at the END of the file so the reset wins.

      The TOC is now a horizontal, scrollable chip list above the article,
      which is the shape that works in a narrow column.

   2. The prev/next titles are full project names. As flex items they sized
      to their content width and spilled out past the card and the viewport.
      They are allowed to shrink and wrap instead.
   ========================================================================== */

@media (max-width: 900px) {

  .case__rail {
    position: static;
    top: auto;
    align-self: auto;
    margin-bottom: var(--sp-xl);
    padding: var(--sp-md) var(--sp-md) var(--sp-md);
    background: var(--graphite);
    border: 1px solid var(--on-dark-line);
    clip-path: var(--clip-sm);
  }

  .case__rail-title {
    margin-bottom: var(--sp-sm);
  }

  .case__toc {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .case__toc::-webkit-scrollbar {
    display: none;
  }

  .case__toc a {
    flex: 0 0 auto;
    padding: 8px 14px;
    border: 1px solid var(--on-dark-line);
    white-space: nowrap;
    font-size: var(--fs-xs);
    letter-spacing: .01em;
    clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  }
  .case__toc a.is-active {
    border-color: var(--copper);
  }
}

/* Long project names must wrap inside the card, not push it wide. */
.case__nav-link {
  max-width: 100%;
  min-width: 0;
}

.case__nav-link b {
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}
