/* ==========================================================================
   Darkroom — a dark cinematic portfolio system
   Palette is committed to a single dark world on purpose. Every colour is
   painted explicitly so the page never borrows a host background.
   ========================================================================== */

:root {
  /* Ground and surfaces: cool blacks, the way a selenium-toned print sits */
  --ink:        #08080a;
  --ink-deep:   #050506;
  --surface:    #101014;
  --surface-2:  #17171c;

  /* Paper tones: warm highlights against the cool black */
  --paper:      #ece6dc;
  --paper-dim:  #b9b2a7;
  --silver:     #8d877e;
  --silver-low: #5e5a55;

  /* Safelight: the one accent, taken straight from the logo's gold.
     Ember is the logo's orange, reserved for the 18+ lock so a gated
     thing never reads the same as an ordinary highlight. */
  --safelight:      #e0a81e;
  --safelight-deep: #8f6a0f;
  --safelight-glow: rgba(224, 168, 30, 0.15);
  --ember:          #ef8b2a;

  --hairline:      rgba(236, 230, 220, 0.10);
  --hairline-soft: rgba(236, 230, 220, 0.05);

  --font-display: "Bodoni Moda", "Didot", "Playfair Display", Georgia, serif;
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --fs-micro: 0.6875rem;
  --fs-xs:    0.75rem;
  --fs-sm:    0.8125rem;
  --fs-base:  0.9375rem;
  --fs-lg:    1.0625rem;
  --fs-xl:    1.375rem;
  --fs-2xl:   clamp(1.75rem, 3.4vw, 2.75rem);
  --fs-3xl:   clamp(2.75rem, 9vw, 7.5rem);

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --measure: 62ch;
  --rule: 1px;

  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.65;
  font-weight: 350;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

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

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--safelight);
  color: var(--ink);
  padding: 0.6rem 1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  z-index: 200;
}
.skip:focus { left: 0.5rem; top: 0.5rem; }

/* --------------------------------------------------------------- shell -- */

.shell {
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site-head {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--ink) 86%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: var(--rule) solid var(--hairline-soft);
}

.site-head__inner {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 0.55rem;
}

/* The logo is the wordmark. Sized by height so the header rhythm holds
   whatever the file's pixel dimensions are. */
.wordmark {
  display: block;
  flex: 0 0 auto;
  line-height: 0;
}

.wordmark img {
  /* Tall enough that the PHOTOGRAPHY line stays readable, no taller. */
  height: clamp(2.1rem, 4vw, 2.75rem);
  width: auto;
  display: block;
}

@media (max-width: 560px) {
  .wordmark img { height: 2.4rem; }
}

.site-head__inner { align-items: center; }

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.9rem, 2.4vw, 2.1rem);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.nav a {
  color: var(--silver);
  padding-block: 0.15rem;
  border-bottom: var(--rule) solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.nav a:hover { color: var(--paper); border-bottom-color: var(--hairline); }
.nav a[aria-current="page"] { color: var(--paper); border-bottom-color: var(--safelight); }
.nav a.is-restricted::after {
  content: "18+";
  font-size: 0.5rem;
  vertical-align: super;
  margin-left: 0.25em;
  letter-spacing: 0.05em;
  color: var(--safelight-deep);
}

/* ----------------------------------------------------------------- hero -- */

.hero {
  position: relative;
  padding-block: clamp(3.5rem, 12vh, 8rem) clamp(2.5rem, 8vh, 5rem);
}

.hero__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--silver-low);
  margin: 0 0 1.6rem;
}

.hero__title {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: 400;
  line-height: 0.94;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}

.hero__title em {
  font-style: italic;
  color: var(--paper-dim);
}

.hero__lede {
  max-width: 46ch;
  margin: clamp(1.5rem, 4vh, 2.75rem) 0 0;
  color: var(--paper-dim);
  font-size: var(--fs-lg);
  line-height: 1.6;
}

.hero__plate {
  margin-top: clamp(2.5rem, 8vh, 5rem);
  position: relative;
  overflow: hidden;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
}

.hero__plate img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
}

.plate-caption {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  padding: 0.85rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-low);
}

/* -------------------------------------------------------------- section -- */

.section {
  padding-block: clamp(3rem, 9vh, 6rem);
  border-top: var(--rule) solid var(--hairline-soft);
}

.section--flush { border-top: 0; }

.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: clamp(1.75rem, 5vh, 3rem);
}

.section__title {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

.section__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
}

.prose {
  max-width: var(--measure);
  color: var(--paper-dim);
}
.prose p { margin: 0 0 1.15em; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--paper); font-weight: 500; }
.prose a {
  color: var(--paper);
  border-bottom: var(--rule) solid var(--safelight-deep);
  transition: border-color 160ms ease;
}
.prose a:hover { border-bottom-color: var(--safelight); }

/* ----------------------------------------------------------- plate grid -- */

.plates {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: start;
  gap: clamp(1.25rem, 3vw, 2.75rem);
}

.plate {
  grid-column: span 12;
  margin: 0;
  position: relative;
}

.plate__frame {
  position: relative;
  overflow: hidden;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
  display: block;
  width: 100%;
  padding: 0;
  cursor: zoom-in;
  color: inherit;
  font: inherit;
  text-align: left;
}

.plate__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1), opacity 400ms ease;
  opacity: 0.92;
}

