/* =========================================================
   PORTFOLIO — video editor
   Palette: bianco/nero puro. Tipografia: Helvetica Neue ovunque
   (titoli e corpo/nav) — --serif e --sans puntano entrambe allo
   stesso font stack, così tutte le regole esistenti che li usano
   restano valide senza doverle toccare una per una.
   ========================================================= */

:root{
  --black: #0a0a0a;
  --white: #fafafa;
  --gray: #8a8a8a;
  --gray-light: #e4e4e4;
  --serif: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --sans: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --ease: cubic-bezier(.16,.8,.24,1);
}

*{ margin:0; padding:0; box-sizing:border-box; }

html{ scroll-behavior:smooth; }

body{
  background: var(--white);
  color: var(--black);
  font-family: var(--sans);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* while a project's lightbox is open, the page behind it can't
   scroll — only the lightbox box itself scrolls (see .lightbox__inner) */
body.lightbox-open{
  overflow: hidden;
}
/* same idea while the Work overlay itself is open (see .work--overlay
   below) — the page underneath stays frozen exactly where it was */
body.work-overlay-open{
  overflow: hidden;
}

a{ color:inherit; text-decoration:none; }
button{ font-family:inherit; background:none; border:none; cursor:pointer; color:inherit; }
em{ font-style: italic; }

/* subtle film-grain texture over everything, very low opacity */
.grain{
  position:fixed; inset:0; pointer-events:none; z-index:999;
  opacity:.025; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

::selection{ background: var(--black); color: var(--white); }

/* ---------- layout helpers ---------- */
section{ padding: 0 6vw; }

/* ---------- nav ---------- */
.nav{
  position: fixed; top:0; left:0; right:0; z-index: 100;
  display:flex; align-items:center; justify-content:space-between;
  padding: 28px 6vw;
  mix-blend-mode: difference;
  transition: padding .4s var(--ease);
}
.nav.scrolled{ padding: 18px 6vw; }
.nav__logo{
  font-family: var(--serif);
  font-size: 1.4rem;
  color: var(--white);
  letter-spacing: .04em;
}
/* "About" mirrors "Editing Studio"/"L.A." on the opposite side of the
   bar — same typography (shares .nav__logo), just pushed to the far
   right instead of sitting at the natural flex start. margin-left:auto
   (not justify-content) so it still lands flush right on pages like
   showreel.html that have no left-side logo at all, and groups
   naturally with .nav__toggle right next to it once that appears on
   mobile. Links to cv.html — the full, dedicated About/CV page —
   instead of scrolling to the small About preview further down. */
/* position:relative + z-index here (not just on mobile) is the actual
   fix for the stuck-mobile-menu bug: a position:fixed sibling with no
   z-index (.nav__links, once open) still paints ABOVE plain in-flow
   elements regardless of DOM order — so the opened drawer covered
   this and the toggle button, and there was no way left to click
   either of them to close it again. Explicit stacking here keeps both
   always on top of the drawer. */
.nav__about{ margin-left: auto; position: relative; z-index: 2; }
/* Work/Film/Spot/Music/Overview/Contact live in an Apple-style glass
   drawer now, on every screen size — not sitting inline on the bar
   (still visible while closed) like before. Closed by default
   (translateX(100%), off past the right edge), slid into view via
   .open (toggled by #navToggle, see js/script.js), same mechanism the
   mobile menu already used — this is just that same drawer made the
   permanent behavior everywhere instead of a mobile-only fallback. */
.nav__links{
  position: fixed; top:0; left:auto; right:0; height:100vh; width: 78vw; max-width: 340px;
  background: rgba(18,18,18,.6);
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  border-left: 1px solid rgba(255,255,255,.14);
  box-shadow: -12px 0 40px rgba(0,0,0,.35);
  display:flex; flex-direction:column; align-items:flex-start; justify-content:center;
  gap: 30px; padding: 0 44px;
  z-index: 1;
  transform: translateX(100%);
  transition: transform .5s var(--ease);
  /* .nav itself uses mix-blend-mode:difference so the logo/toggle
     stay legible over any hero video — cancelled back to normal here,
     otherwise the drawer's own dark glass panel would blend/invert
     against whatever's behind it instead of reading as a solid panel. */
  mix-blend-mode: normal;
}
.nav__links.open{ transform: translateX(0); }
.nav__links a{
  color: var(--white);
  font-size: 1.15rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  position: relative;
}
.nav__links a::after{
  content:''; position:absolute; left:0; bottom:-4px;
  width:0; height:1px; background: var(--white);
  transition: width .3s var(--ease);
}
.nav__links a:hover::after{ width:100%; }
.nav__links a.active::after{ width:100%; } /* persistent underline for the active work filter */

/* Entrance animation: each nav link (Work/Film/Spot/Music/About/
   Contact) fades and drops in on page load, one after another —
   plays once, on load, not tied to scroll like .reveal elsewhere. */
@keyframes navLinkIn{
  from{ opacity:0; transform: translateY(-14px); }
  to{ opacity:1; transform: translateY(0); }
}
.nav__links a{
  opacity:0;
  animation: navLinkIn .7s var(--ease) forwards;
}
.nav__links a:nth-child(1){ animation-delay: .4s; }
.nav__links a:nth-child(2){ animation-delay: .48s; }
.nav__links a:nth-child(3){ animation-delay: .56s; }
.nav__links a:nth-child(4){ animation-delay: .64s; }
.nav__links a:nth-child(5){ animation-delay: .72s; }
.nav__links a:nth-child(6){ animation-delay: .8s; }
.nav__links a:nth-child(7){ animation-delay: .88s; }
.nav__links a:nth-child(8){ animation-delay: .96s; }
@media (prefers-reduced-motion: reduce){
  .nav__links a{ animation:none; opacity:1; }
}

.nav__toggle{
  /* Always visible now, not just on phones (see .nav__links above) —
     Work/Film/Spot/Music etc. only ever show up inside that drawer,
     opened from here. */
  display:flex; flex-direction:column; gap:6px; width:26px;
  position: relative; z-index: 2; /* see .nav__about's comment above */
  /* More breathing room from "About" right next to it, and nudged
     past the nav's own right padding so it sits further out toward
     the true edge instead of lining up flush with About/the logo. */
  margin-left: 28px;
  margin-right: -1.6vw;
}
.nav__toggle span{
  height:1px; width:100%; background:var(--white);
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
/* Morphs the two bars into an ✕ once the drawer is open — besides
   just looking like a proper close control (rather than a hamburger
   that does nothing different when tapped again), it's a second,
   independent way back on top of tapping outside the panel. */
.nav__toggle.open span:nth-child(1){ transform: translateY(3.5px) rotate(45deg); }
.nav__toggle.open span:nth-child(2){ transform: translateY(-3.5px) rotate(-45deg); }

/* Showreel's nav has no "L.A." logo (the fullscreen video sits right
   behind it, a text logo there reads as clutter) — without a first
   flex child, .nav's justify-content:space-between would otherwise
   shove the mobile toggle button to the left instead of the right. */
.nav--no-logo{ justify-content: flex-end; }

/* ---------- hero ---------- */
.hero{
  min-height: 100vh;
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  gap: 14px;
  padding-bottom: 8vh; /* breathing room below the text, off the very edge of the screen */
  position:relative;
  overflow: hidden;
}
.hero__bg{
  position:absolute; inset:0;
  width: 100%; height: 100%;
  object-fit: cover; /* video (or its poster frame) fills the screen like the old background-image did */
  background-color: #111; /* fallback while nothing has loaded yet */
  filter: contrast(1.05) brightness(.85);
  transform: scale(1.03); /* margine per l'effetto parallax leggero */
  z-index: 0;
  /* filter/transform above are the resting state; script.js takes
     over both continuously while scrolling, for the scroll-linked
     hero -> Work transition. will-change hints smoother compositing. */
  will-change: transform, filter;
}
.hero__overlay{
  position:absolute; inset:0;
  background: linear-gradient(180deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,.55) 55%, rgba(0,0,0,.75) 100%);
  z-index: 1;
}
.hero__content{
  position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center; gap:14px;
  text-align: center;
  /* resting state; script.js fades/lifts this away as you scroll,
     for the scroll-linked hero -> Work transition */
  will-change: transform, opacity;
}
.hero__eyebrow{
  font-size: .68rem; letter-spacing:.22em; text-transform:uppercase; color: rgba(255,255,255,.75);
}
.hero__title{
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.8rem, 5vw, 3.6rem);
  line-height: .95;
  letter-spacing: -.01em;
  color: var(--white);
}
.hero__tagline{
  font-size: clamp(.85rem, 1.3vw, 1.05rem);
  font-weight: 300;
  color: rgba(255,255,255,.85);
  max-width: 46ch;
}
.hero__scroll{
  margin-top: 10px;
  display:flex; align-items:center; gap:10px;
  font-size:.68rem; letter-spacing:.1em; text-transform:uppercase;
  color: var(--white);
}
.hero__scroll-line{
  width:36px; height:1px; background: var(--white);
  transition: width .4s var(--ease);
}
.hero__scroll:hover .hero__scroll-line{ width:56px; }

/* Mac-dock-style row of project icons along the bottom of the hero —
   sits right below .hero__content in the same flex column, so it
   inherits the same centering, gap and bottom padding. Just hovering
   an icon already swaps the hero's own background video to that
   project's, live; clicking makes the swap stick (see js/script.js).
   TEMPORARILY HIDDEN (display:none) at your request — the markup and
   js/script.js logic are untouched, so switching this back to
   "display:flex" brings it right back exactly as it was. */
.hero-dock{
  display: none;
  position:relative; z-index:2;
  align-items:flex-end; gap:8px;
  max-width: 90vw;
  padding: 2px 14px 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.hero-dock::-webkit-scrollbar{ display:none; }
.hero-dock__item{
  position: relative;
  flex: 0 0 auto;
  width: 34px; height:34px;
  border-radius: 8px;
  display:flex; align-items:center; justify-content:center;
  background-size: cover;
  background-position: center;
  background-color: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.3);
  cursor: pointer;
  transform-origin: bottom center;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
/* Fallback for a project with no cover uploaded yet — initials
   instead of a photo, so every project still gets an icon (Spot and
   Music included, even before their media is added). */
.hero-dock__fallback{
  font-family: var(--sans);
  font-size: .5rem;
  letter-spacing: .02em;
  color: rgba(255,255,255,.75);
}
.hero-dock__item:hover{
  transform: translateY(-6px) scale(1.15);
  box-shadow: 0 10px 18px rgba(0,0,0,.4);
  border-color: rgba(255,255,255,.7);
}
/* Little dot under the active icon, same idea as the "running app"
   indicator in the real macOS dock — shows which video is currently
   playing as the background. */
.hero-dock__item.active::after{
  content:'';
  position:absolute; left:50%; bottom:-9px;
  transform: translateX(-50%);
  width:5px; height:5px; border-radius:50%;
  background: var(--white);
}

/* ---------- section headings shared ---------- */
h2{
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.2rem, 4.5vw, 3.5rem);
  letter-spacing: -.01em;
}

/* ---------- work / grid ---------- */
.work{
  position: relative;
  overflow: hidden; /* clips the oversized, blurred hover background below */
  padding-top: 14vh;
  padding-bottom: 12vh;
}
/* Hidden by default: the Work grid only becomes visible once you pick
   a category (Film/Spot/Music, either from the #category bands or
   the nav/tabs above) — see applyWorkFilter()/revealWorkSection() in
   js/script.js. Nothing shows "below" on its own; picking a category
   opens it as a fullscreen overlay right on top of wherever you were
   instead (.work--overlay below) — closer to stepping inside that
   section than scrolling down to find it. */
.work.work--hidden{ display:none; }
.work.work--overlay{
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--white);
  overflow-y: auto;
  overflow-x: hidden;
  animation: workOverlayIn .5s var(--ease) forwards;
}
/* Opacity only, no transform/scale here on purpose: a transform on
   this element (even via animation, even one that ends at an
   identity scale(1)) makes it the containing block for any
   position:fixed descendant — which trapped .work__hover-bg to this
   box's own clipped/scrolled bounds instead of the true viewport,
   the cause of the hover backdrop only showing for the first
   screenful of cards and cutting off below that. */
