/* ==========================================================================
   Case Studies — work.html

   Rebuilt around one rule: never render a screenshot smaller than the size
   it was captured at. The old version scaled 1100px dashboard captures into
   478px frames (43%), which put 11px UI labels at 4.7px. Every image here is
   a crop of the region that carries the claim, displayed at 1:1 and capped
   at its own natural width so it can never upscale either.

   Numbers that used to be locked inside those JPEGs are now real HTML, so
   they are legible, selectable, indexable and sharp at any pixel ratio.

   Reads the semantic token layer from style.css only — no raw colours, so
   dark mode comes for free from the one override block there. The single
   exception is the phone bezel, which is a physical object and stays black
   under either lighting.
   ========================================================================== */

/* ---- Case shell ---------------------------------------------------------- */
.case-list {
  display: flex;
  flex-direction: column;
  gap: clamp(80px, 9vw, 128px);
}

.case {
  display: flex;
  flex-direction: column;
  gap: 40px;
  text-align: left;
}

/* ---- Head: tag, name, client -------------------------------------------- */
.case-head { max-width: 60ch; }
.case-head .work-tag { margin-bottom: 14px; }
.case-head h3 {
  font-size: var(--text-heading);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  margin: 0 0 6px;
  text-align: left;
}
.case-client {
  color: var(--mist);
  font-size: var(--text-body-sm);
  margin: 0;
  text-align: left;
}

/* ---- Lede: the problem, and what it does about it ------------------------ */
.case-lede {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 40px 56px;
  align-items: start;
}
.case-lede > p {
  margin: 0;
  color: var(--mist);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  max-width: 56ch;
  text-align: left;
}
.case-lede > p strong { color: var(--ink); font-weight: var(--font-weight-semibold); }

.case-highlights {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
}
.case-highlights li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: var(--text-body-sm);
  line-height: 1.45;
  color: var(--ink);
  text-align: left;
}
.case-highlights li::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--accent-fill);
}

/* ---- Figure: a crop shown at 1:1 ---------------------------------------- */
.shot {
  margin: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}
/* The scroll wrapper must be pinned to the column width. Without an explicit
   100%, it is a flex item sizing to fit-content, so a 1048px frame stretches
   it past the 1016px container and `max-width:100%` on the frame then
   resolves against the overflowing wrapper instead of the column. */
