/* ===========================================================
   Simon van Ackern — Videographer & Journalist
   Style reference: Freytag Anderson (freytaganderson.com)
   Achromatic, single-typeface, full-bleed cinematic portfolio.
   =========================================================== */

/* Self-hosted (not loaded from Google's servers — see index.html head
   comment). Variable font: covers weights 300–400 in one file. */
@font-face {
  font-family: 'Inter';
  src: url('assets/fonts/inter-var-latin.woff2') format('woff2-variations'),
       url('assets/fonts/inter-var-latin.woff2') format('woff2');
  font-weight: 300 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --color-paper: #fafafa;
  --color-ink: #000000;
  --color-charcoal: #1c1c1c;
  --color-midnight-soil: #141109;
  --color-ash: #dcdcdc;
  --color-driftwood: #c2b5ae;

  --font-main: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --text-caption: 15px;
  --leading-caption: 1.4;
  --tracking-caption: -0.02em;

  --text-body: 17px;
  --leading-body: 1.7;
  --tracking-body: -0.02em;

  --text-display: 41px;
  --leading-display: 1.18;
  --tracking-display: -0.022em;

  --spacing-6: 6px;
  --spacing-12: 12px;
  --spacing-16: 16px;
  --spacing-17: 17px;
  --spacing-20: 20px;
  --spacing-29: 29px;
  --spacing-43: 43px;
  --section-gap: 220px;

  --radius-full: 300px;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-main);
  font-weight: 400;
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  -webkit-font-smoothing: antialiased;
}

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

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

.on-dark { color: var(--color-paper); }

/* ---------- Top nav ---------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-29) var(--spacing-29);
  mix-blend-mode: difference;
}

.site-header .brand {
  display: block;
  color: var(--color-paper);
  line-height: 0;
}

.brand-mark {
  display: block;
  height: 30px;
  width: auto;
}

.hamburger {
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--spacing-12);
  display: flex;
  flex-direction: column;
  gap: 5px;
  z-index: 210;
}

.hamburger span {
  display: block;
  width: 24px;
  height: 1px;
  background: var(--color-paper);
  transition: transform 0.3s ease, opacity 0.3s ease, background 0.3s ease;
}

.nav-open .hamburger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-open .hamburger span:nth-child(2) { opacity: 0; }
.nav-open .hamburger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* full screen nav overlay */
.nav-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-ink);
  z-index: 150;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 100px var(--spacing-29);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

.nav-open .nav-overlay {
  opacity: 1;
  pointer-events: auto;
}

.nav-overlay ol {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-overlay li {
  margin-bottom: var(--spacing-20);
}

/* Scoped to .nav-link (not a bare "a") so the footer email address
   below keeps its own small caption size instead of inheriting this
   heading-sized treatment — see .nav-foot. */
.nav-overlay .nav-link {
  color: var(--color-paper);
  font-size: var(--text-display);
  font-weight: 300;
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-display);
  transition: opacity 0.2s ease;
}

.nav-overlay a:hover { opacity: 0.55; }

.nav-overlay .nav-foot {
  position: absolute;
  bottom: var(--spacing-29);
  left: var(--spacing-29);
  right: var(--spacing-29);
  display: flex;
  justify-content: space-between;
  font-size: var(--text-caption);
  font-weight: 300;
  color: var(--color-ash);
  overflow-wrap: anywhere;
}

/* ---------- Hero (Reel) ---------- */

.hero {
  position: sticky;
  top: 0;
  height: 100vh;
  min-height: 560px;
  width: 100%;
  overflow: hidden;
  background: var(--color-charcoal);
}

.hero-video {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--color-charcoal);
}

.hero-video .hero-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Vimeo iframe "cover" trick: oversize a 16:9 embed and center it so it
   always fills the viewport with no letterboxing, like object-fit: cover. */
.hero-video iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100vw;
  height: 56.25vw;   /* 16:9 */
  min-height: 100vh;
  min-width: 177.78vh; /* 16:9 */
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.28) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0.05) 70%, rgba(0,0,0,0.35) 100%);
  pointer-events: none;
}

