/* ===================================================================
   ASSEMBLE — full-bleed scrolling portfolio
   White canvas (so white-bordered images blend). One continuous feed.
   Some items open a story. No menu.
   =================================================================== */

:root{
  --bg:#000;               /* true black throughout */
  --fg:#f6f1e7;            /* warm cream */
  --accent:#F76B1B;        /* Family Post orange (sampled from logo) */
  --muted:rgba(246,241,231,.55);
  --line:rgba(246,241,231,.14);
  --ease:cubic-bezier(.22,.61,.36,1);
  --spring:cubic-bezier(.34,1.56,.64,1);   /* playful overshoot */
  --pad:clamp(1rem,3vw,2rem);
}

*{box-sizing:border-box;margin:0;padding:0;}
html,body{height:100%;}
html{-webkit-text-size-adjust:100%;}
body{
  background:var(--bg);
  color:var(--fg);
  font-family:'Inter',-apple-system,BlinkMacSystemFont,'Helvetica Neue',Arial,sans-serif;
  font-weight:300;
  -webkit-font-smoothing:antialiased;
  letter-spacing:.01em;
  overscroll-behavior-y:none;
}
img,video{display:block;max-width:100%;}
a{color:inherit;text-decoration:none;}

/* Floating chrome uses white + difference blend, so it reads as black on white
   areas and white over dark images — legible on anything. */