@keyframes workOverlayIn{
  from{ opacity: 0; }
  to{ opacity: 1; }
}
.work__close{
  position: absolute;
  top: 28px; right: 6vw;
  z-index: 2;
  color: var(--black);
  font-size: 1.1rem;
  opacity: .6;
  transition: opacity .3s var(--ease);
}
.work__close:hover{ opacity: 1; }

/* Whole-Work-section background that appears behind everything
   (heading, tabs, grid) while hovering a card — set via JS to that
   project's own still/cover. Kept sharp and only lightly veiled (see
   ::after) so the photo actually reads clearly, not just a vague
   color glow; a light text-shadow on the heading/tabs (further down)
   keeps them legible over busier photos. Fully transparent (and
   non-interactive) until a card is actually hovered. */
.work__hover-bg{
  /* fixed, not absolute: .work is now a fixed, internally-scrolling
     overlay (see .work--overlay) — an absolutely positioned child
     scrolls away along with the rest of its content, so past the
     first screen height it was scrolling out of view entirely and
     hovering a card further down showed plain white underneath.
     Fixed to the true viewport (note .work--overlay is deliberately
     kept transform-free — see its comment — so this isn't trapped to
     its box and clipped/scrolled along with it) keeps it covering the
     whole screen no matter how far you've scrolled inside the overlay
     or which row you're hovering. */
  position: fixed; inset: 0;
  z-index: 0;
  opacity: 0;
  background-size: cover;
  background-position: center;
  filter: blur(3px);
  transform: scale(1.06);
  transition: opacity .6s var(--ease);
  pointer-events: none;
}
.work__hover-bg.is-visible{ opacity: 1; }
.work__hover-bg::after{
  content: '';
  position: absolute; inset: 0;
  background: rgba(255,255,255,.28);
}

/* Everything else in the section sits above that background layer.
   The heading/tabs get a soft white text-shadow so they stay crisp
   even when the (now much more visible) photo behind them is busy
   or light-colored. */
.section-head, .grid{ position: relative; z-index: 1; }
.work__hover-bg.is-visible ~ .section-head #workHeading,
.work__hover-bg.is-visible ~ .section-head .work-tab{
  text-shadow: 0 1px 12px rgba(255,255,255,.9), 0 1px 2px rgba(255,255,255,.9);
}

