/* ============================================================
   philip alxander — photographer
   palette: gallery paper, green-black ink, british racing green
   type:    fraunces (display) · ibm plex mono (film-edge captions)
   ============================================================ */

:root {
  --paper: #f5f2ea;
  --sage: #dee3d6;
  --ink: #171f1a;
  --racing: #0b402c;
  --racing-bright: #1e6a49;
  --night: #0e1712;
  --cream: #ede7d8;
  --stone: #6f7568;
  --stone-dark: #8fa094;
  --hairline: rgba(23, 31, 26, 0.14);

  --font-display: "Fraunces", "Georgia", serif;
  --font-mono: "IBM Plex Mono", "SFMono-Regular", monospace;

  --ease-soft: cubic-bezier(0.22, 0.9, 0.3, 1);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--sage);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 340;
  font-optical-sizing: auto;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a { color: inherit; }

::selection { background: var(--racing); color: var(--cream); }

/* ---------- header ---------- */

.site-head {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 1.1rem clamp(1.1rem, 3.5vw, 2.6rem);
  mix-blend-mode: difference;
  color: #fff;
  transition: opacity 0.4s var(--ease-soft), transform 0.4s var(--ease-soft);
}

/* fades out once the visitor starts scrolling */
.site-head.is-hidden {
  opacity: 0;
  transform: translateY(-0.6rem);
  pointer-events: none;
}

/* persistent bottom-centre contact button — same type as the top nav,
   appears after scrolling begins, hides at the contact section */
.contact-fab {
  position: fixed;
  left: 50%;
  bottom: clamp(1.1rem, 3.2vh, 1.9rem);
  z-index: 10;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  color: #fff;
  mix-blend-mode: difference;
  text-decoration: none;
  opacity: 0;
  transform: translate(-50%, 0.6rem);
  pointer-events: none;
  transition: opacity 0.4s var(--ease-soft), transform 0.4s var(--ease-soft);
}