.plate__frame:hover img,
.plate__frame:focus-visible img {
  transform: scale(1.022);
  opacity: 1;
}

.plate__index {
  position: absolute;
  top: 0.7rem;
  left: 0.8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  color: var(--paper);
  mix-blend-mode: difference;
  font-variant-numeric: tabular-nums;
}

.plate__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  padding-top: 0.75rem;
}

.plate__name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-base);
  color: var(--paper);
}

.plate__data {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
}

/* Irregular contact-sheet rhythm at wider viewports */
@media (min-width: 720px) {
  .plate--wide    { grid-column: span 7; }
  .plate--narrow  { grid-column: span 5; }
  .plate--half    { grid-column: span 6; }
  .plate--full    { grid-column: span 12; }
  .plate--offset  { grid-column: 3 / span 8; }
}

.ratio-3-2 .plate__frame { aspect-ratio: 3 / 2; }
.ratio-2-3 .plate__frame { aspect-ratio: 2 / 3; }
.ratio-1-1 .plate__frame { aspect-ratio: 1 / 1; }
.ratio-4-5 .plate__frame { aspect-ratio: 4 / 5; }
.ratio-16-9 .plate__frame { aspect-ratio: 16 / 9; }

/* ------------------------------------------------------------ plate scale -- */
/* Set pages only, since .plates appears nowhere else.
   The grid becomes 24 columns instead of 12 while the width classes keep
   their numbers, so plate--wide goes from 7/12 to 7/24. Every plate lands
   at half its former width, a quarter of its former area, and four fit
   across a row where two did. Below 720px nothing changes: plates are
   still one per row, which is the only sensible thing on a phone. */

@media (min-width: 720px) {
  .plates {
    grid-template-columns: repeat(24, 1fr);
    gap: clamp(0.9rem, 1.8vw, 1.6rem);
  }
}


/* --------------------------------------------------------- set covers -- */

.covers {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(22rem, 100%), 1fr));
  gap: clamp(1.5rem, 3.5vw, 3rem);
}

.cover { display: block; }

.cover__frame {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
}

.cover__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.78;
  transition: transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1), opacity 400ms ease;
}

.cover:hover .cover__frame img,
.cover:focus-visible .cover__frame img {
  transform: scale(1.03);
  opacity: 1;
}

.cover__lock {
  position: absolute;
  top: 0.7rem;
  right: 0.8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  color: var(--ink);
  background: var(--safelight);
  padding: 0.15rem 0.45rem;
}

.cover__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 1.5rem;
  padding-top: 0.85rem;
  border-top: var(--rule) solid var(--hairline-soft);
  margin-top: 0.85rem;
}

.cover__title {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  color: var(--paper-dim);
  transition: color 160ms ease;
}

.cover:hover .cover__title { color: var(--paper); }

.cover__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- set page head -- */

.series-masthead {
  display: grid;
  gap: 0.75rem;
  margin-bottom: clamp(2rem, 6vh, 3.5rem);
  padding-bottom: clamp(1.25rem, 4vh, 2rem);
  border-bottom: var(--rule) solid var(--hairline-soft);
}

.series-masthead__title {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

.series-masthead__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.series-masthead__note {
  max-width: 52ch;
  color: var(--paper-dim);
  margin: 0.35rem 0 0;
}

.series-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-top: clamp(2.5rem, 8vh, 4.5rem);
  padding-top: clamp(1.25rem, 4vh, 2rem);
  border-top: var(--rule) solid var(--hairline-soft);
}

.series-nav__link {
  display: grid;
  gap: 0.3rem;
  color: var(--silver);
  transition: color 160ms ease;
}
.series-nav__link:hover { color: var(--paper); }
.series-nav__link--next { text-align: right; }
.series-nav--single { justify-content: center; }

.series-nav__dir {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--silver-low);
}

.series-nav__name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-lg);
}

.series-nav__link--index {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-bottom: var(--rule) solid var(--hairline);
  padding-bottom: 0.2rem;
}

.ledger__lock {
  font-family: var(--font-mono);
  font-size: 0.5rem;
  vertical-align: super;
  letter-spacing: 0.05em;
  color: var(--safelight-deep);
}

/* ----------------------------------------------------------- model link -- */
/* A box at the top right of a set page, opposite the title, pointing back
   at the page for whoever is in the set. One link per model. */

.series-masthead__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem 2rem;
}

.series-masthead__head .series-masthead__title { margin: 0; }

.model-links {
  display: grid;
  gap: 0.3rem;
  justify-items: end;
  text-align: right;
  padding: 0.7rem 1rem;
  border: var(--rule) solid var(--hairline);
  background: var(--surface);
  flex: 0 0 auto;
  transition: border-color 160ms ease;
}

.model-links:hover { border-color: var(--safelight-deep); }

.model-links__label {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver-low);
}

.model-links__name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-lg);
  color: var(--paper-dim);
  border-bottom: var(--rule) solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}

.model-links__name::after {
  content: " \2192";
  font-style: normal;
  color: var(--silver-low);
}

.model-links__name:hover {
  color: var(--paper);
  border-bottom-color: var(--safelight-deep);
}
.model-links__name:hover::after { color: var(--safelight); }

@media (max-width: 40rem) {
  .model-links { justify-items: start; text-align: left; }
}

