/**
 * Layout primitives shared by every project page, in every section.
 *
 * These used to live in uiux/css/oxytocin.css, which meant motion/ and
 * illustration/ had to load another section's project stylesheet to render.
 * The class names keep the old "oxy-" prefix so the existing fragments
 * work unchanged; treat it as a historical name, not a UI/UX-only thing.
 */

/* Vertical stack that a project fragment's content sits in. */
.oxy-main {
  display: flex;
  flex-direction: column;
  width: 100%;
  gap: var(--fragment-gap, var(--spacing-m));
}

.oxy-main .hero-img > img {
  width: 100%;
  height: auto;
  display: block;
}

/* Section heading group: a rule, a title, and an optional subtitle row. */
.sec-head {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.rule {
  border: 0;
  border-top: 1px solid var(--color-primary);
  margin: 0;
}

.subtitle {
  flex: 1;
}

.subtitle-row {
  display: flex;
  align-items: center;
  width: 100%;
  overflow: visible;
  min-height: auto;
  flex-shrink: 0;
  border-top: 1px solid var(--color-primary);
  border-bottom: 1px solid var(--color-primary);
  padding: var(--spacing-xs) 0;
}

.subtitle-row .subtitle {
  overflow: visible;
  white-space: normal;
  line-height: 1.25;
}

/* Exported diagram (concept map, site map, annotated breakdown). These sit
   narrower than the column in Figma and centred, so they keep their own width
   here instead of stretching to the full content width like a photo. Drop the
   modifier for a diagram that does run full width. */
.diagram {
  margin-inline: auto;
}

.diagram-narrow {
  width: min(100%, 72%);
}

.diagram-wide {
  width: min(100%, 92%);
}

@media screen and (max-width: 1060px) {
  .diagram-narrow,
  .diagram-wide {
    width: 100%;
  }
}

/* Shown when a fragment fails to load (see spa.js). */
.spa-error {
  padding: var(--spacing-m);
}

/* Two media side by side, at whatever ratio the design uses. The Product case
   studies pair a photo with a screen (600:381), or show two states of the same
   surface (1:1). Oxytocin already had .oxy-lowfi-row for this, but that lives in
   web/css/oxytocin.css and only loads on that project — this is the shared one.
   Set the ratio at the call site: style="--media-cols: 600fr 381fr". */
.media-row {
  display: grid;
  grid-template-columns: var(--media-cols, 1fr 1fr);
  /* Four or more narrow panels read as one strip at a tighter gap than a pair
     of large images wants, so the gap is overridable per call site too. */
  gap: var(--media-gap, var(--spacing-m));
  align-items: start;
  width: 100%;
}

/* Pairs two media of different proportions to one shape. Without it the taller
   original sets a ragged bottom edge; the design instead crops both to a single
   cell, so give it that cell's ratio at the call site:
   style="--media-ratio: 1001 / 1340". Only the overflow is lost — nothing is
   scaled out of proportion. .img-duo does something similar but wants <figure>
   children and sizes by viewport height rather than by the design's ratio. */
.media-row-even > .hero-img {
  aspect-ratio: var(--media-ratio, 1 / 1);
}

.media-row-even > .hero-img > img,
.media-row-even > .hero-img > video {
  height: 100%;
  object-fit: cover;
}

/* Like .media-row-even, but only the neighbours are cropped: the first media
   keeps its own proportion and sets the row height, and everything after it
   fills that height. Use it when the design shows one image whole and lets a
   shorter one beside it reach the same bottom edge. */
.media-row-lead {
  align-items: stretch;
}

.media-row-lead > .hero-img:not(:first-child) > img,
.media-row-lead > .hero-img:not(:first-child) > video {
  height: 100%;
  object-fit: cover;
}

/* A single image that sits narrower than the column and centred, given as a
   percentage of the content width so it keeps the design's proportion. */
.media-inset {
  width: var(--media-inset, 60%);
  margin-inline: auto;
}

@media screen and (max-width: 1060px) {
  .media-row {
    grid-template-columns: 1fr;
  }

  /* One column: no shared row height to reach, so the crop goes away. */
  .media-row-lead > .hero-img:not(:first-child) > img,
  .media-row-lead > .hero-img:not(:first-child) > video {
    height: auto;
    object-fit: contain;
  }

  .media-inset {
    width: 100%;
  }
}

/* A .context-row inside a case study is a row of framed cards, not the prose
   block .case-main turns a bare .card into. Put the frame and the full-width
   cell back; Momo's design principles are the first to need it. */
.case-main .context-row > .card:not(:has(> .full-text)) {
  align-items: stretch;
  padding: var(--spacing-l);
  border: 1px solid var(--color-primary);
  border-radius: var(--corner-radius-l);
}

.case-main .context-row > .card:not(:has(> .full-text)) > * {
  width: 100%;
}

@media screen and (max-width: 1060px) {
  .context-row {
    grid-auto-flow: row;
  }
}

/* A starred subtitle and the media or cards it introduces are one unit: they
   stay together, and the seam between two units is wider than the gap inside
   either. .main-sec already puts spacing-m between its children, so add only
   the remainder rather than fighting that gap. */
.sub-block {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-m);
  width: 100%;
}

