/* Dev graphs — "Black room, white print". Spec: DESIGN.md
   Layout: poster-size name on the first screen, then two masonry columns of photos
   in a fixed order; a photo opens as a white-bordered print over the dimmed page.
   Dark by default (black room); a light version is one tap away in the top bar. */

@font-face {
  font-family: "Stardom";
  src: url("fonts/stardom.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Clash Grotesk";
  src: url("fonts/clash-grotesk.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --night: #000000;      /* page */
  --night-2: #0e0e0e;    /* empty photo slot while loading */
  --paper: #efeae0;      /* the print card: warm instant-film paper */
  --ink: #1c1b18;        /* text on the print */
  --ink-2: #5d594f;      /* venue/year on the print */
  --chalk: #edede8;      /* text on the black page */
  --ash: #8a8a86;        /* secondary text */
  --rule: rgba(237, 237, 232, .14);
  --veil: rgba(0, 0, 0, .5);   /* hover + behind the viewer (Emilie: 50 %) */

  --display: "Stardom", "Didot", "Bodoni 72", "Times New Roman", serif;
  --text: "Clash Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --maxw: 1316px;                                  /* 2 × 640 + gap */
  --side: max(16px, min(5vw, 72px));
  --gap: clamp(12px, 2.4vw, 36px);
  --bar-h: 64px;
  --ease: cubic-bezier(.2, .7, .1, 1);

  /* Film look shared by every photo in the grid, so different shoots read as one set.
     The opened print shows the original edit, untouched.
     Lower contrast lifts the blacks to a soft matte, brightness puts the mids back,
     saturation calms mixed stage colours, a touch of sepia warms them alike.
     Remove these two lines (and the grain rules) to show the photos exactly as exported. */
  /* both looks use the same filter functions in the same order, so the browser can blend
     smoothly between colour and black and white instead of snapping halfway */
  --film: grayscale(0) contrast(.9) brightness(1.05) saturate(.86) sepia(.07);
  /* The wall at rest: warm black and white, so every shoot matches. Colour comes back on
     hover (or, on phones, when a photo reaches the middle of the screen). */
  --mono: grayscale(1) contrast(.92) brightness(1.05) saturate(1) sepia(.14);
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  color-scheme: dark;
}
/* Light mode: gallery-white wall. The print, the hover darkening and the dimmed
   backdrop stay the same, so a photo still opens as a paper print over a dimmed page. */
:root[data-theme="light"] {
  --night: #f4f3ef;
  --night-2: #e6e4de;
  --chalk: #141412;
  --ash: #6d6b66;
  --rule: rgba(20, 20, 18, .14);
  color-scheme: light;
}
html.theming, html.theming body, html.theming .bar { transition: background-color .45s ease, color .45s ease; }

* { box-sizing: border-box; }
html {
  background: var(--night);
  scrollbar-gutter: stable;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}
html.locked { overflow: hidden; }
body {
  margin: 0;
  background: var(--night);
  color: var(--chalk);
  font: 400 16px/1.5 var(--text);
  -webkit-font-smoothing: antialiased;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--chalk); outline-offset: 3px; }

.wrap, .intro, .wall, .about {
  width: 100%;
  max-width: calc(var(--maxw) + 2 * var(--side));
  margin-inline: auto;
  padding-left: max(var(--side), env(safe-area-inset-left, 0px));
  padding-right: max(var(--side), env(safe-area-inset-right, 0px));
}

/* ── Top bar ───────────────────────────────────────────── */
.bar {
  position: fixed; inset: 0 0 auto; z-index: 20;
  height: calc(var(--bar-h) + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  padding-left: max(var(--side), env(safe-area-inset-left, 0px));
  padding-right: max(var(--side), env(safe-area-inset-right, 0px));
  display: flex; align-items: center; justify-content: space-between;
  background: transparent;
  transition: background-color .35s ease;
}
.bar.solid { background: var(--night); }
html.locked .bar { opacity: 0; transition: opacity .25s ease; }
.bar-name {
  font-family: var(--display); font-size: 22px; line-height: 1;
  letter-spacing: 0;
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s ease, transform .35s var(--ease);
  pointer-events: none;
}
.bar.solid .bar-name { opacity: 1; transform: none; pointer-events: auto; }
.bar-right { display: flex; align-items: center; gap: clamp(20px, 2.6vw, 36px); }
.bar-link { font-size: 15px; padding: 10px 0; text-transform: uppercase; letter-spacing: .01em; }
.bar-link:hover, .bar-name:hover { opacity: .7; }

/* ── First screen ──────────────────────────────────────── */
.intro {
  min-height: 82vh; min-height: 82svh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-top: calc(var(--bar-h) + 24px);
  padding-bottom: clamp(28px, 4.5vw, 56px);
}
.name {
  margin: 0;
  font-family: var(--display); font-weight: 400;
  font-size: clamp(72px, 17vw, 300px);
  line-height: .98;
  color: var(--chalk);
}
.name-fit { display: inline-block; white-space: nowrap; letter-spacing: -.012em; padding-bottom: .06em; }
.name-fit .ln { display: block; }
/* First second: the name and tagline wait, unseen, until the font is ready, then pull into focus. */
html.pull .name-fit, html.pull .tagline { opacity: 0; }
/* Signature version of the big name */
.name.is-sign { line-height: 0; }
.name.is-sign .name-fit { display: block; width: min(100%, 1120px); padding: 0; white-space: normal; color: var(--chalk); }
.name.is-sign svg { display: block; width: 100%; height: auto; overflow: visible; }
.name.is-sign path { fill: none; stroke: currentColor; stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; }
.tagline { margin: clamp(22px, 3vw, 44px) 0 0; font-size: 15px; color: var(--chalk); max-width: 62ch; text-transform: uppercase; letter-spacing: .01em; }

/* ── Photo wall ────────────────────────────────────────── */
.grid {
  position: relative;
  column-gap: var(--gap);            /* read by app.js as the gutter */
  min-height: 60vh;
}
.tile {
  position: absolute; overflow: hidden;
  background: var(--night-2);
  cursor: zoom-in;
}
.tile img {
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .6s ease, filter 2.4s cubic-bezier(.45, 0, .55, 1);   /* back to B&W: slow, same curve as the stroke fade */
  filter: var(--mono);
}
/* Depth (b): the photo sits a little larger than its frame and drifts with scroll */
.tile.depth img { transform: translate3d(0, var(--py, 0), 0) scale(1.09); }
.tile.live img, .tile:focus-visible img { filter: var(--film); }
/* While the page is scrolling, photos passing under the cursor don't react;
   hover comes back a moment after scrolling stops. */
html.scrolling .tile { pointer-events: none; }
/* Fine film grain over each photo */
.tile::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--grain); background-size: 180px 180px;
  mix-blend-mode: overlay; opacity: .2;
}
.tile img.in { opacity: 1; }
.tile::after {
  content: ""; position: absolute; inset: 0;
  background: #000; opacity: 0;
  transition: opacity .45s ease;
  pointer-events: none;
}
@media (hover: hover) {
  .tile:hover img { filter: var(--film); transition-delay: 0s, .06s; }
  .tile:hover::after { opacity: .35; }
}
.tile:focus-visible { outline-offset: 4px; }
.tile:focus-visible::after { opacity: .35; }
/* Hover details: a thin band of film-label text across the middle of the photo */
.tile-info {
  position: absolute; inset: 0; z-index: 1;
  display: grid; grid-template-columns: auto 1fr auto; align-content: center;
  column-gap: clamp(14px, 2vw, 28px);
  padding-inline: clamp(14px, 1.8vw, 24px);
  color: #f2efe8; text-align: left;
  font-size: 10.5px; line-height: 1.3; letter-spacing: .05em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  opacity: 0; transition: opacity .45s ease;
  pointer-events: none;
}
/* Glass stroke (desktop): moving the mouse over the wall paints one long, tapering stroke of
   frosted glass across the photos (one canvas over the wall, see app.js section 8). Photos the
   stroke passes over stay in colour until it fades. */