.contact-fab.is-shown {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

.site-head a {
  color: inherit;
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
}

.site-head__name { font-size: 0.8rem; }

.site-head__nav { display: flex; gap: 1.6rem; }

.site-head__nav a { opacity: 0.75; transition: opacity 0.35s var(--ease-soft); }
.site-head__nav a:hover, .site-head__nav a:focus-visible { opacity: 1; }

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

.hero {
  position: relative;
  height: 100svh;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: -12svh 0;
  will-change: transform;
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__text {
  position: absolute;
  left: clamp(1.2rem, 4.5vw, 4rem);
  bottom: clamp(2.2rem, 7vh, 5rem);
  color: #f7f3e8;
  text-shadow: 0 1px 30px rgba(20, 15, 5, 0.35);
}

.hero__eyebrow {
  margin: 0 0 0.7rem 0.15em;
  font-family: var(--font-mono);
  font-size: clamp(0.68rem, 1.4vw, 0.8rem);
  letter-spacing: 0.22em;
}

.hero__name {
  margin: 0;
  font-size: clamp(2.9rem, 9.5vw, 7.5rem);
  font-weight: 300;
  font-variation-settings: "opsz" 144;
  letter-spacing: -0.025em;
  line-height: 0.95;
}

.hero__scrollcue {
  position: absolute;
  right: clamp(1.4rem, 4vw, 3rem);
  bottom: 2.4rem;
}

.hero__scrollcue span {
  display: block;
  width: 1px;
  height: 56px;
  background: rgba(247, 243, 232, 0.75);
  animation: cue 2.6s var(--ease-soft) infinite;
  transform-origin: top;
}

@keyframes cue {
  0% { transform: scaleY(0); opacity: 0; }
  35% { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1) translateY(30px); opacity: 0; }
}

/* ---------- chapters ---------- */

.chapter {
  padding: clamp(5rem, 14vh, 10rem) 0 clamp(4rem, 10vh, 8rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(4.5rem, 12vh, 9rem);
}

.chapter--dark {
  background: var(--night);
  color: var(--cream);
  --hairline: rgba(237, 231, 216, 0.16);
  --stone: var(--stone-dark);
}

.chapter--coda { padding-top: 0; padding-bottom: 0; }

/* stills resuming after the video reel (same pale green as the body —
   kept as a hook in case this section ever needs its own tone again) */
.chapter--sage { background: var(--sage); }

/* skip layout/paint of far-offscreen sections; 'auto' remembers the
   real size after first render so the scrollbar stays stable.
   the dark chapter is exempt — render-skipping it defers the reel's
   poster fetches and layout until arrival, showing blank video cells */
.chapter:not(.chapter--dark),
.contact {
  content-visibility: auto;
  contain-intrinsic-size: auto 3200px;
}

/* ---------- story fragments ---------- */

.fragment {
  max-width: 40ch;
  padding: 0 1.4rem;
  text-align: center;
  /* parallax-transformed images create stacking contexts that paint over
     plain text — lift all text above them */
  position: relative;
  z-index: 2;
}

/* wider column on desktop so each authored line of a fragment
   sits on its own row instead of re-wrapping mid-sentence.
   (ch here would resolve against the fragment's own inherited
   font-size, not the larger paragraph size, so use px/vw instead) */
@media (min-width: 900px) {
  .fragment { max-width: min(1200px, 94vw); }
}

.fragment p {
  margin: 0;
  font-size: clamp(1.55rem, 4vw, 2.5rem);
  font-weight: 300;
  line-height: 1.35;
  letter-spacing: -0.01em;
}

.fragment em {
  font-style: italic;
  font-weight: 340;
  color: var(--racing);
}

.chapter--dark .fragment em { color: #7fb89a; }

/* practical copy (availability line) — one step quieter than the voice fragments */
.fragment--fine p { font-size: clamp(1.35rem, 3.3vw, 2.1rem); }


/* ---------- frames (photographs) ---------- */

.frame {
  margin: 0;
  width: min(1120px, 88vw);
  will-change: transform;
}

.frame img {
  width: 100%;
  box-shadow: 0 24px 70px -30px rgba(23, 31, 26, 0.35);
}

.frame--wide { width: min(1120px, 88vw); }
.frame--med  { width: min(680px, 88vw); }
.frame--tall { width: min(460px, 80vw); }

.frame--full {
  width: 100vw;
  overflow: hidden;
  position: relative;
}

.frame--full img { box-shadow: none; }
.frame--full .frame__crop { box-shadow: none; }

.push-l { align-self: flex-start; margin-left: clamp(1rem, 6vw, 6rem); }
.push-r { align-self: flex-end; margin-right: clamp(1rem, 6vw, 6rem); }

/* signature frame — the racing green mat */
.frame--signature img {
  border: clamp(0.8rem, 2vw, 1.6rem) solid var(--racing);
}

/* ---------- two-up rows ---------- */

.duo {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(1.2rem, 4vw, 4rem);
  width: min(1120px, 92vw);
}

.duo .frame { width: 100%; }
.duo > * { flex: 1 1 0; min-width: 0; }

.duo__late { margin-top: clamp(3rem, 9vw, 7rem); }

@media (max-width: 720px) {
  .duo {
    flex-direction: column;
    align-items: center;
    gap: clamp(3.5rem, 10vh, 6rem);
  }
  .duo > * { flex: none; }
  .duo .frame--tall { width: min(460px, 80vw); }
  .duo .frame--med { width: min(680px, 88vw); }
  .duo__late { margin-top: 0; align-self: flex-end; }
  .duo > .frame:first-child { align-self: flex-start; }
}

/* ---------- captions — film-edge markings ---------- */

.cap {
  display: flex;
  align-items: baseline;
  gap: 0.7em;
  margin-top: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  color: var(--stone);
  position: relative; /* keep captions above drifting parallax images */
  z-index: 2;
}

.cap__fr {
  color: var(--racing);
  font-weight: 500;
}

.chapter--dark .cap__fr { color: #7fb89a; }

/* caption for full-bleed images — sits below the image like every other
   caption, inset from the viewport edge */
.cap--onfull {
  padding-left: clamp(1.2rem, 4vw, 3rem);
}

/* ---------- vertical video reel ---------- */

.reel {
  width: min(1120px, 92vw);
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
}

.reel__label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  color: var(--stone);
}

/* gutter on the right reserves space for the arrow, so it sits beside
   the videos rather than on top of the last one */
.reel__viewport {
  position: relative;
  padding-right: clamp(54px, 6vw, 66px);
}

/* minimal scroll cue + control — advances the carousel one clip */
.reel__next {
  position: absolute;
  right: 0;
  top: calc(50% - 1.4rem); /* centre on the cells, not the captions */
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: rgba(14, 23, 18, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: 999px;
  color: #fff;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 3;
  transition: background 0.35s var(--ease-soft), color 0.35s var(--ease-soft);
}

.reel__next svg { width: 18px; height: 18px; display: block; }

.reel__next:hover,
.reel__next:focus-visible {
  background: rgba(237, 231, 216, 0.92);
  color: var(--night);
}

/* "scroll to see more" — mobile only; the arrow is the desktop cue.
   slight negative top margin nudges it up toward the clips above */
.reel__hint {
  display: none;
  margin: -0.7rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  color: var(--stone);
  text-align: center;
}

.reel__hint-arrow {
  margin-left: 0.15em;
  letter-spacing: 0;
}

@media (max-width: 899px) {
  .reel__next { display: none; }
  .reel__viewport { padding-right: 0; } /* reclaim the arrow gutter */
  .reel__hint { display: block; }
}

/* line break that only applies on narrow screens */
.only-mobile { display: none; }
@media (max-width: 720px) {
  .only-mobile { display: inline; }
}

.reel__track {
  --reel-gap: clamp(0.9rem, 2.5vw, 1.6rem);
  display: flex;
  gap: var(--reel-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 0.8rem;
  scrollbar-width: thin;
  scrollbar-color: var(--racing) transparent;
}

.reel__item {
  flex: 0 0 auto;
  width: clamp(200px, 26vw, 280px);
  scroll-snap-align: start;
  margin: 0;
}

/* desktop: exactly four full clips across the track */
@media (min-width: 900px) {
  .reel__item {
    width: calc((100% - 3 * var(--reel-gap)) / 4);
  }
}

.reel__cell {
  position: relative;
  width: 100%;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  background: rgba(237, 231, 216, 0.04);
  border: 1px solid var(--hairline);
  /* promote to its own compositor layer so scrolling the track doesn't
     re-rasterise the video each frame (the mobile-Safari scroll flicker) */
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.reel__sound {
  position: absolute;
  right: 0.6rem;
  bottom: 0.6rem;
  padding: 0.3rem 0.8rem;
  background: rgba(14, 23, 18, 0.55);
  color: rgba(237, 231, 216, 0.85);
  border: 1px solid rgba(237, 231, 216, 0.35);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background 0.35s var(--ease-soft), color 0.35s var(--ease-soft);
}

.reel__sound:hover,
.reel__sound:focus-visible {
  background: rgba(237, 231, 216, 0.9);
  color: var(--night);
}

.reel__sound.is-on {
  background: var(--cream);
  color: var(--racing);
  border-color: var(--cream);
}

.reel__cell video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.reel__cell--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.2rem;
}

.reel__cell--empty p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  line-height: 2;
  color: var(--stone);
  text-align: center;
}

.reel__ig {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--stone);
  text-align: center;
}

.reel__ig a {
  color: #7fb89a;
  text-decoration: none;
  border-bottom: 1px solid rgba(127, 184, 154, 0.4);
  padding-bottom: 1px;
  transition: border-color 0.35s var(--ease-soft), color 0.35s var(--ease-soft);
}

.reel__ig a:hover, .reel__ig a:focus-visible { color: var(--cream); border-color: var(--cream); }


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

.contact {
  background: var(--racing);
  color: var(--cream);
  padding: clamp(5rem, 15vh, 10rem) 1.4rem clamp(2rem, 5vh, 3rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3.2rem;
}

.fragment--contact em { color: #9ed3b6; }

/* form and success occupy the same slot, so the thank-you fades in
   exactly where the form was */
.contact__slot {
  position: relative;
  width: min(560px, 100%);
}

.contact__form {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 1.9rem;
  transition: opacity 0.5s var(--ease-soft);
}

/* #contact-form for specificity — must beat .reveal.is-in's opacity:1,
   which is declared later in the stylesheet and otherwise wins the tie */
#contact-form.is-sent {
  opacity: 0;
  pointer-events: none;
}

.contact__success {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s var(--ease-soft);
}

.contact__success.is-shown {
  opacity: 1;
}

.contact__success-eyebrow {
  margin: 0 0 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  color: rgba(237, 231, 216, 0.65);
}

.contact__success-text {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(1.5rem, 3.6vw, 2.2rem);
  line-height: 1.4;
}

.contact__success-text em {
  font-style: italic;
  color: #9ed3b6;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.field label {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  color: rgba(237, 231, 216, 0.65);
}

.field input,
.field textarea {
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(237, 231, 216, 0.35);
  border-radius: 0;
  padding: 0.45rem 0.1rem;
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 340;
  font-size: 1.05rem;
  transition: border-color 0.4s var(--ease-soft);
  resize: vertical;
}

.field input:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-bottom-color: var(--cream);
}

.contact__send {
  align-self: flex-start;
  margin-top: 0.4rem;
  background: transparent;
  color: var(--cream);
  border: 1px solid rgba(237, 231, 216, 0.5);
  border-radius: 999px;
  padding: 0.75rem 2.2rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  cursor: pointer;
  transition: background 0.4s var(--ease-soft), color 0.4s var(--ease-soft);
}

.contact__send:hover,
.contact__send:focus-visible {
  background: var(--cream);
  color: var(--racing);
}

.contact__send:disabled {
  opacity: 0.55;
  cursor: default;
  background: transparent;
  color: var(--cream);
}

.contact__status {
  margin: 0;
  min-height: 1.2em;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: rgba(237, 231, 216, 0.8);
}

.contact__alt {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  color: rgba(237, 231, 216, 0.75);
}

.contact__alt a {
  color: var(--cream);
  text-decoration: none;
  border-bottom: 1px solid rgba(237, 231, 216, 0.4);
  padding-bottom: 1px;
}

.contact__alt a:hover { border-color: var(--cream); }

.site-foot {
  margin-top: clamp(3rem, 8vh, 5rem);
  width: min(1120px, 100%);
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border-top: 1px solid rgba(237, 231, 216, 0.2);
  padding-top: 1.3rem;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  color: rgba(237, 231, 216, 0.6);
}

.site-foot a { color: inherit; text-decoration: none; }
.site-foot a:hover { color: var(--cream); }

/* ---------- motion: reveals & parallax ---------- */

.reveal {
  opacity: 0;
  transform: translateY(34px);
  transition:
    opacity 1.1s var(--ease-soft),
    transform 1.1s var(--ease-soft);
}

.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* parallax translation is applied to the img inside frames,
   so the reveal transform on the figure never conflicts */
[data-plx] img,
[data-plx-cover] img {
  will-change: transform;
}

/* the drifting image is over-scaled and clipped by its own crop box
   (not the figure — the figure also contains the caption, and clipping
   there lets the scaled image bleed under the caption text), so the
   parallax pans within the photograph and can never touch any text */
.frame__crop {
  overflow: hidden;
  box-shadow: 0 24px 70px -30px rgba(23, 31, 26, 0.35);
}

.frame__crop img { box-shadow: none; }

[data-plx] img { transform: scale(1.15); }

[data-plx-cover] img {
  transform: scale(1.14);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .hero__scrollcue { display: none; }
  [data-plx-cover] img { transform: none; }
  [data-plx] img { transform: none; }
}