.shot-scroll {
  width: 100%;
  max-width: 100%;
  /* Always scrollable, never scrolling until it has to: while the frame is
     capped by max-width there is nothing to scroll, so no scrollbar appears.
     Below 620px the frame is released to its natural size and this is what
     catches it — the panel scrolls, the page never does. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.shot-frame {
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  line-height: 0;
}
.shot-frame img {
  display: block;
  width: 100%;
  height: auto;
}
/* Cap each crop at the width it was actually captured at. Below that it
   scales down with the column; above it, it simply stops. */
.shot-frame.w596  { width: 596px; }
.shot-frame.w800  { width: 800px; }
.shot-frame.w887  { width: 887px; }
.shot-frame.w1048 { width: 1048px; }

.shot figcaption {
  font-size: var(--text-caption);
  line-height: 1.5;
  color: var(--mist-dim);
  max-width: 62ch;
  text-align: left;
  /* center.css sets `figcaption { margin-left/right: auto }` globally, which
     floats a narrow caption into the middle of a wide figure. A caption
     belongs under the left edge of the thing it describes. */
  margin-inline: 0;
}
.shot figcaption b { color: var(--ink); font-weight: var(--font-weight-semibold); }

/* ---- The RatneshGold feature: one claim, one piece of evidence ---------- */
.case-feature {
  display: grid;
  /* minmax(0, …) on both tracks, not `1fr 596px`. A grid item defaults to
     `min-width: auto`, so a 596px figure forces its own track wider than the
     column on narrow screens and `max-width:100%` on the image then resolves
     against the blown-out track instead of the page. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 596px);
  gap: 48px;
  align-items: start;
  padding: 36px 0 0;
  border-top: 1px solid var(--line);
}
.case-feature-copy { text-align: left; }
.case-feature-copy h4 {
  font-size: var(--text-subheading);
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  margin: 0 0 12px;
  text-align: left;
}
.case-feature-copy p {
  margin: 0;
  color: var(--mist);
  font-size: var(--text-body-sm);
  line-height: 1.55;
  max-width: 44ch;
  text-align: left;
}
.case-feature .shot-frame { border-radius: var(--radius); }

/* ---- Phone strip -------------------------------------------------------- */
.phone-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 40px;
  align-items: start;
}
.phone-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.phone {
  position: relative;
  width: min(430px, 100%);
  aspect-ratio: 640 / 1351;
  /* A device bezel is an object, not a surface — it stays black in both
     themes, which is why this is the one raw colour in the file. */
  background: #0b0b0d;
  border-radius: 44px;
  padding: 12px;
  box-shadow: var(--shadow-image);
}
.phone::before {
  content: "";
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  width: 40%;
  height: 22px;
  background: #0b0b0d;
  border-radius: 0 0 14px 14px;
  z-index: 2;
}
.phone-screen {
  width: 100%;
  height: 100%;
  border-radius: 32px;
  overflow: hidden;
  background: var(--void-2);
  line-height: 0;
}
.phone-screen img {
  display: block;
  width: 100%;
  height: 100%;
  /* The captures are 640x1351 and the frame is 640/1351 — there is nothing
     to crop, so nothing gets cropped. The old rule chopped every tab bar. */
  object-fit: contain;
}
.phone-item figcaption {
  font-size: var(--text-caption);
  line-height: 1.5;
  color: var(--mist-dim);
  text-align: center;
  max-width: 34ch;
  margin-inline: auto;   /* centred under the device, deliberately */
}
.phone-item figcaption b {
  display: block;
  color: var(--ink);
  font-weight: var(--font-weight-semibold);
  margin-bottom: 2px;
}

/* ---- Stat row: numbers that used to be trapped in a JPEG ---------------- */
.case-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.case-stat {
  background: var(--surface);
  padding: 22px 20px;
  text-align: left;
}
.case-stat b {
  display: block;
  font-size: 30px;
  font-weight: var(--font-weight-semibold);
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.case-stat span {
  display: block;
  margin-top: 9px;
  font-size: var(--text-caption);
  line-height: 1.4;
  color: var(--mist);
}

/* ---- Pipeline: Beamline's actual mechanism, as type not pixels ---------- */
.pipeline {
  display: flex;
  align-items: stretch;
  gap: 14px;
  padding: 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow-x: auto;
}
.pipe-step {
  flex: 1 1 0;
  min-width: 148px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}
.pipe-step h5, .pipe-step h4 {
  margin: 0;
  font-size: var(--text-caption);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mist);
}
.pipe-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pipe-chips span {
  font-size: 11px;
  line-height: 1.4;
  padding: 4px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  color: var(--ink);
  background: var(--surface-canvas);
  white-space: nowrap;
}
.pipe-step p {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: 1.4;
  color: var(--ink);
  text-align: left;
}
.pipe-step p em {
  display: block;
  font-style: normal;
  font-size: var(--text-caption);
  color: var(--mist);
  margin-top: 4px;
}
.pipe-arrow {
  flex: none;
  align-self: center;
  width: 20px;
  height: 20px;
  color: var(--accent);
}
.pipe-arrow svg { width: 100%; height: 100%; display: block; }

/* ---- Two crops side by side --------------------------------------------- */
/* 800 + 224 + a 32px gap is 1056, wider than the 1016px container. The wide
   crop takes the remainder (768px, 96% of capture) rather than both columns
   being squeezed; the autonomy card keeps its exact 224px. */
.shot-duo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 224px;
  gap: 24px;
  align-items: start;
}

/* ---- Prototype disclosure ----------------------------------------------- */
.case-note {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--accent-tint);
  max-width: 62ch;
}
.case-note svg {
  flex: none;
  width: 17px;
  height: 17px;
  margin-top: 1px;
  color: var(--accent);
}
.case-note p {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: 1.5;
  color: var(--ink);
  text-align: left;
}

/* ==========================================================================
   Responsive. The breakpoints are set where the content actually breaks,
   not at round numbers: 1080 is where the widest crop stops fitting the
   container, 860 is where the two-column lede stops holding a measure.
   ========================================================================== */
