/* ===================================================================
   DESIGN TOKENS
   -------------------------------------------------------------------
   Subject: a director / photographer / designer whose work spans
   motion, stills, and brand systems. The visual language borrows
   from the film-editing world — reel numbers, timecodes, slate tape —
   because that vernacular is native to the work, not decoration
   bolted onto a generic template.
=================================================================== */
:root{
  --blackout:#0B0B0C;
  --paper:#F3EFE4;
  --tape:#F80052;
  --smoke:#9A9484;
  --rule:#2A2A28;
  --scrim-top: rgba(11,11,12,.15);
  --scrim-bottom: rgba(11,11,12,.85);

  --display: "Anton", Impact, sans-serif;
  --mono: "Space Mono", "Courier New", monospace;
  --body: "Inter", -apple-system, sans-serif;

  --nav-h: 76px;
  --row-height: 90dvh; /* ← change this to shorten/lengthen every row, e.g. 80vh or 640px */
}

*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; scroll-behavior:auto !important; }
}

body{
  margin:0;
  overflow-x:hidden;
  background:var(--blackout);
  color:var(--paper);
  font-family:var(--body);
  -webkit-font-smoothing:antialiased;
}

a{ color:inherit; text-decoration:none; }
img, video{ display:block; width:100%; height:100%; object-fit:cover; }

/* ---------------------------- NAV ---------------------------- */
.site-nav{
  position:fixed;
  top:0; left:0; right:0;
  height:var(--nav-h);
  z-index:50;
  display:flex; align-items:center; justify-content:space-between;
  padding:0 clamp(20px,4vw,48px);
  /* Always solid black — no longer fades to transparent at the top of
     the page. The first row's media is pushed down to sit flush below
     this bar (see <main>'s inline padding-top in index.html), so a
     transparent nav is no longer needed to "reveal" the hero video
     behind it. */
  background:var(--blackout);
  transition:border-color .35s ease;
  border-bottom:1px solid transparent;
}
.site-nav.scrolled{
  border-bottom-color:var(--rule);
}

.brand{
  font-family:var(--display);
  font-size:clamp(18px,2.4vw,24px);
  letter-spacing:.02em;
  display:flex; flex-direction:row; align-items:center; gap:11px;
  width:fit-content;
}

.brand .brand-mark{
  color:var(--tape);
  line-height:1;
}
.brand-tagline{
  font-family:var(--mono); font-size:12px; letter-spacing:.06em; text-transform:uppercase;
  line-height:1;
}

.nav-links{
  display:flex; align-items:center; gap:clamp(14px,2vw,28px);
  font-family:var(--mono); font-size:12px; letter-spacing:.06em; text-transform:uppercase;
}
.nav-links a{
  position:relative; padding:6px 2px; color:var(--paper); opacity:.8;
  transition:opacity .2s ease;
  /* Flex row so any link that carries an icon (see .nav-emoji) centers
     that icon against its own text first, rather than leaning on
     inline baseline math — baseline alignment is what threw "Photo
     Stream" out of line with plain-text links like "About / Contact"
     last time, since emoji glyphs carry their own baked-in vertical
     offset that varies by platform/font. */
  display:inline-flex;
  align-items:center;
}
.nav-links a:hover, .nav-links a:focus-visible{ opacity:1; }
.nav-links a::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:var(--tape); transform:scaleX(0); transform-origin:left;
  transition:transform .25s ease;
}
.nav-links a:hover::after, .nav-links a:focus-visible::after{ transform:scaleX(1); }

/* Camera emoji next to "Photo Stream" — sits in a fixed-size box that
   flex-centers the glyph itself (rather than sizing the emoji via
   font-size and leaning on line-height/baseline to place it), so its
   vertical position doesn't ride on emoji font metrics, which vary
   enough across platforms to visibly throw off baseline-based
   centering. Wiggles side to side around its own center, same
   "always-on decorative motion" treatment as .scroll-cue-corner's
   bounce elsewhere on the site. Respects the reduced-motion override
   at the top of this file automatically, since that collapses all
   animation-durations to near-zero. */
.nav-emoji{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:18px;
  height:18px;
  margin-bottom:6px;
  margin-right:10px;
  font-size:22px;
  line-height:1;
  transform-origin:50% 50%;
  animation:navEmojiWiggle 2s ease-in-out infinite;
}
@keyframes navEmojiWiggle{
  0%,100%{ transform:rotate(-18deg); }
  50%{ transform:rotate(18deg); }
}

