:root{
  --charcoal:#2B2C2B; --slate:#333F48; --cream:#FFF8EB; --orange:#F36B36;
  --bg:#2B2C2B; --bg2:#242524; --card:#333F48; --line:#454F57;
  --fg:#FFF8EB; --dim:#A9AFB3; --accent:#F36B36; --accent-dim:#D6572A; --success:#6FCF97;
  box-sizing:border-box; padding-top:env(safe-area-inset-top,0px); padding-bottom:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box; margin:0; padding:0;}
html{scroll-behavior:smooth; scroll-padding-top:env(safe-area-inset-top,0px);}
html,body{max-width:100%; overflow-x:hidden;}
body{background:var(--bg); color:var(--fg); font-family:'Inter',sans-serif; overflow-x:hidden; -webkit-font-smoothing:antialiased;}
h1,h2,.display{font-family:'Bebas Neue',sans-serif; letter-spacing:.01em; line-height:.9; font-weight:400;}
img,svg{max-width:100%; display:block;}
a{color:inherit; text-decoration:none;}
.wrap{max-width:1200px; margin:0 auto; padding:0 24px;}
section{padding:110px 0;}
.eyebrow{display:flex; align-items:center; gap:10px; font-size:12px; letter-spacing:.12em; color:var(--accent); margin-bottom:14px; font-weight:600;}
.eyebrow .num{font-family:'Bebas Neue'; font-size:14px; border:1px solid currentColor; border-radius:4px; padding:1px 6px;}
.panel-cream{background:var(--cream); color:var(--charcoal);}
.panel-cream .dim-text{color:#5B6B74;}
.panel-slate{background:var(--slate); color:var(--cream);}
@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important;}
  html{scroll-behavior:auto;}
}
@media (max-width:640px){ section{padding:70px 0;} .wrap{padding:0 20px;} }

/* NAV */
nav{position:fixed; top:0; left:0; right:0; z-index:50; padding:16px 24px; display:flex; justify-content:flex-end; align-items:center; padding-top:calc(16px + env(safe-area-inset-top,0px)); background:linear-gradient(to bottom, rgba(43,44,43,.85), transparent);}
.navlinks{display:flex; gap:28px; font-size:14px; color:var(--fg);}
.navlinks a{opacity:.85; transition:opacity .2s;}
.navlinks a:hover{opacity:1;}
.burger{display:none; width:30px; height:22px; position:relative; background:none; border:none; cursor:pointer; z-index:60;}
.burger span{position:absolute; left:0; right:0; height:2px; background:var(--fg); transition:transform .25s, opacity .25s;}
.burger span:nth-child(1){top:0;} .burger span:nth-child(2){top:10px;} .burger span:nth-child(3){top:20px;}
.burger.open span:nth-child(1){transform:translateY(10px) rotate(45deg);}
.burger.open span:nth-child(2){opacity:0;}
.burger.open span:nth-child(3){transform:translateY(-10px) rotate(-45deg);}
.mobilemenu{position:fixed; inset:0; background:var(--bg); z-index:45; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:26px; transform:translateY(-100%); transition:transform .35s ease; mix-blend-mode:normal;}
.mobilemenu.open{transform:translateY(0);}
.mobilemenu a{font-family:'Bebas Neue'; font-size:32px; letter-spacing:.04em; color:var(--fg);}
@media (max-width:700px){ .navlinks{display:none;} .burger{display:block;} }
@media (min-width:701px){ .mobilemenu{display:none;} }