.section-head{
  display:flex; align-items:flex-end; justify-content:space-between;
  flex-wrap: wrap; gap: 24px;
  margin-bottom: 6vh;
  border-bottom: 1px solid var(--gray-light);
  padding-bottom: 28px;
}

.work-heading-row{ display:flex; align-items:center; gap:18px; }
.work-heading-group{ display:flex; align-items:center; gap:18px; }

/* Grid/list switch, right next to the "Work" heading — same pill
   outline as the filter tabs, just icon-only and slimmer. The active
   button (whichever view is showing) is solid black/white, same
   language as .work-tab.active. */
.view-toggle{ display:flex; gap:6px; }
.view-toggle__btn{
  display:flex; align-items:center; justify-content:center;
  width: 34px; height:34px;
  border: 1px solid var(--gray-light);
  border-radius: 999px;
  color: var(--gray);
  transition: all .3s var(--ease);
}
.view-toggle__btn:hover{ border-color: var(--black); color: var(--black); }
.view-toggle__btn.active{ background: var(--black); border-color: var(--black); color: var(--white); }

/* filter tabs next to the "Work" heading — same active/inactive
   state as the nav filter above, just styled as pill buttons here */
.work-tabs{ display:flex; gap: 10px; flex-wrap: wrap; }
/* the sliding indicator line only shows up on mobile (see the
   @media block below) — on desktop the pill buttons already show
   which one is active via their solid background */
.work-tabs__indicator{ display:none; }
.work-tab{
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  padding: 8px 18px;
  border: 1px solid var(--gray-light);
  border-radius: 999px;
  color: var(--gray);
  transition: all .3s var(--ease);
}
.work-tab:hover{ border-color: var(--black); color: var(--black); }
.work-tab.active{ background: var(--black); border-color: var(--black); color: var(--white); }

.grid{
  display:grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3vw 2.4vw;
}
/* Film filter only: 2 columns instead of 3, wide cinematic cards
   (16:9-ish, landscape) instead of the default portrait tiles — reads
   as much more "widescreen", closer to filling the row edge to edge.
   data-filter is set by applyWorkFilter() in js/script.js; every
   other filter (all/adv/music) keeps the normal 3-column portrait grid.
   Desktop only (min-width matches where the mobile layout below
   takes over) — on mobile Film stays identical to every other
   section, same portrait cards, same 2-column Instagram-style grid. */
@media (min-width: 901px){
  .grid[data-filter="cinema"]{
    grid-template-columns: repeat(2, 1fr);
    gap: 2.4vw 2vw;
  }
  .grid[data-filter="cinema"] .card__thumb{
    aspect-ratio: 16/9;
  }
}
/* List view: the exact same cards (still clickable, still hoverable,
   still respecting the Film/Spot/Music filter), just laid out as one
   horizontally-scrolling row instead of a wrapping 3-column grid —
   toggled via #viewToggle in js/script.js. Each card gets a fixed
   width since a row has no column to size it by. */
.grid.list-view{
  display:flex;
  overflow-x: auto;
  gap: 20px;
  padding-bottom: 10px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.grid.list-view::-webkit-scrollbar{ display:none; }
.grid.list-view .card{
  flex: 0 0 300px;
}
.card{
  cursor:pointer;
  opacity: 1;
}
.card.hidden{ display:none; }

.card__thumb{
  position:relative;
  aspect-ratio: 4/5;
  background:
    linear-gradient(160deg, #1a1a1a 0%, #0a0a0a 55%, #2a2a2a 100%);
  overflow:hidden;
}
.card__thumb-img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit: cover;
  z-index: 1;
  transition: transform .8s var(--ease);
}
/* subtle zoom on the cover photo itself when hovering the card, on
   top of the existing diagonal-stripe drift — gives the grid a bit
   of life without feeling flashy */
.card:hover .card__thumb-img{ transform: scale(1.06); }

/* Hover preview: a silent, looping video sits on top of the cover
   photo, hidden until the card is hovered (played/paused via JS —
   see the "hover preview" block in script.js). Only present at all
   for projects that have a video file set. */
.card__thumb-video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit: cover;
  z-index: 1;
  opacity: 0;
  transition: opacity .5s var(--ease);
  pointer-events: none;
}
/* No transform/scale animation here on purpose — animating the video
   element's own transform at the exact moment it starts decoding is
   what caused the brief "shake" some clips had right on hover (the
   scale transition and the decoder both fighting over the first
   couple of frames). Opacity fade only; the cover image underneath
   still does the zoom (.card:hover .card__thumb-img above). */
.card:hover .card__thumb-video{ opacity: 1; }
.card__thumb::after{
  content:'';
  position:absolute; inset:0;
  background: repeating-linear-gradient(
    115deg, rgba(255,255,255,.035) 0px, rgba(255,255,255,.035) 1px,
    transparent 1px, transparent 6px
  );
  transition: transform .8s var(--ease);
}
.card:hover .card__thumb::after{ transform: scale(1.08) rotate(1deg); }

/* Dark scrim behind the overlaid text, so title/description/logos
   stay legible over any cover photo — same tier as .card__thumb-img
   (both z-index:1), painted after it in the markup so it sits above. */
.card__scrim{
  position:absolute; inset:0;
  background: linear-gradient(to top, rgba(0,0,0,.9) 0%, rgba(0,0,0,.45) 40%, rgba(0,0,0,0) 72%);
  z-index: 1;
  pointer-events: none;
}

/* everything — title, director, category/year, description, client
   logos — now sits directly on the cover image, anchored to the
   bottom, instead of in a separate block underneath. Keeps each tile
   compact by default; the description only appears on hover (see
   .card__desc-wrap below), pushing the row above it up since this
   whole block stays bottom-anchored. */
.card__overlay{
  position:absolute; left:0; right:0; bottom:0;
  z-index: 2;
  padding: 18px;
  display:flex; flex-direction:column;
}
.card__overlay-row{
  display:flex; align-items:flex-end; justify-content:space-between; gap:14px;
}
.card__overlay-text h3{
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.2rem;
  color: var(--white);
}
.card__overlay-director{
  font-size: .78rem;
  color: rgba(255,255,255,.75);
  font-weight: 300;
  margin-top: 2px;
}
.card__overlay-meta{
  font-size: .72rem; letter-spacing:.06em; text-transform:uppercase;
  color: rgba(255,255,255,.65);
  margin-top: 3px;
}
/* Description: hidden by default, revealed on hover only, spanning
   the full width of the card so long captions are never truncated.
   grid-template-rows 0fr -> 1fr is the trick used to animate a
   height that would otherwise be "auto" (can't transition auto
   directly). Since .card__overlay is bottom-anchored, growing this
   pushes .card__overlay-row up smoothly for free. */
.card__desc-wrap{
  display:grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .35s ease;
}
.card:hover .card__desc-wrap,
.card:focus-within .card__desc-wrap{
  grid-template-rows: 1fr;
}
.card__desc-wrap .card__desc{
  overflow: hidden;
  min-height: 0;
}
.card__desc{
  margin-top: 8px;
  font-size: calc(.8rem + 3pt);
  color: rgba(255,255,255,.85);
  font-weight: 300;
  width: 100%;
}

/* client logo strip on the card: real logos (icons or wordmarks)
   shown at their natural aspect ratio on a small white chip (needed
   now that they sit over a photo/scrim instead of the plain white
   page background), or a single initials circle as fallback until
   logos are added */