/* "Photo Stream" label next to the camera emoji — visible on
   non-mobile by default (no rule needed here, it just inherits
   .nav-links a's normal mono/uppercase look). Hidden at the mobile
   breakpoint below so only the emoji itself shows there. */

.nav-toggle{ display:none; }
@media (max-width:640px){
  /* No hamburger/menu toggle exists in the markup, so hiding .nav-links
     here would remove all site navigation on mobile with no way to get
     it back. Keep the links visible and just tighten them to fit.

     "MEDIA" used to just disappear here (display:none on
     .brand-tagline) — it never should have, since that's the only
     place the tagline appeared at all on small screens. Instead the
     whole .brand lockup switches from a side-by-side row to a stacked
     column, with align-items:flex-end so "MEDIA" (the narrower word)
     sits right-flush under "COZZOLINO" instead of overlapping the nav
     links or floating off on its own. */
  .brand{
    flex-direction:column;
    align-items:flex-end;
    gap:2px;
  }
  .brand-tagline{
    font-size:10px;
  }
  /* Emoji-only on mobile — "Photo Stream" drops out entirely rather
     than shrinking, since the camera emoji alone already reads fine
     as a link at this size. */
  .nav-photo-text{
    display:none;
  }
  /* Small mobile: links go as small as they can read ("on point") and
     sit close together — the camera emoji next to "Photo Stream"
     already reads as its own visual break, so a tight gap here still
     keeps the two links looking like a single cluster rather than
     spread across the bar. */
  .nav-links{
    gap:8px;
    font-size:10px;
  }
}

/* --------------------------- REELS ---------------------------- */
.reel{
  position:relative;
  min-height:var(--row-height);
  display:flex;
  align-items:flex-end;
  overflow:hidden;
  isolation:isolate;
}

.reel-media{
  position:absolute; inset:0; z-index:0;
}
.reel-media img, .reel-media video{
  width:100%; height:100%; object-fit:cover;
}
/* A <picture> wrapper (used when a row swaps in a narrower mobile crop
   — see reel-7's mobileSrc in index.html) is inline by default and
   wouldn't otherwise fill .reel-media the way a bare <img> does; give
   it the same absolute-fill treatment so the <img> inside still has a
   definite box to size against. */
.reel-media picture{
  display:block; width:100%; height:100%;
}
/* Vimeo embeds are an <iframe>, which has no object-fit support, so
   it's oversized and centered instead — the standard "cover" trick
   for 16:9 embeds. */
.video-bg-wrap{
  position:absolute; inset:0; overflow:hidden;
}
.video-bg-wrap iframe{
  position:absolute; top:50%; left:50%;
  width:177.78vh; height:100vh; /* 16:9 sized off viewport height */
  min-width:100%; min-height:56.25vw; /* 16:9 sized off row width */
  transform:translate(-50%,-50%);
  border:0; pointer-events:none;
}
/* Slideshow — stacked images that crossfade on a timer */
.slideshow-wrap{
  position:absolute; inset:0;
}
.slideshow-slide{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  transition:opacity 1.2s ease;
}
.slideshow-slide.is-active{
  opacity:1;
}

/* Fallback look when no media file is supplied yet — a graded gradient
   that still reads as "designed" rather than a blank box. Swap any
   row's src in MEDIA_CONFIG (bottom of index.html) and this disappears
   beneath the real asset. */
