/* ================================================
   POLINO — Scroll-driven table film
   Full-bleed footage with a restrained aged-paper
   treatment inspired by workshop materials.
   ================================================ */

.table-film {
  --film-progress: 0;
  position: relative;
  height: 205svh;
  background: #281f18;
  isolation: isolate;
}

/* The film is decorative; without JavaScript there is no useful scroll state. */
.no-js .table-film { display: none; }

.table-film__sticky {
  position: sticky;
  top: 0;
  width: 100%;
  height: 100svh;
  overflow: hidden;
  background: #281f18;
  contain: paint;
}

/* Fine fibres and dust sit over the entire moving image. */
.table-film__sticky::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background-image:
    repeating-linear-gradient(7deg, rgba(62,39,20,0.045) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(97deg, rgba(255,241,205,0.035) 0 1px, transparent 1px 13px),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)' opacity='.55'/%3E%3C/svg%3E");
  background-size: auto, auto, 210px 210px;
  opacity: 0.22;
}

/* Uneven exposure and faint fold marks echo the supplied paper reference. */
.table-film__sticky::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  background:
    linear-gradient(13deg, transparent 0 18%, rgba(249,224,176,0.10) 18.1% 18.25%, rgba(51,31,16,0.12) 18.4% 18.6%, transparent 18.75% 100%),
    linear-gradient(169deg, transparent 0 79%, rgba(40,25,13,0.11) 79.15% 79.35%, rgba(246,218,164,0.08) 79.5% 79.65%, transparent 79.8% 100%),
    linear-gradient(180deg, rgba(23,18,14,0.18), transparent 9%, transparent 88%, rgba(23,18,14,0.14)),
    radial-gradient(ellipse at 50% 46%, transparent 48%, rgba(50,31,16,0.08) 80%, rgba(27,17,10,0.26) 100%);
  opacity: 0.82;
}

.table-film__frame {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #281f18;
  background-image: url('../assets/table-crane-poster-v1.webp');
  background-position: 50% 50%;
  background-size: cover;
}

.table-film__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: 50% 50%;
  background: transparent;
  filter: sepia(0.12) saturate(0.90) contrast(1.035) brightness(0.93);
  opacity: 0;
  transform: scale(1.003);
  backface-visibility: hidden;
  transition: opacity 240ms ease-out;
}

.table-film.is-ready .table-film__video { opacity: 1; }
.table-film.has-error .table-film__video { display: none; }

/* Translucent kraft wash: the picture remains readable underneath. */
.table-film__frame::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(circle at 15% 22%, rgba(246,214,159,0.10), transparent 32%),
    radial-gradient(circle at 82% 68%, rgba(65,39,19,0.12), transparent 42%),
    linear-gradient(118deg, rgba(196,145,82,0.11), rgba(86,53,26,0.08)),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)' opacity='.48'/%3E%3C/svg%3E");
  background-size: cover, cover, cover, 170px 170px;
  opacity: 0.34;
}

.table-film__frame::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  box-shadow:
    0 0 8vw rgba(36,22,11,0.24) inset,
    0 0 1.5vw rgba(28,17,9,0.12) inset;
}

/* ---- HERO SEAM --------------------------------------------------
   The film would otherwise start on a hard horizontal cut against the
   hero. This sits at the top of the section — in flow, not stuck —
   so it travels up with the frame as the section arrives, softening
   and tinting the emerging picture into the hero's own cream.
   It dissolves over the first third of the scrub, by which point the
   hero is long gone from the screen.
   ------------------------------------------------------------------ */

.table-film__seam {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 6;
  height: clamp(160px, 30svh, 420px);
  pointer-events: none;
  opacity: calc(1 - var(--film-progress) * 3);
}

/* Blur first, so the mosaic's hard tile edges do not read through the tint. */
.table-film__seam::before {
  content: '';
  position: absolute;
  inset: 0;
  backdrop-filter: blur(16px) saturate(0.90) brightness(1.06);
  -webkit-backdrop-filter: blur(16px) saturate(0.90) brightness(1.06);
  mask-image: linear-gradient(
    to bottom,
    #000 0%,
    rgba(0, 0, 0, 0.88) 30%,
    rgba(0, 0, 0, 0.42) 62%,
    transparent 100%);
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0%,
    rgba(0, 0, 0, 0.88) 30%,
    rgba(0, 0, 0, 0.42) 62%,
    transparent 100%);
}

/* #EDDFC3 is the hero's colour at its bottom edge. The seam now carries
   cream down onto the dark film, so the light-to-dark cut is a dissolve
   instead of a hard edge. */
.table-film__seam::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    #eddfc3 0%,
    rgba(237, 223, 195, 0.92) 22%,
    rgba(229, 210, 176, 0.60) 48%,
    rgba(214, 191, 152, 0.22) 76%,
    transparent 100%);
}