/* HERO */
.hero{display:flex; flex-direction:column; justify-content:center; align-items:center; position:relative; text-align:center; padding:calc(88px + env(safe-area-inset-top,0px)) 20px 34px; overflow:hidden;}
#pixelCanvas{position:absolute; inset:0; width:100%; height:100%; z-index:0; pointer-events:none;}
.hero-stack,.hero>.sparkle,.hero>.hero-line,.hero>.scrolldown{position:relative; z-index:1;}
.hero-stack{display:flex; flex-direction:column; align-items:center;}
.hero-name{font-family:'Anton',sans-serif; font-size:clamp(58px,17vw,190px); letter-spacing:.005em; color:var(--accent); text-transform:lowercase; position:relative; line-height:.86;}
.hero-name.line1{margin-bottom:clamp(-34px,-6vw,-10px); z-index:1;}
.hero-name.line2{margin-top:clamp(-34px,-6vw,-10px); z-index:1;}
.portrait-stage{position:relative; width:clamp(112px,20vw,190px); aspect-ratio:1/1.12; margin:6px auto; z-index:2;}
.portrait-stage::before{content:''; position:absolute; inset:-18%; border-radius:50%; background:radial-gradient(circle, rgba(243,107,54,.35) 0%, rgba(243,107,54,0) 70%); z-index:-1;}
.portrait-img{width:100%; height:100%; object-fit:cover; border-radius:50%; border:3px solid var(--accent); box-shadow:0 18px 40px -10px rgba(0,0,0,.75), inset 0 0 0 1px rgba(255,255,255,.15), 0 0 0 6px rgba(243,107,54,.12); animation:drift 7s ease-in-out infinite;}
@keyframes drift{0%,100%{transform:translateY(0) rotate(0deg);}50%{transform:translateY(-8px) rotate(-1deg);}}
.icon-badge{position:absolute; width:clamp(34px,6.4vw,58px); height:clamp(34px,6.4vw,58px); border-radius:24%; z-index:3; animation:float 5.5s ease-in-out infinite; filter:drop-shadow(0 12px 18px rgba(0,0,0,.55));}
.icon-inner{position:relative; width:100%; height:100%; border-radius:24%; overflow:hidden; background:var(--card); box-shadow:inset 0 1px 1px rgba(255,255,255,.25), inset 0 -6px 10px rgba(0,0,0,.4);}
.icon-inner::after{content:''; position:absolute; inset:0; background:linear-gradient(135deg, rgba(255,255,255,.32) 0%, rgba(255,255,255,0) 55%); pointer-events:none;}
.icon-inner img{width:100%; height:100%; object-fit:contain; padding:9%;}
.icon-badge.ic1{top:-8%; left:-30%; animation-delay:.1s;} .icon-badge.ic1 .icon-inner{transform:rotate(-8deg);}
.icon-badge.ic2{top:6%; right:-32%; animation-delay:.8s;} .icon-badge.ic2 .icon-inner{transform:rotate(7deg);}
.icon-badge.ic3{bottom:26%; left:-38%; animation-delay:1.5s;} .icon-badge.ic3 .icon-inner{transform:rotate(-6deg);}
.icon-badge.ic4{bottom:22%; right:-38%; animation-delay:2.2s;} .icon-badge.ic4 .icon-inner{transform:rotate(6deg);}
.icon-badge.ic5{bottom:-10%; left:-14%; animation-delay:1.1s;} .icon-badge.ic5 .icon-inner{transform:rotate(4deg);}
.icon-badge.ic6{bottom:-12%; right:-14%; animation-delay:2.8s;} .icon-badge.ic6 .icon-inner{transform:rotate(-5deg);}
@media (max-width:600px){
  .icon-badge{width:clamp(28px,9vw,40px); height:clamp(28px,9vw,40px);}
  .icon-badge.ic1{left:-20%; top:-10%;} .icon-badge.ic2{right:-20%; top:4%;}
  .icon-badge.ic3{left:-24%; bottom:24%;} .icon-badge.ic4{right:-24%; bottom:20%;}
  .icon-badge.ic5{left:-4%; bottom:-14%;} .icon-badge.ic6{right:-4%; bottom:-16%;}
}
@keyframes float{0%,100%{transform:translateY(0);}50%{transform:translateY(-9px);}}
.sparkle{color:var(--accent); font-size:16px; margin:14px 0 8px;}
.hero-line{color:var(--dim); font-size:clamp(13.5px,2.2vw,16px); max-width:440px; margin:0 auto 22px; line-height:1.55;}
.scrolldown{display:flex; flex-direction:column; align-items:center; gap:8px;}
.scrolldown .track{position:relative; width:1px; height:30px; background:var(--line); overflow:hidden;}
.scrolldown .track::after{content:''; position:absolute; top:-30px; left:0; width:100%; height:100%; background:var(--accent); animation:sd 2s ease-in-out infinite;}
.scrolldown span{font-size:10px; letter-spacing:.15em; color:var(--dim);}
@keyframes sd{50%{top:0;}100%{top:30px;}}
@media (max-width:640px){ .hero{padding-top:calc(72px + env(safe-area-inset-top,0px)); padding-bottom:16px;} }