.sound-toggle {
  position: absolute;
  right: var(--spacing-29);
  bottom: var(--spacing-29);
  z-index: 2;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(250,250,250,0.5);
  background: rgba(0,0,0,0.25);
  color: var(--color-paper);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.sound-toggle:hover {
  background: rgba(0,0,0,0.45);
  border-color: var(--color-paper);
}

.sound-toggle svg {
  width: 20px;
  height: 20px;
}

.sound-toggle .icon-unmuted { display: none; }
.sound-toggle.is-unmuted .icon-muted { display: none; }
.sound-toggle.is-unmuted .icon-unmuted { display: block; }

.hero-text {
  position: absolute;
  left: var(--spacing-29);
  top: 100px;
  right: var(--spacing-29);
  z-index: 2;
  max-width: 720px;
}

.hero-text .hello {
  font-size: 22px;
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--color-paper);
  margin: 0;
}

.hero-text .hello span {
  display: block;
}

/* ---------- Section framework ---------- */

/* min-height:100vh on every sticky panel is load-bearing, not
   cosmetic: a sticky section stays "stuck-eligible" for as long as its
   shared ancestor (<body>) hasn't ended, and is only visually hidden
   once a later section's box fully covers the same screen area. Any
   panel shorter than the viewport leaves a gap where older, still-
   "stuck" sections bleed through underneath it (confirmed — with
   .work-item at 72vh, Services' paragraph text was visible showing
   through beneath a Work item that hadn't fully covered the screen).
   Forcing every panel to at least one viewport tall guarantees full
   coverage regardless of how short its actual content is. #gallery and
   #work (the plain, non-sticky wrapper around .work-item) are already
   taller than this from their own content, so the rule is a no-op
   there — no need to opt them out. */
section {
  position: sticky;
  top: 0;
  min-height: 100vh;
  padding: 100px var(--spacing-29) var(--section-gap);
}

.section-dark {
  background: var(--color-charcoal);
  color: var(--color-paper);
}

.section-midnight {
  background: var(--color-midnight-soil);
  color: var(--color-paper);
}

/* Every section in the sticky-slide chain needs its own opaque
   background — otherwise, once it locks in place, whatever is stacked
   behind it (an earlier section, not just the one right after) shows
   through instead of being cleanly covered. */
.work-intro {
  background: var(--color-paper);
}

.statement {
  font-size: var(--text-display);
  font-weight: 400;
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  max-width: 760px;
  margin: 0 0 100px;
}

.eyebrow {
  font-size: var(--text-caption);
  font-weight: 300;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-driftwood);
  margin: 0 0 var(--spacing-20);
}

/* ---------- Services: three-column body grid ---------- */

.services-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 60px var(--spacing-43);
}

.service-col h3 {
  font-size: var(--text-body);
  font-weight: 400;
  margin: 0 0 var(--spacing-17);
  letter-spacing: var(--tracking-body);
}

.service-col p {
  font-size: var(--text-body);
  font-weight: 300;
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  color: var(--color-ash);
  margin: 0 0 var(--spacing-17);
}

.service-col p:last-child { margin-bottom: 0; }

/* ---------- Work: full-bleed project planes ---------- */

.work-section { position: static; padding: 0; }

.work-item {
  position: sticky;
  top: 0;
  height: 100vh;
  min-height: 560px;
  display: flex;
  align-items: flex-start;
  overflow: hidden;
  border-top: 1px solid rgba(255,255,255,0.08);
  background: var(--color-charcoal);
}

.work-item img,
.work-item video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s ease;
}

.work-item:hover img,
.work-item:hover video { transform: scale(1.03); }

/* Vimeo iframe "cover" trick, same as the hero: oversize a 16:9 embed and
   center it so it fills the panel like object-fit: cover. Clicks fall
   through to the surrounding <a>. */
.work-item iframe.work-video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100vw;
  height: 56.25vw;
  min-height: 100%;
  min-width: 177.78vh;
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;
}

/* Darkens the TOP now, not the bottom — the title/tag moved up there
   (see .work-item .work-meta below) so it needs the contrast instead. */
.work-item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0) 45%);
}

/* Title+arrow and the tag both live at the TOP of the panel now, not
   the bottom. Reasoning from how the scroll-slide covering actually
   plays out: a panel's TOP content is what's visible first as it
   slides up into place, and stays visible longest — right up until
   the next panel fully covers it — while bottom-anchored content only
   becomes visible for a brief moment right as the panel finishes
   arriving, then gets covered almost immediately as the next one
   starts sliding in. Bottom placement meant a quick scroll could pass
   through without ever showing the title. Top-padding (100px) clears
   the fixed header/hamburger, matching every other section's opening. */