/* ------------------------------------------------------------- lightbox -- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: color-mix(in srgb, var(--ink-deep) 96%, transparent);
  display: grid;
  grid-template-rows: 1fr auto;
  padding: clamp(1rem, 4vw, 3rem);
  gap: 1rem;
}

.lightbox[hidden] { display: none; }

.lightbox__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  overflow: hidden;
  cursor: zoom-out;
}

.lightbox__holder {
  position: relative;
  display: inline-flex;
  max-width: 100%;
  max-height: 100%;
  min-height: 0;
}

.lightbox__stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border: var(--rule) solid var(--hairline-soft);
  cursor: default;
}

/* Sits over the enlarged plate so the browser's context menu has no image
   to offer. See the note in the README: a deterrent, not protection. */
.lightbox__shield {
  position: absolute;
  inset: 0;
  cursor: default;
}

.lightbox__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver);
}

.lightbox__controls { display: flex; gap: 0.5rem; }

.lb-btn {
  background: transparent;
  border: var(--rule) solid var(--hairline);
  color: var(--paper-dim);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease;
}
.lb-btn:hover { color: var(--paper); border-color: var(--safelight-deep); }

/* ----------------------------------------------------------- safelight -- */
/* The 18+ gate, styled as a darkroom door. Closed by default in CSS so it
   never depends on JavaScript running to stay closed. */

body.is-gated { overflow: hidden; }
body.is-gated .gated-content { display: none; }

.gate {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(207, 139, 60, 0.10), transparent 60%),
    var(--ink-deep);
}

body:not(.is-gated) .gate { display: none; }

.gate__panel {
  max-width: 34rem;
  width: 100%;
  text-align: left;
  border: var(--rule) solid var(--hairline);
  background: var(--surface);
  padding: clamp(1.75rem, 5vw, 3rem);
}

.gate__lamp {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--safelight);
  margin-bottom: 1.75rem;
}

.gate__lamp::before {
  content: "";
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--safelight);
  box-shadow: 0 0 0 0.35rem var(--safelight-glow);
  animation: breathe 4s ease-in-out infinite;
}

@keyframes breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

.gate__title {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 400;
  line-height: 1.05;
  margin: 0 0 1rem;
  text-wrap: balance;
}

.gate__body {
  color: var(--paper-dim);
  font-size: var(--fs-sm);
  max-width: 46ch;
  margin: 0 0 1.75rem;
}

.gate__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.btn {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.85rem 1.5rem;
  border: var(--rule) solid var(--hairline);
  background: transparent;
  color: var(--paper-dim);
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.btn:hover { color: var(--paper); border-color: var(--paper-dim); }

.btn--primary {
  background: var(--safelight);
  border-color: var(--safelight);
  color: var(--ink);
  font-weight: 500;
}
.btn--primary:hover {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

.gate__fine {
  margin: 1.5rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  line-height: 1.7;
  color: var(--silver-low);
}

.restricted-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  padding: 0.7rem 1rem;
  margin-bottom: clamp(1.75rem, 5vh, 3rem);
  border: var(--rule) solid var(--safelight-deep);
  background: var(--safelight-glow);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-dim);
}

.restricted-bar button {
  background: none;
  border: 0;
  border-bottom: var(--rule) solid var(--safelight-deep);
  color: var(--safelight);
  font: inherit;
  padding: 0 0 0.1rem;
  cursor: pointer;
}
.restricted-bar button:hover { color: var(--paper); }

/* --------------------------------------------------------------- index -- */

.ledger {
  display: grid;
  gap: 0;
  border-top: var(--rule) solid var(--hairline-soft);
}

.ledger__row {
  display: grid;
  grid-template-columns: 4rem 1fr auto;
  gap: 1rem 1.5rem;
  align-items: baseline;
  padding-block: 1.1rem;
  border-bottom: var(--rule) solid var(--hairline-soft);
  transition: background 200ms ease, padding-inline 200ms ease;
}

.ledger__row:hover { background: var(--surface); }

.ledger__num,
.ledger__year {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
}

.ledger__name {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 400;
}

.ledger__row:hover .ledger__name { color: var(--paper); }

/* -------------------------------------------------------------- contact -- */

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}

.field {
  border-top: var(--rule) solid var(--hairline);
  padding-top: 0.9rem;
}

.field__label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver-low);
  margin-bottom: 0.5rem;
}

.field__value {
  font-size: var(--fs-lg);
  color: var(--paper);
}

/* --------------------------------------------------------------- footer -- */

.site-foot {
  border-top: var(--rule) solid var(--hairline-soft);
  padding-block: clamp(2rem, 6vh, 3.5rem);
  margin-top: clamp(3rem, 10vh, 6rem);
}

.site-foot__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver-low);
}

.site-foot a { border-bottom: var(--rule) solid transparent; }
.site-foot a:hover { color: var(--paper-dim); border-bottom-color: var(--hairline); }

/* ------------------------------------------------------------- protect -- */
/* Makes saving a picture inconvenient rather than impossible. The image is
   still in the browser's cache and still at a public URL; this only removes
   the one-click paths (right-click, long-press, drag to desktop). */

[data-protect] img {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  user-drag: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
}