.reel-media.placeholder{
  background:
    linear-gradient(160deg, var(--tint-a,#1c1a19), var(--tint-b,#0B0B0C) 70%);
}
.reel-media.placeholder::after{
  content:""; position:absolute; inset:0;
  background-image:radial-gradient(rgba(255,255,255,.04) 1px, transparent 1px);
  background-size:3px 3px;
  mix-blend-mode:overlay;
}

.reel-scrim{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(to top, var(--scrim-bottom) 0%, var(--scrim-top) 55%, transparent 100%);
}

.reel-frame-meta{
  position:absolute; top:calc(var(--nav-h) + 20px); left:clamp(20px,4vw,48px);
  z-index:2;
  font-family:var(--mono); font-size:12px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--paper);
  display:flex; align-items:center; gap:10px;
}
.reel-frame-meta .dot{ width:6px; height:6px; border-radius:50%; background:var(--tape); }

.reel-content{
  position:relative; z-index:2;
  width:100%;
  /* Top padding is 0 by default (every row starts flush with the top
     of its content area) but adjustable per-instance via
     --content-pad-top, e.g. style="--content-pad-top:80px;" on the
     .reel-content div — used by reel-7 to add breathing room above
     "Call me Tony". */
  padding:var(--content-pad-top, 0) clamp(20px,4vw,48px) clamp(64px,10vh,120px);
  max-width:1400px; margin:0 auto;
  display:flex; flex-direction:column; gap:22px;
  opacity:0; transform:translateY(28px);
  transition:opacity .7s ease, transform .7s ease;
}
.reel.in-view .reel-content{ opacity:1; transform:translateY(0); }

.reel:nth-child(even) .reel-content{ align-items:flex-end; text-align:right; }

/* reel-7 (the merged "Call me Tony" sign-off) is pinned right-aligned
   here explicitly, rather than relying on .reel:nth-child(even) above
   (which right-aligns a row based purely on sibling position —
   removing an earlier row, like when "Who I've worked with" was
   deleted, can silently flip a later row's odd/even parity). An ID
   selector outranks the nth-child rule's specificity no matter what
   position reel-7 ends up in, so this stays correct even if rows are
   added or removed above it again.

   .footer-bottom is deliberately exempted from the shrink-and-align
   that the other children get (align-self:stretch keeps it full
   width) — its ::before divider line centers itself off this
   element's own box, so if it were left to shrink like its siblings
   the line would end up off-center instead of spanning the full
   page width. justify-content:flex-end pushes the copyright text to
   the right edge of that full-width bar instead, so the line stays
   correct while the text still reads right-aligned. */
#reel-7 .reel-content{ align-items:flex-end; text-align:right; }
#reel-7 .reel-sub{ margin-left:auto; }
/* justify-content:flex-start left-aligns the copyright line within
   .footer-bottom's own full-width bar — independent of the
   right-alignment everything above it in this section gets, since
   .footer-bottom is deliberately exempted from that shrink-and-align
   (see the comment above #reel-7 .reel-content). */
#reel-7 .footer-bottom{ align-self:stretch; justify-content:flex-start; }

/* Very slow "Ken Burns" pan on reel-7's photo (index_tony.jpg) —
   scoped to just this image, not every image sitewide. Scaled up
   slightly (1.08x) so the pan never reveals an edge, then drifted
   diagonally and back over a long, slow cycle. .reel already clips
   overflow, so the oversized/moving image never bleeds past the
   section. Automatically shortened to near-zero by the
   prefers-reduced-motion override at the top of this file. */
@keyframes reel7PhotoPan{
  0%{ transform:scale(1.08) translate(0,0); }
  100%{ transform:scale(1.08) translate(-2.5%,-2.5%); }
}
#reel-7 .reel-media img{
  animation:reel7PhotoPan 50s ease-in-out infinite alternate;
}

/* The "About" button in reel-7 uses a reversed color scheme from
   every other .reel-cta on the site (this section only — the base
   .reel-cta rule above is untouched, so buttons elsewhere keep their
   pink-fill/black-text look): black at rest, filling pink on hover,
   with the border staying pink throughout so the button still reads
   as a button against the black backdrop when it's not hovered. */
#reel-7 .reel-cta{
  background:var(--blackout);
  color:var(--tape);
  border-color:var(--tape);
}
#reel-7 .reel-cta:hover, #reel-7 .reel-cta:focus-visible{
  background:var(--tape);
  color:var(--blackout);
}

.reel-headline{
  font-family:var(--display);
  font-weight:400;
  text-transform:uppercase;
  line-height:.92;
  letter-spacing:.01em;
  font-size:clamp(38px, 7vw, 96px);
  max-width:18ch;
  margin:0;
}

.reel-sub{
  font-family:var(--body);
  font-size:clamp(14px,1.6vw,17px);
  color:var(--paper);
  opacity:.75;
  max-width:46ch;
  margin:0;
}
.reel:nth-child(even) .reel-sub{ margin-left:auto; }

