/* =========================================================
   Viewfinder hero — shared across the public pages.

   A split hero: the copy sits on paper at the left, the
   photograph holds still at the right and cross-fades between
   frames. Type never sits on the photograph, so legibility is
   structural rather than something a wash has to rescue.

   Camera cues are STILLS, not motion: the readout is shutter
   speed and aperture, and the corner marker is a frame number.
   No frame rate, no blinking record light.

   Per-page content is declared in window.TMB_VIEWFINDER and
   driven by js/viewfinder.js.
   ========================================================= */

:root {
  /* The fixed nav's height. The viewfinder frame is inset past it so
     the Menu button and the Book pill never land on a bracket. */
  --nav-h: 84px;
}

/* ---------- the split ---------- */
/* minmax() rather than min-height: an auto row sizes to the copy and
   centres itself, leaving paper above and below the photograph.
   padding:0 because theme.css puts padding on a bare <section>. */
.vf {
  position: relative;
  display: grid;
  grid-template-columns: 48fr 52fr;
  grid-template-rows: minmax(100svh, auto);
  align-content: stretch;
  padding: 0;
  overflow: hidden;
  background: var(--paper);
}
/* Browse pages keep their grid near the fold, so their hero is shorter. */
.vf.vf-compact { grid-template-rows: minmax(66svh, auto); }

/* ---------- left: the copy column ---------- */
.vf-copy {
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(104px, 13vh, 150px) clamp(26px, 3.6vw, 54px)
           clamp(40px, 6vh, 70px)   clamp(30px, 5vw, 86px);
}

/* The exposure readout and the hairline that sell the viewfinder idea. */
.vf-meta {
  position: absolute;
  top: clamp(96px, 13vh, 140px);
  left: clamp(30px, 5vw, 86px);
  font-size: 10.5px; font-weight: 600; letter-spacing: .3em;
  text-transform: uppercase; color: var(--ink-dim);
}
.vf-meta b { color: var(--gold); font-weight: 600; }
/* An f-number is written lowercase. The uppercase readout must not eat it. */
.vf-meta .lc { text-transform: none; }

.vf-rule {
  position: absolute;
  top: clamp(140px, 18vh, 195px);
  bottom: clamp(40px, 6vh, 70px);
  left: clamp(18px, 3.2vw, 56px);
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--line-2) 12%,
                              var(--line-2) 88%, transparent);
}

/* Slides stack on top of each other; only the active one is shown.
   Every slide stays absolute, including the active one, and the deck is
   given the height of the tallest slide by JS. If the active slide were
   the one defining the height, a longer headline would shove the rail
   and the buttons down mid-rotation. */
.vf-deck { position: relative; }
/* Text is NOT cross-faded. Two headlines at 50% opacity on top of each other
   are unreadable, so the outgoing slide clears first and the incoming one
   waits for it: out over .4s, in over .7s after a .42s delay. Photographs
   cross-dissolve fine and still do; words do not. */
.vf-slide {
  position: absolute; top: 0; left: 0; right: 0;
  opacity: 0; pointer-events: none;
  transform: translateY(16px);
  transition: opacity .7s var(--ease) .42s, transform .7s var(--ease) .42s;
}
.vf-slide.is-out {
  transform: translateY(-16px);
  transition: opacity .4s var(--ease) 0s, transform .4s var(--ease) 0s;
}
.vf-slide.is-active { opacity: 1; transform: none; pointer-events: auto; }

.vf-eyebrow {
  display: inline-flex; align-items: center; gap: 12px;
  margin-bottom: clamp(18px, 2.6vh, 30px);
  font-size: 11.5px; font-weight: 600; letter-spacing: .26em;
  text-transform: uppercase; color: var(--ink-mid);
}
.vf-eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--gold-lit); box-shadow: 0 0 0 4px rgba(220,171,87,.18);
}
.vf-title {
  font-family: var(--display); font-weight: 300; margin: 0;
  font-size: clamp(34px, 3.35vw, 58px); line-height: 1.06;
  letter-spacing: .004em; color: var(--ink);
}
.vf-title em { font-style: normal; color: var(--gold); }
.vf-sub {
  margin: clamp(18px, 2.6vh, 30px) 0 0; max-width: 40ch;
  font-size: clamp(14.5px, 1.05vw, 17px); font-weight: 300;
  line-height: 1.65; color: var(--ink-mid);
}