[data-protect] {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* ----------------------------------------------------------- set groups -- */
/* Collapsible bars for dividing one set by model, location, or session.
   Built on <details>/<summary>, so it works with no JavaScript at all and
   the keyboard handles it for free. Plates inside a closed group are
   display:none, which is why the lightbox skips them automatically. */

.set-groups {
  display: grid;
}

.set-group {
  border-top: var(--rule) solid var(--hairline);
}

/* The masthead already draws a rule, so the first bar does not need one. */
.set-groups > .set-group:first-of-type { border-top: 0; }

.set-group:last-of-type {
  border-bottom: var(--rule) solid var(--hairline);
}

.set-group__bar {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.15rem 0;
  cursor: pointer;
  list-style: none;
}

/* Hide the browser's default triangle in every engine. */
.set-group__bar::-webkit-details-marker { display: none; }
.set-group__bar::marker { content: ""; }

.set-group__bar:focus-visible {
  outline: 2px solid var(--safelight);
  outline-offset: 3px;
}

.set-group__name {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  color: var(--paper-dim);
  transition: color 160ms ease;
}

.set-group__bar:hover .set-group__name,
.set-group[open] .set-group__name { color: var(--paper); }

.set-group__meta {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--silver-low);
  font-variant-numeric: tabular-nums;
}

/* A box on the right of a group bar linking to that model's page.
   It sits first in the right-hand cluster, so the reading order across
   the bar is: model name, link out, plate count, open/close mark. */

.set-group__link {
  margin-left: auto;
  align-self: center;
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--silver);
  border: var(--rule) solid var(--hairline);
  padding: 0.35rem 0.7rem;
  transition: color 160ms ease, border-color 160ms ease;
}

.set-group__link:hover { color: var(--paper); border-color: var(--safelight-deep); }

/* With a link present it owns the auto margin, so the count must not. */
.set-group__link ~ .set-group__meta { margin-left: 0; }

/* A plus that becomes a minus when the group is open. */
.set-group__mark {
  position: relative;
  align-self: center;
  flex: 0 0 auto;
  width: 0.7rem;
  height: 0.7rem;
}

.set-group__mark::before,
.set-group__mark::after {
  content: "";
  position: absolute;
  background: var(--silver);
  transition: transform 220ms ease, background 160ms ease;
}

.set-group__mark::before {
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  transform: translateY(-50%);
}

.set-group__mark::after {
  left: 50%;
  top: 0;
  width: 1px;
  height: 100%;
  transform: translateX(-50%);
}

.set-group[open] .set-group__mark::after { transform: translateX(-50%) scaleY(0); }
.set-group[open] .set-group__mark::before { background: var(--safelight); }

.set-group__body {
  padding-bottom: clamp(1.75rem, 5vh, 3rem);
}

/* --------------------------------------------------------- compact covers -- */
/* Small cover plates, used on model pages where one model may appear in
   several sets and the page is an index rather than a gallery. */

.covers--compact {
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: clamp(1.1rem, 2.4vw, 1.9rem);
}

.covers--compact .cover__frame { aspect-ratio: 4 / 3; }
.covers--compact .cover__title { font-size: var(--fs-lg); }
.covers--compact .cover__caption {
  padding-top: 0.7rem;
  margin-top: 0.7rem;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
}

/* ------------------------------------------------------------ locked cover -- */
/* A cover plate for a gated set. It deliberately carries no photograph:
   a picture here would be visible to everyone the gate is meant to stop. */

.cover--locked .cover__frame {
  display: grid;
  place-content: center;
  gap: 0.75rem;
  justify-items: center;
  text-align: center;
  padding: 1.25rem;
  border-color: var(--safelight-deep);
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(239, 139, 42, 0.10), transparent 65%),
    var(--surface);
}

.cover--locked .cover__lamp {
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: var(--ember);
  box-shadow: 0 0 0 0.35rem rgba(239, 139, 42, 0.14);
}

.cover--locked .cover__locked-label {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ember);
}

.cover--locked .cover__locked-note {
  font-size: var(--fs-sm);
  color: var(--silver);
  max-width: 22ch;
}

.cover--locked:hover .cover__frame { border-color: var(--ember); }

.cover__lock { background: var(--ember); }

/* ------------------------------------------------------------ gated veil -- */
/* An alternative to the locked card: the cover photograph shows, and a
   translucent panel slides across the right half on hover carrying the
   18+ mark. Note the trade: the photograph itself is public here, so
   pick a cover frame you are happy to have indexed. On touch, where
   there is no hover, the panel simply stays put. */

.cover--gated .cover__frame { position: relative; overflow: hidden; }

.cover__veil {
  position: absolute;
  inset: 0 0 0 50%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.5rem;
  padding: 0.75rem;
  text-align: center;
  background: color-mix(in srgb, var(--ink-deep) 74%, transparent);
  -webkit-backdrop-filter: blur(7px) saturate(0.6);
  backdrop-filter: blur(7px) saturate(0.6);
  border-left: var(--rule) solid var(--ember);
  transform: translateX(101%);
  transition: transform 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
  will-change: transform;
}

.cover--gated:hover .cover__veil,
.cover--gated:focus-visible .cover__veil { transform: translateX(0); }

.cover__veil-mark {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--ember);
  line-height: 1;
}

.cover__veil-note {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-dim);
  line-height: 1.5;
}

/* No hover to trigger it, so show it. */
@media (hover: none) {
  .cover__veil { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .cover__veil { transition: none; }
}

/* ---------------------------------------------------------- template banner -- */
/* Only appears on the template files. Delete it in your copy. */

.template-banner {
  background: var(--safelight-glow);
  border-bottom: var(--rule) solid var(--safelight-deep);
}

.template-banner__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.25rem;
  padding-block: 0.7rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.08em;
  line-height: 1.7;
  color: var(--paper-dim);
}