.work-item .work-meta {
  position: relative;
  z-index: 2;
  padding: 100px var(--spacing-29) 0;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-6);
  width: 100%;
}

.work-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spacing-20);
}

.work-item .work-title {
  color: var(--color-paper);
  font-size: var(--text-display);
  font-weight: 400;
  letter-spacing: var(--tracking-display);
  line-height: 1.15;
}

.work-item .work-arrow {
  color: var(--color-paper);
  font-size: var(--text-display);
  font-weight: 300;
  flex-shrink: 0;
}

.work-item .work-tag {
  color: var(--color-paper);
  font-size: var(--text-caption);
  font-weight: 300;
  letter-spacing: 0.02em;
  opacity: 0.8;
}

.work-item.is-progress {
  cursor: default;
}

.work-item.is-progress .work-title { opacity: 0.85; }

/* ---------- Gallery: raw edge-to-edge grid ---------- */

/* position:relative (not static) despite this section never actually
   moving — it's needed so Gallery paints in the same "positioned
   elements" layer as the sticky sections around it. Per CSS stacking
   rules, positioned elements always paint over static ones regardless
   of DOM order — so a static Gallery sitting after several still-
   "stuck" sticky sections (their containing block is <body>, so they
   never really release until near the very bottom of the page) would
   stay invisible, hidden underneath .work-intro, for its entire
   scroll-through (confirmed on a real device test). Gallery still
   isn't sticky itself — it scrolls normally, exactly as before. */
.gallery-section {
  position: relative;
  background: var(--color-paper);
  padding-bottom: var(--section-gap);
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
}

.gallery-grid img {
  display: block;
  width: 100%;
  height: auto;
  -webkit-user-drag: none;
  user-select: none;
}

.gallery-grid a { display: block; overflow: hidden; cursor: pointer; }
.gallery-grid img { transition: transform 0.5s ease; }
.gallery-grid a:hover img { transform: scale(1.04); }

/* ---------- Lightbox ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px var(--spacing-29);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.lightbox.is-open {
  opacity: 1;
  pointer-events: auto;
}

.lightbox-frame {
  position: relative;
  max-width: 100%;
  max-height: 100%;
  line-height: 0;
}

.lightbox-image {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - 120px);
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
}

.lightbox-watermark {
  position: absolute;
  bottom: var(--spacing-20);
  left: var(--spacing-20);
  width: auto;
  height: 104px;
  color: var(--color-paper);
  opacity: 0.65;
  pointer-events: none;
}

.lightbox-close,
.lightbox-nav {
  position: fixed;
  background: none;
  border: none;
  color: var(--color-paper);
  cursor: pointer;
  z-index: 301;
}

.lightbox-close {
  top: var(--spacing-29);
  right: var(--spacing-29);
  font-size: 32px;
  line-height: 1;
  font-weight: 300;
}

.lightbox-nav {
  top: 50%;
  transform: translateY(-50%);
  font-size: 48px;
  font-weight: 300;
  padding: var(--spacing-12);
}

.lightbox-prev { left: var(--spacing-12); }
.lightbox-next { right: var(--spacing-12); }

.lightbox-close:hover,
.lightbox-nav:hover { opacity: 0.6; }

@media (max-width: 600px) {
  .lightbox-nav { font-size: 32px; }
}

/* ---------- Contact ---------- */

/* position:relative, not sticky, and no forced 100vh: this is the last
   section and on phones it's taller than the screen. A sticky element
   taller than the viewport can never scroll its lower part into view
   (the form's Send button was unreachable, covered by the footer).
   relative keeps it painting above the earlier sticky sections, and the
   grey form block now ends flush against the footer. */
.contact-section {
  position: relative;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding-bottom: 0;
}

/* Bleeds edge-to-edge and down to the section's own bottom edge by
   cancelling the parent section's padding with negative margins, then
   re-applying it as its own padding — a plain grey block living
   inside the same sticky section as the black contact-row above it,
   not a separate sliding panel (that was the "too much dead space /
   why is there a separate slide here" complaint). */