/* ---------- the progress rail ---------- */
.vf-rail { display: flex; align-items: center; gap: 18px; margin-top: clamp(30px, 4.4vh, 52px); }
.vf-rail-label {
  font-size: 10.5px; font-weight: 600; letter-spacing: .26em;
  text-transform: uppercase; color: var(--gold); white-space: nowrap;
}
.vf-rail-track { position: relative; flex: 1; max-width: 260px; height: 1px; background: var(--line-2); }
.vf-rail-track i { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--gold-lit); }
.vf-rail-track i::after {
  content: ''; position: absolute; right: -3px; top: -2.5px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold-lit);
}

/* ---------- actions (persistent, they do not slide) ---------- */
.vf-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 26px; margin-top: clamp(28px, 4vh, 46px); }
.vf-btn {
  display: inline-flex; align-items: center; gap: 11px; text-decoration: none;
  border-radius: 999px; padding: 15px 30px;
  font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  background: var(--gold-lit); color: #241a06;
  box-shadow: 0 14px 34px rgba(220,171,87,.26);
  transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.vf-btn:hover { color: #1c1405; transform: translateY(-2px); box-shadow: 0 18px 44px rgba(220,171,87,.4); }
.vf-link {
  display: inline-flex; align-items: center; gap: 9px; text-decoration: none;
  font-size: 12px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-mid); border-bottom: 1px solid transparent; padding-bottom: 2px;
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.vf-link:hover { color: var(--ink); border-bottom-color: var(--gold-lit); }
.vf-btn .ar, .vf-link .ar { transition: transform var(--fast) var(--ease); }
.vf-btn:hover .ar, .vf-link:hover .ar { transform: translateX(4px); }

/* ---------- right: the photograph ---------- */
.vf-photo { position: relative; overflow: hidden; background: var(--paper-2); border-left: 1px solid var(--line-2); }
.vf-frame {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  opacity: 0; transition: opacity 1.4s var(--ease);
  animation: vfDrift 26s ease-in-out infinite alternate;
}
.vf-frame.is-active { opacity: 1; }
/* Mirrors a left-facing subject onto the right. Applied per frame from the
   config, never blanket: a mirrored ring lands on the wrong hand. */
.vf-frame.flip { transform: scaleX(-1); }
@keyframes vfDrift { from { scale: 1; } to { scale: 1.06; } }

/* ---------- viewfinder corner brackets ---------- */
.vf-marks {
  position: absolute; z-index: 4; pointer-events: none;
  inset: calc(var(--nav-h) + clamp(6px, 1vw, 14px)) clamp(20px, 2.6vw, 34px) clamp(20px, 2.6vw, 34px);
}
.vf-marks span {
  position: absolute; width: 28px; height: 28px;
  border: 1px solid rgba(255,255,255,.75);
  filter: drop-shadow(0 0 3px rgba(30,24,18,.45));
}
.vf-marks span:nth-child(1) { top: 0;    left: 0;  border-right: 0; border-bottom: 0; }
.vf-marks span:nth-child(2) { top: 0;    right: 0; border-left: 0;  border-bottom: 0; }
.vf-marks span:nth-child(3) { bottom: 0; right: 0; border-left: 0;  border-top: 0; }
.vf-marks span:nth-child(4) { bottom: 0; left: 0;  border-right: 0; border-top: 0; }

/* The frame counter. A stills camera shows a frame number here, so it holds
   steady: no blinking recording light. Bottom-right, clear of the nav. */
.vf-no {
  position: absolute; z-index: 4;
  right: clamp(58px, 4.6vw, 78px); bottom: clamp(26px, 3vw, 42px);
  font-size: 10px; font-weight: 600; letter-spacing: .26em; text-transform: uppercase;
  color: rgba(255,255,255,.82); display: flex; align-items: center; gap: 9px;
  text-shadow: 0 0 6px rgba(30,24,18,.5);
}
.vf-no .tick { width: 8px; height: 1px; background: var(--gold-lit); }

/* ---------- nav over the photograph ----------
   The brand mark sits on a photograph that changes, so a fixed colour is
   wrong half the time: black vanishes on a dark frame, white on a pale one.

   mix-blend-mode was tried first and does NOT reach the page from inside
   .v2-nav. Verified, not assumed: with a solid white strip painted directly
   under the nav, a difference-blended white mark should render black and
   instead stayed light. The likely cause is that the fixed, z-indexed nav
   forms an isolated group, leaving a blended child only the transparent nav
   to blend against, though a standalone prototype nav did blend, so treat
   the mechanism as probable rather than settled. Either way the failure mode
   is nasty: over a DARK frame an unblended white mark still looks correct,
   so the bug hides until a pale frame comes around.

   backdrop-filter samples what is actually painted behind the element,
   stacking context or not, so it is the mechanism that works. The mark is
   used as an alpha MASK over a filter that desaturates, inverts, then pushes
   contrast, giving a neutral light-on-dark / dark-on-light result. The <img>
   stays in the DOM at opacity 0 so it keeps the layout box and its alt text.

   Known limit: against an exact mid-tone an invert approaches the backdrop.
   contrast(3) pushes the result toward an extreme rather than sitting on it,
   and a thin script mark on a real photograph is rarely uniform enough to
   vanish entirely. Scoped to .vf-nav-adaptive, so pages without a photo hero
   are untouched. */
.vf-nav-adaptive .v2-brand { position: relative; }
.vf-nav-adaptive .v2-brand img { opacity: 0; }
.vf-nav-adaptive .v2-brand::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  -webkit-mask: url('../media/signature.png') center / contain no-repeat;
          mask: url('../media/signature.png') center / contain no-repeat;
  -webkit-backdrop-filter: grayscale(1) invert(1) contrast(3);
          backdrop-filter: grayscale(1) invert(1) contrast(3);
}
/* No backdrop-filter means nothing to invert, so show the plain black mark
   rather than an empty gap. */
@supports not ((backdrop-filter: invert(1)) or (-webkit-backdrop-filter: invert(1))) {
  .vf-nav-adaptive .v2-brand::after { display: none; }
  .vf-nav-adaptive .v2-brand img { opacity: 1; }
}

/* The Menu label is small text, and masking text to a backdrop-filter is not
   worth the machinery. A shadow alone was tested and is too weak against a
   near-white frame, so the button carries a local scrim instead: it darkens
   only the few square centimetres behind the word, which a dark frame barely
   notices and a blown-out one needs. This is not the wash the hero rejected;
   it is the size of the label, not the size of the picture. */
.vf-nav-adaptive .v2-menu-btn {
  color: #fff; background: transparent; border-color: transparent;
  border-radius: 999px;
  -webkit-backdrop-filter: brightness(.48) saturate(.85);
          backdrop-filter: brightness(.48) saturate(.85);
  text-shadow: 0 1px 2px rgba(20,16,10,.5);
}
/* Without backdrop-filter the scrim cannot exist, so lean on the shadow. */
@supports not ((backdrop-filter: brightness(.5)) or (-webkit-backdrop-filter: brightness(.5))) {
  .vf-nav-adaptive .v2-menu-btn { text-shadow: 0 1px 3px rgba(20,16,10,.85), 0 0 14px rgba(20,16,10,.6); }
}
.vf-nav-adaptive .v2-menu-btn:hover,
.vf-nav-adaptive .v2-menu-wrap.open .v2-menu-btn { color: #fff; }

/* Once the nav gains its paper bar the backdrop is known, so stop adapting
   and let the normal ink colours take over. The dropdown panel is a sibling
   of the button, so it is never touched and keeps its own paper styling. */
.vf-nav-adaptive.scrolled .v2-brand::after { display: none; }
.vf-nav-adaptive.scrolled .v2-brand img { opacity: 1; }
.vf-nav-adaptive.scrolled .v2-menu-btn {
  color: var(--ink-mid); border-color: rgba(0,0,0,.18); text-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.vf-nav-adaptive.scrolled .v2-menu-btn:hover { color: var(--ink); }

/* ---------- narrow screens: stack, never overlap ---------- */
@media (max-width: 900px) {
  .vf, .vf.vf-compact { grid-template-columns: 1fr; grid-template-rows: 46svh auto; min-height: 100svh; }
  .vf.vf-compact { min-height: 0; }
  .vf-photo { order: -1; border-left: 0; border-bottom: 1px solid var(--line-2); }
  /* Same nav clearance as desktop: stacked, the photograph is at the top
     and the nav sits right on it. */
  .vf-marks { inset: calc(var(--nav-h) + clamp(4px, 1.4vw, 12px)) clamp(14px, 3vw, 22px) clamp(14px, 3vw, 22px); }
  .vf-copy { padding: clamp(26px, 4vh, 40px) clamp(20px, 6vw, 40px) clamp(40px, 7vh, 64px) clamp(34px, 9vw, 56px); }
  .vf-meta { position: static; margin-bottom: 20px; }
  .vf-rule { top: 0; left: clamp(16px, 4.5vw, 26px); }
  .vf-title { font-size: clamp(32px, 7.4vw, 46px); }
}

@media (prefers-reduced-motion: reduce) {
  .vf-slide { transition: opacity .3s linear; transform: none !important; }
  .vf-frame { animation: none; transition: opacity .3s linear; }
  .vf-rail-track i { display: none; }
}