.template-banner__tag {
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--safelight);
  font-weight: 500;
}

/* ------------------------------------------------------------ home page -- */
/* The front page is a doorway, not a gallery. Everything here is sized so
   the whole thing lands inside a screen or so. */

.hero--home {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  padding-block: clamp(2rem, 6vh, 3.5rem) clamp(1.5rem, 4vh, 2.5rem);
}

@media (min-width: 60rem) {
  .hero--home { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); }
}

.brandmark { display: block; max-width: min(20rem, 100%); margin: 0; }
.brandmark img { width: 100%; height: auto; display: block; }

.hero--home .hero__title {
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  line-height: 1.02;
  margin: 0;
}

.hero--home .hero__lede {
  font-size: var(--fs-base);
  margin-top: 1rem;
  max-width: 44ch;
}

/* --------------------------------------------------------- series intro -- */
/* The write-up under a set's title. On a wide screen it simply sits there
   at three quarters width. On a phone, where a few hundred words push the
   photographs right off the bottom of the screen, it becomes a fixed
   box with its own scrollbar, so the wall starts near the top either way.

   The width also goes back to full on a phone. Three quarters of a 390px
   screen is about thirty characters a line, which makes a short piece of
   writing look twice as long as it is. */

.series-intro {
  width: 75%;
  margin: clamp(1rem, 3vh, 1.6rem) auto 0;
  color: var(--paper-dim);
  font-size: var(--fs-base);
  line-height: 1.7;
}

.series-intro p { margin: 0 0 1em; }
.series-intro p:last-child { margin-bottom: 0; }

@media (max-width: 47.999rem) {
  .series-intro {
    width: 100%;
    max-height: clamp(11rem, 34vh, 17rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: clamp(0.8rem, 3vw, 1.1rem);
    border: var(--rule) solid var(--hairline);
    background: var(--ink-deep);
    scrollbar-width: thin;
    scrollbar-color: var(--silver-low) transparent;
  }

  .series-intro::-webkit-scrollbar { width: 9px; }
  .series-intro::-webkit-scrollbar-track { background: transparent; }
  .series-intro::-webkit-scrollbar-thumb {
    background: var(--silver-low);
    border: 3px solid var(--ink-deep);
    border-radius: 5px;
  }
  .series-intro::-webkit-scrollbar-thumb:hover { background: var(--silver); }
}

/* -------------------------------------------------------------- portals -- */
/* The two doors on the front page. Each is one big link with photographs
   cross-fading behind its name, the same trick as the Sets banner.

   Deliberately open-ended: they say "Sets" and "Models" rather than
   listing them, so adding a fiftieth set changes nothing here. To add a
   photograph to either door, add one more <img class="portal__layer">.
   The two run on slightly different intervals so they do not flip in
   step with each other. */

.portals {
  display: grid;
  gap: clamp(0.9rem, 2vw, 1.6rem);
}

@media (min-width: 48rem) {
  .portals { grid-template-columns: 1fr 1fr; }
}

.portal {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  height: clamp(13rem, 34vh, 21rem);
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
  text-decoration: none;
  transition: border-color 240ms ease;
}

.portal:hover,
.portal:focus-visible { border-color: var(--silver-low); }

.portal__layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 900ms ease, transform 900ms ease;
}

.portal__layer.is-on { opacity: 1; }
.portal:hover .portal__layer.is-on { transform: scale(1.03); }

.portal__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(8,8,10,0.34), rgba(8,8,10,0.62)),
    radial-gradient(65% 60% at 50% 50%, rgba(8,8,10,0.20), rgba(8,8,10,0.58));
  transition: opacity 240ms ease;
}

.portal:hover .portal__scrim { opacity: 0.82; }

.portal__title {
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 5.5vw, 3.6rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.03em;
  color: var(--paper);
  text-shadow: 0 2px 24px rgba(0,0,0,0.7);
}

.portal__hint {
  position: absolute;
  bottom: clamp(0.8rem, 2.5vh, 1.4rem);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--paper-dim);
  text-shadow: 0 1px 10px rgba(0,0,0,0.8);
  opacity: 0.75;
  transition: opacity 240ms ease;
}

.portal:hover .portal__hint { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .portal__layer { transition: none; }
}

/* -------------------------------------------------------------- collage -- */
/* Masonry: equal-width columns, each filled top to bottom with whole
   photographs. Nothing is cropped, so a portrait tile is simply taller
   than a landscape one and the bottom edge comes out ragged. That is the
   trade for keeping every frame intact.

   The order is shuffled by the script on every load. The file's own order
   is pre-mixed as well, so with JavaScript off the wall is still an
   assortment rather than one model followed by the next.

   Column count follows the width. Each tile carries its real width and
   height, so the columns are laid out correctly before a single
   photograph has downloaded, and nothing jumps as they arrive. */

.collage {
  columns: 2;
  column-gap: clamp(0.5rem, 1.2vw, 0.9rem);
}

@media (min-width: 40rem) { .collage { columns: 3; } }
@media (min-width: 62rem) { .collage { columns: 4; } }
@media (min-width: 90rem) { .collage { columns: 5; } }

.collage__tile {
  display: block;
  margin: 0 0 clamp(0.5rem, 1.2vw, 0.9rem);
  -webkit-column-break-inside: avoid;
  break-inside: avoid;
}

