/* ============================================================
   AA.VISION — dark, kinetic, image-first
   ============================================================ */
:root{
  --bg:#0a0a0b;
  --bg-2:#111113;
  --ink:#c7c3bd;          /* warm grey: the default voice */
  --ink-bright:#e9e6e1;    /* display type only */
  --ink-soft:#807c77;
  --ink-faint:#56524e;
  --rule:#1f1f22;
  --accent:#8b5cf6;          /* violet: carries the purple of the drawings */
  --accent-ink:#0a0a0b;

  --serif:"Didot","Bodoni 72",Georgia,"Times New Roman",serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;

  --pad:clamp(1rem,3vw,2.5rem);
  --bar-inset:clamp(.75rem,2.5vw,2rem);   /* plate distance from the screen edge */
  --bar-gutter:clamp(1.4rem,3.5vw,3rem);  /* breathing room inside the plate */
  --gap:clamp(4px,.7vw,12px);
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:var(--mono);font-size:13px;line-height:1.6;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
::selection{background:var(--accent);color:var(--accent-ink)}

.skip{position:absolute;left:-9999px;top:0;z-index:300;padding:.75rem 1rem;background:var(--bg-2)}
.skip:focus{left:.5rem;top:.5rem}

/* ---------- scroll progress ---------- */
.progress{
  position:fixed;top:0;left:0;height:2px;width:100%;z-index:150;
  background:transparent;pointer-events:none;
}
.progress i{
  display:block;height:100%;width:0;background:var(--accent);
  transition:width .12s linear;
}

/* ---------- header: transparent, no banner ---------- */
.site-head{
  position:fixed;inset:0 0 auto 0;z-index:100;
  padding:clamp(1.05rem,2.2vw,1.6rem) calc(var(--bar-inset) + var(--bar-gutter));
  /* three columns rather than space-between: the outer two share whatever is
     left over, so the nav sits on the page's true centre however wide the
     wordmark and the social row happen to be */
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:1.5rem;
  background:none;border:0;
  transition:transform .5s var(--ease),opacity .4s var(--ease);
}
/* The same plate as the name, run the full width as one continuous bar, so
   the wordmark, nav and socials all sit on a single designed band instead of
   floating over the logo field. Chevron ends are shallower here because the
   bar is viewport-wide and the angle would otherwise read as a huge taper. */
/* inset from the edges so the bar floats rather than butting into the
   corners; 2mm matches the margin already around the video */
.site-head::before{
  content:"";position:absolute;inset:3mm var(--bar-inset);z-index:-1;
  background:#08080a;
  clip-path:polygon(0% 50%, 2% 0%, 98% 0%, 100% 50%, 98% 100%, 2% 100%);
}
.site-head::after{
  content:"";position:absolute;inset:calc(3mm - 4px) calc(var(--bar-inset) - 8px);z-index:-2;
  background:rgba(8,8,10,.5);
  clip-path:polygon(0% 50%, 2% 0%, 98% 0%, 100% 50%, 98% 100%, 2% 100%);
}
.site-head.is-hidden{transform:translateY(-120%);opacity:0}
/* On the home page the bar waits for the opening: while the logo field is
   still zooming there is nothing to navigate to, and a bar over it competes
   with the film. Every other page shows it from the start. */
.is-home .site-head{transform:translateY(-120%);opacity:0;pointer-events:none}
.is-home.opening-done .site-head{transform:none;opacity:1;pointer-events:auto}
.is-home.opening-done .site-head.is-hidden{transform:translateY(-120%);opacity:0}
.wordmark{
  font-family:var(--serif);font-size:clamp(.88rem,1.54vw,1.12rem);
  letter-spacing:.06em;line-height:1;color:var(--ink);
  transition:color .4s var(--ease);
  text-shadow:0 1px 18px rgba(0,0,0,.55);
}
.wordmark:hover{color:var(--accent)}
.wordmark span{display:inline-block;transition:transform .45s var(--ease-out)}
.wordmark:hover span:nth-child(1){transform:translateY(-3px)}
.wordmark:hover span:nth-child(2){transform:translateY(-3px);transition-delay:.05s}
.wordmark:hover span:nth-child(3){transform:translateY(-3px);transition-delay:.1s}

/* more than one link now, so the row needs its own spacing */
.nav{display:flex;align-items:center;gap:clamp(1.1rem,3vw,2.2rem)}
.nav a{
  font-size:.68rem;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-soft);
  position:relative;padding:.3rem 0;transition:color .35s var(--ease);
  text-shadow:0 1px 14px rgba(0,0,0,.5);
}
.nav a::after{
  content:"";position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:right;
  transition:transform .4s var(--ease-out);
}
.nav a:hover,.nav a[aria-current="page"]{color:var(--accent)}
.nav a:hover::after,.nav a[aria-current="page"]::after{transform:scaleX(1);transform-origin:left}