.contact-form-wrap {
  /* .contact-section is a flex column with align-items:flex-start, so
     without this a flex item shrinks to its content width instead of
     filling the cross-axis — the negative margins below need a full-
     width box to bleed correctly from. */
  align-self: stretch;
  margin: var(--spacing-43) calc(-1 * var(--spacing-29)) 0;
  padding: 70px var(--spacing-29);
  background: #2a2a2a;
}

@media (max-width: 860px) {
  .contact-form-wrap {
    margin: var(--spacing-43) calc(-1 * var(--spacing-20)) 0;
    padding: 50px var(--spacing-20);
  }
}

.contact-row {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: var(--spacing-29);
  width: 100%;
  margin-bottom: var(--spacing-43);
}

.contact-portrait-wrap {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.contact-portrait {
  width: 120px;
  height: 120px;
  border-radius: 50%;
}

.contact-row .statement {
  margin: 0;
}

.social-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-6);
  margin-top: var(--spacing-20);
}

.social-link {
  font-size: var(--text-caption);
  font-weight: 300;
  color: var(--color-ash);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

.social-link:hover {
  color: var(--color-paper);
}

.pill {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-full);
  padding: var(--spacing-12) var(--spacing-20);
  font-size: var(--text-caption);
  font-weight: 400;
  letter-spacing: -0.01em;
  transition: background 0.2s ease, color 0.2s ease;
}

.pill:hover {
  background: var(--color-ink);
  color: var(--color-paper);
}

.on-dark .pill,
.section-dark .pill,
.section-midnight .pill {
  border-color: var(--color-paper);
  color: var(--color-paper);
}

.section-dark .pill:hover,
.section-midnight .pill:hover {
  background: var(--color-paper);
  color: var(--color-ink);
}

button.pill {
  background: none;
  font-family: inherit;
  cursor: pointer;
}

/* ---------- Contact form ---------- */

.contact-form {
  width: 100%;
  max-width: 480px;
  margin-top: var(--spacing-43);
}

.form-row {
  margin-bottom: var(--spacing-29);
}

.form-row label {
  display: block;
  font-size: var(--text-caption);
  font-weight: 300;
  color: var(--color-ash);
  margin-bottom: var(--spacing-6);
}

.form-row input,
.form-row textarea {
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--color-ash);
  color: var(--color-paper);
  font-family: inherit;
  font-size: var(--text-body);
  font-weight: 300;
  padding: var(--spacing-6) 0;
  resize: vertical;
  transition: border-color 0.2s ease;
}

.form-row input:focus,
.form-row textarea:focus {
  outline: none;
  border-color: var(--color-paper);
}

.form-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

.form-status {
  font-size: var(--text-caption);
  font-weight: 400;
  margin: 0 0 var(--spacing-20);
  padding: var(--spacing-12) 0;
}

.form-status[data-state="ok"] { color: var(--color-paper); }
.form-status[data-state="error"] { color: var(--color-driftwood); }

/* ---------- Footer ---------- */

footer {
  /* Same fix as .gallery-section above: footer is static, sitting
     right after the still-"stuck" contact section (its containing
     block is <body>, so it never releases until scroll reaches the
     true bottom of the page). Without position:relative here, footer
     would stay hidden underneath it, painted-over, for that whole
     final stretch — this is what "the footer is gone" actually was. */
  position: relative;
  background: var(--color-paper);
  padding: var(--spacing-43) var(--spacing-29);
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-16);
  justify-content: space-between;
  font-size: var(--text-caption);
  font-weight: 300;
  color: #6b6b6b;
}

footer a { border-bottom: 1px solid transparent; }
footer a:hover { border-bottom-color: currentColor; }

/* ---------- Responsive ---------- */

@media (max-width: 860px) {
  :root { --section-gap: 140px; }
  .text-display, .statement, .work-item .work-title, .nav-overlay .nav-link {
    font-size: 32px;
  }
  .hero-text .hello {
    font-size: 19px;
  }
  .services-grid { grid-template-columns: 1fr; gap: 40px; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  section { padding: 70px var(--spacing-20) var(--section-gap); }
  .hero-text { top: 90px; }
}

@media (max-width: 480px) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  .work-item .work-title { font-size: 26px; }
}