.collage__frame {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  border: var(--rule) solid var(--hairline-soft);
  background: var(--ink-deep);
  cursor: zoom-in;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 200ms ease;
}

.collage__frame img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0.82;
  transition: opacity 300ms ease;
}

.collage__frame:hover img,
.collage__frame:focus-visible img { opacity: 1; }
.collage__frame:hover { border-color: var(--hairline); }

/* --------------------------------------------------------------- ribbon -- */
/* A band of uncropped photographs that drifts sideways for ever. The box
   is a fixed height, so however many photographs you list the front page
   costs the same. Each one keeps its own shape: portrait plates come out
   narrow, landscape plates wide, nothing is cut.

   Without JavaScript, or for anyone who has asked for reduced motion, it
   stays put and can be dragged sideways instead. The script adds is-live,
   clones the row to close the loop, and works out the timing from the real
   width so the speed is the same whether you list eight or eighty. */

.ribbon {
  position: relative;
  height: clamp(9rem, 20vh, 13rem);
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--ink-deep);
  border-block: var(--rule) solid var(--hairline-soft);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
}

.ribbon::-webkit-scrollbar { display: none; }

/* Once the script has cloned the row, native scrolling gives way to the
   animation. */
.ribbon.is-live { overflow: hidden; }

.ribbon__track {
  display: flex;
  align-items: center;
  height: 100%;
  width: max-content;
  gap: clamp(0.4rem, 1vw, 0.8rem);
}

.ribbon.is-live .ribbon__track {
  animation: ribbon-drift var(--ribbon-time, 120s) linear infinite;
  will-change: transform;
}

/* Hovering, tabbing into it, or holding a finger on it all stop the drift,
   so a photograph can be looked at or clicked without chasing it. */
.ribbon.is-live:hover .ribbon__track,
.ribbon.is-live:focus-within .ribbon__track,
.ribbon.is-held .ribbon__track { animation-play-state: paused; }

@keyframes ribbon-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(var(--ribbon-shift, 0px) * -1), 0, 0); }
}

.ribbon__item {
  display: block;
  height: 100%;
  flex: 0 0 auto;
}

.ribbon__frame {
  display: block;
  height: 100%;
  border: var(--rule) solid var(--hairline-soft);
  background: var(--ink);
}

/* height fixed, width free: this is what keeps every plate uncropped. */
.ribbon__frame img {
  display: block;
  height: 100%;
  width: auto;
  opacity: 0.72;
  transition: opacity 300ms ease;
}

.ribbon__item:hover .ribbon__frame img,
.ribbon__item:focus-visible .ribbon__frame img { opacity: 1; }
.ribbon__item:hover .ribbon__frame { border-color: var(--hairline); }

@media (prefers-reduced-motion: reduce) {
  .ribbon.is-live { overflow-x: auto; }
  .ribbon.is-live .ribbon__track { animation: none; }
}

/* ---------------------------------------------------------------- strip -- */
/* The older front-page row: square tiles, cropped to fit. Kept so any page
   still using it does not break. */

.strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: clamp(0.5rem, 1.2vw, 0.9rem);
}

.tile { display: block; position: relative; }

.tile__frame {
  display: block;
  position: relative;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
}

.tile__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.75;
  transition: transform 600ms cubic-bezier(.2,.7,.2,1), opacity 300ms ease;
}

.tile:hover .tile__frame img,
.tile:focus-visible .tile__frame img { opacity: 1; transform: scale(1.05); }

.tile__label {
  display: block;
  padding-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver-low);
  transition: color 160ms ease;
}
.tile:hover .tile__label { color: var(--paper-dim); }

/* ------------------------------------------------------------------ duo -- */
/* Sets and Models side by side, so the two short lists cost one screen
   between them rather than one each. */

.duo {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
}

@media (min-width: 48rem) {
  .duo { grid-template-columns: 1fr 1fr; }
}

.section--tight { padding-block: clamp(1.75rem, 4.5vh, 2.75rem); }

.section--tight .section__head { margin-bottom: 1.1rem; }
.duo .section__head { margin-bottom: 1rem; }

/* --------------------------------------------------------- sets banner -- */
/* A third-of-a-screen band at the top of the Sets page. Photographs stack
   on top of each other and cross-fade; the script picks the next one at
   random. With one image, or with reduced motion asked for, it simply
   holds. The title and its sentence sit against the left edge. */

.sets-hero {
  position: relative;
  overflow: hidden;
  height: clamp(11rem, 33vh, 22rem);
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
  display: grid;
  place-items: center start;
  padding-inline: clamp(1.25rem, 5vw, 3.5rem);
  margin-bottom: clamp(1.5rem, 4vh, 2.5rem);
}

.sets-hero__layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 900ms ease;
}

.sets-hero__layer.is-on { opacity: 1; }

/* Enough darkness for the title to sit on any photograph. Weighted to the
   left now, since that is where the words are. */
.sets-hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, rgba(8,8,10,0.72), rgba(8,8,10,0.34) 62%, rgba(8,8,10,0.28)),
    linear-gradient(to bottom, rgba(8,8,10,0.28), rgba(8,8,10,0.52));
}

/* Title and sentence together, held against the left edge. */
.sets-hero__text {
  position: relative;
  max-width: 46ch;
}

.sets-hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 7.5vw, 5rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--paper);
  text-shadow: 0 2px 24px rgba(0,0,0,0.55);
  text-align: left;
}