.reel-cta{
  display:inline-flex; align-items:center; gap:12px;
  font-family:var(--mono); font-size:12px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--blackout); background:var(--tape);
  padding:14px 22px;
  border:1px solid var(--tape);
  width:fit-content;
  transition:background-color .2s ease, color .2s ease;
}
.reel-cta:hover, .reel-cta:focus-visible{
  background:transparent; color:var(--paper);
}

/* The ">" character used inside every CTA button, standardized across
   all reels so they all share one consistent arrow treatment. */
.arrow-icon{
  font-family:var(--mono);
  font-weight:700;
  line-height:1;
}

/* Scroll cue on the hero row — thin line + bouncing down-arrow
   telling visitors there's more content below. */
.scroll-cue{
  position:absolute;
  left:50%;
  bottom:32px;
  z-index:2;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:8px;
  color:var(--paper);
  opacity:.7;
  transition:opacity .2s ease;
  animation:scrollCueBounce 2.2s ease-in-out infinite;
}
.scroll-cue:hover, .scroll-cue:focus-visible{ opacity:1; }
.scroll-cue-line{
  width:1px;
  height:36px;
  background:var(--paper);
  opacity:.5;
}
.scroll-cue-arrow{
  font-family:var(--mono);
  font-size:16px;
  line-height:1;
}
@keyframes scrollCueBounce{
  0%,100%{ transform:translate(-50%,0); }
  50%{ transform:translate(-50%,10px); }
}

/* Large corner scroll cue — a second, more attention-grabbing "there's
   more below" indicator for pages like entertainment.html that don't
   open on a full-bleed .reel hero to hang the standard .scroll-cue
   off of. Fixed to the viewport (not the page), bottom-center, so it
   stays visible for as long as there's more page below; the page's
   IntersectionObserver (see the script at the bottom of the HTML)
   adds .is-hidden the moment the footer heading first scrolls into
   view, since its job is done at that point. Purely decorative
   (aria-hidden in the markup) — pointer-events are off so it never
   intercepts clicks on whatever is underneath it. Size and opacity
   are adjustable per-instance via --corner-arrow-size /
   --corner-arrow-opacity, e.g. style="--corner-arrow-size:64px;" on
   the element, same pattern as the rest of this site's spacing knobs. */
.scroll-cue-corner{
  position:fixed;
  left:50%;
  bottom:clamp(24px,5vh,64px);
  z-index:30;
  font-family:var(--mono);
  font-size:var(--corner-arrow-size, clamp(48px,8vw,88px));
  line-height:1;
  color:var(--tape);
  opacity:var(--corner-arrow-opacity, 1.0);
  pointer-events:none;
  animation:cornerArrowBounce 2.4s ease-in-out infinite;
  transition:opacity .4s ease;
}
.scroll-cue-corner.is-hidden{
  opacity:0;
}
@keyframes cornerArrowBounce{
  0%,100%{ transform:translate(-50%,0); }
  50%{ transform:translate(-50%,14px); }
}

/* ------------------------- SCROLL REVEAL -------------------------
   Generic version of the fade-up-into-view treatment .reel-content
   uses on the homepage (there, JS toggles .in-view on the whole
   .reel once it's on screen). This is the same idea as a standalone
   utility class, so it can be dropped onto any headline, paragraph,
   label, or button/link on a page that doesn't have .reel rows —
   project pages (2d3dreel.html, entertainmentreel.html, etc). JS at
   the bottom of each page observes every .reveal element and adds
   .in-view once it scrolls into the viewport (unobserving after, so
   it only plays once). Respects the reduced-motion override at the
   top of this file automatically, since that collapses all
   transition-durations to near-zero. */
.reveal{
  opacity:0;
  transform:translateY(20px);
  transition:opacity .7s ease, transform .7s ease;
  /* Stagger multiple .reveal elements that land in view together by
     giving each one its own delay, e.g. style="--reveal-delay:.15s;" */
  transition-delay:var(--reveal-delay, 0s);
}
.reveal.in-view{
  opacity:1;
  transform:translateY(0);
}