.card__client{
  flex-shrink: 0;
  display:flex; align-items:center; flex-wrap:wrap; gap:6px;
  max-width: 120px;
  justify-content:flex-end;
}
.card__client-logo{
  height: 18px;
  width: auto;
  max-width: 56px;
  object-fit: contain;
  background: var(--white);
  padding: 4px 6px;
  border-radius: 4px;
}
.card__client-fallback{
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--white);
  color: var(--black);
  font-size: .58rem;
  letter-spacing: .02em;
  display:flex; align-items:center; justify-content:center;
  flex-shrink: 0;
}
/* Award/festival logo badge, top-left corner — thin border, rounded
   pill, sits on the cover photo. Only shows up once a project has
   real logo files in its "awardLogos" field (put them in
   assets/awards/<n>-<slug>/). Logos get a bit more room than the
   client-logo chips elsewhere, since these should read clearly at a
   glance, not just as a detail. */
.card__awards-badge{
  position:absolute; top:14px; left:14px;
  display:flex; align-items:center; gap:6px;
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 999px;
  padding: 6px 10px;
  background: rgba(0,0,0,.25);
  z-index: 2;
}
.card__awards-logo{
  height: 24px;
  width: auto;
  max-width: 72px;
  object-fit: contain;
  background: var(--white);
  padding: 3px 7px;
  border-radius: 999px;
}

/* ---------- awards & screenings (inside a project's own lightbox) ---------- */
.lightbox__awards{
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,.12);
  display:flex; flex-direction:column;
}
.lightbox__award-row{
  display:flex; align-items:baseline; justify-content:space-between;
  gap: 16px;
  padding: 10px 0;
  flex-wrap: wrap;
  text-align: left;
}
.lightbox__award-festival{
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--white);
}
.lightbox__award-meta{
  text-align: right;
}
.lightbox__award-result{
  font-size: .8rem;
  color: #ddd;
}
.lightbox__award-place{
  font-size: .7rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--gray);
  margin-top: 2px;
}

/* ---------- about ---------- */
.about{
  display:grid;
  grid-template-columns: .8fr 1.2fr;
  gap: 6vw;
  align-items:center;
  padding-top: 12vh; padding-bottom: 14vh;
}
.about__image{
  aspect-ratio: 3/4;
  background: linear-gradient(160deg,#111 0%,#000 60%,#232323 100%);
  background-size: cover;
  background-position: center;
}
.about__text p{
  margin-top: 22px;
  font-size: 1.05rem;
  font-weight: 300;
  color: #222;
  max-width: 56ch;
}
.about__text h2{ margin-bottom: 4px; }
/* Points to the full, dedicated About/CV page (cv.html) — this
   section is only ever a short preview/teaser of it now. */
.about__more{
  display: inline-block;
  margin-top: 20px;
  font-size: .78rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--black);
  padding-bottom: 3px;
  transition: opacity .3s var(--ease);
}
.about__more:hover{ opacity: .6; }

/* ---------- contact ---------- */
.contact{
  min-height: 70vh;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center;
  gap: 26px;
  border-top: 1px solid var(--gray-light);
}
.contact__email{
  font-family: var(--serif);
  font-size: clamp(1.6rem, 4vw, 2.6rem);
  border-bottom: 1px solid var(--black);
  padding-bottom: 4px;
  transition: opacity .3s var(--ease);
}
.contact__email:hover{ opacity:.55; }
.contact__socials{ display:flex; gap: 30px; }
.contact__socials a{
  font-size: .78rem; letter-spacing:.1em; text-transform:uppercase; color: var(--gray);
  transition: color .3s var(--ease);
}
.contact__socials a:hover{ color: var(--black); }

.footer{
  padding: 30px 6vw 40px;
  font-size: .72rem; color: var(--gray);
  text-align:center;
}

/* ---------- studio.html (the "Editing Studio" page linked from the
   nav logo) ---------- */
/* Per "rimuovi il nero, lascia solo i vari lavori che si mischiano":
   no flat colour background at all — the backdrop IS the work itself.
   .studio__mosaic is a fixed grid of tiles, each crossfading between
   real project stills/covers on its own timer (the "mixing" effect),
   with a scroll-linked parallax (see js/script.js) and a mouse
   "spotlight" that sharpens/brightens the tiles nearest the cursor and
   dims the rest. #111 below is only the loading-state colour visible
   for a split second before the first images decode, not a design
   choice. .nav stays untouched: mix-blend-mode:difference keeps its
   white text/logo readable over this busy backdrop too. */
.studio-page{ background: #111; }
.studio__mosaic{
  position: fixed; inset: 0;
  z-index: -1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 2px;
  overflow: hidden;
  background: #111;
}
.studio__mosaic-tile{
  position: relative;
  overflow: hidden;
  transform: translateY(0) scale(1.08); /* scale hides blur's soft edge */
  transition: transform .5s var(--ease);
}
.studio__mosaic-layer{
  position: absolute; inset: -6%;
  background-size: cover;
  background-position: center;
  filter: blur(7px) brightness(.68) saturate(1.1);
  opacity: 0;
  transition: opacity 1.4s ease, filter .4s ease;
}
.studio__mosaic-layer.is-visible{ opacity: 1; }
@media (prefers-reduced-motion: reduce){
  .studio__mosaic-tile{ transition: none; }
  .studio__mosaic-layer{ transition: opacity .01s linear; }
}
.studio{
  position: relative;
  min-height: 100vh;
  /* flex-start, not center: with the photo + skills grid the content
     is now taller than one screen, and centering a flex column taller
     than its container can clip the top out of scroll reach in some
     browsers. Top padding below still gives it the same
     visually-centered feel when content is short. */
  display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
  text-align:center;
  gap: 24px;
  padding: 22vh 6vw 12vh;
}
/* No dark vignette panel anymore (removed per "rimuovi il nero") —
   just enough text-shadow on the heading/paragraph to stay legible
   over the busy mosaic behind them. */
.studio h1, .studio p{ text-shadow: 0 2px 18px rgba(0,0,0,.7); }

.studio h1{
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2.2rem, 5vw, 3.6rem);
  color: var(--white);
}
.studio p{
  max-width: 58ch;
  font-size: 1.05rem;
  font-weight: 300;
  color: rgba(255,255,255,.72);
}
.studio__photo-wrap{
  position: relative;
  width: min(720px, 88vw);
  border-radius: 14px;
  overflow: hidden;
}
.studio__photo{
  width: 100%;
  display: block;
  object-fit: cover;
  aspect-ratio: 4/3;
}
/* Apple-glass location pill, same "liquid glass" language as the
   category page's Film/Spot/Music panels — blurred, translucent,
   thin light border — floating over the photo's bottom-left corner. */
.studio__location{
  position: absolute; left: 20px; bottom: 20px;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255,255,255,.4);
  box-shadow: 0 8px 28px rgba(0,0,0,.2);
  color: var(--white);
  font-size: .8rem;
  letter-spacing: .02em;
  text-shadow: 0 1px 8px rgba(0,0,0,.35);
}
.studio__location-icon{ flex-shrink: 0; }

/* Skills: small icon grid further down the page — see the HTML
   comment for the graceful text-only fallback while icon files are
   still placeholders. */