.sets-hero__lead {
  margin: clamp(0.6rem, 1.6vh, 1rem) 0 0;
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--paper-dim);
  text-shadow: 0 1px 12px rgba(0,0,0,0.8);
  text-align: left;
}

@media (prefers-reduced-motion: reduce) {
  .sets-hero__layer { transition: none; }
}

/* ------------------------------------------------------------------ bio -- */
/* The Chase page. Three photographs in three different shapes, so the
   page has a rhythm rather than three identical blocks: a portrait beside
   the opening text, a wide plate across the middle, and a third beside
   the closing notes with the image and text swapped over. Everything
   stacks to a single column on a phone, portrait first each time. */

.bio {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
  margin-block: clamp(2rem, 6vh, 4rem);
}

@media (min-width: 52rem) {
  .bio {
    grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
    max-width: 78rem;
    margin-inline: auto;
  }
  /* The closing block reads text first, picture second. */
  .bio--flip { grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr); }
  .bio--flip .bio__frame { order: 2; }
}

.bio__frame {
  position: relative;
  overflow: hidden;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
}

.bio__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.bio__frame--portrait img { aspect-ratio: 4 / 5; }
.bio__frame--square img   { aspect-ratio: 1 / 1; }

.bio__kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--silver-low);
  margin: 0 0 1rem;
}

.bio__title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5.5vw, 3.75rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.015em;
  margin: 0 0 clamp(1.25rem, 3vh, 2rem);
}

.bio__body { color: var(--paper-dim); max-width: 50ch; }
.bio__body p { margin: 0 0 1.1em; }
.bio__body p:last-child { margin-bottom: 0; }
.bio__body strong { color: var(--paper); font-weight: 500; }

/* The wide plate across the middle, with a line of its own underneath. */
.bio-band {
  margin-block: clamp(2.5rem, 7vh, 5rem);
  border-block: var(--rule) solid var(--hairline-soft);
  padding-block: clamp(2rem, 5vh, 3.5rem);
}

.bio-band__frame {
  overflow: hidden;
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
}

.bio-band__frame img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  display: block;
}

@media (max-width: 40rem) {
  .bio-band__frame img { aspect-ratio: 3 / 2; }
}

.bio-band__note {
  max-width: 54ch;
  margin: clamp(1.5rem, 4vh, 2.5rem) auto 0;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.4vw, 1.7rem);
  font-style: italic;
  line-height: 1.45;
  color: var(--paper);
}

.bio-band__by {
  display: block;
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-style: normal;
  font-size: var(--fs-micro);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--silver-low);
}

/* The short spec list at the end. */
.bio-facts {
  margin: clamp(1.5rem, 4vh, 2.25rem) 0 0;
  display: grid;
  gap: 0.55rem;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
}

.bio-facts div {
  display: grid;
  grid-template-columns: 9.5rem 1fr;
  gap: 0.75rem;
  padding-bottom: 0.55rem;
  border-bottom: var(--rule) solid var(--hairline-soft);
}

.bio-facts dt { color: var(--silver-low); text-transform: uppercase; letter-spacing: 0.18em; }
.bio-facts dd { margin: 0; color: var(--paper-dim); }

.bio-cta {
  display: inline-block;
  margin-top: clamp(1.5rem, 4vh, 2.25rem);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  border-bottom: var(--rule) solid var(--safelight-deep);
  padding-bottom: 0.3rem;
  transition: border-color 180ms ease;
}
.bio-cta:hover { border-bottom-color: var(--safelight); }

/* -------------------------------------------------------------- feature -- */
/* The two panels between the Sets banner and the list. Each is a quarter
   of the window tall, side by side on a wide screen and stacked on a
   phone. Both are ordinary links with a cover photograph behind them.

   The left one is fixed. The right one rotates through a pool of sets
   written into the markup, changing photograph, name and destination
   together. It holds still while the pointer is over it, so the link
   cannot change under someone about to click it. */

.feature-pair {
  display: grid;
  gap: clamp(0.7rem, 1.6vw, 1.2rem);
  margin-bottom: clamp(1rem, 2.5vh, 1.6rem);
}

@media (min-width: 48rem) {
  .feature-pair { grid-template-columns: 1fr 1fr; }
}

.feature {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  height: clamp(9rem, 25vh, 15rem);
  background: var(--ink-deep);
  border: var(--rule) solid var(--hairline-soft);
  text-decoration: none;
  transition: border-color 220ms ease;
}

.feature:hover,
.feature:focus-visible { border-color: var(--silver-low); }

.feature__layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 700ms ease, transform 700ms ease;
}

.feature__layer.is-on { opacity: 1; }
.feature:hover .feature__layer.is-on { transform: scale(1.03); }

.feature__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(8,8,10,0.30), rgba(8,8,10,0.66)),
    radial-gradient(70% 65% at 50% 50%, rgba(8,8,10,0.18), rgba(8,8,10,0.58));
}

.feature__text {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 0.45rem;
  text-align: center;
  padding: 1rem;
}

.feature__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--paper-dim);
  text-shadow: 0 1px 10px rgba(0,0,0,0.8);
}

.feature__name {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  font-weight: 400;
  line-height: 1.05;
  color: var(--paper);
  text-shadow: 0 2px 20px rgba(0,0,0,0.7);
}