/* subtle per-row tint variety so the placeholder gradients aren't identical */
.reel:nth-child(1){ --tint-a:#241d19; --tint-b:#0B0B0C; }
.reel:nth-child(2){ --tint-a:#1a1d24; --tint-b:#0B0B0C; }
.reel:nth-child(3){ --tint-a:#231a1d; --tint-b:#0B0B0C; }
.reel:nth-child(4){ --tint-a:#1d2419; --tint-b:#0B0B0C; }
.reel:nth-child(5){ --tint-a:#191c24; --tint-b:#0B0B0C; }
.reel:nth-child(6){ --tint-a:#241923; --tint-b:#0B0B0C; }
.reel:nth-child(7){ --tint-a:#221d24; --tint-b:#0B0B0C; }

/* ---------------------------- FOOTER ---------------------------- */
.site-footer{
  position:relative;
  background:var(--blackout);
  border-top:1px solid var(--rule);
  padding:clamp(48px,8vw,96px) clamp(20px,4vw,48px) 32px;
}
.footer-grid{
  display:grid; gap:40px;
  grid-template-columns: 1.4fr 1fr 1fr;
  max-width:1400px; margin:0 auto;
}
/* Modifier for a .footer-grid holding just link columns (no brand
   column) — used when the footer is folded into a .reel's own
   content instead of standing alone, as on the homepage's merged
   "Call me Tony" / sign-off section. Declared before the responsive
   media query below (same specificity, source order decides) so the
   mobile 1-column collapse still wins at narrow widths. */
.footer-grid-2col{
  grid-template-columns:1fr 1fr;
}
@media (max-width:760px){
  .footer-grid{ grid-template-columns:1fr; }
}
.footer-brand .reel-headline{ font-size:clamp(28px,4vw,44px); margin-bottom:12px; }
.footer-col h3{
  font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--smoke); margin:0 0 16px;
}
.footer-col ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px; }
.footer-col a{
  font-family:var(--body); font-size:14px; opacity:.85; transition:opacity .2s ease;
}
.footer-col a:hover, .footer-col a:focus-visible{ opacity:1; text-decoration:underline; text-underline-offset:3px; }

/* A .reel-cta button occasionally lands inside a .footer-col (e.g. the
   "Tony on Facebook" button in the homepage's merged sign-off section)
   — .footer-col a above sets its own font-family/font-size/opacity on
   every <a> inside it, and at equal-or-higher specificity than
   .reel-cta alone, so without this it would silently override the
   button's mono/uppercase treatment with the footer's plain link
   style. Re-assert .reel-cta's own look here. */
.footer-col .reel-cta{
  font-family:var(--mono);
  font-size:12px;
  opacity:1;
}
.footer-col .reel-cta:hover, .footer-col .reel-cta:focus-visible{
  opacity:1;
  text-decoration:none;
}

/* footer-bottom's border stretches the full viewport width via a
   full-bleed ::before, even though the row itself stays inside the
   1400px content column. */
.footer-bottom{
  position:relative;
  /* z-index:0 (on top of position:relative) makes .footer-bottom its
     own stacking context, so the -blackout::before backdrop's
     z-index:-1 below is guaranteed to land behind THIS element's own
     text on every device/browser — it no longer depends on how far
     up the tree a negative z-index happens to escape to, which is
     where mobile browsers and desktop ones can disagree. */
  z-index:0;
  max-width:1400px; margin:56px auto 0;
  padding-top:20px;
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:12px;
  font-family:var(--mono); font-size:11px; color:var(--smoke); text-transform:uppercase; letter-spacing:.06em;
}
.footer-bottom::before{
  content:"";
  position:absolute;
  top:0;
  left:50%;
  width:100vw;
  transform:translateX(-50%);
  border-top:1px solid var(--rule);
}

/* Modifier for a .footer-bottom that sits directly on a photo/video
   background instead of an already-solid-black <footer> (e.g. the
   homepage's merged "Call me Tony" sign-off section, reel-7) — turns
   the existing full-bleed divider line into a solid black backdrop
   that runs from the line down through the rest of the section, so
   the copyright bar reads as a real footer strip instead of floating
   on the photo. The generous negative bottom value just needs to
   reach the section's bottom edge; the .reel it lives in clips
   overflow, so over-extending is harmless. No effect on pages where
   .footer-bottom already sits inside a solid-black <footer>.

   z-index:-1 keeps the copyright text readable: this ::before is
   position:absolute, and an absolutely positioned element paints ON
   TOP of ordinary in-flow content (like the &copy; text right next
   to it) by default — "before" only means first in the markup, not
   underneath visually. Once this pseudo-element gained a solid black
   background instead of just a thin line, that default stacking
   order was quietly painting the black backdrop over the text.
   Pinning it to -1 drops it behind .footer-bottom's own text (still
   above the photo/scrim further back, since those live in an outer
   stacking context of their own) — and because .footer-bottom itself
   now has z-index:0 (see above), that negative value is scoped to
   THIS element's own stacking context specifically, rather than
   escaping up to whichever ancestor happens to be the nearest one
   that establishes one. That escaping behavior is where different
   browsers (mobile Safari included) can disagree; pinning the
   context locally removes the ambiguity. */
.footer-bottom-blackout::before{
  background:var(--blackout);
  bottom:-200px;
  z-index:-1;
}

/* ------------------------- PROJECT PAGES -------------------------
   Shared by every project-template.html copy (photography.html,
   interactive.html, etc.) so a subpage always matches the index's
   look and feel — they all load this same stylesheet. */

/* "Back to Home" breadcrumb — sits in the same spot as .reel-frame-meta
   on the index, but is itself a link back to the homepage. */
.crumb{
  position:absolute; top:calc(var(--nav-h) + 20px); left:clamp(20px,4vw,48px);
  z-index:2;
  font-family:var(--mono); font-size:12px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--paper); opacity:.85;
  display:flex; align-items:center; gap:10px;
  transition:opacity .2s ease;
}
.crumb:hover, .crumb:focus-visible{ opacity:1; }
.crumb .dot{
  width:auto; height:auto; border-radius:0; background:none;
  color:var(--tape);
  font-family:var(--mono); font-size:14px; line-height:1;
}
/* Modifier for using the same breadcrumb in normal document flow
   instead of overlaid on a full-bleed hero (e.g. above an inline
   video embed, where there's no .project-hero to anchor it to). */
.crumb-inline{ position:static; margin-bottom:24px; }

/* Page intro — headline + one-line description in normal flow (no
   full-bleed background video), used above an inline .video-embed. */
.page-intro{
  max-width:1400px; margin:0 auto;
  padding:calc(var(--nav-h) + clamp(32px,6vw,64px)) clamp(20px,4vw,48px) 0;
}
.page-intro .reel-headline{ margin-bottom:14px; }
.page-intro .reel-sub{ max-width:60ch; }

/* Standard responsive 16:9 embed (a real, interactive video — controls
   on, not the muted/looping background treatment used on the reels). */
.video-embed{
  position:relative;
  width:100%;
  aspect-ratio:16/9;
  background:var(--rule);
  overflow:hidden;
  /* Space above/below the embed. Override per-instance with e.g.
     style="--embed-pad-top:24px; --embed-pad-bottom:24px;" on the div.
     (Uses margin, not padding, so the 16:9 box itself never distorts.) */
  margin:var(--embed-pad-top, 0) 0 var(--embed-pad-bottom, 40px);
}
.video-embed iframe{
  position:absolute; inset:0;
  width:100%; height:100%;
  border:0;
}

/* Link below a video embed pointing to the live post on social media
   (e.g. "View on Instagram >"). Same small mono/uppercase treatment
   used for the site's other secondary links. */
.video-link{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--mono); font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--smoke);
  opacity:.85;
  transition:opacity .2s ease, color .2s ease;
  /* Space between the video above and this link. Override per-instance
     with e.g. style="--link-pad-top:16px;" on the <a>. */
  margin-top:var(--link-pad-top, 10px);
}
.video-link:hover, .video-link:focus-visible{ opacity:1; color:var(--paper); }

/* Project hero — a shorter one-off version of .reel (no scroll-cue,
   no data-row driven array; just the single HERO_MEDIA object at the
   bottom of the page). Reuses .reel-media / .reel-scrim / .reel-content
   / .reel-headline / .reel-sub / .reel-cta as-is. */
.project-hero{
  position:relative;
  min-height:60vh;
  display:flex;
  align-items:flex-end;
  overflow:hidden;
  isolation:isolate;
  --tint-a:#1c1a19; --tint-b:#0B0B0C;
}
.project-hero .reel-content{ opacity:1; transform:none; } /* no in-view reveal needed on a single hero */

.project-meta{
  display:flex; flex-wrap:wrap; gap:28px;
  list-style:none; margin:0;
  /* Space above/below the whole list. Override per-instance with e.g.
     style="--meta-pad-top:24px; --meta-pad-bottom:24px;" on the <ul>. */
  padding:var(--meta-pad-top, 4px) 0 var(--meta-pad-bottom, 0);
}
.project-meta li{
  display:flex; align-items:baseline; gap:8px; /* label + value on one line */
  font-family:var(--mono); font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--smoke);
}
.project-meta li strong{
  color:var(--paper); font-size:13px; letter-spacing:.01em; font-weight:600;
}

.project-body{
  max-width:1400px; margin:0 auto;
  /* --body-pad-top is the space between whatever comes before this
     section (e.g. the .page-intro paragraph) and its first child
     (e.g. the .video-embed). Override per-instance, e.g.
     style="--body-pad-top:16px;" on the <section class="project-body">. */
  padding:var(--body-pad-top, clamp(48px,8vw,96px)) clamp(20px,4vw,48px) clamp(48px,8vw,96px);
}
.project-body p{
  font-family:var(--body); font-size:clamp(15px,1.6vw,18px); line-height:1.7;
  color:var(--paper); opacity:.85; max-width:70ch; margin:0 0 24px;
}

.project-gallery{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(280px,1fr)); gap:16px;
  margin-top:16px;
}
.project-gallery figure{ margin:0; }
.project-gallery img, .project-gallery video{
  width:100%; aspect-ratio:4/3; object-fit:cover; display:block;
}
.project-gallery figcaption{
  font-family:var(--mono); font-size:11px; letter-spacing:.04em; color:var(--smoke);
  margin-top:8px;
}