.glass-layer { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 5; pointer-events: none; }
html.locked .glass-layer { display: none; }
.tile.inked img { filter: var(--film); }
/* into colour: quick (hover, stroke, phones) */
.tile:hover img, .tile.inked img, .tile.live img, .tile:focus-visible img { transition-duration: .6s, .75s; }
.tile-info > span { display: flex; flex-direction: column; min-width: 0; }
.tile-info span span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ti-r { text-align: right; }
@media (hover: hover) {
  .tile:hover .tile-info { opacity: 1; }
}
.tile:focus-visible .tile-info { opacity: 1; }

/* ── About (bottom): bio, drawn signature, links, local time ─ */
.about {
  padding-top: clamp(120px, 16vw, 220px);
  padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px));
  scroll-margin-top: var(--bar-h);
}
.about-inner { max-width: 420px; margin-inline: auto; }
/* Signature under the bio, slightly tilted; it writes itself each time it scrolls into view. */
.sig {
  width: clamp(250px, 24vw, 310px); margin: 14px auto 0;
  transform: translateX(-28px) rotate(-4deg); transform-origin: center;
  color: var(--chalk); pointer-events: none;
}
.sig svg { display: block; width: 100%; height: auto; overflow: visible; }
.sig path { fill: none; stroke: currentColor; stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 640px) { .sig { transform: translateX(-10px) rotate(-4deg); } }   /* phones: sits centred under the full-width bio */
.bio {
  margin: 0;
  font-size: 15.5px; line-height: 1.22; letter-spacing: .01em;
  text-transform: uppercase; text-wrap: pretty;
}
.links {
  list-style: none; margin: 40px 0 0; padding: 0;
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.links a {
  font-size: 15.5px; text-transform: uppercase; letter-spacing: .01em;
  text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 4px;
  transition: text-decoration-color .2s;
}
.links a:hover { text-decoration-color: currentColor; }
.about-foot {
  display: flex; justify-content: space-between; gap: 16px;
  margin-top: 44px; font-size: 15.5px; font-variant-numeric: tabular-nums;
}

/* ── Viewer: the print (warm paper, fine grain) ────────── */
.viewer {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
}
.veil { position: absolute; inset: 0; background: var(--veil); }
/* Flash sits on the print only, with a short glow past its edges. */
.flash {
  position: absolute; inset: 0; z-index: 2;
  background: #fff; opacity: 0; pointer-events: none;
  box-shadow: 0 0 40px 8px rgba(255, 255, 255, .3);
}
.v-close {
  position: absolute; z-index: 2;
  top: calc(12px + env(safe-area-inset-top, 0px));
  right: calc(12px + env(safe-area-inset-right, 0px));
  width: 44px; height: 44px; display: grid; place-items: center;
  color: #fff; opacity: .85;
}
.v-close:hover { opacity: 1; }
.v-close:focus-visible { outline-offset: -4px; border-radius: 50%; }
.print:focus { outline: none; }
.print {
  position: relative; z-index: 1; margin: 0;
  padding: var(--pad, 48px);
  padding-bottom: calc(var(--pad, 48px) * .8);
  color: var(--ink);
  isolation: isolate;
  touch-action: pan-y;
}
.paper {
  position: absolute; inset: 0; z-index: -1;
  background-color: var(--paper);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .27 0 0 0 0 .2 0 0 0 .55 -.2'/%3E%3C/filter%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.018' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .45 0 0 0 0 .38 0 0 0 0 .28 0 0 0 .22 -.06'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  box-shadow:
    inset 0 0 70px rgba(120, 98, 64, .1),   /* edges slightly aged */
    0 40px 90px -30px rgba(0, 0, 0, .7);
}
.print-photo {
  position: relative; overflow: hidden;
  background: #e8e8e5;
  transition: width .28s var(--ease), height .28s var(--ease);
}
.print-photo img { width: 100%; height: 100%; object-fit: cover; }   /* the print shows the original edit */
.print-cap {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px;
  margin-top: clamp(14px, 1.8vw, 24px);
  font-size: 11px; line-height: 1.3; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.sheen {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(55% 45% at var(--sx, 50%) var(--sy, 45%), rgba(255, 255, 255, .16), transparent 62%);
  mix-blend-mode: screen; opacity: 0; transition: opacity .5s ease;
}
.cap-shot {
  grid-column: 1 / -1; justify-self: center; margin-top: 2px;
  font-size: 9.5px; letter-spacing: .1em; color: var(--ink-2); white-space: nowrap; text-transform: none;
}
.cap-l, .cap-r { display: flex; flex-direction: column; min-width: 0; }
.cap-r { text-align: right; }
.cap-c { font-size: 16px; letter-spacing: .02em; text-align: center; max-width: 34ch; text-wrap: balance; }
.cap-by { display: block; margin-top: 3px; font-size: 10px; letter-spacing: .08em; color: var(--ink-2); }
.v-nav {
  position: absolute; z-index: 2; top: 50%; transform: translateY(-50%);
  width: 48px; height: 64px; display: grid; place-items: center;
  color: #fff; opacity: .6; transition: opacity .15s;
}
.v-nav:hover { opacity: 1; }
.v-prev { left: calc(8px + env(safe-area-inset-left, 0px)); }
.v-next { right: calc(8px + env(safe-area-inset-right, 0px)); }

/* ── Phones ────────────────────────────────────────────── */
@media (max-width: 699px) {
  :root { --side: 16px; --gap: 10px; --bar-h: 56px; }
  .intro { min-height: 76vh; min-height: 76svh; }
  .tagline { font-size: 14px; }
  .bar-name { font-size: 20px; }
  .bio, .links a, .about-foot { font-size: 14.5px; }
  .print-cap { font-size: 9px; gap: 8px; }
  .cap-c { font-size: 13px; }
  .cap-shot { font-size: 8px; letter-spacing: .06em; }
  .name.is-sign path { stroke-width: 10; }
  .v-nav { display: none; }
  .v-close { color: #fff; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