.socials{display:flex;gap:.85rem;align-items:center}
.site-head .socials{justify-self:end}
.socials a{color:var(--ink-soft);transition:transform .3s var(--ease-out),color .35s var(--ease)}
.socials a:hover{transform:translateY(-2px);color:var(--accent)}
.socials svg{width:16px;height:16px;display:block;fill:currentColor}
/* with the socials hidden the third column is empty, so the row drops to two
   and the nav sits at the right rather than floating mid-bar */
@media (max-width:640px){
  .site-head .socials{display:none}
  .site-head{grid-template-columns:auto 1fr}
  .site-head .nav{justify-self:end}
}

/* ---------- HUD ---------- */
.hud{
  position:fixed;left:var(--pad);bottom:clamp(.9rem,2vw,1.4rem);z-index:100;
  font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink-soft);pointer-events:none;display:flex;gap:1.1rem;
  opacity:0;transition:opacity .5s var(--ease);
}
.hud.is-on{opacity:1}
.hud b{font-weight:400;color:var(--accent)}

/* ---------- opening ----------
   A 300vh scroll region with a sticky 100vh viewport. Scroll progress scales
   the veil, which is a dark layer with AAV-shaped holes punched through it;
   as it grows, the holes widen until the video is all that remains. Only
   `transform` and `opacity` animate, so it stays on the compositor. */
.opening{position:relative;height:300vh}
.opening__sticky{
  position:sticky;top:0;height:100svh;overflow:hidden;
  display:grid;place-items:center;isolation:isolate;background:var(--bg);
}
/* full bleed: the film runs to every edge, no plate around it */
.opening__media{position:absolute;inset:0;overflow:hidden}
.opening__video{width:100%;height:100%;object-fit:cover;display:block}

/* the veil: oversized so it still covers the screen once scaled */
/* The veil: a solid sheet over the video with Andrea's AAV mark punched
   through it, tiled. Two mask layers — full coverage, and the repeated logo —
   combined with `exclude`, which subtracts the logo from the sheet so the
   footage shows through the mark and nowhere else. Without the composite the
   mask does the exact opposite, so the whole thing sits behind @supports and
   falls back to a plain veil that simply fades. */
/* Unscaled, viewport-sized. The fade lives here rather than on the veil
   itself: the veil is 300% tall and scales as you scroll, so a percentage
   gradient on it would sit off-screen and drift as it zooms. */
.opening__veilwrap{
  position:absolute;inset:0;overflow:hidden;pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 14%,#000 76%,transparent 97%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 14%,#000 76%,transparent 97%);
}
/* The veil is NOT transform-scaled. A scaled layer is rasterised once at its
   CSS size and then magnified on the GPU, so the mask would be a 30px bitmap
   blown up twenty times however large the source file is. Driving `mask-size`
   instead makes the browser re-render the mask at its true size every frame,
   which keeps the logo edges sharp all the way in. */