@media (max-width: 1080px) {
  .case-feature { grid-template-columns: 1fr; gap: 32px; }
  .case-feature .shot-frame { width: 596px; }
  .shot-duo { grid-template-columns: 1fr; gap: 28px; }
  .shot-duo .shot-frame.w224 { width: 224px; }
}

@media (max-width: 860px) {
  .case-lede { grid-template-columns: 1fr; gap: 28px; }
  .case-head h3 { font-size: var(--text-heading-sm); line-height: var(--leading-heading-sm); }
  .case { gap: 32px; }
  .case-stat { padding: 18px 16px; }
  .case-stat b { font-size: 26px; }
}

@media (max-width: 620px) {
  .phone-strip { grid-template-columns: 1fr; gap: 44px; }
  .phone { width: min(340px, 88vw); }
  /* Below this width a landscape crop can no longer be read inline, so it is
     released to its full capture size and scrolls inside its own panel
     rather than shrinking into an unreadable thumbnail. */
  .shot-scroll .shot-frame { width: max-content; max-width: none; }
  .shot-scroll .shot-frame img { width: auto; height: auto; max-width: none; }
  .shot-hint { display: block; }
  .pipeline { padding: 20px; }
}

.shot-hint {
  display: none;
  font-size: 11px;
  color: var(--mist-dim);
  letter-spacing: 0.04em;
}

@media (prefers-reduced-motion: reduce) {
  .shot-scroll { scroll-behavior: auto; }
}

/* ==========================================================================
   Screen gallery + viewer

   The page shows cropped detail; this is where the full screens live. A
   native <details> so it works with JavaScript off, enhanced into a
   full-screen viewer with an actual-size mode for the dense dashboards.
   ========================================================================== */

.screens {
  border-top: 1px solid var(--line);
  padding-top: 22px;
}

/* --- The disclosure row, styled as a control ---------------------------- */
.screens > summary {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  list-style: none;
  padding: 9px 16px 9px 13px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--ink);
  background: var(--surface);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.screens > summary::-webkit-details-marker { display: none; }
.screens > summary:hover { border-color: var(--accent); background: var(--accent-tint); }
.screens > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.screens-chevron {
  width: 16px; height: 16px;
  flex: none;
  color: var(--accent);
  transition: transform 0.25s cubic-bezier(0.28, 0.11, 0.32, 1);
}
.screens[open] .screens-chevron { transform: rotate(90deg); }
.screens-count { color: var(--mist); font-weight: var(--font-weight-regular); }

.screens-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
}
.screens-viewall {
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-body-sm);
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.screens-viewall:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }
.screens-hint { font-size: var(--text-caption); color: var(--mist-dim); }

/* --- The grid ----------------------------------------------------------- */
.screens-grid {
  display: grid;
  gap: 26px;
  margin-top: 22px;
}
.screens-grid.is-phone   { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
.screens-grid.is-desktop { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }

.screen { margin: 0; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.screen-shell {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--void-2);
  line-height: 0;
}
.is-phone   .screen-shell { aspect-ratio: 640 / 1351; }
.is-desktop .screen-shell { aspect-ratio: 1100 / 515; }
.screen-shell img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* The whole tile is the control, so the hit area matches what you see. */
.screen-open {
  position: absolute;
  inset: 0;
  z-index: 2;
  border: 0;
  padding: 0;
  cursor: zoom-in;
  background: transparent;
  color: #fff;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
}
.screen-open::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0) 42%);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.screen-open span {
  position: relative;
  z-index: 1;
  margin: 12px;
  padding: 6px 11px;
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.62);
  font-size: 11px;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.screen-open:hover::after,
.screen-open:focus-visible::after { opacity: 1; }
.screen-open:hover span,
.screen-open:focus-visible span { opacity: 1; transform: translateY(0); }
.screen-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.screen figcaption {
  font-size: var(--text-caption);
  line-height: 1.4;
  color: var(--mist);
  text-align: left;
  margin-inline: 0;
}

/* ==========================================================================
   Viewer overlay
   ========================================================================== */
