/* baltbender.com
   Mobile (< 900px) follows the 430px Figma frame; content never scales up,
   the column centres and margins grow.
   Desktop (>= 900px) follows the 1280px frame. Every length is N * --u, where
   --u is 1px at 1280px and wider and shrinks proportionally down to 900px. */

:root {
  --color-warm-white: #f3f2ec;
  --color-grey: #b3b3b3;
  --color-bg: #1e1e1e;
  --gut: clamp(24px, 13.26vw, 57px);
  --ease: cubic-bezier(.65, 0, .35, 1);
  --ease-out: cubic-bezier(.2, .6, .2, 1);
  --u: min(1px, calc(100cqw / 1280));
  color-scheme: dark;
}

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

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-warm-white);
  font-family: Montserrat, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.menu-open body, .lightbox-open body { overflow: hidden; }

img, video { display: block; max-width: 100%; height: auto; }
figure { margin: 0; }
h1, h2, h3, p { margin: 0; font-weight: inherit; }
button { font: inherit; color: inherit; }
a { color: inherit; }
a:hover { color: var(--color-warm-white); }
:focus-visible { outline: 1px solid var(--color-warm-white); outline-offset: 4px; }
::selection { background: rgba(243, 242, 236, .85); color: var(--color-bg); }

.visually-hidden, .skip:not(:focus) {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip:focus { position: fixed; top: 8px; left: 50%; transform: translateX(-50%); z-index: 50; padding: 8px 12px; background: var(--color-bg); }

/* ---------- type ---------- */

.label {
  font-size: 12px;
  font-style: italic;
  font-weight: 400;
  line-height: 1.2258;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-grey);
}

.body {
  font-size: 13px;
  font-weight: 500;
  line-height: 27px;
  letter-spacing: .02em;
  color: var(--color-warm-white);
}
.body p { text-wrap: pretty; }
.body p + p, .body p + img, .body img + p, .body img + img { margin-top: 27px; }
.body a { text-underline-offset: .2em; }

/* ---------- page + background ---------- */

.page { position: relative; overflow: clip; container-type: inline-size; }

.bg { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
/* Faint grain over the glow: breaks up banding in the dark gradients. */
.bg::after { content: ''; position: absolute; inset: 0; background: url(grain.png); opacity: .025; }

.glow {
  position: absolute;
  transform: translate(-50%, -50%) rotate(var(--a));
  background: radial-gradient(closest-side,
    rgba(255, 255, 255, .15),
    rgba(191, 191, 191, .1125) 25%,
    rgba(128, 128, 128, .075) 50%,
    rgba(64, 64, 64, .0375) 75%,
    rgba(0, 0, 0, 0));
}
/* Positions are the gradient centres measured from the Figma ellipses. */
.glow-1 { left: calc(50% - 264px); top: 26px; width: 934px; height: 550px; --a: 23deg; }
.glow-2 { display: none; }
.glow-3 { left: calc(50% - 68px); top: calc(100% + 40px); width: 776px; height: 804px; --a: 163deg; }

.wrap {
  position: relative;
  max-width: 430px;
  margin: 0 auto;
  padding: 146px 0 160px;
}
.wrap > * + * { margin-top: 119px; }
.wrap > .hero + .stories { margin-top: 219px; }

.col { padding-inline: var(--gut); }

/* ---------- motion ---------- */

/* Hero: plays once on load, the label, name and two lines, then the photo. */
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }
@keyframes appear { from { opacity: 0; } }
.hero-text > * { animation: rise .9s var(--ease-out) both; }
.hero-text > :nth-child(1) { animation-delay: .1s; }
.hero-text > :nth-child(2) { animation-delay: .22s; }
.hero-text > :nth-child(3) { animation-delay: .34s; }
.hero-text > :nth-child(4) { animation-delay: .46s; }
.hero-photo { animation: appear 1.1s var(--ease-out) .3s both; }

/* Scroll reveal: main.js adds .is-in as each element comes into view. Only
   with JS (the .js class is set in the page head), so nothing stays hidden. */