.feature__badge {
  position: absolute;
  top: 0.7rem;
  right: 0.8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  color: var(--ink);
  background: var(--ember);
  padding: 0.15rem 0.5rem;
}

.feature__pool { display: none; }

@media (prefers-reduced-motion: reduce) {
  .feature__layer { transition: none; }
}

/* ------------------------------------------------------------ set bands -- */
/* One wide card per set, the name centred on the photograph. */

/* A fixed-height box with its own scrollbar, so the banner and the list
   together sit inside one screen however many sets there are. Scrolling
   inside it does not chain out to the page. */
.set-list {
  display: grid;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  height: clamp(38rem, 92vh, 62rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(0.6rem, 1.4vw, 1rem);
  border: var(--rule) solid var(--hairline);
  background: var(--ink-deep);
  scrollbar-width: thin;
  scrollbar-color: var(--silver-low) transparent;
}

.set-list::-webkit-scrollbar { width: 10px; }
.set-list::-webkit-scrollbar-track { background: transparent; }
.set-list::-webkit-scrollbar-thumb {
  background: var(--silver-low);
  border: 3px solid var(--ink-deep);
  border-radius: 6px;
}
.set-list::-webkit-scrollbar-thumb:hover { background: var(--silver); }

/* Narrower and taller than the photograph's own shape, centred in the box.
   Full width on a phone, where three quarters would be too thin to read. */
.set-band {
  position: relative;
  display: block;
  overflow: hidden;
  flex: 0 0 auto;
  width: 100%;
  margin-inline: auto;
  border: var(--rule) solid var(--hairline-soft);
  background: var(--ink-deep);
  height: clamp(8.1rem, 16vh, 11.9rem);
  transition: border-color 200ms ease;
}

@media (min-width: 40rem) {
  .set-band { width: 75%; }
}

.set-band img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.62;
  transition: transform 800ms cubic-bezier(.2,.7,.2,1), opacity 300ms ease;
}

.set-band:hover img,
.set-band:focus-visible img { opacity: 0.85; transform: scale(1.04); }
.set-band:hover { border-color: var(--hairline); }

.set-band__inner {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.4rem;
  text-align: center;
  padding: 1rem;
  background: linear-gradient(to bottom, rgba(8,8,10,0.15), rgba(8,8,10,0.45));
  transition: right 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.set-band__name {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  font-weight: 400;
  color: var(--paper);
  text-shadow: 0 2px 18px rgba(0,0,0,0.65);
  line-height: 1.05;
}

.set-band__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--paper-dim);
  text-shadow: 0 1px 10px rgba(0,0,0,0.8);
  font-variant-numeric: tabular-nums;
}

.set-band__badge {
  position: absolute;
  top: 0.7rem;
  right: 0.8rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  color: var(--ink);
  background: var(--ember);
  padding: 0.15rem 0.5rem;
}

.set-band--gated { border-color: var(--safelight-deep); }
.set-band--gated:hover { border-color: var(--ember); }

/* The same translucent panel the model-page covers use, sized for a band.
   It slides across the right half on hover and carries the 18+ mark; the
   little corner badge fades out underneath it so the two do not overlap.
   On touch, where there is no hover, the panel simply stays put. */

.set-band__veil {
  position: absolute;
  inset: 0 0 0 50%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.35rem;
  padding: 0.6rem;
  text-align: center;
  background: color-mix(in srgb, var(--ink-deep) 74%, transparent);
  -webkit-backdrop-filter: blur(7px) saturate(0.6);
  backdrop-filter: blur(7px) saturate(0.6);
  border-left: var(--rule) solid var(--ember);
  transform: translateX(101%);
  transition: transform 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
  will-change: transform;
}

.set-band--gated:hover .set-band__veil,
.set-band--gated:focus-visible .set-band__veil { transform: translateX(0); }

/* The set name lives in the middle of the band, so it moves over into the
   half the veil leaves free rather than being cut in two by it. */
.set-band--gated:hover .set-band__inner,
.set-band--gated:focus-visible .set-band__inner { right: 50%; }

.set-band--gated:hover .set-band__badge,
.set-band--gated:focus-visible .set-band__badge { opacity: 0; }

.set-band__badge { transition: opacity 220ms ease; }

.set-band__veil-mark {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--ember);
  line-height: 1;
}

.set-band__veil-note {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-dim);
  line-height: 1.5;
}

@media (hover: none) {
  .set-band__veil { transform: translateX(0); }
  .set-band--gated .set-band__inner { right: 50%; }
  .set-band--gated .set-band__badge { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .set-band__veil,
  .set-band__inner { transition: none; }
}

/* ---------------------------------------------------------------- misc -- */

.stack-lg > * + * { margin-top: clamp(1.5rem, 4vh, 2.5rem); }

.notfound {
  min-height: 60vh;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 1.25rem;
}

@media (max-width: 560px) {
  .site-head__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.85rem;
  }
  .nav { gap: 1.15rem; }
  .lightbox__bar { justify-content: flex-start; }
}

/* The gate moves focus here on entry for screen readers; the heading is not
   interactive, so it does not need a visible ring. */
[data-gate-target]:focus,
[data-gate-target]:focus-visible { outline: none; }

.gate__noscript {
  margin: 1.5rem 0 0;
  padding: 0.85rem 1rem;
  border: var(--rule) solid var(--safelight-deep);
  color: var(--paper-dim);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  line-height: 1.7;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