.opening__veil{
  position:absolute;inset:0;
  background:var(--bg);
  opacity:var(--veil-opacity,1);
  pointer-events:none;
}
@supports (mask-composite: exclude) or (-webkit-mask-composite: xor){
  .opening__veil{
    -webkit-mask-image:linear-gradient(#000,#000),url('/img/brand/aav-logo.png');
            mask-image:linear-gradient(#000,#000),url('/img/brand/aav-logo.png');
    -webkit-mask-repeat:no-repeat,repeat;
            mask-repeat:no-repeat,repeat;
    -webkit-mask-size:100% 100%,var(--tile,30px) var(--tile,30px);
            mask-size:100% 100%,var(--tile,30px) var(--tile,30px);
    -webkit-mask-position:center,center;
            mask-position:center,center;
    -webkit-mask-composite:xor;
            mask-composite:exclude;
  }
}

.opening__inner{
  position:relative;z-index:2;text-align:center;color:var(--ink);
  opacity:var(--mark-opacity,1);
  padding:1.15rem clamp(2.5rem,9vw,7rem);
}
/* Feathered at the ends rather than cut: the band is dark enough through the
   middle to carry the text, and dissolves into the logo field instead of
   drawing an edge against it. */
.opening__inner::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to right,
    rgba(8,8,9,0) 0%,
    rgba(8,8,9,.97) 14%,
    rgba(8,8,9,.97) 86%,
    rgba(8,8,9,0) 100%);
}
.opening__mark{
  font-family:var(--serif);font-size:clamp(.95rem,1.9vw,1.45rem);line-height:1;
  letter-spacing:.34em;margin:0;text-transform:uppercase;
}
.opening__mark .ch{display:inline-block;opacity:0;transform:translateY(.4em);
  animation:chIn 1.2s var(--ease-out) forwards}
.opening__mark .ch:nth-child(1){animation-delay:.25s}
.opening__mark .ch:nth-child(2){animation-delay:.4s}
@keyframes chIn{to{opacity:1;transform:none}}

.opening__cue{
  position:absolute;bottom:2rem;left:50%;translate:-50% 0;z-index:2;
  color:var(--accent);font-size:.6rem;letter-spacing:.26em;text-transform:uppercase;
  display:flex;flex-direction:column;align-items:center;gap:.55rem;
  opacity:var(--cue-opacity,1);transition:opacity .3s linear;
}
.opening__cue i{display:block;width:1px;height:40px;background:currentColor;
  transform-origin:top;animation:pulse 2.2s var(--ease) 1.4s infinite}
@keyframes pulse{0%,100%{transform:scaleY(.3);opacity:.35}50%{transform:scaleY(1);opacity:1}}

/* no JS: no zoom to drive, so show the footage plainly */
.no-opening .opening{height:100svh}
.no-opening .opening__veil{display:none}

@media (prefers-reduced-motion:reduce){
  .opening{height:100svh}
  .opening__veil{display:none}
  .opening__mark .ch{animation:none;opacity:1;transform:none}
  .opening__cue i{animation:none}
}

/* ---------- client strip: horizontal, drag-scrolled ---------- */
.clients{padding:0 0 clamp(1.6rem,4vw,3.2rem);border-top:1px solid var(--rule);margin-top:clamp(2rem,6vw,5rem)}
.clients__head{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:clamp(2rem,5vw,3.5rem) var(--pad) clamp(1.25rem,3vw,2rem);
}
.clients__head h2{
  margin:0;font-family:var(--mono);font-weight:400;
  font-size:.7rem;letter-spacing:.3em;text-transform:uppercase;color:var(--ink-soft);
}
.clients__hint{font-size:.64rem;letter-spacing:.22em;text-transform:uppercase;color:var(--accent)}

.clients__track{
  display:flex;gap:var(--gap);padding:0 var(--pad);
  overflow-x:auto;overscroll-behavior-x:contain;
  /* without this, snapping to a tile puts its edge on the scrollport edge and
     swallows the padding above, clipping the first caption */
  scroll-snap-type:x proximity;scroll-padding-inline:var(--pad);cursor:grab;
  scrollbar-width:none;-ms-overflow-style:none;
}
.clients__track::-webkit-scrollbar{display:none}
.clients__track.is-dragging{cursor:grabbing;scroll-snap-type:none}
.clients__track.is-dragging img{pointer-events:none}

.client{margin:0;flex:0 0 clamp(210px,24vw,340px);scroll-snap-align:start}
.client__media{
  position:relative;isolation:isolate;
  display:grid;place-items:center;
  aspect-ratio:4/3;padding:clamp(1.25rem,3vw,2.25rem);
  background:var(--bg-2);border:1px solid var(--rule);overflow:hidden;
  transition:border-color .4s var(--ease);
}
/* the photograph sits behind the mark, dimmed so the logo keeps its contrast */
.client__bg{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;object-fit:cover;
  filter:grayscale(1) brightness(.42) contrast(1.05);
  transition:filter .6s var(--ease),transform 1.1s var(--ease-out);
}
.client__media::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:rgba(8,8,10,.42);
  transition:background .5s var(--ease);
}
.client:hover .client__bg{filter:grayscale(0) brightness(.6) contrast(1.05);transform:scale(1.05)}
.client:hover .client__media::after{background:rgba(8,8,10,.25)}
/* removed: `.client:hover .client__media img` caught the logo <img> too, and
   its trailing element selector outranked the logo rules, so the violet
   hover never applied. The background image has its own rule above. */