.js .reveal { opacity: 0; transform: translateY(12px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out), filter .3s; }
.js .reveal.is-in { opacity: 1; transform: none; }

/* Lazy photos stay transparent until their file has arrived, then fade in. */
.js img.fade-in:not(.reveal) { transition: opacity .6s var(--ease-out); }
.js img.fade-in:not(.is-loaded) { opacity: 0; }

/* Photos that open in the lightbox. */
.zoomable { cursor: zoom-in; }
@media (hover: hover) {
  .zoomable:hover { filter: brightness(1.08); }
}

/* ---------- nav + mobile menu ---------- */

.nav {
  position: fixed;
  left: 7px;
  top: 56px;
  z-index: 20;
  visibility: hidden;
  opacity: 0;
  transition: opacity .25s, visibility 0s .25s;
}
.nav ul { list-style: none; margin: 0; padding: 0; }
.nav a {
  display: block;
  padding: 6px 0;
  text-decoration: none;
  font-size: 12px;
  font-style: italic;
  line-height: 1.2258;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-grey);
}
.nav a:hover { color: var(--color-warm-white); }
.nav a.is-active { font-weight: 700; color: var(--color-warm-white); }
.menu-open .nav { visibility: visible; opacity: 1; transition: opacity .25s; }
/* Menu items arrive one after another (--i is set per item in the page). */
.nav li { opacity: 0; transform: translateY(6px); transition: opacity .2s, transform .2s; }
.menu-open .nav li {
  opacity: 1;
  transform: none;
  transition: opacity .4s var(--ease-out), transform .4s var(--ease-out);
  transition-delay: calc(60ms + var(--i) * 45ms);
}

.menu-button, .lightbox-close {
  position: fixed;
  left: -1px;
  top: 5px;
  width: 44px;
  height: 44px;
  padding: 7px;
  border: 0;
  color: var(--color-warm-white);
  cursor: pointer;
}
.menu-button svg, .lightbox-close svg { width: 30px; height: 30px; }
.menu-button { z-index: 30; background: none; }
/* No backing plate; a soft shadow keeps the lines readable over photos. */
.menu-button svg { overflow: visible; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .6)); }
/* Focus ring for keyboard use only, never after a tap. */
.menu-button:focus:not(:focus-visible) { outline: none; }
.menu-button path { transform-box: fill-box; transform-origin: center; transition: transform .3s var(--ease), opacity .2s; }
.menu-open .menu-button path.hb-top { transform: translateY(21px) rotate(45deg); }
.menu-open .menu-button path.hb-mid { opacity: 0; }
.menu-open .menu-button path.hb-bot { transform: translateY(-21px) rotate(-45deg); }

/* The faded blur behind the mobile menu and the lightbox. */
.menu-blur, .lightbox::before {
  position: fixed;
  inset: 0;
  background: rgba(30, 30, 30, .45);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  opacity: 0;
  transition: opacity .25s;
}
.menu-blur { z-index: 10; }
.menu-open .menu-blur { opacity: 1; }

/* ---------- lightbox ---------- */
/* The backdrop, cross and photo animate separately: the photo grows out of
   its thumbnail while the other two fade. */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox[hidden] { display: none; }
.lightbox::before { content: ''; }
.lightbox-close { z-index: 1; background: none; opacity: 0; transition: opacity .3s; }
.lightbox-open .lightbox::before, .lightbox-open .lightbox-close { opacity: 1; }
.lightbox-img {
  position: relative;
  transform-origin: 0 0;
  box-shadow: 0 4px 28px -2px rgba(0, 0, 0, .35);
  transition: transform .5s var(--ease-out), opacity .25s;
}
.lightbox-img.is-swapping { opacity: 0; transition: opacity .18s; }

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