/* Prev/next + back-to-home bar under the gallery, above the shared footer */
.project-footer-nav{
  max-width:1400px; margin:0 auto;
  padding:32px clamp(20px,4vw,48px) 0;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:16px;
  border-top:1px solid var(--rule);
  font-family:var(--mono); font-size:12px; letter-spacing:.06em; text-transform:uppercase;
}
.project-footer-nav a{ opacity:.8; transition:opacity .2s ease; }
.project-footer-nav a:hover, .project-footer-nav a:focus-visible{ opacity:1; }

/* Row of embedded social posts below a project hero (Instagram/TikTok/
   Facebook's own embed widgets) — used on project pages like
   2d3d-reel.html. Reuses .project-body for the outer padding. */
.social-row-heading{
  font-family:var(--mono); font-size:12px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--smoke);
  /* Space above/below the heading. Override per-instance with e.g.
     style="--heading-pad-top:60px; --heading-pad-bottom:24px;" on the <h2>. */
  margin:var(--heading-pad-top, 0) 0 var(--heading-pad-bottom, 24px);
}
.social-row{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(300px,1fr)); gap:24px;
  align-items:start;
}
.social-embed{
  display:flex; justify-content:center;
  min-height:400px;
}

/* Modifier for .social-row when a page has more than one video row
   that should share the exact same column width (e.g. a 3-up square
   row and a 2-up vertical row below it) — a fixed 3-track grid
   instead of .social-row's normal auto-fit, so a row's column width
   isn't driven by how many items are in THAT particular row. A row
   with fewer than 3 items just leaves trailing columns empty rather
   than stretching to fill. Collapses to one column on narrow screens,
   same as .social-row's own auto-fit behavior did. */
.video-grid-3up{
  grid-template-columns:repeat(3, minmax(0,1fr));
}
@media (max-width:900px){
  .video-grid-3up{ grid-template-columns:1fr; }
}

/* Modifier for a .social-row holding a single lone item that should
   still sit at the same column width as a normal 2-up row above/below
   it (e.g. an odd fifth image after two paired rows) — a fixed
   2-track grid instead of .social-row's normal auto-fit, so the lone
   item doesn't stretch to fill the full row width; the second column
   is simply left empty. Collapses to one column at the same ~624px
   breakpoint .social-row's own auto-fit already collapses at, so it
   keeps matching the paired rows above it at every screen size. */
.social-row-2up{
  grid-template-columns:repeat(2, minmax(0,1fr));
}
@media (max-width:624px){
  .social-row-2up{ grid-template-columns:1fr; }
}

.skip-link{
  position:absolute; left:-999px; top:0; background:var(--tape); color:var(--blackout);
  padding:10px 16px; z-index:100; font-family:var(--mono); font-size:12px;
}
.skip-link:focus{ left:20px; }

:focus-visible{ outline:2px solid var(--tape); outline-offset:3px; }