.client figcaption{
  margin-top:.7rem;font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-soft);
}
.client figcaption b{font-weight:400;color:var(--accent);margin-right:.5rem}

.clients__bar{height:1px;background:var(--rule);margin:clamp(1.5rem,4vw,2.5rem) var(--pad) 0}
.clients__bar i{display:block;height:1px;width:0;background:var(--accent);margin-top:-1px}

@media (max-width:860px){
  /* narrow portrait strips rather than wide landscape cards: on a phone the
     wide format showed barely one and a half brands, so the row read as a
     single tile rather than a list of clients */
  .client{flex:0 0 29vw}
  .client__media{aspect-ratio:1/2.4;padding:clamp(.5rem,2.5vw,1rem)}
  .client__logo{max-width:82%;max-height:26%}
  .client__logo--raster{max-width:86%;max-height:28%}
  .client__logo--alpha{max-width:60%;max-height:22%}
  .client figcaption{font-size:.5rem;letter-spacing:.1em;line-height:1.5}
  .clients__track{scroll-snap-type:x proximity}
}


/* ---------- client logo tiles: one optical size for every mark ---------- */
/* a second .client__media rule used to live here, left over from before the
   background photographs. It sat after the mobile media query and silently
   overrode it, which is why the narrow tiles kept their 4/3 ratio. */
