/* Shared plumbing for all five design previews.
   Only the reset, the accessibility floor and the photo-frame system live here.
   Every colour, border, radius and layout decision belongs to the design file. */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: 8px; top: -44px; z-index: 100;
  background: var(--ink); color: var(--bg); padding: 8px 14px; font-size: 13px;
  transition: top .15s linear;
}
.skip:focus { top: 8px; }

/* ── photo frames ─────────────────────────────────────────────────────────
   A frame always reserves its space. If the file is missing the image is
   hidden and a placeholder silhouette plus a size label shows instead, so a
   layout under review never shifts because a photo has not arrived yet. */
.photo {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--ph-bg);
  min-width: 0;
}
.photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: relative;
  z-index: 1;
}
.photo.is-empty img { display: none; }

.photo-ph { position: absolute; inset: 0; z-index: 0; }
.photo:not(.is-empty) .photo-ph { display: none; }

/* one figure, for a portrait */
.photo--portrait .photo-ph {
  background-image:
    radial-gradient(circle at 50% 34%, var(--ph-ink) 0 11%, transparent 11.5%),
    radial-gradient(ellipse 34% 26% at 50% 92%, var(--ph-ink) 0 99%, transparent 100%);
  background-repeat: no-repeat;
}
/* a row of figures, for a group shot */
.photo--group .photo-ph {
  background-image:
    radial-gradient(circle at 22px 22px, var(--ph-ink) 0 8px, transparent 8.5px),
    linear-gradient(var(--ph-ink), var(--ph-ink));
  background-size: 44px 100%, 100% 30%;
  background-position: 0 26%, 0 100%;
  background-repeat: repeat-x, no-repeat;
}
.photo-ph::after {
  content: attr(data-label);
  position: absolute; left: 50%; top: 8px; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
  color: var(--ph-label); white-space: nowrap;
  border: 1px solid var(--ph-label); padding: 1px 6px; background: var(--ph-bg);
}

.photo-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 18px 12px 8px;
  font-size: 11px; line-height: 1.4; color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, .62));
}
.photo.is-empty .photo-cap { color: var(--ph-label); background: none; }

img { max-width: 100%; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ── gallery page intro ──────────────────────────────────────────────────
   Each design restyles this; the defaults just keep it readable. */
.galintro { padding: 22px 0 18px; }
.galintro h1 { font-size: 22px; font-weight: 700; margin: 0 0 6px; letter-spacing: -.015em; }
.galintro p { font-size: 13.5px; color: var(--ink-2); margin: 0; max-width: 76ch; line-height: 1.6; }
.galintro .galmeta {
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-3);
  margin-top: 8px; letter-spacing: .04em;
}

.photo--portrait img { object-position: center 20%; }

/* group shots put faces in the upper third; bias the crop so heads survive
   a wide frame. The source images are only 533x417, so the wider the band the
   more aggressive the crop — ask the group for high-resolution originals. */
.photo--group img { object-position: center 30%; }