/* ---- COPY BEATS -------------------------------------------------
   Three short lines handed off by scroll progress, so the film says
   what the piece is and what to do about it at the point the table
   finally resolves. No pins or leader lines: the camera scales and
   travels, and the crop differs per viewport, so anything anchored to
   the image itself would drift.
   ------------------------------------------------------------------ */

.table-film__beats {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}

/* The mosaic underneath is high-contrast and busy; text needs a floor. */
.table-film__beats::before {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 64%;
  pointer-events: none;
  background: linear-gradient(
    to top,
    rgba(18, 11, 6, 0.88) 0%,
    rgba(18, 11, 6, 0.62) 26%,
    rgba(18, 11, 6, 0.28) 58%,
    transparent 100%);
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-out);
}
.table-film.is-ready .table-film__beats::before,
.table-film.has-error .table-film__beats::before { opacity: 1; }

.table-film__beat {
  position: absolute;
  left: clamp(var(--space-6), 6vw, var(--space-24));
  right: clamp(var(--space-6), 6vw, var(--space-24));
  bottom: clamp(var(--space-10), 9vh, var(--space-20));
  max-width: 40rem;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px);
  transition:
    opacity    var(--duration-slow) var(--ease-out),
    transform  var(--duration-slow) var(--ease-out),
    visibility 0s linear var(--duration-slow);
}

.table-film:is(.is-ready, .has-error)[data-beat="1"] .table-film__beat[data-film-beat="1"],
.table-film:is(.is-ready, .has-error)[data-beat="2"] .table-film__beat[data-film-beat="2"],
.table-film:is(.is-ready, .has-error)[data-beat="3"] .table-film__beat[data-film-beat="3"] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* Same 48x2 terracotta mark the section headers use, in the light-on-dark
   variant, so the copy is anchored rather than floating on the picture. */
.table-film__beat::before {
  content: '';
  width: 48px;
  height: 2px;
  flex: none;
  background: var(--amber);
  box-shadow: 0 1px 4px rgba(18, 11, 6, 0.65);
}

.table-film__kicker {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 1px 3px rgba(18, 11, 6, 0.8);
}

/* The display serif, matching every other heading on the site. It was set in
   Manrope on the theory that a caption over moving footage wants a sans that
   reads at a glance — but that made this the one heading in a different voice,
   and the break was more noticeable than the legibility gain. Semi-bold and a
   step larger than the sans was, because Cormorant sets visually smaller and
   this one has to hold its own over a picture. */
.table-film__line {
  font-family: var(--font-display);
  /* Semi-bold serif at near-4rem read heavy rather than elegant — regular
     weight is what makes Cormorant Garamond feel like a serif, and the
     cap is pulled back so it sits closer to the other section headings. */
  font-size: clamp(var(--text-2xl), 3.4vw, 2.75rem);
  font-weight: var(--weight-regular);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--white-mosaic);
  text-shadow:
    0 1px 2px rgba(18, 11, 6, 0.72),
    0 2px 22px rgba(18, 11, 6, 0.68);
  text-wrap: balance;
}

/* The beats layer is pass-through so it never eats a scroll gesture. */
.table-film__cta {
  margin-top: var(--space-2);
  pointer-events: auto;
}

.table-film__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 640px) {
  .table-film { height: 190svh; }
  .table-film__video { object-position: 50% 50%; }
}

/* Both sources are 16:9. Cropping them to fill a portrait phone throws away
   roughly three quarters of the width, and the pull-back never resolves into
   a whole table — the one thing the shot exists to show. Give the film its
   own band and let the kraft field carry the copy underneath it. */
/* Full-bleed and cropped by preference: a fitted window surrounded by kraft
   read as dead weight on a phone. The trade is that a 16:9 source cropped to a
   portrait screen shows only about a quarter of its width, so the pull-back
   never resolves the whole table here — only a portrait export of the footage
   would give both. */
@media (orientation: portrait) and (max-width: 900px) {
  .table-film__line { font-size: clamp(var(--text-xl), 6.5vw, var(--text-3xl)); }
}

@media (prefers-reduced-motion: reduce) {
  .table-film {
    height: auto;
    min-height: 100svh;
  }
  .table-film__sticky {
    position: relative;
    min-height: 100svh;
  }
  .table-film__video { display: none; }

  /* No scrub to hand the beats off, so the copy stands as a static stack
     over the poster frame. */
  .table-film__beats {
    position: relative;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: var(--space-8);
    padding:
      var(--space-24)
      clamp(var(--space-6), 6vw, var(--space-24))
      clamp(var(--space-10), 9vh, var(--space-20));
  }
  /* All three beats sit over the poster at once, so the wash has to hold
     across the whole frame rather than taper off toward the top. */
  .table-film__beats::before {
    opacity: 1;
    inset: 0;
    height: auto;
    background: linear-gradient(
      to top,
      rgba(18, 11, 6, 0.90) 0%,
      rgba(18, 11, 6, 0.80) 60%,
      rgba(18, 11, 6, 0.66) 100%);
  }
  .table-film__beat {
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
  }
}