.client__logo{
  width:auto;height:auto;max-width:58%;max-height:46%;
  fill:var(--ink-soft);transition:fill .4s var(--ease),transform .6s var(--ease-out);
}
.client__wordmark{
  font-size:clamp(.72rem,1.5vw,.95rem);letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink-soft);text-align:center;line-height:1.4;
  transition:color .4s var(--ease);
}
.client:hover .client__media{border-color:var(--accent);background:#141416}
.client:hover .client__logo{fill:#fff;transform:scale(1.06)}
.client:hover .client__wordmark{color:#fff}



/* ---------- generic sections (contact, 404) ---------- */
.section{padding:clamp(7rem,14vw,11rem) var(--pad) clamp(4rem,10vw,8rem);max-width:980px;margin:0 auto}
.display{
  font-family:var(--serif);font-weight:400;line-height:1.02;letter-spacing:-.01em;
  font-size:clamp(2.4rem,8vw,5.5rem);margin:0;font-style:italic;color:var(--ink-bright);
}
.lede{max-width:50ch;color:var(--ink-soft);margin:1.75rem 0 0;font-size:.85rem;letter-spacing:.06em}
/* About and Get in touch read in the same measure as the brand pages: the
   column is centred and the heading sits over it, with the copy ranged left. */
.section--tight{max-width:62ch}
.section--tight .display{text-align:center}
.section--tight .lede{max-width:none}
.section--tight .form{max-width:none;margin-left:auto;margin-right:auto}

.reveal{opacity:0;transform:translateY(26px);
  transition:opacity 1s var(--ease-out),transform 1s var(--ease-out)}
.reveal.is-in{opacity:1;transform:none}

/* ---------- contact form ---------- */
.form{max-width:620px;margin:3rem 0 0}
.field{position:relative;margin:0 0 1.9rem}
.field input,.field textarea{
  width:100%;background:none;border:0;border-bottom:1px solid var(--rule);
  padding:.85rem 0;font:inherit;color:var(--ink);border-radius:0;
  transition:border-color .4s var(--ease);
}
.field textarea{resize:vertical;min-height:130px}
.field label{position:absolute;left:0;top:.85rem;color:var(--ink-faint);pointer-events:none;
  font-size:.8rem;letter-spacing:.1em;text-transform:uppercase;transition:all .35s var(--ease-out)}
.field input:focus,.field textarea:focus{outline:0;border-bottom-color:var(--accent)}
.field input:focus+label,.field textarea:focus+label,
.field input:not(:placeholder-shown)+label,.field textarea:not(:placeholder-shown)+label{
  top:-.7rem;font-size:.6rem;color:var(--accent)}
.hp{position:absolute!important;left:-9999px!important}
.btn{
  background:var(--accent);color:var(--accent-ink);border:0;font:inherit;
  font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;
  padding:1rem 2.6rem;border-radius:999px;cursor:pointer;
  transition:transform .35s var(--ease-out),opacity .3s var(--ease);
}
.btn:hover{transform:translateY(-2px)}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none}
.form__note{margin-top:1.3rem;font-size:.75rem;min-height:1.4em;letter-spacing:.06em}
.form__note.ok{color:var(--accent)}
.form__note.err{color:#ff5c5c}

/* ---------- footer ---------- */
/* ---------- closing call to action ----------
   Sits between the last section and the footer: the page ends on the one
   action worth taking, in the accent so it reads as the exit. */
.cta{display:flex;justify-content:center;padding:clamp(3.5rem,9vw,7rem) var(--pad) clamp(2rem,5vw,3.5rem)}
/* on the home page the strip of clients leads straight into the invitation,
   so the air between them is cut right back */
.is-home .cta{padding-top:clamp(1.4rem,3.6vw,2.8rem)}
.cta__btn{
  display:inline-flex;align-items:center;gap:.9rem;
  color:var(--accent);
  font-family:var(--mono);font-weight:400;
  font-size:clamp(.68rem,1.6vw,.8rem);letter-spacing:.3em;text-transform:uppercase;
  transition:color .45s var(--ease);
}
.cta__btn::after{content:"→";transition:transform .45s var(--ease-out)}
.cta__btn:hover{color:var(--ink-bright)}
.cta__btn:hover::after{transform:translateX(.35rem)}
@media (prefers-reduced-motion:reduce){
  .cta__btn,.cta__btn::after{transition:none}
}

.site-foot{
  border-top:1px solid var(--rule);padding:clamp(2rem,5vw,3.5rem) var(--pad);
  display:flex;flex-wrap:wrap;gap:1.1rem;justify-content:space-between;align-items:center;
  color:var(--ink-faint);font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;
}
.site-foot__socials{display:flex;gap:1rem;align-items:center}
.site-foot__socials a{color:var(--ink-faint);transition:color .3s var(--ease)}
.site-foot__socials a:hover{color:var(--accent)}
/* without an explicit size these inherit the SVG default of 300x150 */
.site-foot__socials svg{width:15px;height:15px;fill:currentColor;display:block;flex:0 0 auto}
.site-foot a:hover{color:var(--accent)}

/* marks ride above the photograph and its dimming layer */
.client__logo,.client__wordmark{position:relative;z-index:2}

/* Raster client marks. These arrive as black-or-colour artwork on a solid white
   background, so they are desaturated (colour logos would invert to their
   opposite hue), inverted to white-on-black, then screen-blended — which drops
   the black away and leaves a white mark matching the vector ones. */
.client__logo--raster{
  width:auto;height:auto;max-width:62%;max-height:52%;
  /* --logo-filter lets a single awkward source override the default chain */
  filter:var(--logo-filter, grayscale(1) invert(1) contrast(1.15) brightness(.92));
  mix-blend-mode:screen;
  opacity:.82;
  transition:opacity .4s var(--ease),transform .6s var(--ease-out);
}
/* Hover simply brings the mark to full white. The earlier hue-rotate chain
   landed on a different colour for each source image, because the result
   depends on the original artwork's tones. */
.client:hover .client__logo--raster{opacity:1;transform:scale(1.06)}

/* Marks that already carry transparency. No background to drop, so they just
   get forced to flat white — brightness(0) crushes any colour to black, then
   invert lifts it to white while the alpha channel is untouched. */
.client__logo--alpha{
  width:auto;height:auto;max-width:48%;max-height:48%;
  /* brightness(0) flattens the artwork to black while keeping its transparency,
     so invert() then sets the tone: .503 lands on the same grey as the vector
     marks' fill, 1 is white. */
  filter:brightness(0) invert(.503);
  transition:filter .4s var(--ease),transform .6s var(--ease-out);
}
.client:hover .client__logo--alpha{filter:brightness(0) invert(1);transform:scale(1.06)}

/* ---------- brand work pages ----------
   The page scrolls vertically but the photographs travel horizontally: a tall
   section with a sticky viewport, and scroll progress drives translateX on the
   rail. Reads as moving through a body of work rather than down a list, and it
   is the same sticky technique as the opening so the site feels of a piece. */
.work{position:relative;height:calc(100vh + (var(--count,1) * 62vh))}
.work__sticky{
  position:sticky;top:0;height:100svh;overflow:hidden;
  display:flex;flex-direction:column;justify-content:flex-start;background:var(--bg);
  padding-top:calc(var(--bar-inset) + 5.2rem);
}
/* the mark leads the page rather than sitting behind it as a watermark */
.work__brand{
  margin:0 0 clamp(.05rem,.2vw,.18rem);
  width:clamp(96px,16vmin,170px);
}
.work__brand svg{width:100%;height:auto;fill:var(--ink-soft)}
/* a brand with no mark on file is set in type instead */
.work__wordmark{
  display:block;font-family:var(--mono);font-weight:400;
  font-size:clamp(.78rem,1.6vw,1rem);letter-spacing:.34em;text-transform:uppercase;
  color:var(--ink-bright);text-align:center;
}
.work__brand:has(.work__wordmark){width:auto}
.work__brand img{
  width:100%;height:auto;
  filter:var(--logo-filter,grayscale(1) invert(1) contrast(1.15) brightness(.92));
  mix-blend-mode:screen;opacity:.85;
}
.work__brand .work__logo--alpha{filter:grayscale(1) brightness(0) invert(1);mix-blend-mode:normal}
.work__brand svg{width:100%;height:auto;fill:var(--ink)}
.work__brand img{width:100%;height:auto;filter:var(--logo-filter,grayscale(1) invert(1))}

.work__head{
  position:absolute;top:0;left:0;right:0;z-index:3;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:calc(var(--bar-inset) + 2.6rem) calc(var(--bar-inset) + var(--bar-gutter)) 0;
  font-size:.62rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-soft);
}
.work__name{color:var(--ink)}
.work__count b{font-weight:400;color:var(--accent)}
.work__back{color:var(--ink-soft);transition:color .3s var(--ease)}
.work__back:hover{color:var(--accent)}

.work__rail{position:relative;z-index:2;overflow:hidden}
.work__track{
  display:flex;align-items:center;gap:clamp(1rem,3vw,3rem);
  padding:0 max(var(--pad),calc(50vw - 35vh));
  will-change:transform;
}
.frame{
  flex:0 0 auto;margin:0;position:relative;
  height:78vh;aspect-ratio:var(--ar,3/2);
  background:var(--bg-2);overflow:hidden;
}
.frame img{width:100%;height:100%;object-fit:cover;transition:filter .5s var(--ease)}
.frame:hover img{filter:brightness(1.08)}
.frame figcaption{
  position:absolute;left:.8rem;bottom:.6rem;
  font-size:.58rem;letter-spacing:.2em;color:var(--accent);
  opacity:0;transition:opacity .4s var(--ease);
}
.frame:hover figcaption{opacity:1}

.work__bar{position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--rule);z-index:3}
.work__bar i{display:block;height:100%;width:0;background:var(--accent)}

/* ---------- full-bleed stream ----------
   No gutters and no margins: the photographs run edge to edge, singles at full
   width and portraits in pairs, so the page reads as one continuous sequence. */
.work--stream{height:auto;padding:0}
.work--stream .work__head{
  position:static;
  padding:0 var(--pad) clamp(1.1rem,3vw,1.8rem);
}
.work__stream{display:grid;grid-template-columns:1fr 1fr;gap:0}
.work--stream .frame{
  width:100%;height:100%;margin:0;aspect-ratio:var(--ar,3/2);
}
.work--stream .frame--full{grid-column:1 / -1}
.work--stream .frame img{
  width:100%;height:100%;object-fit:cover;
  transition:filter .5s var(--ease);
}
.work--stream .frame:hover img{filter:brightness(1.06)}

/* the film sits in the grid like any other frame, at its own 9:16 */
.frame--reel{background:#000;cursor:default}
.frame--reel video{width:100%;height:100%;object-fit:cover;display:block}
/* autoplay has to be silent, so sound is a deliberate click */
.frame__sound{
  position:absolute;right:1rem;bottom:.9rem;z-index:2;
  padding:.45rem .8rem;border:1px solid rgba(233,230,225,.35);background:rgba(10,10,11,.45);
  color:var(--ink-bright);font-family:var(--mono);
  font-size:.56rem;letter-spacing:.2em;text-transform:uppercase;
  backdrop-filter:blur(6px);cursor:pointer;
  transition:border-color .3s var(--ease),color .3s var(--ease);
}
.frame__sound:hover{border-color:var(--accent);color:var(--accent)}
.frame--reel.is-live .frame__sound{border-color:var(--accent);color:var(--accent)}

/* ---------- film beside the words ----------
   A portrait film leaves half the screen empty, so the standing text takes
   that half and the two sit as one block. */
.work-split{
  /* the words start level with the top of the film rather than floating
     centred beside it */
  display:grid;grid-template-columns:1fr 1fr;align-items:start;gap:0;
  padding-top:calc(var(--bar-inset) + 5.5rem);
}
.work-split__text{
  display:flex;flex-direction:column;align-items:flex-start;
  padding:0 clamp(1.5rem,5vw,4rem) clamp(1.5rem,5vw,3.5rem);
  max-width:52ch;
}
.work-split__text .work__brand{margin-bottom:clamp(.8rem,2vw,1.4rem)}
.work-split__text p{
  margin:0 0 1.4em;
  font-size:clamp(.82rem,1.4vw,1rem);line-height:1.9;letter-spacing:.04em;color:var(--ink);
  text-wrap:pretty;
}
.work-split .frame--reel{height:auto;aspect-ratio:var(--ar,9/16);cursor:default}
@media (max-width:860px){
  .work-split{grid-template-columns:1fr;padding-top:calc(var(--bar-inset) + 4.5rem)}
  .work-split__text{padding:0 var(--pad) clamp(1.2rem,4vw,2rem)}
}

/* ---------- film, then the words ----------
   A landscape film fills the width the way a frame does, and the standing
   text sits beneath it in the same measure as the other pages. */
.work-film{padding:0 0 clamp(1.5rem,4vw,3rem)}
/* the base head floats over the page; here it simply sits above the film */
.work-film .work__head{position:static;padding:0 var(--pad) clamp(1.1rem,3vw,1.8rem)}
.work-film .frame--wide{width:100%;height:auto;margin:0;aspect-ratio:var(--ar,16/9);cursor:default}
.work-film__text{
  max-width:62ch;margin:0 auto;
  padding:clamp(1.6rem,4vw,2.6rem) var(--pad) 0;
  display:flex;flex-direction:column;align-items:flex-start;
}
.work-film__text p{
  margin:0 0 1.4em;
  font-size:clamp(.82rem,1.4vw,1rem);line-height:1.9;letter-spacing:.04em;color:var(--ink);
  text-wrap:pretty;
}

/* ---------- about: one full-bleed frame, the words over its top corner ---------- */
/* The photograph keeps its own proportions rather than being cropped to fill
   the viewport, so the whole car stays in frame; the words then run down the
   left of it from the bar to the lower edge instead of bunching at the top. */
.about{position:relative;display:block;background:var(--bg-2);padding-top:calc(var(--bar-inset) + 4.6rem)}
.about__img{
  /* between the two extremes: taller than the frame's own proportions so it
     holds the screen, but far short of a full-height crop, so the car stays in */
  display:block;width:100%;height:min(86svh,64vw);
  object-fit:cover;object-position:center;
}
/* a soft wash under the corner only, so the type holds without flattening
   the whole photograph */
.about::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,rgba(8,8,10,.8) 0%,rgba(8,8,10,.45) 30%,rgba(8,8,10,0) 58%);
}
.about__text{
  position:absolute;z-index:2;
  top:50%;transform:translateY(-50%);
  left:calc(var(--bar-inset) + var(--bar-gutter));
  max-width:34ch;
  display:flex;flex-direction:column;
  pointer-events:none;
}
.about__name{
  margin:0 0 clamp(.9rem,2vw,1.4rem);
  font-family:var(--serif);font-weight:400;font-style:normal;
  font-size:clamp(1.05rem,2.25vw,1.68rem);line-height:1.1;letter-spacing:.06em;white-space:nowrap;
  color:var(--ink-bright);
}
.about__text p + p{margin-top:1.1em}
/* the marks sit under the words with the same air above and below them */
.about__marks{
  display:flex;align-items:center;gap:clamp(1.4rem,3vw,2.2rem);
  margin:clamp(.8rem,1.75vw,1.3rem) 0 clamp(1.6rem,3.5vw,2.6rem);
}
.about__marks svg{width:auto;fill:var(--ink-bright);display:block}
/* Both marks are drawn inside a square box, but Sony's is a thin wordmark and
   Adobe's a full-height glyph, so matching their box heights would leave the
   Sony letters unreadable. They are sized optically instead. */