.studio__skills{
  width: 100%;
  max-width: 640px;
  margin-top: 20px;
  padding-top: 36px;
  border-top: 1px solid rgba(255,255,255,.15);
}
.studio__skills-heading{
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255,255,255,.5);
  margin-bottom: 28px;
}
.studio__skills-grid{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 32px;
}
.studio__skill{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 84px;
}
.studio__skill img{
  width: 44px; height: 44px;
  object-fit: contain;
}
.studio__skill span{
  font-size: .68rem;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: rgba(255,255,255,.55);
  text-align: center;
}

/* Clients: a wide, continuously-scrolling banner — deliberately
   breaks out to full viewport width (the negative-margin trick,
   same idea as the hero's full-bleed video inside a padded section)
   rather than staying inside .studio's narrower centered column, per
   "abbastanza grande" (fairly large). */
.studio__clients{
  width: 100vw;
  margin-left: calc(-50vw + 50%);
  margin-right: calc(-50vw + 50%);
  margin-top: 24px;
  padding-top: 40px;
  border-top: 1px solid rgba(255,255,255,.15);
}
.studio__clients-heading{
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255,255,255,.5);
  text-align: center;
  margin-bottom: 28px;
}
/* Soft gradient canvas behind the chips — flat black has nothing for
   the chips' backdrop-blur to actually blur, so the "glass" effect
   would otherwise barely read; this gives it something (dark version
   of the original light gradient, now that the page background is
   black — see .studio-page above). */