.chrome{color:#fff;mix-blend-mode:difference;}

/* ---------- masthead (feed landing header — Family Post) ----------
   A studio intro that scrolls with the feed. The fixed corner brand fades
   in only after you scroll past this, so the name never doubles up. */
.masthead{
  padding:clamp(3rem,8vh,5.2rem) var(--pad) clamp(2.4rem,6vh,4rem);
  max-width:1280px;
}
.masthead .wm{
  font-family:'Playfair Display',Georgia,'Times New Roman',serif;
  font-weight:800;font-size:clamp(3.2rem,11vw,8rem);
  letter-spacing:-.02em;line-height:.82;text-transform:none;
  color:var(--accent);
  /* optical hang: pull the round F/round forms left so the edge aligns with the body below */
  margin-left:-.02em;
}
/* home masthead uses the ACTUAL logo art (orange-on-black), so it matches the brand
   exactly. Category service words keep the styled .wm text treatment above. */
.masthead .wm-logo{margin-left:-.4vw;}
/* 20% smaller than it was (was 74vw/560px), so the first film peeks above the fold
   and it's obvious there's more to scroll. */
.masthead .wm-logo img{
  width:min(59vw,448px);
  /* THE FIX for the flicker: the real ratio of the logo art, so the browser
     reserves the right height BEFORE the file arrives. Without this the image had
     zero height until it loaded, then appeared and shoved the statement below it
     down the page. That shove was the glitch, not the fade. */
  aspect-ratio:2526 / 1413;
  height:auto;
  /* opacity only. The old version also slid up 18px on a spring curve that
     overshoots, which read as a jump on top of the reflow. */
  animation:wm-fade .7s var(--ease) both;
}
@keyframes wm-fade{from{opacity:0;}to{opacity:1;}}
@media (prefers-reduced-motion:reduce){
  .masthead .wm-logo img{animation:none;}
}
.masthead .mh-tag{
  margin-top:clamp(1.5rem,3vh,2.2rem);font-size:.8rem;letter-spacing:.32em;text-transform:uppercase;
  font-weight:500;color:var(--muted);
}
/* studio-name kicker shown ABOVE the big service word on category pages */
.masthead .mh-kicker{margin-top:0;margin-bottom:clamp(.9rem,2vh,1.4rem);opacity:.7;}
/* service pages: raise the masthead so the small FAMILY POST logo (top-left) lines
   up with the top-right menu. The big service word below uses the same .wm treatment
   as the home wordmark. The fixed corner logo still fades in on scroll (rule above). */
/* (the per-craft category pages were replaced by one services page) */
/* the big Modern-Post-style statement */
/* description text = Newsreader ExtraLight (200), stretched ~22% taller for a
   tall, lean look. The scale doesn't affect layout height, so line-height is
   pre-divided by the same factor and a little bottom padding covers the rest. */
.masthead .mh-intro,
.story-intro .si-text{
  font-family:'Newsreader',Georgia,'Times New Roman',serif;
  font-weight:200;font-optical-sizing:auto;
  transform:scaleY(1.22);transform-origin:top;
}
/* 20% smaller than it was (1.45/3.6vw/2.8rem), matching the logo reduction */
.masthead .mh-intro{
  margin-top:clamp(1.5rem,3vh,2.2rem);max-width:24ch;
  font-size:clamp(1.16rem,2.88vw,2.24rem);letter-spacing:-.005em;color:var(--fg);
  line-height:.92;padding-bottom:.95em;   /* pre-divided for the 1.22 scaleY */
}
/* base rule: used at body level on the home page, so it spans the whole screen.
   Needs breathing room below or it sits flush against the first film and vanishes. */
.mh-rule{
  height:1px;width:100%;
  background:rgba(246,241,231,.24);
  margin:1.15rem 0 clamp(2.4rem,5.5vh,3.8rem);
  /* same edge fade as the marquee band above it */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
}
/* inside a masthead (service pages) it keeps its generous top gap */
.masthead .mh-rule{
  margin-top:clamp(2.6rem,6vh,4.2rem);height:1px;width:100%;background:var(--line);
}

/* ============================================================
   ITERATION: black + orange, "fun / quirky but expensive"
   (grain, client marquee, cursor dot, springy micro-interactions)
   ============================================================ */

/* --- client marquee: a full-bleed ticker band below the masthead.
       Sits outside .masthead in the DOM, so it spans the whole screen. --- */
.marquee{
  width:100%;padding:.4rem 0 1.05rem;
  overflow:hidden;white-space:nowrap;
  /* wide fades at both edges so names dissolve well before the screen edge */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
}
.marquee-track{
  display:inline-flex;gap:0;will-change:transform;
  animation:marquee 78s linear infinite;   /* longer roster, so a slower crawl */
}
.marquee-track .mq{
  font-size:.82rem;letter-spacing:.28em;text-transform:uppercase;font-weight:500;
  color:var(--muted);padding:0 1.15em;
}
.marquee-track .mq::after{content:"\2022";color:var(--accent);margin-left:2.3em;opacity:.9;}
@keyframes marquee{from{transform:translateX(0);}to{transform:translateX(-50%);}}

/* --- film grain: subtle moving texture over the whole canvas --- */
.grain{
  position:fixed;inset:-50%;z-index:60;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%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");
  animation:grain 1.1s steps(4) infinite;
}
@keyframes grain{
  0%{transform:translate(0,0)}25%{transform:translate(-4%,3%)}
  50%{transform:translate(3%,-4%)}75%{transform:translate(-3%,-2%)}100%{transform:translate(2%,4%)}
}

/* --- The cursor is the plain OS pointer. No custom dot, nothing hidden.
       (An orange dot cursor lived here and was removed; the snapshot is
       _archive/design-experiments/1-orange-dot-cursor/.) --- */

/* --- "VIEW" ring: appears + follows the cursor while over a clickable film --- */
.cursor-view{
  position:fixed;left:0;top:0;z-index:71;pointer-events:none;
  width:92px;height:92px;margin:-46px 0 0 -46px;border-radius:50%;
  border:1.5px solid var(--accent);
  display:flex;align-items:center;justify-content:center;
  opacity:0;transform:scale(.6);
  transition:opacity .28s var(--ease),transform .38s var(--spring);
}
.cursor-view.on{opacity:1;transform:scale(1);}
.cursor-view span{
  font-family:'Playfair Display',Georgia,serif;
  font-size:.62rem;letter-spacing:.24em;text-transform:uppercase;color:var(--accent);
}
@media (hover:none),(pointer:coarse){ .cursor-view{display:none;} }

/* --- INTERFACE type: Syne, the same voice as the top-right menu ---
       Everything you click or navigate by: the corner wordmark, Back, Contact,
       and the small uppercase labels inside the contact panel. Buttons also
       repeat this in their own rules further down (they set `font:inherit`
       first, which would otherwise reset it). --- */
.brand,
.back,
.contact-corner .cc-trigger,
.cc-list .row .k{
  font-family:'Syne','Helvetica Neue',Helvetica,Arial,sans-serif;
  font-weight:500;
  letter-spacing:.16em;      /* Syne is wider than the serif, so a touch tighter */
}

/* --- DATA type: Inter for the actual contact details ---
       Syne is built for display, and its lowercase gets hard to read at length —
       an email address is the worst case. Emails, handles and the bio use Inter
       instead, smaller and with more space between lines. The uppercase labels
       above them stay Syne, so the panel still reads as part of the interface. */
.cc-list .row,
.cc-list .cc-bio,
.cc-list a{
  font-family:'Inter',system-ui,-apple-system,'Helvetica Neue',Arial,sans-serif;
  font-weight:400;
}

/* --- EDITORIAL type: the logo's serif, kept for the things you read rather
       than click — service words, film captions, client ticker, tagline,
       project kickers. --- */
.section-name,
.masthead .mh-tag,
.marquee-track .mq,
.story-intro .si-kicker,
.story-intro .si-egs{
  font-family:'Playfair Display',Georgia,'Times New Roman',serif;
  font-weight:600;
  letter-spacing:.13em;
}

/* ---------- fixed brand (top-left, every page) ---------- */
.brand-wrap{
  position:fixed;top:var(--pad);left:var(--pad);z-index:40;
  mix-blend-mode:difference;pointer-events:none;
}
/* on pages with a masthead (home + service pages), hide the corner mark until
   the masthead scrolls away — it then fades in, just like on the homepage */
body[data-page="feed"] .brand-wrap{opacity:0;transition:opacity .4s var(--ease);}
body[data-page="feed"] .brand-wrap.show{opacity:1;}
/* sub-sections (service + story pages) never show the corner home mark —
   "Work" in the menu and the Back button handle navigation there */
body[data-page="services"] .brand-wrap,
body[data-page="story"] .brand-wrap{display:none;}
.brand{
  display:inline-block;text-decoration:none;
  font-size:.8rem;letter-spacing:.24em;text-transform:uppercase;color:#fff;
  pointer-events:auto;
}
/* corner brand has no asterisk (only the big masthead wordmark does) */

/* ---------- top-right menu (feed page) ---------- */
.nav-menu{
  position:fixed;top:var(--pad);right:var(--pad);z-index:45;
  display:flex;gap:1.5rem;align-items:baseline;
}
/* Syne, on purpose: the one bit of chrome that ISN'T the logo serif, so the
   nav reads as a separate voice from the wordmark instead of competing with it. */
.nav-menu .nav-link{
  font-family:'Syne','Helvetica Neue',Helvetica,Arial,sans-serif;
  color:#fff;font-size:.8rem;font-weight:500;letter-spacing:.2em;text-transform:uppercase;
  text-shadow:0 1px 14px rgba(0,0,0,.45);
  pointer-events:auto;transition:color .25s var(--ease),transform .35s var(--spring);
}
/* Hover changes colour only. It used to lift 3px, which flickered: the box moved
   out from under the pointer, hover switched off, it dropped back, and round it
   went. Never animate transform on the element that owns the :hover. */
.nav-menu .nav-link:hover{color:var(--accent);}
.nav-menu .nav-link.is-active{text-decoration:underline;text-underline-offset:.32em;text-decoration-color:var(--accent);text-decoration-thickness:2px;}
.cat-empty{color:#fff;opacity:.6;text-align:center;padding:clamp(3rem,10vh,6rem) var(--pad);}
/* Only three items now (Work / Services / Contact), so the phone sizes can stay
   generous. Syne is wide, hence still a step down under 380px. */
@media (max-width:640px){
  .nav-menu{gap:1.05rem;}
  .nav-menu .nav-link,
  .nav-menu .contact-corner .cc-trigger{font-size:.62rem;letter-spacing:.12em;}
}
@media (max-width:380px){
  .nav-menu{gap:.8rem;}
  .nav-menu .nav-link,
  .nav-menu .contact-corner .cc-trigger{font-size:.58rem;letter-spacing:.08em;}
}
.brand-tagline{
  margin-top:.3rem;
  font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:#fff;opacity:.7;
  pointer-events:none;
}

/* ---------- story: section name (top-right) ---------- */
.section-name{
  position:fixed;top:var(--pad);right:var(--pad);z-index:45;
  font-size:.72rem;letter-spacing:.22em;text-transform:uppercase;color:#fff;
  mix-blend-mode:difference;pointer-events:none;max-width:60vw;text-align:right;
}
@media (max-width:600px){               /* mobile only — desktop size unchanged */
  .section-name{ font-size:.56rem;letter-spacing:.16em; }
}

/* ---------- story: small orange logo (top-left) — click to go back ---------- */
.story-home{
  position:fixed;top:var(--pad);left:var(--pad);z-index:46;
  display:inline-block;pointer-events:auto;
  filter:drop-shadow(0 1px 10px rgba(0,0,0,.55));
  transition:opacity .25s var(--ease);
}
.story-home:hover{opacity:.7;}
.story-home img{width:clamp(74px,13vw,104px);height:auto;display:block;}

/* ---------- story: back button (fixed bottom-centre) ---------- */
/* Back button — identical size/style to the Contact trigger (see cc-trigger).
   Default: bottom-centre (desktop). Phone orientations reposition it below. */
.back{
  /* sits a little higher than the screen edge — var(--pad) alone felt cramped */
  position:fixed;left:50%;bottom:calc(var(--pad) + 1rem);transform:translateX(-50%);z-index:50;
  background:none;border:none;cursor:pointer;color:#fff;
  font:inherit;font-family:'Syne','Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:500;
  font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
  text-shadow:0 1px 14px rgba(0,0,0,.5);padding:.4rem 0;
}
.back:hover{opacity:.6;}

/* ---------- story: left-edge "back" zone (desktop only) ----------
   Hovering the left 25% shows a back-arrow cursor; clicking goes back. */
/* Left THIRD, and deliberately above the video wrapper (36) so the arrow shows
   even over the player. Still below Contact (40) and Back (50) so those keep
   working. Trade-off: a click in this strip goes back rather than reaching the
   player, including the play button in the bottom-left of Vimeo's control bar. */
.back-zone{
  position:fixed;top:0;left:0;width:33.333vw;height:100vh;z-index:38;
  cursor: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2730%27%20height%3D%2730%27%20viewBox%3D%270%200%2030%2030%27%3E%3Cpath%20d%3D%27M21%205%20L8%2015%20L21%2025%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%274%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%2F%3E%3C%2Fsvg%3E") 8 15, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABsUlEQVR4nN2Wu0oDURCGd5M0WgghVewULOyCRQoFsbMURPIAkt59gzxCWkEL27yBD2AThJQWNnZWkRArNZfPYueYP8do4Z7dwoGQYXf2fHP+OZeJov9gQAkoFQ4VPy4KWrH/bWDXTyQPYAyUzd8HRsADsG7vws/cAc1PgA8Wdp1LvUXaKtAT4ET8Iz/BLECVdg8YCNDNeAycA2tBZmzSxea3gVeBupk+As3MMIE6aSvApSftzPweUNP4UNAd4M4gU6+eicRnq6nVs2R+C3hZIe0zcGwxX6XIBBW/84O0t0DdYoJIG9uvZoNjsJkk0JX47NtFBwJuDPJu0DnwBJzY+0wHxG8fbq54NoyiqG9+OY7j+V/B38wtEqBhi8etYif1CGhJbLhjkcVBUffqPJU6dyQ+TJ1tML1fu4WsbIWzvJeHAte9fGAxZUJehSyfXn2p+0QSSSQ+qPQOvgFcedI76wFViwu66LTubdIrENIr0SUwABp5wPVObpJehX7d34BD5LwPmYCTvsaiC3HNwD1pd1JI33Vh0DGwZc9y7zTdljsDTv2kcjVv9sU09ArPVd4Q9glt+DFPDcqZsgAAAABJRU5ErkJggg==) 8 15, pointer;
}
@media (hover:none){ .back-zone{ display:none; } }   /* no hover/cursor on touch */

/* ---------- contact: a dropdown inside the top-right nav ----------
   It used to be fixed to the bottom-left corner. Now it's the third nav item, and
   its details drop down beneath the button, right-aligned to the nav. */
.contact-corner{position:relative;}
/* Contact must look EXACTLY like Work and Services. It's a <button>, so it needs
   every type property restated: `font:inherit` wipes family AND size, which left
   it a different size from its neighbours. Size and tracking are repeated here to
   match .nav-link, including at both phone breakpoints further down. */
.contact-corner .cc-trigger{
  background:none;border:none;color:#fff;cursor:pointer;
  font:inherit;
  font-family:'Syne','Helvetica Neue',Helvetica,Arial,sans-serif;
  font-size:.8rem;font-weight:500;letter-spacing:.2em;text-transform:uppercase;
  line-height:inherit;padding:0;
  text-shadow:0 1px 14px rgba(0,0,0,.45);
}
.contact-corner.open .cc-trigger{color:var(--accent);}
.contact-corner .cc-list{
  position:absolute;top:calc(100% + .85rem);right:0;
  width:max-content;min-width:15rem;max-width:min(22rem,80vw);
  text-align:left;
  display:grid;gap:.95rem;   /* air between each contact */
  max-height:0;overflow:hidden;opacity:0;
  transition:max-height .55s var(--spring),opacity .3s var(--ease),padding .3s var(--ease);
  /* translucent dark box behind the details for legibility over video */
  background:rgba(8,8,8,.82);border-radius:12px;padding:0 1rem;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.contact-corner:hover .cc-list,
.contact-corner:focus-within .cc-list,
.contact-corner.open .cc-list{padding:1rem 1.1rem 1.1rem;}
.contact-corner .cc-trigger{transition:color .25s var(--ease);}
/* hover and open both go orange, exactly like the other two nav items. This rule
   used to force white and was overriding the match. */
.contact-corner:hover .cc-trigger,
.contact-corner.open .cc-trigger{color:var(--accent);}
.cc-list a{transition:border-color .25s var(--ease),color .25s var(--ease);}
.cc-list a:hover{color:var(--accent);border-bottom-color:var(--accent);}
.contact-corner:hover .cc-list,
.contact-corner:focus-within .cc-list,
.contact-corner.open .cc-list{max-height:480px;opacity:1;}
.cc-list .row{font-size:.82rem;line-height:1.6;color:#fff;letter-spacing:.01em;}
.cc-list .cc-bio{
  max-width:34ch;margin-bottom:.55rem;line-height:1.65;
  font-size:.78rem;color:#fff;opacity:.82;letter-spacing:0;
}
.cc-list .row .k{display:block;font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;opacity:.55;margin-bottom:.3rem;}
.cc-list a{border-bottom:1px solid rgba(255,255,255,.5);}

/* ---------- SERVICES PAGE ----------
   One page of words. It replaced a page per craft, each of which re-showed the
   same films. Columns side by side on desktop, stacked on a phone. */
.services{
  min-height:100dvh;display:flex;flex-direction:column;justify-content:center;
  max-width:1560px;margin:0 auto;
  /* top padding clears the corner logo, which sits at var(--pad) and is ~104px tall */
  padding:clamp(9rem,20vh,13rem) var(--pad) clamp(3rem,8vh,5rem);
}
.services .sv-head{
  font-family:'Syne','Helvetica Neue',Helvetica,Arial,sans-serif;
  font-size:.8rem;font-weight:500;letter-spacing:.28em;text-transform:uppercase;
  color:var(--accent);margin-bottom:clamp(1.6rem,4vh,2.8rem);
}
.services .sv-grid{
  display:grid;gap:clamp(2.4rem,4.5vw,3.6rem);
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  align-items:start;
}
/* Big: the craft names carry the page. Sized against their own COLUMN, not the
   viewport, because "Finishing" is 9 characters and a viewport-based size wrapped
   it at 1280px wide. 20cqw keeps the longest name inside its column at every
   width. The vw line first is the fallback for anything without container queries. */
.sv-item{container-type:inline-size;}
.services .sv-name{
  font-family:'Playfair Display',Georgia,'Times New Roman',serif;
  font-weight:800;line-height:.92;
  font-size:clamp(2.6rem,5.6vw,4.6rem);
  font-size:clamp(2.6rem,20cqw,5.6rem);
  letter-spacing:-.02em;color:var(--accent);margin-bottom:.75rem;
}
/* same stretched Newsreader as the home statement, so the voice matches */
.services .sv-copy{
  font-family:'Newsreader',Georgia,'Times New Roman',serif;
  font-weight:200;font-optical-sizing:auto;
  transform:scaleY(1.22);transform-origin:top;
  font-size:clamp(1.15rem,2.1vw,1.75rem);line-height:1.02;  /* pre-divided for the 1.22 scaleY */
  letter-spacing:-.005em;color:var(--fg);padding-bottom:.7em;max-width:26ch;
}
.services .sv-bio{
  margin-top:clamp(2.4rem,6vh,4rem);padding-top:clamp(1.4rem,3.5vh,2.2rem);
  border-top:1px solid var(--line);
  font-family:'Inter',system-ui,-apple-system,sans-serif;
  font-size:.86rem;line-height:1.7;color:var(--muted);max-width:60ch;
}
@media (max-width:640px){
  body[data-page="services"] .story-home{display:none;}
  .services{padding-top:clamp(5rem,13vh,7rem);display:block;}
  .services .sv-grid{grid-template-columns:1fr;gap:2.1rem;}
  .services .sv-name{font-size:clamp(2.5rem,13vw,3.6rem);}
  .services .sv-copy{font-size:1.12rem;max-width:none;}
  .services .sv-bio{font-size:.82rem;}
}

/* ---------- THE FEED ---------- */
.feed{display:block;width:100%;}
.feed-item{
  position:relative;display:block;width:100%;line-height:0;
  background:#000;margin-bottom:clamp(3rem,7vh,6rem);
}
.feed-item img,.feed-item video{width:100%;height:auto;display:block;}
.feed-item.is-story{cursor:pointer;}

/* ---- credit-structured caption (persistent, below each film) ---- */
.feed-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:5;pointer-events:none;
  line-height:1.1;padding:clamp(1.6rem,4vw,3.2rem);
  color:#fff;
}
.cap-head{font-family:'Playfair Display',Georgia,'Times New Roman',serif;font-size:clamp(2rem,4.2vw,3.65rem);font-weight:500;color:#fff;letter-spacing:-.005em;}
.cap-proj{font-family:'Playfair Display',Georgia,'Times New Roman',serif;font-size:clamp(2rem,4.2vw,3.65rem);font-weight:500;color:var(--accent);margin-top:.1rem;letter-spacing:-.005em;}
.cap-credits{margin-top:1.1rem;font-size:1.29rem;color:#fff;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 1px 26px rgba(0,0,0,.45);}
.cap-credits b{font-weight:500;color:#fff;}
.cap-credits .dot{margin:0 .55rem;opacity:.5;}
/* chunky rounded arrow (from the uploaded mark), oriented up-right, white only.
   Drawn as an SVG mask filled with currentColor so it stays white like the caption. */
.feed-item.is-story .cap-head::after{
  content:"";display:inline-block;
  width:.78em;height:.78em;margin-left:.18em;vertical-align:.12em;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cg fill='none' stroke='%23fff' stroke-width='11' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M28 72 L72 28'/%3E%3Cpath d='M46 28 L72 28 L72 54'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cg fill='none' stroke='%23fff' stroke-width='11' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M28 72 L72 28'/%3E%3Cpath d='M46 28 L72 28 L72 54'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
  transition:transform .4s var(--spring);
}
.feed-item.is-story:hover .cap-head::after{transform:translate(.18em,-.18em) rotate(8deg);}

/* two consecutive PORTRAIT covers sit side by side — wide desktop only.
   Below 1000px they stack full-width like everything else. */
.feed-pair{display:block;}
@media (min-width:1000px){
  .feed-pair{display:flex;}
  /* equal-height halves: crop each cover to a common 4:5 portrait so the row lines up */
  .feed-pair > .feed-item{width:50%;aspect-ratio:4 / 5;overflow:hidden;}
  .feed-pair > .feed-item img,
  .feed-pair > .feed-item video{width:100%;height:100%;object-fit:cover;}
}

/* ---------- STORY PAGE ---------- */
.story{width:100%;padding-bottom:clamp(3.5rem,10vh,6.5rem);}  /* room for the fixed Back button */

/* intro: brief service description shown above the example videos */
.story-intro{
  max-width:840px;margin:0 auto;text-align:center;color:#fff;
  padding:clamp(4.4rem,10vh,6.4rem) var(--pad) clamp(1.8rem,5vh,3rem);
}
.story-intro .si-kicker{font-size:.72rem;letter-spacing:.32em;text-transform:uppercase;color:#fff;opacity:.7;}
.story-intro .si-title{font-size:clamp(1.5rem,3vw,2.3rem);letter-spacing:-.015em;line-height:1.08;margin-top:.6rem;}
.story-intro .si-title .si-dot{opacity:.5;margin:0 .15em;}
.story-intro .si-text{font-size:clamp(1rem,1.4vw,1.18rem);line-height:1.24;color:#cfcfd2;margin:1rem auto 0;max-width:600px;padding-bottom:.5em;}
/* stand-in: black space below the single looping video */
.story-spacer{height:clamp(38vh,50vh,60vh);background:var(--bg);}
/* desktop: a centered, moderate-size player (stand-in for the future Vimeo embed) —
   not full-bleed. Mobile media queries below override this for the fit-to-screen look. */
.story-item{width:100%;line-height:0;background:#000;display:flex;justify-content:center;align-items:center;padding:clamp(1.5rem,5vh,3.5rem) var(--pad);}
.story-item img,.story-item video{width:auto;max-width:940px;max-height:78vh;height:auto;display:block;}
/* embedded video player — responsive 16:9, clear of the top bar.
   This base rule is for the rare page with SEVERAL embeds stacked, which is meant
   to scroll. The single-embed case below fits the screen instead. */
.story-video{width:100%;max-width:min(1600px,94vw);margin:0 auto;padding:clamp(4.5rem,12vh,7.5rem) var(--pad) clamp(0.5rem,2vh,1.5rem);position:relative;z-index:36;}  /* above the back-zone so video controls stay clickable */
.story-video + .story-video{padding-top:clamp(0.5rem,2vh,1.5rem);}  /* tighter gap between stacked videos */
.vid-ratio{position:relative;width:100%;padding-top:56.25%;background:#000;}
.vid-ratio iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block;}

/* ---------- ONE embed: the player takes whatever the page has left ----------
   This used to cap the width with a fixed height reserve, which guessed badly on
   short wide windows — a 1699x646 screen left the player at ~520px with a sea of
   black around it. Now the page is a flex column of a definite 100dvh, the title
   takes what it needs (one line or two, it doesn't matter), and the player gets
   the rest. `height:min(100%, …)` is what keeps it honest: 100% is the real
   leftover space, and the calc stops the derived width exceeding --maxw, so the
   16:9 ratio is never clamped from two directions at once. */
body.embed-single .story{
  height:100dvh;                     /* definite, so the % height below resolves */
  display:flex;flex-direction:column;
  padding-bottom:4.4rem;             /* clears the fixed Back button, which sits at --pad + 1rem */
}
body.embed-single .story-intro{
  flex:0 0 auto;
  padding:clamp(1.5rem,6vh,4rem) var(--pad) clamp(.8rem,2.5vh,1.5rem);
}
body.embed-single .story-video{
  --maxw:min(1600px,94vw);
  flex:1 1 auto;min-height:0;width:100%;max-width:none;
  display:flex;align-items:center;justify-content:center;
  padding:0 var(--pad);
  /* This wrapper now spans the FULL window width (it centres the player), and it
     sits above .back-zone at z-index 36. Left as-is it swallowed the left-edge
     back arrow, which is a hover zone underneath. So the wrapper itself ignores
     the mouse and only the player takes it. */
  pointer-events:none;
}
body.embed-single .vid-ratio{pointer-events:auto;}
body.embed-single .vid-ratio{
  padding-top:0;                     /* the 56.25% hack isn't needed — real height */
  height:min(100%, calc(var(--maxw) * 9 / 16));
  min-height:200px;                  /* floor: never collapse if % height misbehaves */
  aspect-ratio:16 / 9;
  width:auto;max-width:100%;
}
body.embed-single .story-spacer{display:none;}   /* it all fits: nothing to scroll to */

/* Desktop embed pages: more air under the player, Back sits lower, and the
   left-edge back-arrow zone is off so it doesn't fight the iframe controls. */
@media (min-width:641px){
  body.has-embed.embed-single .story{padding-bottom:6rem;}
  body.has-embed .back{bottom:var(--pad);}
  body.has-embed .back-zone{display:none;}
}

/* hidden but readable by search engines */
.visually-hidden{
  position:absolute!important;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:-1px;
}

@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;}}

/* ---------- touch / small screens ---------- */
@media (hover:none){
  .feed-item .feed-title{opacity:.82;}     /* no hover -> show titles softly */
  /* on touch, hover/focus "stick" after a tap — so let ONLY the tapped .open
     class control the panel (the 6s timer removes it). */
  .contact-corner .cc-list,
  .contact-corner:hover .cc-list,
  .contact-corner:focus-within .cc-list{max-height:0;opacity:0;}
  .contact-corner.open .cc-list{max-height:480px;opacity:1;}
}

/* ---------- phones: tune the iteration bits for small screens ---------- */
@media (max-width:640px){
  /* nav menu: centered, full-width bar pinned to the very top */
  .nav-menu{
    left:0;right:0;top:0;transform:none;
    justify-content:center;gap:1.35rem;
    padding:.8rem var(--pad);
    background:transparent;transition:background-color .3s var(--ease);
  }
  /* black banner behind the menu once you've scrolled into the feed */
  body.scrolled .nav-menu{background:var(--bg);}

  /* logo / service word sit clear below the centered top menu bar */
  .masthead{padding-top:clamp(3.9rem,10vh,4.8rem);}

  .masthead .wm-logo img{width:69vw;}   /* 20% down from 86vw */
  /* client marquee: smaller, tighter, still continuous */
  .marquee{padding:.75rem 0;}
  .marquee-track .mq{font-size:.64rem;letter-spacing:.2em;padding:0 .85em;}
  /* studio statement + captions scale down so they don't swamp the phone */
  .masthead .mh-intro{font-size:clamp(1.02rem,4.32vw,1.48rem);}   /* 20% down */
  .cap-head,.cap-proj{font-size:clamp(1.45rem,6vw,2.1rem);}
  .feed-cap{padding:1.15rem 1.15rem 1.3rem;}
  /* detail rows nudge up slightly on a phone — thumbs need a bigger tap target,
     but nowhere near the old 0.95rem, which was the size Sam found unreadable */
  .cc-list .row{font-size:.86rem;}
  .cc-list .cc-bio{font-size:.8rem;}

  /* project page: keep generous headroom on phones, description above */
  .story-intro{padding-top:5.2rem;padding-bottom:1.3rem;}
  .story-intro .si-title{font-size:clamp(1.35rem,5.6vw,1.9rem);}
  .story-intro .si-text{font-size:.98rem;}

  /* embed project pages: nav is the only back control — drop the extras */
  body.has-embed .story-home,
  body.has-embed .back{display:none;}
  body.has-embed.embed-single .story{padding-bottom:0;}
  /* Title sits halfway between the nav bar and the top of the centred player.
     Intro is lifted out of the flex column so the iframe keeps the full height. */
  body.has-embed.embed-single .story{
    --embed-h:calc(min(1600px,94vw) * 9 / 16);
    --mob-nav-h:3.1rem;   /* .8rem pad ×2 + label line */
  }
  body.has-embed.embed-single .story-intro{
    position:absolute;left:0;right:0;z-index:5;
    padding:0 var(--pad);
    top:calc(var(--mob-nav-h) / 2 + (100dvh - var(--embed-h)) / 4);
    transform:translateY(-50%);
  }
  /* several embeds stacked: normal scroll, just clear the fixed nav */
  body.has-embed:not(.embed-single) .story-intro{
    padding-top:calc(var(--mob-nav-h) + 1rem);
  }
}

/* ---------- phone PORTRAIT: video centered on screen, description floating above ---------- */
@media (max-width:640px) and (orientation:portrait){
  .story{position:relative;min-height:100vh;min-height:100dvh;padding-bottom:0;}
  /* video dead-centre in the viewport */
  .story-item{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:0 var(--pad);}
  .story-item video,.story-item img{max-width:100%;max-height:62vh;width:auto;height:auto;min-width:0;}
  /* description sits above the video, raised a little for more black breathing room */
  body:not(.has-embed) .story-intro{position:absolute;left:0;right:0;bottom:calc(50% + 30vw + 2.2rem);z-index:5;padding:0 var(--pad);}
  .story-intro .si-title{font-size:clamp(1.15rem,4.6vw,1.55rem);}
  .story-intro .si-text{font-size:.86rem;}
  .story-spacer{display:none;}
  /* buttons aligned on one bottom row: Contact bottom-left, Back bottom-right */
  .back{left:auto;right:var(--pad);bottom:var(--pad);top:auto;transform:none;}

  /* Embed pages: title is positioned above (see the 640px embed rules). */
  body.has-embed.embed-single .story-intro{position:absolute;padding:0 var(--pad);}
  body.has-embed:not(.embed-single) .story-intro{position:static;padding:calc(var(--mob-nav-h,3.1rem) + 1rem) var(--pad) .9rem;}
}

/* ---------- phone LANDSCAPE (short viewport): smaller text, more room for the video ---------- */
@media (orientation:landscape) and (max-height:600px){
  .story{
    min-height:100vh;min-height:100dvh;
    display:flex;flex-direction:column;justify-content:center;padding-bottom:0;
  }
  .story-intro{flex:0 0 auto;position:static;padding:0 var(--pad) .35rem;max-width:820px;}
  .story-intro .si-kicker{font-size:.6rem;}
  .story-intro .si-title{font-size:clamp(.98rem,3.4vh,1.3rem);margin-top:.28rem;}
  .story-intro .si-text{font-size:.78rem;line-height:1.4;margin-top:.38rem;}
  .story-item{flex:0 0 auto;display:flex;align-items:center;justify-content:center;padding:0 var(--pad);}
  /* dvh is a definite unit → the whole clip is contained, never cropped */
  .story-item video,.story-item img{max-width:100%;max-height:74dvh;width:auto;height:auto;min-width:0;}
  .story-home img{width:60px;}
  /* Back sits ON the video's bottom edge. The group (intro + 74dvh video) is
     centred, so the video's lower edge is (100dvh - 74dvh - intro)/2, which is
     about 13dvh - 2.5rem up from the bottom. Contact is no longer down here: it
     moved into the top-right nav. */
  .back{left:auto;right:var(--pad);top:auto;bottom:calc(13dvh - 2.5rem);transform:none;text-align:right;}
  .story-spacer{display:none;}

  /* Embed pages: no extra back chrome on mobile; player sizing stays flex-fill. */
  body.has-embed.embed-single .story{padding-bottom:0;}
  body.has-embed .story-home,
  body.has-embed .back{display:none;}
  body.has-embed.embed-single .story-intro{
    position:absolute;left:0;right:0;z-index:5;
    padding:0 var(--pad);
    top:calc(var(--mob-nav-h,3.1rem) / 2 + (100dvh - var(--embed-h, calc(min(1600px,94vw) * 9 / 16))) / 4);
    transform:translateY(-50%);
  }
}