.about__mark--sony{height:clamp(58px,10vw,86px);margin-left:-.35em}
.about__mark--adobe{height:clamp(17px,2.6vw,25px)}

.about__text p{
  margin:0;color:var(--ink-bright);
  font-size:clamp(.58rem,.98vw,.7rem);line-height:1.9;letter-spacing:.04em;
  text-wrap:pretty;
}
@media (max-width:860px){
  /* the photograph is only a few hundred pixels tall on a phone, so the words
     read beneath it rather than piling up over it */
  .about{padding-bottom:clamp(1.2rem,5vw,2rem)}
  /* a 4:3 block stood on its end, so the photograph holds the screen */
  .about__img{height:min(66svh,133vw)}
  .about::after{display:none}
  .about__text{
    position:static;transform:none;max-width:none;
    padding:clamp(1.3rem,5vw,2rem) var(--pad) 0;
    gap:clamp(1rem,4vw,1.6rem);
  }
}

.work-empty{padding:calc(var(--bar-inset) + 9rem) var(--pad) 6rem;max-width:720px;margin:0 auto}
.work-empty code{
  font-size:.82em;color:var(--ink);background:var(--bg-2);
  padding:.15em .45em;border:1px solid var(--rule);
}

@media (max-width:860px){
  /* On a phone the rail scrolls natively sideways rather than being driven by
     vertical scroll: swiping is what a thumb expects, and it avoids pinning a
     tall section that the reader has to scroll past to leave. */
  .work{height:auto!important}
  .work__sticky{
    position:static;height:auto;overflow:visible;
    padding-top:calc(var(--bar-inset) + 4.2rem);
    padding-bottom:0;
  }
  .work__rail{
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x proximity;
    scrollbar-width:none;-ms-overflow-style:none;
    -webkit-overflow-scrolling:touch;
  }
  .work__rail::-webkit-scrollbar{display:none}
  .work__track{transform:none!important;padding:0 var(--pad);gap:.75rem}
  .frame{height:58vh;scroll-snap-align:center}
  .work__head{
    position:static;padding:0 var(--pad) .9rem;font-size:.54rem;
  }
  .work__bar{position:static;margin:.9rem var(--pad) 0}
  /* a hairline of breathing room, then the footer */
  .work{padding-bottom:1.25rem}
}
@media (prefers-reduced-motion:reduce){
  .work{height:auto}
  .work__sticky{position:static;height:auto;padding:7rem 0 3rem}
  .work__rail{overflow-x:auto}
  .work__track{transform:none!important}
}