.studio__clients-viewport{
  overflow: hidden;
  padding: 26px 0;
  background: linear-gradient(135deg, #1c1c1c 0%, #101010 100%);
  /* fades the strip out at both edges instead of a hard cut where
     chips suddenly appear/disappear */
  -webkit-mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
}
.studio__clients-track{
  display: flex;
  width: max-content;
  animation: studioClientsScroll 34s linear infinite;
}
.studio__clients-row{
  display: flex;
  align-items: center;
  gap: 16px;
  padding-right: 16px;
}
@keyframes studioClientsScroll{
  from{ transform: translateX(0); }
  /* exactly -50%: the track holds two identical copies of the row
     back to back, so translating by half its total width lines the
     second copy up perfectly where the first started — the loop
     point is invisible */
  to{ transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce){
  .studio__clients-track{ animation: none; }
}
/* Apple-glass chip — same translucent/blurred/thin-border language as
   the category page panels and the studio location pill above. Plain
   text by default (see the onerror fallback in studio.html); becomes
   a real logo automatically once a PNG is added at the matching path. */
.studio__client-chip{
  display: inline-flex; align-items: center; justify-content: center;
  height: 52px;
  padding: 0 28px;
  border-radius: 999px;
  flex-shrink: 0;
  white-space: nowrap;
  background: rgba(255,255,255,.1);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(255,255,255,.22);
  box-shadow: 0 6px 20px rgba(0,0,0,.25);
  font-size: .85rem;
  letter-spacing: .02em;
  color: var(--white);
}
.studio__client-chip img{
  height: 22px; width: auto; max-width: 130px;
  object-fit: contain;
  display: block;
}

@media (max-width: 640px){
  .studio__location{ font-size: .72rem; padding: 8px 14px; }
  .studio__skills-grid{ gap: 22px; }
  .studio__client-chip{ height: 44px; padding: 0 20px; font-size: .78rem; }
}

/* ---------- #category (index.html) — sits in the scroll flow right
   between the hero and the Work grid: scroll past the landing page
   and you land here before reaching the projects themselves. Three
   full-width horizontal bands stacked one under the other (never
   side-by-side strips), each with a softly cross-fading blurred still
   from that category's own projects as background, and an Apple-glass
   frosted panel (blur + translucency + hairline border, "liquid
   glass" style) centered on top holding just the name. Stills are
   swapped in, and the click-through to the Work grid handled, by the
   "#category section" block in js/script.js. ---------- */
.category{
  min-height: 100vh;
  display:flex; flex-direction:column;
  padding: 0; /* override the generic section{padding:0 6vw} — this
                 needs to be truly edge-to-edge, no side gutters,
                 same trick the hero relies on. */
}
.category__item{
  flex: 1;
  min-height: 33.334vh;
  display:flex; align-items:center; justify-content:center;
  position: relative;
  overflow: hidden;
  background: var(--black); /* shows while the first still loads — no
    border/divider between bands on purpose, so they read as one
    continuous surface with no visible seam as you scroll past them */
}

/* Two stacked layers so a new still can fade in over the current one
   instead of popping — js/script.js just toggles which one is at
   opacity 1 every few seconds. */
.category__bg{
  position:absolute; inset:0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  filter: blur(6px) brightness(.5);
  transform: scale(1.1); /* hides the soft blurred edge past the frame */
  transition: opacity 1.4s var(--ease);
  z-index: 0;
}
/* Dark scrim on top of the stills for legibility, same gradient
   family used on the card covers. */
.category__scrim{
  position:absolute; inset:0;
  background: rgba(0,0,0,.25);
  z-index: 1;
  pointer-events: none;
}

/* The glass panel itself: translucent + backdrop-blur, thin light
   border, soft shadow — the "Apple glass" look (Control Center /
   visionOS panels), floating over the blurred cover photo. */
.category__glass{
  position: relative;
  z-index: 2;
  padding: 20px 64px;
  border-radius: 999px;
  background: rgba(255,255,255,.12);
  backdrop-filter: blur(22px) saturate(180%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255,255,255,.35);
  box-shadow: 0 8px 32px rgba(0,0,0,.25);
  transition: background .4s var(--ease), transform .4s var(--ease), box-shadow .4s var(--ease);
}
.category__item:hover .category__glass{
  background: rgba(255,255,255,.2);
  transform: scale(1.04);
  box-shadow: 0 10px 40px rgba(0,0,0,.3);
}
.category__label{
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  letter-spacing: .02em;
  color: var(--white);
  text-shadow: 0 2px 14px rgba(0,0,0,.4);
}

@media (max-width: 640px){
  .category__glass{ padding: 16px 40px; }
  .category__label{ font-size: clamp(1.5rem, 7vw, 2.2rem); }
}

/* Desktop only: the three bands go side by side (vertical columns,
   each full height) instead of stacked one above the other. Mobile
   (and tablet, below this breakpoint) keeps the original stacked
   horizontal-band layout untouched — three tall columns would be far
   too narrow to read on a phone. */
@media (min-width: 901px){
  .category{ flex-direction: row; }
  .category__item{ min-height: 100vh; }
}

/* ---------- cv.html — modeled after an agency "director profile"
   page: centered name + portrait, a thin divider, then a
   Download-CV/IMDb row and a bio paragraph, kept in this site's own
   light Helvetica look rather than that reference's dark theme. ---------- */
.cv{
  min-height: 100vh;
  display:flex; flex-direction:column; align-items:center;
  text-align:center;
  padding: 22vh 6vw 12vh;
  position: relative;
}
.cv__back{
  position:absolute; top:28px; right:6vw;
  font-size:.78rem; letter-spacing:.08em; text-transform:uppercase;
  color: var(--gray);
  transition: color .3s var(--ease);
}
.cv__back:hover{ color: var(--black); }
.cv__back-arrow{ display:inline-block; margin-right:4px; }
.cv__name{
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2rem, 5vw, 3.4rem);
  margin-bottom: 32px;
}
.cv__portrait{
  width: min(340px, 70vw);
  aspect-ratio: 3/4;
  background: linear-gradient(160deg,#111 0%,#000 60%,#232323 100%);
  background-size: cover;
  background-position: center;
  margin-bottom: 44px;
}
.cv__divider{
  width: 100%;
  max-width: 900px;
  border-top: 1px solid var(--gray-light);
  padding-top: 18px;
  margin-bottom: 40px;
  display:flex; align-items:center; justify-content:flex-end; gap:18px;
}
.cv__cv-link{
  font-size: .85rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: opacity .3s var(--ease);
}
.cv__cv-link:hover{ opacity: .6; }
.cv__imdb-badge{
  display:inline-flex; align-items:center; justify-content:center;
  height: 26px; padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--gray-light);
  transition: border-color .3s var(--ease), transform .3s var(--ease);
}
.cv__imdb-badge:hover{ border-color: var(--black); transform: scale(1.05); }
.cv__imdb-badge img{ height:14px; width:auto; object-fit:contain; display:block; }
.cv__bio{
  max-width: 70ch;
  text-align: left;
  font-size: 1.05rem;
  font-weight: 300;
  color: #222;
  line-height: 1.7;
}
.cv__bio p + p{ margin-top: 18px; }

/* Technical Skills / Language Skills — same left-aligned column width
   as the bio above, small uppercase tracked heading (same treatment
   as .card__overlay-meta/.studio__skills-heading elsewhere), each
   entry a plain bordered pill rather than an icon — no logos to
   source or reproduce here. */
.cv__section{
  width: 100%;
  max-width: 70ch;
  text-align: left;
  margin-top: 36px;
}
.cv__section-heading{
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gray);
  margin-bottom: 14px;
}
.cv__tags{
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.cv__tag{
  font-size: .82rem;
  padding: 7px 16px;
  border-radius: 999px;
  border: 1px solid var(--gray-light);
  color: #222;
}

/* "Creative Directions" — richer treatment than the plain tag pills
   above: real clickable cards (logo + name + external-link arrow)
   through to Cinerunning/Tropicale's own pages, not just a label. */
.cv__directions{
  display:flex; flex-direction:column; gap:12px;
}
.cv__direction{
  display:flex; align-items:center; gap:14px;
  padding: 14px 20px;
  border: 1px solid var(--gray-light);
  border-radius: 14px;
  color: var(--black);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.cv__direction:hover{
  transform: translateY(-3px);
  box-shadow: 0 10px 30px rgba(0,0,0,.1);
  border-color: var(--black);
}
.cv__direction-logo{
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--gray-light);
  flex-shrink: 0;
}
.cv__direction-name{
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 500;
  flex: 1;
}
.cv__direction-arrow{
  font-size: 1.1rem;
  color: var(--gray);
  transition: transform .3s var(--ease);
}
.cv__direction:hover .cv__direction-arrow{ transform: translate(2px, -2px); }

/* Contact icons — Email / Telegram / Instagram. Plain custom outline
   icons (envelope, paper plane, camera-square) rather than official
   brand marks, same restrained line-icon language as the rest of the
   site (view-toggle, location pin, showreel hint). */
.cv__contacts{
  display: flex;
  gap: 16px;
}
.cv__contact-icon{
  display: inline-flex; align-items:center; justify-content:center;
  width: 42px; height: 42px;
  border-radius: 999px;
  border: 1px solid var(--gray-light);
  color: var(--black);
  transition: background .3s var(--ease), color .3s var(--ease), transform .3s var(--ease);
}
.cv__contact-icon:hover{
  background: var(--black);
  color: var(--white);
  transform: scale(1.06);
}

@media (max-width: 640px){
  .cv{ padding-top: 18vh; }
  .cv__portrait{ width: min(240px, 60vw); margin-bottom: 32px; }
  .cv__name{ font-size: clamp(1.7rem, 8vw, 2.4rem); }
  .cv__divider{ justify-content:center; flex-wrap:wrap; }
}

/* ---------- reveal on scroll ---------- */
.reveal{
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
}
.reveal.in-view{ opacity:1; transform: translateY(0); }

/* ---------- lightbox ---------- */
.lightbox{
  position: fixed; inset:0; z-index: 200;
  background: rgba(10,10,10,.97); /* fallback base color, shows if a project has no image to use as backdrop */
  display:flex; align-items:center; justify-content:center;
  opacity:0; visibility:hidden;
  overflow: hidden; /* keeps the oversized, blurred backdrop image from creating scrollbars */
  transition: opacity .4s var(--ease), visibility .4s var(--ease);
}
.lightbox.open{ opacity:1; visibility:visible; }
.lightbox__backdrop{
  position:absolute; inset:0;
  background-size: cover;
  background-position: center;
  /* the still should read clearly, just softened and dimmed enough
     to keep the box's own text/media legible on top of it */
  filter: blur(6px) brightness(.5) saturate(1);
  transform: scale(1.15); /* hides the soft blurred edge past the viewport */
  z-index: 0;
}
.lightbox__close{
  position:absolute; top:28px; right:6vw;
  color: var(--white); font-size:1.1rem;
  z-index: 1;
}
.lightbox__inner{
  position: relative;
  z-index: 1;
  width: min(70vw, 900px);
  max-height: 85vh;
  overflow-y: auto;
  overscroll-behavior: contain; /* scrolling inside the box never bleeds into the page behind it */
  -webkit-overflow-scrolling: touch;
  text-align:center;
  /* the native OS scrollbar is hidden here — replaced by the custom,
     always-visible thin line (.lightbox__scrollbar below), since real
     browser scrollbars only auto-show while actively scrolling on most
     platforms and can't be forced to stay visible reliably via CSS */
  scrollbar-width: none;
}
.lightbox__inner::-webkit-scrollbar{ display: none; }

/* Custom scroll indicator: a hairline-thin white bar, positioned via
   JS just outside the box's right edge (see updateLightboxScrollbar()
   in script.js), always visible for as long as the project's content
   is taller than the box — independent of OS/browser scrollbar
   behavior, and of whether the person is actively scrolling. */
.lightbox__scrollbar{
  position: absolute;
  width: 1px;
  background: rgba(255,255,255,.15);
  z-index: 2;
  pointer-events: none;
}
.lightbox__scrollbar-thumb{
  position: absolute;
  left:0; right:0;
  background: rgba(255,255,255,.65);
}
.lightbox__media-wrap{ position: relative; }
.lightbox__media{
  position: relative;
  aspect-ratio: 16/9;
  background: #141414;
  display:flex; align-items:center; justify-content:center;
  margin-bottom: 10px;
  /* Needed once .lightbox__still-bg exists: that blurred backdrop
     deliberately oversizes itself (inset:-10% + scale(1.15)) to hide
     its own blur edge, but without clipping here it bled outside this
     box on every side — most visibly upward, overlapping the lightbox's
     close button / top area above it. */
  overflow: hidden;
}
/* Blurred backdrop + letterboxed video for the main lightbox player —
   see the comment in renderMainMedia (js/script.js) for why. */
.lightbox__media-bg{
  position: absolute; inset: -10%;
  background-size: cover;
  background-position: center;
  filter: blur(34px) saturate(1.15);
  transform: scale(1.15);
  z-index: 0;
}
.lightbox__media-video{
  /* position:absolute + inset:0 (not just a plain flex child) — same
     proven pattern as .lightbox__still-overlay just below. A flex item
     with no "position" of its own is *supposed* to still honor z-index
     (the spec carves out an exception for exactly this), but that was
     leaving the video invisible behind .lightbox__media-bg in
     practice — audio played, no picture — so this sidesteps that
     entirely instead of relying on it. */
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  z-index: 1;
}
.lightbox__placeholder{
  color: var(--gray); font-size:.85rem; letter-spacing:.1em; text-transform:uppercase;
}
/* Prev/next arrows for projects with more than one video — sit on
   the media box's own left/right edges (see .lightbox__media-wrap),
   independent of whatever's currently inside #lightboxMedia (video,
   still overlay, cover) so they never get wiped out when that
   content is replaced. */
.lightbox__media-nav{
  position: absolute; top:50%; transform: translateY(-50%);
  z-index: 2;
  display:flex; align-items:center; justify-content:center;
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.35);
  background: rgba(0,0,0,.45);
  color: var(--white);
  font-size: 1.2rem;
  line-height: 1;
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
.lightbox__media-nav:hover{ background: rgba(0,0,0,.7); border-color: rgba(255,255,255,.7); }
.lightbox__media-nav--prev{ left: 12px; }
.lightbox__media-nav--next{ right: 12px; }
.lightbox__media-nav[hidden]{ display:none; }
/* Sits on top of the video (never replaces it) while a still from the
   strip below is clicked — the video just pauses underneath, so
   #lightboxBackToVideo below can resume it exactly where it left off
   instead of restarting. */
/* Blurred, scaled-up copy of the still behind it, filling the 16:9
   box's leftover top/bottom or side gaps now that the still itself
   shows in full instead of being cropped (see .lightbox__still-overlay
   below) — same letterbox-blur idea used by Instagram/Stories.
   inset:-10% + extra scale hides the blur's own edge from clipping. */
.lightbox__still-bg{
  position: absolute; inset: -10%;
  background-size: cover;
  background-position: center;
  filter: blur(34px) saturate(1.15);
  transform: scale(1.15);
  z-index: 0;
}
.lightbox__still-overlay{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: center center;
  z-index: 1;
}
/* Small play-triangle button, right under the media box — appears
   only while a still is on display in place of the video (toggled via
   js/script.js). Deliberately separate from the media box itself
   (rather than overlaid on it), so it never covers the still/video. */
.lightbox__back-to-video{
  display:flex; align-items:center; justify-content:center;
  width: 32px; height: 32px;
  margin-bottom: 10px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.35);
  color: var(--white);
  font-size: .62rem;
  transition: all .25s var(--ease);
}
.lightbox__back-to-video:hover{ border-color: var(--white); transform: scale(1.08); }
.lightbox__back-to-video[hidden]{ display:none; }