html.sv-open, html.sv-open body { overflow: hidden; }

.sv {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
}
.sv[hidden] { display: none; }
/* Solid, not a backdrop-filter. This page already stacks a WebGL waves
   canvas and the ambient blur layer; adding a backdrop root on top of those
   made the overlay composite as good as transparent. A flat black is what
   the job needs anyway — this is a viewer, not a scrim. */
.sv-backdrop {
  position: absolute;
  inset: 0;
  background: #000;
}
.sv-shell {
  position: relative;
  z-index: 1;
  flex: 1;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0;
}

/* --- Top bar ------------------------------------------------------------ */
.sv-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 18px;
  color: #f5f5f7;
}
.sv-meta { margin: 0; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; text-align: left; }
.sv-project {
  font-size: 11px;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(245, 245, 247, 0.55);
}
.sv-label { font-size: var(--text-body-sm); font-weight: var(--font-weight-semibold); }
.sv-tools { display: flex; align-items: center; gap: 12px; flex: none; }
.sv-count {
  font-size: var(--text-caption);
  color: rgba(245, 245, 247, 0.6);
  font-variant-numeric: tabular-nums;
}
.sv-btn {
  font: inherit;
  font-size: var(--text-caption);
  font-weight: var(--font-weight-semibold);
  color: #f5f5f7;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-pill);
  padding: 7px 14px;
  cursor: pointer;
  transition: background 0.18s ease;
}
.sv-btn:hover { background: rgba(255, 255, 255, 0.22); }
.sv-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sv-btn[aria-pressed="true"] { background: var(--accent-fill); border-color: var(--accent-fill); }
.sv-icon { width: 34px; height: 34px; padding: 0; display: flex; align-items: center; justify-content: center; }
.sv-icon svg { width: 17px; height: 17px; }

/* --- Stage -------------------------------------------------------------- */
.sv-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 64px;
  overflow: hidden;
  min-height: 0;
}
.sv-stage:focus { outline: none; }
.sv-img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
  background: #fff;
}

/* Actual size: the image is released to its own pixels and the stage
   becomes the scroll port, so a 1100px dashboard is read at 1100px. */
.sv-stage.is-actual {
  overflow: auto;
  align-items: flex-start;
  justify-content: flex-start;
  cursor: grab;
  padding: 24px 64px;
}
.sv-stage.is-actual .sv-img {
  max-width: none;
  max-height: none;
  margin: auto;
}
.sv-stage.is-panning { cursor: grabbing; }

/* --- Prev / next -------------------------------------------------------- */
.sv-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.2);
  background: rgba(0, 0, 0, 0.55);
  color: #f5f5f7;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.18s ease;
}
.sv-nav:hover { background: rgba(0, 0, 0, 0.85); }
.sv-nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sv-nav svg { width: 20px; height: 20px; }
.sv-prev { left: 12px; }
.sv-next { right: 12px; }

/* --- Thumbnail rail ----------------------------------------------------- */
.sv-rail {
  display: flex;
  gap: 10px;
  padding: 14px 18px 18px;
  overflow-x: auto;
  scrollbar-width: none;
  justify-content: center;
}
.sv-rail::-webkit-scrollbar { display: none; }
.sv-thumb {
  flex: none;
  width: 62px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 5px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.06);
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.2s ease, border-color 0.2s ease;
}
.sv-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
.sv-thumb:hover { opacity: 0.85; }
.sv-thumb.is-active { opacity: 1; border-color: var(--accent-fill); }
.sv-thumb:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

@media (max-width: 700px) {
  .sv-stage { padding: 0 12px; }
  .sv-stage.is-actual { padding: 12px; }
  .sv-nav { width: 38px; height: 38px; }
  .sv-prev { left: 6px; }
  .sv-next { right: 6px; }
  .sv-rail { justify-content: flex-start; }
  .sv-bar { padding: 12px 14px; gap: 12px; }
  .sv-tools { gap: 8px; }
  .screens-grid.is-phone { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 18px; }
  .screens-grid.is-desktop { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .screens-chevron,
  .screen-open::after,
  .screen-open span,
  .sv-btn,
  .sv-nav,
  .sv-thumb { transition: none; }
}