/* ---------- brand page intro ----------
   Sits above the gallery as its own screen: the horizontal rail below is a
   sticky section, so text placed inside it would be dragged sideways. */
.work-intro{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;
  max-width:62ch;margin:0 auto;
  padding:calc(var(--bar-inset) + 7rem) var(--pad) clamp(.4rem,1vw,.9rem);
}
/* with no standing text the mark is the whole block, so it centres */
.work-intro--bare{align-items:center}
/* the mark centres over the text, which stays ranged left to read */
.work-intro .work__brand{align-self:center}
.work-intro p:not(.eyebrow){
  margin:0 0 1.2em;
  font-size:clamp(.82rem,1.5vw,1rem);
  line-height:1.9;letter-spacing:.04em;color:var(--ink);
}
.work-intro p:last-child{margin-bottom:0}
@media (max-width:860px){
  .work-intro{padding:calc(var(--bar-inset) + 5.5rem) var(--pad) .5rem}
}

/* the whole tile is the link: without display:block an inline anchor wrapping
   block children gives an unreliable hit area */
.client__link{display:block;color:inherit;text-decoration:none}
.client__link:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* the header floats over the page, so an anchor jump needs clearance or the
   section lands underneath it */
#clients{scroll-margin-top:calc(var(--bar-inset) + 5.5rem)}

/* where supported, the browser also balances the remaining lines */
.work-intro p{text-wrap:pretty}
