﻿/* ==========================================================================
   VDPL Next — Work index and case studies
   Loaded on /work/; the case-study card rules are also needed on the single
   and archive templates, which pull this file in the same way.
   ========================================================================== */

/* ---- Filter -------------------------------------------------------------- */

.w-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  border: 0;
  padding: 0;
}

/* ---- Card ---------------------------------------------------------------
   The card itself (.w-case and its children) moved to components.css - see
   the note there. What is left here is specific to the /work/ page's own
   grid: the slot wrapper and the featured span. */

.w-slot { display: flex; }
.w-slot[hidden] { display: none; }

/* The lead project spans two columns where there is room. The span sits on
   the slot because the slot is the grid item — putting it on the card would
   do nothing, since the card is a grid *child's* child. */
.w-slot--featured { grid-column: span 2; }
.w-slot--featured .w-case__cover { aspect-ratio: 21 / 9; }
@media (max-width: 900px) {
  .w-slot--featured { grid-column: span 1; }
  .w-slot--featured .w-case__cover { aspect-ratio: 16 / 10; }
}

/* ---- Single case study --------------------------------------------------- */

/* The cover frame.

   The image used to be a bare .c-figure - width:100%, height:auto - so the
   page rendered whatever was attached at whatever size the wrap happened to
   be. On /case-studies/clinical-authority-hub-for-dr-j-m-hans/ that was a
   192x77 logo drawn at 1472x590: a 7.7x upscale, unreadable, and the largest
   element on the page.

   The frame holds the shape (16/9, the same proportion the work cards use)
   so the page's rhythm no longer depends on what was uploaded. Inside it the
   image is sized `auto` against max-width/max-height rather than being
   stretched to fit: a cover at 1600px wide fills the frame exactly, and
   anything smaller than the frame renders at its own size, centred, sharp.
   An undersized image then reads as an image that is too small - which is
   true, and fixable by uploading a better one - instead of as a broken page. */
.cs-cover {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--c-surface-2);
  box-shadow: var(--e-md);
}

/* `scale-down` is the whole trick: it paints the smaller of `none` (natural
   size) and `contain` (fit the box). A real cover is contained by the frame;
   a 192x77 logo stays 192x77 and is never enlarged. max-width/max-height do
   NOT achieve this - measured, a 1600x1200 image still rendered 1472x1104
   inside an 828px-tall frame and was cropped by the overflow.

   The frame carries the rounding and the shadow now, so the image inside must
   not draw its own on top of them. */
/* Pinned with `inset: 0` rather than sized in percentages: an <img> carries
   its own aspect-ratio, so `height: 100%` on it does not resolve against the
   frame - measured, a 150x150 file produced a 1472x1472 box inside an 828px
   frame and the overflow cropped what should have been centred. Absolute
   positioning gives the box the frame's exact rectangle, and object-fit does
   the rest. */
.cs-cover .c-figure {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: scale-down;
  border-radius: 0;
  box-shadow: none;
}

.cs-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s-8);
  padding: var(--s-8) 0;
  border-block: 1px solid var(--c-line);
}

/* The text column was a bare 1fr, so on a wide screen it stretched to fill
   whatever the wrap left after the 300px sidebar - often 850px+ - while the
   prose inside self-caps at --measure (~600px) and sits left-aligned. The gap
   between where the paragraph actually ends and where "Project facts" starts
   was empty grid track, not a deliberate margin. Capped in rem, not ch: this
   column also holds the h2 headings, and ch resolves against the column's own
   font-size, not a heading's larger one - the same trap documented on
   .l-head.

   🔴 The cap was first written as minmax(0, min(44rem, 1fr)), which is
   INVALID: fr units are not allowed inside min()/max()/clamp(). The browser
   drops the whole declaration, so the grid lost its columns entirely, fell
   back to one, and the sidebar landed under the article at 1310px wide.
   Nothing errors - the rest of the rule applies and the page just looks
   wrong. Never put fr inside a math function.

   So the cap goes on the text track directly, and the sidebar track takes
   the remainder while .cs-side holds itself to 300px at the right edge -
   both columns stay flush with the page's own margins. */
.cs-layout {
  display: grid;
  grid-template-columns: minmax(0, 44rem) minmax(300px, 1fr);
  gap: var(--s-12) var(--s-16);
  align-items: start;
}
@media (max-width: 900px) { .cs-layout { grid-template-columns: 1fr; } }

/* Its track is flexible so the two columns span the full wrap; the panel
   itself stays 300px and sits at the right edge of that track, which keeps
   its right edge on the same line as the masthead above it. */
.cs-side {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  width: 100%;
  max-width: 300px;
  margin-inline-start: auto;
  padding: var(--s-6);
  border-radius: var(--r-md);
  background: var(--c-surface-2);
  position: sticky;
  top: calc(var(--s-20) + var(--s-4));
}
@media (max-width: 900px) { .cs-side { position: static; max-width: none; } }

.cs-facts { display: grid; grid-template-columns: auto 1fr; gap: var(--s-2) var(--s-5); font-size: var(--t-sm); }
.cs-facts dt { color: var(--c-ink-3); }
.cs-facts dd { color: var(--c-ink); }

.cs-quote {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-10);
  border-radius: var(--r-lg);
  background: var(--c-surface-2);
}
.cs-quote blockquote::before { content: "\201C"; }
.cs-quote blockquote::after  { content: "\201D"; }
.cs-quote figcaption { display: flex; flex-wrap: wrap; gap: var(--s-2); }