.hero { display: flex; flex-direction: column; padding-inline: var(--gut); }
.hero-photo { order: -1; align-self: center; width: 163px; height: 163px; object-fit: cover; margin-bottom: 45px; }
.hero-name {
  margin-top: 14px;
  font-family: 'Calendas Plus', Georgia, serif;
  font-size: 48px;
  font-weight: 400;
  line-height: 1;
  color: var(--color-warm-white);
}
.hero-sub { font-size: clamp(13px, 3.72vw, 16px); font-weight: 700; line-height: 1.25; color: var(--color-grey); }
.hero-name + .hero-sub { margin-top: 3px; }
.hero-sub + .hero-sub { margin-top: 9px; }

/* ---------- stories ---------- */

/* Each story's submitter, date and caption share one grid cell with the
   others and cross-fade. The caption area is as tall as the longest caption,
   so nothing below moves when the story changes. */
.story-meta-top, .story-dates, .story-captions { display: grid; }
.story-submitted, .story-date, .story-caption {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity .6s var(--ease), visibility 0s .6s;
}
.is-current.story-submitted, .is-current.story-date, .is-current.story-caption {
  opacity: 1;
  visibility: visible;
  transition: opacity .6s var(--ease) .3s;
}

.story-meta-top, .story-meta-bottom { padding-inline: var(--gut); }
.story-meta-top { margin-bottom: 5px; }
.story-dates { margin-top: 5px; text-align: right; }
.story-captions { margin-top: 26px; }

/* Mobile: one card at a time, chevrons either side. */
.story-cards {
  position: relative;
  margin-inline: var(--gut);
  aspect-ratio: var(--minr, 1.27);
}
.story-card {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  opacity: 0;
  transition: opacity .6s var(--ease);
}
.story-card[data-slot="0"] { opacity: 1; }
.story-card img { width: 100%; }

.story-prev, .story-next {
  position: absolute;
  top: 50%;
  width: 41px;
  height: 41px;
  margin-top: -20.5px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-warm-white);
  cursor: pointer;
}
.story-prev { left: calc(6px - var(--gut)); }
.story-next { right: calc(5px - var(--gut)); }
.story-prev svg, .story-next svg { width: 100%; height: 100%; }

/* ---------- tributes ---------- */

.tribute-list { display: flex; flex-direction: column; gap: 20px; margin-top: 5px; }
.tribute-head { font-size: inherit; }
.tribute-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: 32px;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}
.tribute-icon { flex: none; width: 29px; height: 29px; color: var(--color-warm-white); }
.tribute-icon svg { display: block; width: 100%; height: 100%; transition: transform .45s var(--ease); }
.tribute.is-open .tribute-icon svg { transform: rotate(45deg); }
.tribute-name { font-size: 16px; font-weight: 700; line-height: 1.25; color: var(--color-warm-white); }

/* main.js animates the body's height; the text fades in a beat behind it. */
.tribute-body { overflow: hidden; }
.tribute-inner { padding: 8px 0 0 33px; opacity: 0; transition: opacity .2s; }
.tribute.is-open .tribute-inner { opacity: 1; transition: opacity .6s var(--ease-out) .25s; }
.tribute-img { width: 100%; }

/* ---------- gallery ---------- */