/* SHOWREEL */
#showreel{padding-top:56px;}
#showreel .shead{margin-bottom:28px; align-items:center;}
.sr-video{position:relative; width:100%; height:auto; aspect-ratio:16/9; min-height:0; max-height:none; border-radius:10px; overflow:hidden; border:1px solid var(--line); background:
    repeating-linear-gradient(90deg, rgba(255,248,235,.06) 0 3px, transparent 3px 26px) top/100% 14px no-repeat,
    repeating-linear-gradient(90deg, rgba(255,248,235,.06) 0 3px, transparent 3px 26px) bottom/100% 14px no-repeat,
    radial-gradient(120% 100% at 30% 10%, #3a4048 0%, var(--bg2) 70%);}
.sr-video > img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block;}
/* UNIFIED PLAY BUTTON — single design source (originally the Showreel button) applied
   identically to Showreel (.sr-play) and every Long Form / AI Skills card (.vplay,
   shared via .vposter): same color, size, icon, glow, pulse animation and hover
   behavior, on static/default content and cards rendered live from Supabase, with or
   without a thumbnail. Reels intentionally keep their own transparent outline style
   (see .reel-card .play further down) — not part of this unification. */
.sr-play, .vposter .vplay{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:74px; height:74px; border-radius:50%;
  background:var(--accent); color:#2B2C2B; border:none;
  font-size:20px; display:flex; align-items:center; justify-content:center;
  cursor:pointer; box-shadow:0 0 0 0 rgba(243,107,54,.5);
  animation:pulse 2.6s ease-out infinite;
  transition:transform .25s ease;
  z-index:2;
}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(243,107,54,.4);}70%{box-shadow:0 0 0 22px rgba(243,107,54,0);}100%{box-shadow:0 0 0 0 rgba(243,107,54,0);}}
@media (hover:hover) and (pointer:fine){
  .sr-video:hover .sr-play,
  .vposter:hover .vplay{
    transform:translate(-50%,-50%) scale(1.08);
  }
}
.sr-label{position:absolute; bottom:22px; left:24px; color:var(--dim); font-size:12px; letter-spacing:.05em; text-align:left;}
.sr-label strong{display:block; color:var(--fg); font-size:13px; font-weight:600; margin-bottom:2px;}
@media (max-width:640px){ #showreel{padding-top:34px;} .sr-label{left:16px; bottom:16px;} }

/* reveal */
.js .rv{opacity:0; transform:translateY(28px); transition:opacity .7s ease, transform .7s ease;}
.js .rv.in{opacity:1; transform:none;}
.hero-stack .line1{opacity:0; transform:translateY(24px); animation:heroIn .8s ease .1s forwards;}
.hero-stack .line2{opacity:0; transform:translateY(24px); animation:heroIn .8s ease .28s forwards;}
.portrait-stage{opacity:0; animation:heroFade .9s ease .45s forwards;}
.sparkle,.hero-line,.scrolldown{opacity:0; transform:translateY(14px); animation:heroIn .8s ease .7s forwards;}
@keyframes heroIn{to{opacity:1; transform:none;}}
@keyframes heroFade{to{opacity:1;}}

/* SECTION HEAD */
.shead{display:flex; align-items:flex-end; justify-content:space-between; gap:24px; margin-bottom:48px; flex-wrap:wrap;}
.shead h2{font-size:clamp(38px,6vw,64px); text-transform:uppercase;}
.shead p{color:var(--dim); max-width:320px; font-size:14px; line-height:1.5;}

/* REELS CAROUSEL */
.carousel-row{display:flex; align-items:center; gap:16px;}
.carousel{display:flex; gap:22px; overflow-x:auto; scroll-snap-type:x mandatory; padding:6px 2px 10px; -webkit-overflow-scrolling:touch; scrollbar-width:none;}
.carousel::-webkit-scrollbar{display:none;}
.reel-item{scroll-snap-align:start; flex:0 0 auto; width:220px;}
.reel-card{position:relative; width:100%; height:auto; aspect-ratio:9/16; min-height:0; max-height:none; border-radius:8px; background:var(--card); border:1px solid var(--line); overflow:hidden; transition:transform .35s ease, border-color .35s ease; cursor:pointer;}
.reel-card:hover{transform:translateY(-8px); border-color:var(--accent-dim);}
.reel-fill{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; color:var(--dim); font-size:11.5px; letter-spacing:.04em; text-align:center; background:
    repeating-linear-gradient(0deg, rgba(255,248,235,.05) 0 3px, transparent 3px 22px) left/10px 100% no-repeat,
    repeating-linear-gradient(0deg, rgba(255,248,235,.05) 0 3px, transparent 3px 22px) right/10px 100% no-repeat,
    radial-gradient(140% 90% at 50% 15%, #3a4048 0%, var(--bg2) 100%);}
.reel-card > img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
/* Reels intentionally keep their own transparent, thin-outline play button — not the
   unified orange design above — with a lightweight hover/focus animation of its own
   (subtle scale + brighter outline), suited to the vertical 9:16 card. */
.play{position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:40px; height:40px; border-radius:50%; border:1px solid rgba(255,248,235,.5); display:flex; align-items:center; justify-content:center; font-size:13px; background:rgba(43,44,43,.35); transition:transform .25s ease, border-color .25s ease, background-color .25s ease;}
@media (hover:hover) and (pointer:fine){
  .reel-card:hover .play{transform:translate(-50%,-50%) scale(1.1); border-color:rgba(255,248,235,.85); background:rgba(43,44,43,.5);}
}
.reel-card:focus-visible .play{transform:translate(-50%,-50%) scale(1.1); border-color:rgba(255,248,235,.85);}
.reel-meta{padding:12px 2px 0; display:flex; justify-content:space-between; align-items:baseline; gap:10px;}
.reel-num{font-family:'Bebas Neue'; color:var(--accent); font-size:14px;}
.reel-title{font-size:14.5px; font-weight:600;}
.reel-cat{color:var(--dim); font-size:11px; letter-spacing:.04em; text-transform:uppercase;}
.arrow{width:44px; height:44px; border-radius:50%; border:1px solid var(--line); background:transparent; color:var(--fg); font-size:16px; cursor:pointer; flex:0 0 auto; transition:border-color .2s;}
.arrow:hover{border-color:var(--accent);}
@media (max-width:640px){ .arrow{display:none;} .reel-item{width:172px;} }

/* MODAL */
.modal-overlay{position:fixed; inset:0; background:rgba(20,20,20,.82); z-index:80; display:none; align-items:center; justify-content:center; padding:24px;}
.modal-overlay.open{display:flex;}
.modal-box{background:var(--charcoal); border:1px solid var(--line); border-radius:10px; max-width:420px; width:100%; aspect-ratio:9/16; position:relative; display:flex; align-items:center; justify-content:center; text-align:center; padding:24px; color:var(--dim); font-size:13px;}
.modal-box.landscape{max-width:960px; aspect-ratio:16/9; padding:24px 56px;}
.modal-box.has-video{padding:0; overflow:hidden; background:#000;}
.modal-video{display:none; width:100%; height:100%; object-fit:contain; background:#000;}
.modal-box.has-video .modal-video{display:block;}
.modal-box.has-video #modalText{display:none;}
.modal-box.has-video .modal-close{z-index:2; background:rgba(20,20,20,.6);}
.modal-soon{display:block; font-family:'Bebas Neue'; font-size:clamp(28px,5vw,48px); color:var(--accent); letter-spacing:.03em; margin-bottom:8px;}
@media (max-width:640px){ .modal-overlay{padding:16px;} .modal-box.landscape{padding:18px 44px;} }
.modal-close{position:absolute; top:12px; right:12px; width:36px; height:36px; border-radius:50%; border:1px solid var(--line); background:transparent; color:var(--fg); font-size:16px; cursor:pointer;}
/* Showreel → YouTube lightbox: the approved frame is unchanged; only the lightbox differs */
#showreelFrame{cursor:pointer;}
#showreelFrame .sr-play{z-index:2; transition:opacity .3s ease;}
.modal-yt{display:none; position:absolute; inset:0; width:100%; height:100%; border-radius:10px; overflow:hidden;}
.modal-yt iframe{position:absolute; inset:0; display:block; width:100%; height:100%; border:0;}
.modal-box.has-yt{padding:0; overflow:visible; background:#000;}
.modal-box.has-yt .modal-yt{display:block;}
.modal-box.has-yt #modalText{display:none;}
.modal-box.has-yt .modal-close{z-index:2; top:-46px; right:0; background:rgba(20,20,20,.6);}
.modal-overlay.yt-open{padding-top:64px;}
@media (max-width:640px){ .modal-overlay.yt-open{padding-top:56px;} }

/* VIDEO CARDS (shared: Long Form + AI Skills) */
.vcard{min-width:0;}
.vposter{position:relative; display:block; width:100%; height:auto; aspect-ratio:16/9; min-height:0; max-height:none; border-radius:10px; overflow:hidden; border:1px solid var(--line); padding:0; cursor:pointer; color:var(--fg); font:inherit; text-align:left; transition:transform .35s ease, border-color .35s ease; background:
    repeating-linear-gradient(90deg, rgba(255,248,235,.06) 0 3px, transparent 3px 26px) top/100% 12px no-repeat,
    repeating-linear-gradient(90deg, rgba(255,248,235,.06) 0 3px, transparent 3px 26px) bottom/100% 12px no-repeat,
    radial-gradient(120% 100% at 30% 10%, #3a4048 0%, var(--bg2) 70%);}
.vposter:hover{transform:translateY(-6px); border-color:var(--accent-dim);}
.vposter:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
.vposter img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
.vposter .vmark{position:absolute; top:18px; left:18px; font-family:'Bebas Neue'; font-size:clamp(34px,6vw,64px); line-height:.85; color:rgba(255,248,235,.08); pointer-events:none;}
.vposter .vsoon{position:absolute; top:12px; right:12px; font-size:10.5px; letter-spacing:.1em; font-weight:600; text-transform:uppercase; color:var(--accent); background:rgba(43,44,43,.75); border:1px solid rgba(243,107,54,.45); border-radius:20px; padding:4px 10px;}
.vposter .vratio{position:absolute; bottom:12px; right:14px; font-size:10.5px; letter-spacing:.08em; color:var(--dim);}
.vmeta{padding:12px 2px 0; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;}
.vmeta .reel-title{font-size:15px;}
.vmeta .reel-cat{margin-left:auto;}

/* LONG FORM */
#longform{padding-top:40px;}
.lf-grid{display:grid; grid-template-columns:1fr 1fr; gap:26px 22px;}
.lf-grid .vcard.featured{grid-column:1 / -1;}
.lf-grid .vcard.featured .reel-title{font-size:18px;}
@media (max-width:700px){ .lf-grid{grid-template-columns:1fr; gap:22px;} #longform{padding-top:10px;} }

/* AI SKILLS */
.ai-grid{display:grid; grid-template-columns:1fr 1fr; gap:22px;}
.ai-card{background:var(--card); color:var(--fg); border:1px solid var(--line); border-radius:12px; overflow:hidden; min-width:0;}
.ai-card .vposter{border:none; border-bottom:1px solid var(--line); border-radius:0;}
.ai-card .vposter:hover{transform:none;}
.ai-body{padding:16px 18px 18px;}
.ai-body .ai-num{font-family:'Bebas Neue'; color:var(--accent); font-size:14px; display:block; margin-bottom:2px;}
.ai-body h3{font-size:18px; font-weight:600; margin-bottom:6px;}
.ai-body p{color:var(--dim); font-size:13.5px; line-height:1.5; margin-bottom:12px;}
.tags{display:flex; gap:8px; flex-wrap:wrap;}
.tag{font-size:11px; color:var(--dim); border:1px solid var(--line); border-radius:20px; padding:4px 10px;}
@media (max-width:760px){ .ai-grid{grid-template-columns:1fr; gap:18px;} }

/* THUMBNAIL INTEGRATION — uploaded thumbnails read as part of the existing
   cinematic film-frame texture rather than pasted on top of it. Applies to
   Showreel, Long Form, Reels and AI Skills alike (they all share the same
   `.thumb-overlay` + `.has-thumb` pattern). The overlay sits above the
   image and below the play button/labels (DOM order after the <img>, and
   those controls keep their own stacking as before), so texture/labels/
   play button remain visible exactly as before; only the frame's own
   placeholder texture (visible when there is no thumbnail) is naturally
   covered by the photo itself, same as it already was for existing
   thumbnails. */
.thumb-overlay{position:absolute; inset:0; background:linear-gradient(rgba(0,0,0,.15), rgba(0,0,0,.35)); pointer-events:none;}
.sr-video img, .vposter img, .reel-card > img{transition:transform .3s ease, filter .3s ease;}
.vposter.has-thumb .vmark{display:none;}
.reel-card.has-thumb .reel-fill{display:none;}
@media (hover:hover) and (pointer:fine){
  .sr-video:hover img, .vposter:hover img, .reel-card:hover img{transform:scale(1.04); filter:brightness(1.05);}
}

/* ABOUT */
.about-grid{display:grid; grid-template-columns:1.1fr .9fr; gap:64px; align-items:start;}
.about-grid h2{font-size:clamp(40px,7vw,80px); text-transform:uppercase; margin-bottom:22px;}
.about-grid .bio{color:var(--dim); font-size:15px; line-height:1.7; max-width:52ch;}
.services{margin-top:36px; border-top:1px solid var(--line);}
.service-row{display:flex; justify-content:space-between; padding:16px 0; border-bottom:1px solid var(--line); font-size:16px;}
.service-row span:last-child{color:var(--dim); font-size:13px;}
.stats{display:grid; grid-template-columns:repeat(3,1fr); gap:20px;}
.stat b{font-family:'Bebas Neue'; font-size:clamp(38px,5vw,56px); color:var(--accent); display:block;}
.stat span{color:var(--dim); font-size:12.5px; letter-spacing:.03em;}
@media (max-width:800px){ .about-grid{grid-template-columns:1fr;} }

/* CONTACT */
.contact-grid{display:grid; grid-template-columns:1fr 1fr; gap:60px;}
.contact-grid h2{font-size:clamp(38px,7vw,72px); text-transform:uppercase; margin-bottom:20px;}
.field{margin-bottom:18px;}
.field label{display:block; font-size:12px; color:var(--dim); margin-bottom:6px; letter-spacing:.03em;}
.field input, .field textarea{width:100%; background:transparent; border:none; border-bottom:1px solid var(--line); color:var(--fg); font-family:inherit; font-size:15px; padding:10px 2px; outline:none; transition:border-color .25s;}
.field input:focus, .field textarea:focus{border-color:var(--accent);}
.cta-btn{margin-top:10px; display:inline-block; background:var(--accent); color:#2B2C2B; font-weight:700; padding:15px 34px; border-radius:40px; border:none; font-size:14px; cursor:pointer; position:relative; overflow:hidden; transition:box-shadow .3s;}
.cta-btn:hover{box-shadow:0 0 34px rgba(243,107,54,.55);}
.contact-side{display:flex; flex-direction:column; justify-content:space-between;}
.contact-side .email{font-size:clamp(18px,3vw,26px); word-break:break-all; margin-bottom:26px;}
.socials{display:flex; gap:22px; font-size:14px; color:var(--dim); flex-wrap:wrap;}
.socials a{position:relative; padding-bottom:3px;}
.socials a::after{content:''; position:absolute; left:0; bottom:0; width:0; height:1px; background:var(--accent); transition:width .3s;}
.socials a:hover::after{width:100%;}
.socials a:hover{color:var(--fg);}
@media (max-width:800px){ .contact-grid{grid-template-columns:1fr; gap:40px;} }

footer{padding:34px 0 calc(34px + env(safe-area-inset-bottom,0px)); border-top:1px solid var(--line); text-align:center; color:var(--dim); font-size:12.5px; display:flex; flex-direction:column; align-items:center; gap:10px;}
.footer-logo{height:44px; width:auto;}
.hp-field{position:absolute; left:-9999px; width:1px; height:1px; opacity:0;}
.form-status{font-size:14px; line-height:1.5; margin-top:16px; min-height:1px; max-width:42ch;}
.form-status.ok{color:var(--success); font-weight:600;}
.form-status.err{color:#E8A08A;}
.form-status a{text-decoration:underline;}
.form-note{color:var(--dim); font-size:12.5px; line-height:1.5; margin:-6px 0 20px; max-width:38ch;}

/* ── Mobile (≤640px): keep Long Form + Reels as real video cards ── */
@media (max-width:640px){
  /* Never leave mobile video cards hidden while waiting for the scroll reveal. */
  .js #longFormGrid.rv,
  .js #reels .carousel-row.rv{opacity:1 !important; transform:none !important;}

  /* Long Form: 01 featured, 02–03 stacked — all full-width, true 16:9 cards */
  .lf-grid{display:grid !important; grid-template-columns:minmax(0,1fr) !important; gap:22px;}
  .lf-grid .vcard{display:block !important; width:100%; min-width:0;}
  .lf-grid .vposter{display:block !important; width:100%; height:auto; aspect-ratio:16/9; min-height:0;}
  .lf-grid .vmeta{display:flex !important;}

  /* Reels: a controlled-width portrait card per view, next card peeking in — matches the
     desktop carousel's organization instead of stretching to full screen width/height. */
  .carousel-row{display:block;}
  .carousel{gap:14px; padding:6px 0 12px; scroll-snap-type:x mandatory; scroll-padding-left:0; overscroll-behavior-x:contain; touch-action:pan-x pan-y; -webkit-overflow-scrolling:touch; margin-right:-20px; padding-right:20px;}
  .reel-item{flex:0 0 clamp(210px, 68vw, 280px); width:clamp(210px, 68vw, 280px); scroll-snap-align:start; scroll-snap-stop:always; min-width:0;}
  .reel-card{display:block !important; width:100%; height:auto; aspect-ratio:9/16; min-height:0;}
  .reel-card:hover{transform:none;}
  .reel-meta{display:flex !important;}
}

/* Reliable fallback for browsers that do not support `aspect-ratio` at all. Uses the
   classic padding-bottom technique (needs content-box sizing to compute correctly, since
   the page otherwise uses border-box globally) — only ever active where aspect-ratio is
   unsupported, so it never changes anything in a supporting browser. */
@supports not (aspect-ratio: 16 / 9){
  .sr-video,
  .vposter{
    box-sizing:content-box; height:0; min-height:0; max-height:none; padding-bottom:56.25%;
  }
  .sr-video > *,
  .vposter > *{box-sizing:border-box;}
  .reel-card{
    box-sizing:content-box; height:0; min-height:0; max-height:none; padding-bottom:177.7778%;
  }
  .reel-card > *{box-sizing:border-box;}
}

/* Mobile fix: constrain the 9:16 Reels video modal to the visible viewport height.
   Without this, a shrunken Android browser toolbar can push the aspect-ratio-sized
   modal (and its YouTube iframe) outside the visible area, leaving only a border
   line and the close button on screen. */
@media (max-width: 640px) {
  .modal-overlay.yt-open {
    box-sizing: border-box;
    padding: 56px 12px 16px;
    overflow-y: auto;
    align-items: center;
    justify-content: center;
  }

  .modal-overlay.yt-open .modal-box:not(.landscape) {
    width: min(
      calc(100vw - 24px),
      calc((100vh - 88px) * 0.5625)
    );
    max-width: 420px;
    max-height: calc(100vh - 88px);
    aspect-ratio: 9 / 16;
    flex: 0 0 auto;
    margin: auto;
  }

  .modal-overlay.yt-open .modal-yt,
  .modal-overlay.yt-open .modal-yt iframe {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
  }
}

@supports (height: 100dvh) {
  @media (max-width: 640px) {
    .modal-overlay.yt-open .modal-box:not(.landscape) {
      width: min(
        calc(100vw - 24px),
        calc((100dvh - 88px) * 0.5625)
      );
      max-height: calc(100dvh - 88px);
    }
  }
}

/* Explicit mobile guard: on some older Android browsers, stale padding/visibility
   from other states can otherwise linger and shrink or hide the modal content. */
@media (max-width: 640px) {
  .modal-overlay.yt-open .modal-box {
    padding: 0;
  }

  .modal-overlay.yt-open .modal-yt,
  .modal-overlay.yt-open iframe {
    visibility: visible;
    opacity: 1;
  }
}

/* Mobile-safe fallback for browsers that do not support `aspect-ratio` at all (e.g.
   older Samsung/Android browsers). The previous height:0 + percentage padding-bottom
   technique depended on the modal-box having a definite width from its flex parent,
   which it does not reliably get inside a centered flex overlay — so the calculated
   height (and the YouTube iframe inside it) collapsed to zero, leaving only the
   border line and close button visible even though audio kept playing. This version
   sizes the modal directly from the viewport instead, so it never depends on that. */
@supports not (aspect-ratio: 9 / 16) {
  @media (max-width: 640px) {
    .modal-overlay.yt-open {
      padding: 56px 24px 16px;
      overflow: hidden;
      align-items: center;
      justify-content: center;
    }

    .modal-overlay.yt-open .modal-box:not(.landscape) {
      box-sizing: border-box;
      width: calc(100vw - 48px);
      height: calc(177.7778vw - 85.333px);
      max-width: 420px;
      max-height: calc(100vh - 88px);
      min-height: 300px;
      padding: 0;
      margin: auto;
      overflow: hidden;
    }

    .modal-overlay.yt-open .modal-yt,
    .modal-overlay.yt-open .modal-yt iframe {
      position: absolute;
      inset: 0;
      display: block;
      width: 100%;
      height: 100%;
      min-height: 100%;
      border: 0;
    }
  }
}

/* ================================================================
   INTERACTIVE GRID BACKGROUND — Showreel/Long Form/Reels (continuous) + Contact
   Purely decorative square-grid background drawn by assets/js/interactive-grid.js
   on <canvas> elements placed behind the content. Applies only to
   `.interactive-grid-section` (added in index.html): the #gridSurface wrapper
   that spans Showreel + Long Form + Reels as ONE continuous grid surface, and
   the separate #contact section — never the Hero (which keeps its own
   #pixelCanvas), AI Skills, About, the modal, nav, or the admin dashboard.

   Showreel/Long Form/Reels intentionally share a single wrapper (#gridSurface)
   and a single canvas sized to that wrapper's full height, so the grid lines
   and seeded orange cells are drawn once across all three sections with no
   per-section restart — this is what removes the seam at each section
   boundary. #contact stays spatially separate (other panels sit between it
   and Reels) but uses the same cell size/seeding/opacity values.

   Stacking: `isolation:isolate` opens a fresh stacking context; the canvas
   sits at z-index:-1 inside that context (behind the auto-stacked content)
   and `.wrap` is lifted to z-index:1 to make that explicit. The canvas itself
   is `position:absolute; inset:0` so it never changes layout size, and
   `pointer-events:none` so it can never intercept clicks/taps/scroll — every
   button, link, card and the Reels carousel underneath remain fully
   interactive.

   A CSS-only static grid (faint lines + a handful of fixed faint orange
   squares, same subtlety as the canvas version) is the base layer for when
   canvas is unavailable or JS fails; assets/js/interactive-grid.js adds
   `.grid-js-ready` once it successfully starts drawing, which hides this
   fallback so the two never show at once. */
.interactive-grid-section{
  position:relative;
  isolation:isolate;
  background-repeat:repeat, repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  background-image:
    repeating-linear-gradient(to right, rgba(69,79,87,.08) 0 1px, transparent 1px 37px),
    repeating-linear-gradient(to bottom, rgba(69,79,87,.08) 0 1px, transparent 1px 37px),
    linear-gradient(rgba(243,107,54,.05), rgba(243,107,54,.05)),
    linear-gradient(rgba(243,107,54,.04), rgba(243,107,54,.04)),
    linear-gradient(rgba(243,107,54,.06), rgba(243,107,54,.06)),
    linear-gradient(rgba(243,107,54,.03), rgba(243,107,54,.03)),
    linear-gradient(rgba(243,107,54,.04), rgba(243,107,54,.04));
  background-size:37px 37px, 37px 37px, 37px 37px, 37px 37px, 37px 37px, 37px 37px, 37px 37px;
  background-position:
    0 0, 0 0,
    118px 74px, 340px 222px, 559px 37px, 812px 296px, 970px 148px;
}
.interactive-grid-section.grid-js-ready{ background-image:none; }
.interactive-grid-section .wrap{ position:relative; z-index:1; }
.interactive-grid-canvas{
  position:absolute; inset:0; width:100%; height:100%;
  z-index:-1; pointer-events:none; display:block;
}
@media (max-width:640px){
  .interactive-grid-section{
    background-size:29px 29px, 29px 29px, 29px 29px, 29px 29px, 29px 29px, 29px 29px, 29px 29px;
    background-position:
      0 0, 0 0,
      58px 116px, 203px 29px, 319px 174px, 87px 261px, 261px 58px;
  }
}
@media (prefers-reduced-motion: reduce){
  .interactive-grid-canvas{ transition:none; }
}

/* JS-measured mobile video box. Kept last so it wins over legacy modal rules. */
@media (max-width: 640px) {
  .modal-box.mobile-video-fit {
    box-sizing: border-box;
  }

  .modal-box.mobile-video-fit .modal-close {
    top: 8px;
    right: 8px;
    z-index: 4;
    background: rgba(20,20,20,.72);
  }

  .modal-box.mobile-video-fit .modal-yt,
  .modal-box.mobile-video-fit .modal-yt iframe,
  .modal-box.mobile-video-fit .modal-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-width: 100%;
    min-height: 100%;
    visibility: visible;
    opacity: 1;
  }
}