/* IMDb badge: small pill, bottom-right, right under the video */
.lightbox__imdb{
  display:flex; justify-content:flex-end;
  min-height: 20px; /* keeps layout stable even when empty (no imdb link) */
  margin-bottom: 20px;
}
.lightbox__imdb-badge{
  display:inline-flex; align-items:center; justify-content:center;
  height: 26px; padding: 0 14px;
  border-radius: 999px;
  background: var(--white);
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
.lightbox__imdb-badge:hover{ transform: scale(1.06); }
.lightbox__imdb-badge img{
  height: 14px; width:auto; object-fit:contain;
  display:block;
}

/* carosello stills: striscia di thumbnail scorrevole */
.lightbox__stills{
  display:flex; gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  margin-bottom: 28px;
  scrollbar-width: thin;
}
.lightbox__still{
  flex: 0 0 auto;
  width: 90px; aspect-ratio: 4/3;
  background: linear-gradient(135deg, #1c1c1c, #050505);
  object-fit: cover; /* only applies when this is a real <img> still */
  opacity: .8;
  transition: opacity .3s var(--ease);
  cursor: pointer;
}
.lightbox__still:hover{ opacity: 1; }

/* Award/festival logos inside the lightbox, below the description and
   right above the festival list — a clean row of marks framed by a
   thin divider (same treatment as .lightbox__head/.lightbox__awards),
   each on a small white chip so any logo colour/shape stays legible
   against the dark backdrop. Hidden entirely (via JS) when the
   project has none. */
.lightbox__award-logos{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center;
  gap: 18px;
  padding-top: 22px;
  margin-top: 22px;
  border-top: 1px solid rgba(255,255,255,.12);
}
.lightbox__award-logo{
  height: 46px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  background: var(--white);
  padding: 6px 12px;
  border-radius: 8px;
}

.lightbox__head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap: 20px; text-align:left;
  border-top: 1px solid rgba(255,255,255,.12);
  padding-top: 18px;
}
.lightbox__title{
  font-family: var(--serif); color: var(--white); font-size:1.5rem;
}
.lightbox__meta{
  font-size: .74rem; letter-spacing:.08em; text-transform:uppercase;
  color: var(--gray); margin-top: 4px;
}
.lightbox__desc{
  color: #bbb; font-size: calc(.9rem + 7pt); margin-top:14px; text-align:left;
  max-width: 60ch; font-weight: 300; line-height:1.6;
}

/* client logo strip inside the lightbox */
.lightbox__client{
  flex-shrink: 0;
  display:flex; align-items:center; gap:10px;
}
.lightbox__client-logos{
  display:flex; flex-wrap:wrap; gap:6px;
  justify-content:flex-end;
}
.lightbox__client-logo{
  height: 30px;
  width: auto;
  max-width: 110px;
  object-fit: contain;
  background: #fff;
  padding: 5px 8px;
  border-radius: 4px;
}
.lightbox__client-fallback{
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(255,255,255,.12);
  color: var(--white);
  font-size: .72rem;
  display:flex; align-items:center; justify-content:center;
  flex-shrink: 0;
}
.lightbox__client-name{
  font-size: .78rem; letter-spacing:.04em; color: var(--white);
}
.lightbox__client-role{
  font-size: .68rem; color: var(--gray); margin-top:2px;
}

/* ---------- showreel (showreel.html) ---------- */
.showreel{
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: var(--black);
}
/* The scrollable feed itself: each project's video is a full-screen
   "page" that snaps into place as you scroll, like Reels/Shorts —
   scroll-snap-type does the snapping natively, no JS needed for the
   scroll motion itself (js/showreel.js only builds the items and
   plays/pauses whichever one is on screen). */
.showreel__track{
  height: 100vh;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.showreel__track::-webkit-scrollbar{ display: none; }
.showreel__item{
  position: relative;
  width: 100%;
  height: 100vh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  cursor: pointer;
  background: var(--black);
}
.showreel__video{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Soft gradient behind the title so it stays readable over any
   video, without darkening the whole frame like .card__scrim does. */
.showreel__scrim{
  position: absolute; left:0; right:0; bottom:0;
  height: 45%;
  background: linear-gradient(to top, rgba(0,0,0,.6), rgba(0,0,0,0));
  z-index: 1;
  pointer-events: none;
}
/* Project title, bottom-left of each fullscreen video — same serif
   family as the Work cards' titles, just larger since it has the
   whole screen to sit in. */
.showreel__title{
  position: absolute; left: 28px; right: 28px; bottom: 13vh;
  z-index: 2;
  pointer-events: none;
}
.showreel__title h2{
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.3rem, 3.4vw, 2rem);
  letter-spacing: .01em;
  color: var(--white);
  text-shadow: 0 2px 20px rgba(0,0,0,.55);
}
.showreel__empty{
  position: absolute; inset: 0;
  display:flex; align-items:center; justify-content:center;
  text-align:center; padding: 0 8vw;
  color: var(--gray);
  font-size: .9rem;
  z-index: 1;
}
.showreel__empty[hidden]{ display: none; }
/* Small "scroll for more" arrow, right side, fixed over the whole
   feed regardless of which item is in view — a gentle up/down bounce
   is the only thing hinting at "scroll", no text needed. */
.showreel__hint{
  position: fixed; right: 6vw; bottom: 6vh;
  color: var(--white);
  text-shadow: 0 1px 10px rgba(0,0,0,.6);
  z-index: 2;
  pointer-events: none;
  animation: showreelHintBounce 1.8s ease-in-out infinite;
}
@keyframes showreelHintBounce{
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce){
  .showreel__hint{ animation: none; }
}

/* ---------- responsive ---------- */
@media (max-width: 900px){
  .grid{ grid-template-columns: repeat(2, 1fr); gap: 8vw 5vw; }
  .about{ grid-template-columns: 1fr; }
  .about__image{ aspect-ratio: 16/9; }
}

@media (max-width: 640px){

  /* Smaller dock icons on phones — same row, just tighter, and no
     lift-on-hover (hover doesn't really apply on touch anyway; tapping
     still fires the click swap). */
  .hero-dock{ gap: 6px; padding: 2px 12px 6px; }
  .hero-dock__item{ width: 26px; height: 26px; border-radius: 6px; }
  .hero-dock__item:hover{ transform:none; box-shadow:none; }

  /* Instagram-profile-like grid on phones: 2 columns. A small gap
     between tiles (was a 2px hairline, per "serve un piccolo spazio
     ... tra un lavoro e l'altro perché crea confusione" — Spot/Music
     tiles blurring together edge-to-edge read as one confusing block
     without it). Film keeps its own single-column override below,
     unaffected by this. */
  .grid{ grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .grid.list-view .card{ flex-basis: 220px; }

  /* Film filter on phones: single column instead of the 2-column
     Instagram grid, with wide/horizontal previews (matches the
     desktop Film treatment, just adapted to one-per-row instead of
     two-per-row). data-filter is set by applyWorkFilter() in
     js/script.js. */
  .grid[data-filter="cinema"]{
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .grid[data-filter="cinema"] .card__thumb{
    aspect-ratio: 16/9;
  }
  .card__desc, .card__client{ display: none; }
  .card__overlay-text h3{ font-size: 1.05rem; }
  .card__overlay-meta{ font-size: .68rem; }

  /* Spot/Music specifically (the 2-column grid — Film above already
     gets its own single-column, more spacious treatment): the overlay
     text was reading too large for a half-width tile and "creava
     confusione" — shrink title/director/meta further and tighten the
     overlay padding just here. */
  .grid:not([data-filter="cinema"]) .card__overlay{ padding: 12px; }
  .grid:not([data-filter="cinema"]) .card__overlay-text h3{
    font-size: .82rem;
    line-height: 1.2;
  }
  .grid:not([data-filter="cinema"]) .card__overlay-director{
    font-size: .66rem;
    margin-top: 1px;
  }
  .grid:not([data-filter="cinema"]) .card__overlay-meta{
    font-size: .58rem;
    margin-top: 2px;
  }

  /* The awards badge needs to shrink to fit a half-width card:
     smaller logos, tighter padding. max-width stops it overflowing
     the card when there are a lot of logos — it wraps to a second
     line within its own bounded width instead of stretching edge to
     edge. */
  .card__awards-badge{
    top: 8px; left: 8px; right: auto;
    max-width: calc(100% - 16px);
    padding: 4px 6px;
    gap: 4px;
    flex-wrap: wrap;
  }
  .card__awards-logo{
    height: 14px;
    max-width: 34px;
    padding: 2px 4px;
    border-radius: 6px;
  }

  /* The showreel's badge sits on a fullscreen video, not a half-width
     card, so it doesn't need to shrink nearly as much — bigger and
     positioned with more breathing room than the Work-grid version
     above, closer to the desktop card size. */
  .showreel__item .card__awards-badge{
    top: 20px; left: 20px; right: auto;
    max-width: 80vw;
    padding: 6px 10px;
    gap: 6px;
  }
  .showreel__item .card__awards-logo{
    height: 26px;
    max-width: 70px;
    padding: 3px 7px;
    border-radius: 999px;
  }

  /* Category tabs restyled as a plain underline bar (Instagram's
     Posts/Reels/Tagged look) instead of the pill buttons used on
     desktop, with a thin line that slides beneath the active one —
     signals that the grid below can also be swiped left/right to
     move between categories, not just tapped here. */
  .work-tabs{
    position: relative;
    width: 100%;
    justify-content: flex-start;
    gap: 22px;
    border-top: 1px solid var(--gray-light);
    padding-top: 14px;
  }
  .work-tab{
    background: none; border: none; padding: 0 0 14px;
    color: var(--gray);
  }
  .work-tab.active{ background: none; color: var(--black); }
  .work-tabs__indicator{
    display: block;
    position: absolute; left: 0; bottom: 0;
    height: 2px; width: 0;
    background: var(--black);
    transition: transform .35s var(--ease), width .35s var(--ease);
  }

  .section-head{ flex-direction:column; align-items:flex-start; }
  .work-heading-row{ justify-content: space-between; width: 100%; }

  /* Dark backdrop instead of white for the Work overlay on phones,
     with a blurred still of one of the works always showing behind
     everything (see startMobileWorkBg in js/script.js) — reuses the
     same .work__hover-bg layer the desktop hover effect uses, just
     always on instead of only while hovering (there's no hover on
     touch) and cycling through the current category's projects every
     few seconds instead of following the mouse. */
  .work.work--overlay{ background: var(--black); }
  .work__hover-bg{ opacity: 1; }
  .work__hover-bg::after{
    background: rgba(0,0,0,.55); /* dark veil, not the white wash used
      for the desktop hover effect — reads moodier against the dark
      page instead of washed out */
  }
  .work__close{ color: var(--white); }
  .work__hover-bg.is-visible ~ .section-head #workHeading,
  .work__hover-bg.is-visible ~ .section-head .work-tab{
    text-shadow: none; /* that halo was only ever for dark text on the
      white-washed photo — text is white now, doesn't need it */
  }
  #workHeading{ color: var(--white); }
  .work-tabs{ border-top-color: rgba(255,255,255,.25); }
  .work-tab{ color: rgba(255,255,255,.6); }
  .work-tab.active{ color: var(--white); }
  .work-tabs__indicator{ background: var(--white); }
  .view-toggle__btn{ border-color: rgba(255,255,255,.35); color: rgba(255,255,255,.7); }
  .view-toggle__btn:hover{ border-color: var(--white); color: var(--white); }
  .view-toggle__btn.active{ background: var(--white); border-color: var(--white); color: var(--black); }

  .lightbox__inner{ width: 90vw; }
  .lightbox__head{ flex-direction:column; }
  .lightbox__award-row{ flex-direction:column; align-items:flex-start; gap:4px; }
  .lightbox__award-meta{ text-align:left; }
}