.gallery { padding-inline: 13px; }
.gallery .col-label { padding-left: calc(var(--gut) - 13px); margin-bottom: 12px; }
.gallery-desktop { display: none; }
.gallery-mobile { display: flex; gap: 12px; align-items: flex-start; }
.gallery-col { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.gallery-col img { width: 100%; }

/* ---------- works ---------- */

.works-intro { margin-top: 5px; }
.works-desktop { display: none; }
.works-mobile { margin: 18px calc(13px - var(--gut)) 0; }
/* Mobile: the video spans the text column; the photos below span the gallery width. */
.works-mobile .works-video-slot { padding-inline: calc(var(--gut) - 13px); }
.works-video { width: 100%; }
.works-video video { width: 100%; aspect-ratio: 9 / 16; object-fit: cover; background: #2a2a2a; }
.works-pair { display: flex; gap: 12px; margin-top: 12px; align-items: flex-start; }
.works-stack { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.works-stack img { width: 100%; }

/* ---------- ceremony + contact ---------- */

.ceremony .body, .contact .body { margin-top: 5px; }
.player { margin-top: 28px; }
.player + .player { margin-top: 36px; }
.player-title { margin-bottom: 8px; }
.player-frame { position: relative; }
.ceremony-video { width: 100%; aspect-ratio: 16 / 9; background: #2a2a2a; }
/* One quiet play button over the poster; the browser controls appear once playing. */
.player-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-warm-white);
  cursor: pointer;
}
.player-play[hidden] { display: none; }
.player-play svg { width: 64px; height: 64px; transition: transform .35s var(--ease-out); }
.player-play:hover svg { transform: scale(1.06); }

/* ================= desktop ================= */

@media (min-width: 900px) {
  .label { font-size: max(11px, calc(12 * var(--u))); }
  .body { font-size: max(13px, calc(14 * var(--u))); line-height: 2.143; }
  .body p + p, .body p + img, .body img + p, .body img + img { margin-top: 2.143em; }

  .glow-1 { left: calc(50% - 597 * var(--u)); top: calc(63 * var(--u)); width: calc(1888 * var(--u)); height: calc(1112 * var(--u)); }
  .glow-2 { display: block; left: calc(50% + 810 * var(--u)); top: calc(1149 * var(--u)); width: calc(1888 * var(--u)); height: calc(1112 * var(--u)); --a: 147deg; }
  .glow-3 { left: calc(50% + 64 * var(--u)); top: calc(100% + 238 * var(--u)); width: calc(2178 * var(--u)); height: calc(2256 * var(--u)); }

  .wrap {
    max-width: none;
    width: calc(1280 * var(--u));
    padding: calc(201 * var(--u)) 0 calc(223 * var(--u));
  }
  .wrap > * + * { margin-top: calc(121 * var(--u)); }
  .wrap > .hero + .stories { margin-top: calc(221 * var(--u)); }

  .col { width: calc(600 * var(--u)); margin-inline: auto; padding-inline: 0; }

  /* nav: always visible top left; no menu button */
  .menu-button, .menu-blur { display: none; }
  .nav { left: 25px; top: 21px; visibility: visible; opacity: 1; transition: none; }
  .nav a { padding: 0; }
  .nav li { opacity: 1; transform: none; transition: none; }
  .lightbox-close { left: 20px; top: 20px; }

  /* hero */
  .hero {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    width: calc(865 * var(--u));
    min-height: calc(260 * var(--u));
    margin-inline: auto;
    padding-inline: 0;
  }
  .hero-photo { order: 0; width: calc(260 * var(--u)); height: calc(260 * var(--u)); margin: 0; }
  .hero-name { font-size: calc(96 * var(--u)); margin-top: calc(14 * var(--u)); }
  .hero-sub { font-size: max(16px, calc(24 * var(--u))); line-height: 1.21; }
  .hero-name + .hero-sub { margin-top: 0; }
  .hero-sub + .hero-sub { margin-top: calc(14 * var(--u)); }

  /* stories: five cards on fixed slots around the centre. The text above and
     below spans the current card's width (--cw, set by main.js). */
  .story-stage { --cw: 600; }
  .story-meta-top, .story-meta-bottom {
    width: calc(var(--cw) * var(--u));
    margin-inline: auto;
    padding-inline: 0;
  }
  .story-meta-top { margin-bottom: calc(10 * var(--u)); }
  .story-dates { margin-top: calc(10 * var(--u)); }
  .story-captions { margin-top: calc(29 * var(--u)); max-width: calc(445 * var(--u)); }

  .story-cards { margin-inline: 0; aspect-ratio: auto; height: calc(400 * var(--u)); }
  /* Cards share one 400px-tall base size; slots move and scale them. */
  .story-card {
    inset: auto;
    left: calc(640 * var(--u));
    top: 50%;
    height: calc(400 * var(--u));
    width: calc(400 * var(--r) * var(--u));
    transform: translate(-50%, -50%) translateX(calc(var(--x, 0) * var(--u))) scale(var(--s, 1));
    box-shadow: 0 calc(4 * var(--u)) calc(28.4 * var(--u)) calc(-2 * var(--u)) rgba(0, 0, 0, .25);
    transition: transform .9s var(--ease), opacity .6s var(--ease);
  }
  .story-card[data-slot="-2"] { --x: -429; --s: .3375; z-index: 1; opacity: 1; }
  .story-card[data-slot="-1"] { --x: -238; --s: .73;   z-index: 2; opacity: 1; }
  .story-card[data-slot="0"]  { --x: 0;    --s: 1;     z-index: 3; opacity: 1; }
  .story-card[data-slot="1"]  { --x: 238;  --s: .73;   z-index: 2; opacity: 1; }
  .story-card[data-slot="2"]  { --x: 429;  --s: .3375; z-index: 1; opacity: 1; }
  .story-card[data-slot="hidden"] { --x: 0; --s: .3375; z-index: 0; opacity: 0; }
  .story-card.no-anim { transition: opacity .6s var(--ease); }
  .story-card:not([data-slot="0"]):not([data-slot="hidden"]) { cursor: pointer; }
  /* Side photos sit back a little and brighten as they reach the centre. */
  .story-card img { width: 100%; height: 100%; object-fit: cover; transition: filter .9s var(--ease); }
  .story-card[data-slot="-1"] img, .story-card[data-slot="1"] img { filter: brightness(.72); }
  .story-card[data-slot="-2"] img, .story-card[data-slot="2"] img { filter: brightness(.55); }
  .story-card:not([data-slot="0"]):hover img { filter: brightness(.9); }
  .story-prev, .story-next { display: none; }

  /* tributes */
  .tribute-list { gap: calc(28 * var(--u)); margin-top: calc(10 * var(--u)); }
  .tribute-toggle { gap: calc(6 * var(--u)); min-height: calc(45 * var(--u)); }
  .tribute-icon { width: calc(45 * var(--u)); height: calc(45 * var(--u)); }
  .tribute-name { font-size: max(18px, calc(24 * var(--u))); }
  .tribute-inner { padding-top: calc(6 * var(--u)); padding-left: calc(51 * var(--u)); }

  /* gallery: justified rows, widths follow each photo's aspect ratio */
  .gallery { width: calc(904 * var(--u)); margin-inline: auto; padding-inline: 0; }
  .gallery .col-label { padding-left: calc(152 * var(--u)); margin-bottom: calc(10 * var(--u)); }
  .gallery-mobile { display: none; }
  .gallery-desktop { display: flex; flex-direction: column; gap: calc(16 * var(--u)); }
  .gallery-row { display: flex; gap: calc(16 * var(--u)); }
  .gallery-row img { flex: var(--r) 1 0%; min-width: 0; aspect-ratio: var(--r); }

  /* works */
  .works-intro { margin-top: calc(5 * var(--u)); }
  .works-mobile { display: none; }
  .works-desktop { display: block; margin-top: calc(18 * var(--u)); }
  .works-block { display: flex; justify-content: space-between; align-items: flex-start; }
  .works-block + .works-block { margin-top: calc(16 * var(--u)); }
  .works-stack { flex: none; gap: calc(16 * var(--u)); }
  .w336 { width: calc(336 * var(--u)); }
  .w249 { width: calc(249 * var(--u)); }
  .w271 { width: calc(271 * var(--u)); }
  .works-video { width: calc(250 * var(--u)); }

  /* ceremony + contact */
  .ceremony .body, .contact .body { margin-top: calc(5 * var(--u)); }
  .player { margin-top: calc(28 * var(--u)); }
  .player + .player { margin-top: calc(36 * var(--u)); }
  .player-title { margin-bottom: calc(8 * var(--u)); }
  .player-play svg { width: calc(80 * var(--u)); height: calc(80 * var(--u)); }
}

/* Reduced motion: no transitions or animations, everything shown at once. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; transition-delay: 0s !important; animation: none !important; }
  .js .reveal { opacity: 1; transform: none; }
}
