/* ============================================================
   Get Reel WKND — skin matched to the original getreel.us
   Tokens, type scale and layout metrics lifted from the
   Webflow stylesheet so the rebuild reads as the same site.
   ============================================================ */
@font-face{font-family:"BDO Grotesk";src:url("/assets/fonts/BDOGrotesk-Light.woff2") format("woff2");
  font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:"BDO Grotesk";src:url("/assets/fonts/BDOGrotesk-Regular.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"BDO Grotesk";src:url("/assets/fonts/BDOGrotesk-Medium.woff2") format("woff2");
  font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"BDO Grotesk";src:url("/assets/fonts/BDOGrotesk-DemiBold.woff2") format("woff2");
  font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"BDO Grotesk";src:url("/assets/fonts/BDOGrotesk-Bold.woff2") format("woff2");
  font-weight:700;font-style:normal;font-display:swap}

:root{
  --black:#030303; --black-soft:#1a1a1a; --primary:#262626;
  --secondary:#dadada; --secondary-accent:#c1b9ae; --bold:#b00d23;
  --grey-medium:#9a9a9a; --grey-strong:#777; --soft:#636363; --white:#fff;

  --font:"BDO Grotesk",Arial,Helvetica,sans-serif;

  /* display scale — 11.25/7.5/4.5rem at full width, stepped down fluidly */
  --d-xl:clamp(3.25rem,10.2vw,11.25rem);
  --d-l:clamp(2.6rem,7vw,7.5rem);
  --d-m:clamp(2rem,4.4vw,4.5rem);
  --b-xl:clamp(1.2rem,1.9vw,1.5rem);
  --b-l:clamp(1.05rem,1.4vw,1.25rem);
  --b-m:1.125rem;
  --b-s:1rem;
  --b-xs:.875rem;

  --pad:30px;
  --gap-l:clamp(84px,12vw,180px);
  --gap-xl:clamp(104px,15vw,220px);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--black);color:var(--secondary);
  font-family:var(--font);font-weight:300;font-size:var(--b-m);line-height:1.6;
  -webkit-font-smoothing:antialiased;
  /* clip, not hidden: overflow-x:hidden forces overflow-y to auto, which makes
     <body> its own scroll container and stops scroll events reaching window. */
  overflow-x:clip}
img,video{display:block;max-width:100%}
/* width-only sizing must not inherit the HTML height attribute */
.nav__mark,.hero__mono{height:auto}
a{color:inherit}
h1,h2,h3,h4{margin:0;font-weight:500;letter-spacing:-.02em;line-height:1.05}
p{margin:0}
ul{margin:0;padding:0;list-style:none}

.page-padding{padding-inline:var(--pad)}
.container{width:100%;max-width:1300px;margin-inline:auto;position:relative}
.section{padding-block:var(--gap-l)}
.caps{text-transform:uppercase}
.soft{color:var(--soft)}
.accent{color:var(--secondary-accent)}

/* ---------- section marker: "/ Process"  …  "N. 03" ---------- */
.top-bar{display:flex;justify-content:space-between;width:100%;
  border-top:1px solid var(--black-soft);padding-top:20px;margin-bottom:clamp(40px,6vw,80px);
  font-size:var(--b-xs);line-height:1.25rem;font-weight:300;text-transform:uppercase;
  letter-spacing:.04em}

/* ---------- header ---------- */
.nav{position:fixed;inset:0 0 auto;z-index:90;display:flex;align-items:center;
  justify-content:space-between;padding:22px calc(var(--pad) + 18px);
  /* fully transparent: no gradient, no hairline, no shadow */
  background:transparent}
.nav__mark{display:block;width:44px;flex:0 0 auto}
/* (old .burger/.menu overlay retired — replaced by the .grn nav cluster) */

/* ---------- hero ---------- */
.hero{position:relative;min-height:100svh;display:grid;align-items:end;overflow:hidden}
.hero__frame{position:absolute;inset:0}
.hero__frame video,.hero__frame img{width:100%;height:100%;object-fit:cover}
.hero__frame::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(3,3,3,.55),rgba(3,3,3,.25) 45%,var(--black))}
.hero__mono{position:absolute;left:50%;top:50%;translate:-50% -50%;
  width:min(38vw,420px);opacity:.92;z-index:1}
.hero__say{position:relative;z-index:2;padding-block:0 clamp(56px,9vh,96px)}
.hero h1{font-size:var(--d-l);font-weight:500}
.hero__sub{margin-top:1.4rem;font-size:var(--b-l);color:var(--grey-medium);max-width:32ch}

/* ---------- generic display heading ---------- */
.display{font-size:var(--d-m);font-weight:500;max-width:20ch}
.display--wide{max-width:26ch}
.lede{font-size:var(--b-l);color:var(--grey-medium);max-width:56ch}

/* ---------- stat row ---------- */
.stats{display:flex;flex-wrap:wrap;gap:clamp(32px,6vw,90px);margin-top:clamp(44px,6vw,72px)}
.stat__n{font-size:var(--d-m);font-weight:500;line-height:1;color:var(--white)}
.stat__n sup{font-size:.42em;vertical-align:super;font-weight:400}
.stat__k{margin-top:.6rem;font-size:var(--b-s);color:var(--white)}
.stat__d{font-size:var(--b-xs);color:var(--soft)}

/* ---------- film grid ---------- */
/* Two columns at desktop, matching the original's ~641px cards in a 1300px
   container. Single column below 760px. */
.films{display:grid;grid-template-columns:1fr;
  gap:clamp(28px,3.4vw,48px) clamp(24px,2.6vw,40px)}
@media(min-width:760px){.films{grid-template-columns:1fr 1fr}}
.film a{display:block;text-decoration:none}
.film__shot{width:100%;aspect-ratio:3/2;object-fit:cover;
  transition:opacity .45s ease}
.film a:hover .film__shot{opacity:.82}
.film__row{display:flex;justify-content:space-between;align-items:baseline;
  gap:1rem;margin-top:14px}
.film__t{font-size:var(--b-l);font-weight:400;color:var(--secondary);
  transition:color .3s ease}
.film__y{font-size:var(--b-xs);color:var(--soft);letter-spacing:.04em}
.film a:hover .film__t{color:var(--white)}

/* ---------- process ---------- */
.steps{display:grid;gap:1px;background:var(--black-soft);
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-top:clamp(40px,6vw,72px)}
.step{background:var(--black);padding:clamp(26px,3vw,40px) clamp(20px,2.4vw,32px)}
.step__n{font-size:var(--b-xs);color:var(--soft);letter-spacing:.04em}
.step__t{margin-top:clamp(48px,7vw,92px);font-size:var(--b-xl);font-weight:500;color:var(--white)}

/* (old .quotes grid retired — replaced by the .grw-tcar carousel) */

/* ---------- faq ---------- */
.faq{border-top:1px solid var(--black-soft);margin-top:clamp(30px,4vw,48px)}
.faq details{border-bottom:1px solid var(--black-soft)}
.faq summary{list-style:none;cursor:pointer;padding-block:clamp(18px,2.2vw,26px);
  display:flex;justify-content:space-between;align-items:center;gap:1.5rem;
  font-size:var(--b-xl);font-weight:400;color:var(--secondary);transition:color .3s ease}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--white)}
.faq summary::after{content:"";flex:0 0 auto;width:13px;height:13px;
  background:linear-gradient(var(--grey-medium),var(--grey-medium)) center/100% 1.5px no-repeat,
             linear-gradient(var(--grey-medium),var(--grey-medium)) center/1.5px 100% no-repeat;
  transition:rotate .35s ease}
.faq details[open] summary{color:var(--white)}
.faq details[open] summary::after{rotate:45deg}
.faq__a{padding-bottom:clamp(20px,2.6vw,30px);max-width:74ch;
  font-size:var(--b-m);color:var(--grey-medium)}

/* ---------- team ---------- */
.team{display:grid;gap:clamp(30px,3.4vw,44px);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));margin-top:clamp(30px,4vw,54px)}
.member img{width:100%;aspect-ratio:3/4;object-fit:cover}
.member__t{margin-top:18px;font-size:var(--b-xl);font-weight:500;color:var(--white)}
.member__r{margin-top:.35rem;font-size:var(--b-xs);color:var(--secondary-accent)}
.member__b{margin-top:.9rem;font-size:var(--b-s);color:var(--grey-medium);line-height:1.55}
.member__n{margin-top:1.1rem;font-size:var(--b-xs);color:var(--soft)}

/* ---------- form ---------- */
.form{display:grid;gap:clamp(20px,2.4vw,28px);max-width:620px;
  margin-top:clamp(34px,4.5vw,56px)}
.form label{display:block;font-size:var(--b-xs);text-transform:uppercase;
  letter-spacing:.05em;color:var(--soft);margin-bottom:.6rem}
.form input,.form textarea{width:100%;padding:.95rem 1rem;background:transparent;
  color:var(--white);border:1px solid var(--black-soft);border-radius:0;
  font-family:inherit;font-size:var(--b-s);transition:border-color .3s ease}
.form textarea{min-height:170px;resize:vertical}
.form input:focus,.form textarea:focus{outline:none;border-color:var(--grey-strong)}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.form-note{font-size:var(--b-xs);color:var(--soft)}

/* ---------- button ---------- */
.btn{display:inline-flex;align-items:center;gap:.6rem;margin-top:1.8rem;
  padding:1rem 2.1rem;background:var(--bold);color:var(--white);text-decoration:none;
  font-size:var(--b-xs);font-weight:500;text-transform:uppercase;letter-spacing:.06em;
  border:0;cursor:pointer;font-family:inherit;transition:background .3s ease}
.btn:hover{background:#8d0a1c}
.btn--ghost{background:transparent;border:1px solid var(--grey-strong);color:var(--secondary)}
.btn--ghost:hover{background:var(--black-soft)}

/* ---------- join / footer ---------- */
/* The fanned prints translate +/-80px at rest, which reaches past a narrow
   viewport. Clip at the section so they can never widen the page. */
.join{position:relative;padding-block:var(--gap-xl);text-align:center;overflow-x:clip}
.join__say{position:relative;z-index:2}
.join__k{font-size:var(--b-xs);text-transform:uppercase;letter-spacing:.06em;color:var(--soft)}
.join h2{margin-top:1rem;font-size:var(--d-l);font-weight:500}

.foot{border-top:1px solid var(--black-soft);padding-block:clamp(40px,5vw,64px)}
.foot__grid{display:flex;flex-wrap:wrap;gap:clamp(24px,4vw,60px);
  justify-content:space-between;align-items:flex-start}
.foot a{text-decoration:none;color:var(--grey-medium);transition:color .3s ease}
.foot a:hover{color:var(--white)}
.foot__tel{font-size:var(--b-l);color:var(--white);font-weight:400}
.foot__col{display:flex;flex-direction:column;gap:.55rem;font-size:var(--b-xs);
  text-transform:uppercase;letter-spacing:.05em}
.foot__social{display:flex;gap:1.1rem;font-size:var(--b-xs);
  text-transform:uppercase;letter-spacing:.05em}
.foot__base{margin-top:clamp(30px,4vw,52px);display:flex;justify-content:space-between;
  flex-wrap:wrap;gap:1rem;font-size:var(--b-xs);color:var(--soft)}

/* ---------- scroll text fill ----------
   Letters are coloured inline by site.js, scrubbed to scroll position.
   .w keeps each word unbreakable so lines still wrap on word boundaries. */
.reveal .w{display:inline-block}
.reveal .l{color:#4f4f4f}

@media(prefers-reduced-motion:reduce){
  .reveal .l{color:var(--secondary)}
  .faq summary::after{transition:none}
}

/* ---------- cta photo fan ---------- */
.fan{position:relative;display:flex;justify-content:center;align-items:center;
  margin-top:clamp(40px,6vw,72px)}
.fan img{width:min(351px,62vw);aspect-ratio:2/3;object-fit:cover;display:block}
.fan__main{position:relative;z-index:1}
.fan__left,.fan__right{position:absolute;top:0;z-index:0;
  transform:translateX(0) rotate(0deg)}

/* ---------- narrow ---------- */
@media(max-width:640px){
  :root{--pad:20px}
  .nav__links{gap:.9rem}
  .nav__links a .n{display:none}
  .hero__mono{width:52vw}
  .foot__grid{flex-direction:column}
}


/* ============================================================
   Content additions — accent runs, about row, CTA, footer marks
   ============================================================ */

/* letters inside a marked run fill to accent red; site.js sets the ramp */
.reveal .l.hot{color:#4f4f4f}

.stat__n--accent{color:var(--bold)}

/* about section regains its image alongside the copy */
.about-row{display:grid;gap:clamp(32px,4vw,64px);align-items:start}
.about-row__img{width:100%;aspect-ratio:4/3;object-fit:cover}
@media(min-width:900px){
  .about-row{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
    gap:clamp(40px,5vw,88px);align-items:center}
}

/* "Want to Join?" now matches "Let's Talk" in size, case and weight */
.join__k--big{font-size:var(--d-l);font-weight:600;letter-spacing:-.02em;
  /* 15% tighter between "Want to Join?" and "Let's Talk" */
  line-height:.89;color:var(--secondary);text-transform:none;margin:0}
.join h2.reveal{font-weight:600;line-height:.89}

/* footer: social marks and the small centred monogram */
.foot__social a{display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;color:var(--grey-medium);transition:color .45s ease}
.foot__social a:hover{color:var(--bold)}
.foot__social svg{display:block}
.foot__col a,.foot__tel{transition:color .45s ease}
.foot__col a:hover,.foot__tel:hover{color:var(--bold)}
.foot__mark{display:block;width:41px;margin:clamp(28px,4vw,44px) auto 0}
/* the mark is a white PNG, so a red hover means recolouring it through a
   mask rather than swapping the file */
.foot__mark img{width:100%;height:auto;opacity:.72;
  transition:opacity .8s cubic-bezier(.22,.72,.2,1)}
.foot__mark{position:relative}
.foot__mark::after{content:"";position:absolute;inset:0;background:var(--bold);
  -webkit-mask:url("/assets/img/grw-logomark-light.png") center/contain no-repeat;
          mask:url("/assets/img/grw-logomark-light.png") center/contain no-repeat;
  opacity:0;transition:opacity .8s cubic-bezier(.22,.72,.2,1)}
.foot__mark:hover img{opacity:0}
.foot__mark:hover::after{opacity:1}
.foot__base{justify-content:center;text-align:center}


/* ======================================================================
   NAV CLUSTER + PAGE TRANSITION
   ====================================================================== */
/* ============================================================
   Nav cluster (.grn) + page transition (.grt)
   Appended after the existing rules. Replaces the .burger /
   .menu overlay behaviour above — once build.py stops emitting
   that markup, the .burger, .menu and .menu-open blocks
   (site.css ~lines 73-102) are dead and can be deleted.
   Every selector here is namespaced grn-/grt-; neither prefix
   appears anywhere in the existing sheet.
   ============================================================ */

/* ---------- nav cluster ----------
   Fixed to the top right on the header's own 22px / var(--pad) inset, so the
   burger's centre lands level with the logomark's. The cluster is pointer-
   transparent: only the links, the burger and an open dropdown take the
   pointer, so the hero underneath stays clickable through the gaps.
   .grn__anchor is burger-sized and everything hangs off it absolutely — that
   is what keeps the dropdown pinned directly under the burger however tall
   the hero stack gets.

   Hit-testing note, and it applies three times below: every hidden state here
   fades for .5s and only then flips to visibility:hidden. pointer-events is
   NOT animatable, so it is switched on the class instead. Without that, an
   element that has visually gone still swallows taps for half a second —
   and because pointer-events:auto on a child beats none on its parent, the
   .grn / .grn a pair cannot do it for us. */
.grn{position:fixed;top:0;right:0;z-index:95;padding:22px calc(var(--pad) + 18px) 0 0;
  pointer-events:none;-webkit-tap-highlight-color:transparent}
.grn__anchor{position:relative;width:34px;height:40px}

/* first two frames only: land in the right state instead of animating into it */
.grn.is-init,.grn.is-init *{transition:none!important;animation:none!important}

/* ---------- links: accent red at rest, white on hover ---------- */
.grn a{display:flex;align-items:center;justify-content:flex-end;min-height:40px;
  padding-left:1.4rem;text-align:right;text-decoration:none;color:var(--bold);
  pointer-events:auto;font-size:clamp(.95rem,1.05vw,1.0625rem);font-weight:600;
  line-height:1.15;letter-spacing:.06em;text-transform:uppercase;
  transition:color .5s cubic-bezier(.22,.61,.36,1)}
@media(hover:hover){.grn a:hover{color:var(--white)}}
.grn a:focus-visible{color:var(--white);outline:2px solid var(--white);outline-offset:3px}
.grn a[aria-current]{text-decoration:underline;text-underline-offset:.42em;
  text-decoration-thickness:1px}
/* touch has no hover, so every row gets a full-size target */
@media(hover:none){.grn a{min-height:44px}}

/* ---------- hero state: the stack ---------- */
.grn__hero{position:absolute;top:0;right:0;width:max-content;max-width:66vw;
  display:flex;flex-direction:column;align-items:flex-end;
  opacity:1;visibility:visible;transform:none;
  transition:opacity .72s cubic-bezier(.22,.61,.36,1),
             transform .72s cubic-bezier(.22,.61,.36,1),visibility 0s 0s}
/* 85% lighter than it was (.92/.8 -> .14/.12): the links are --bold red on
   bright footage, and at full strength the 24px black halo read as a heavy
   drop shadow rather than as legibility support. Blur and offset unchanged,
   so it keeps its shape and only loses weight. */
.grn__hero a{text-shadow:0 1px 2px rgba(3,3,3,.14),0 2px 24px rgba(3,3,3,.12)}
.grn.is-compact .grn__hero{opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .5s cubic-bezier(.4,0,.2,1),
             transform .5s cubic-bezier(.4,0,.2,1),visibility 0s .5s}
/* dead the instant the burger takes over, not .5s later: otherwise a tap
   aimed at the new burger lands on an invisible "Home" and navigates */
.grn.is-compact .grn__hero a{pointer-events:none}

/* ---------- scrolled state: the burger ---------- */
.grn__burger{position:absolute;top:9px;right:0;width:34px;height:22px;padding:0;
  border:0;background:none;cursor:pointer;pointer-events:auto;
  opacity:0;visibility:hidden;transform:translateY(-7px);
  transition:opacity .5s cubic-bezier(.4,0,.2,1),
             transform .5s cubic-bezier(.4,0,.2,1),visibility 0s .5s}
/* mirror of the rule above: the burger is painted over the first hero link,
   so while it fades out on the way back to the hero it must stop taking taps */
.grn:not(.is-compact) .grn__burger{pointer-events:none}
.grn.is-compact .grn__burger{opacity:1;visibility:visible;transform:none;
  transition:opacity .7s cubic-bezier(.22,.61,.36,1) .1s,
             transform .7s cubic-bezier(.22,.61,.36,1) .1s,visibility 0s 0s}
/* 58x48 touch target without moving the 34x22 glyph */
.grn__burger::before{content:"";position:absolute;inset:-13px -12px}
.grn__burger span{position:absolute;left:0;right:0;height:2px;border-radius:2px;
  background:var(--bold);box-shadow:0 1px 10px rgba(3,3,3,.75);
  transition:transform .55s cubic-bezier(.66,0,.34,1),opacity .38s ease,
             background-color .5s ease}
.grn__burger span:nth-child(1){top:3px}
.grn__burger span:nth-child(2){top:10px}
.grn__burger span:nth-child(3){top:17px}
@media(hover:hover){.grn__burger:hover span{background:var(--white)}}
.grn__burger:focus-visible{outline:2px solid var(--white);outline-offset:8px}
.grn__burger:focus-visible span{background:var(--white)}
.grn.is-open .grn__burger span{background:var(--white)}
.grn.is-open .grn__burger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.grn.is-open .grn__burger span:nth-child(2){opacity:0;transform:scaleX(.5)}
.grn.is-open .grn__burger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ---------- dropdown ----------
   Hangs off the burger. The 16px of top padding is deliberate: it bridges the
   gap so a mouse travelling from the burger down to the links never crosses
   dead ground and never trips the leave timer. */
.grn__drop{position:absolute;top:100%;right:0;width:max-content;
  min-width:9.5rem;max-width:min(66vw,17rem);padding:16px 0 22px;
  display:flex;flex-direction:column;align-items:flex-end;
  opacity:0;visibility:hidden;transform:translateY(-9px);pointer-events:none;
  transition:opacity .46s cubic-bezier(.4,0,.2,1),
             transform .46s cubic-bezier(.4,0,.2,1),visibility 0s .46s}
.grn.is-open .grn__drop{opacity:1;visibility:visible;transform:none;
  pointer-events:auto;
  transition:opacity .66s cubic-bezier(.22,.61,.36,1),
             transform .66s cubic-bezier(.22,.61,.36,1),visibility 0s 0s}

/* Heavy but heavily diffused: a blurred pool of black under the links plus a
   shadow on the glyphs themselves. No panel, no edge — the type stays legible
   over footage, stills or a display heading without drawing a box on the page.
   Centre and reach were tuned on the 390px about page, where the dropdown
   lands straight on top of the h1. */
.grn__drop::before{content:"";position:absolute;z-index:0;
  top:-20px;right:-32px;bottom:-40px;left:-54px;filter:blur(18px);
  background:radial-gradient(78% 80% at 76% 46%,rgba(3,3,3,.96) 0%,
    rgba(3,3,3,.9) 38%,rgba(3,3,3,.64) 62%,rgba(3,3,3,.28) 80%,rgba(3,3,3,0) 100%)}
/* pointer-events:none until open — the closed panel keeps its .46s of
   visibility, and .grn a would otherwise leave four invisible links live
   over the top of the page content directly under the burger */
.grn__drop a{position:relative;z-index:1;opacity:0;transform:translateY(-6px);
  pointer-events:none;
  /* matched to .grn__hero a above: the same four links must not carry a
     heavy shadow in the dropdown and a light one in the hero. The blurred
     pool in .grn__drop::before is what actually holds these legible over
     page content, so dropping the glyph shadow costs nothing there. */
  text-shadow:0 1px 2px rgba(3,3,3,.14),0 2px 20px rgba(3,3,3,.13),
              0 6px 40px rgba(3,3,3,.11);
  transition:opacity .42s ease,transform .42s ease,color .5s ease}
/* longhands, not the shorthand: the stagger must delay the entrance without
   also delaying the hover colour */
.grn.is-open .grn__drop a{opacity:1;transform:none;pointer-events:auto;
  transition-property:opacity,transform,color;
  transition-duration:.6s,.6s,.5s;
  transition-timing-function:cubic-bezier(.22,.61,.36,1),
    cubic-bezier(.22,.61,.36,1),ease;
  transition-delay:.05s,.05s,0s}
.grn.is-open .grn__drop a:nth-child(2){transition-delay:.11s,.11s,0s}
.grn.is-open .grn__drop a:nth-child(3){transition-delay:.17s,.17s,0s}
.grn.is-open .grn__drop a:nth-child(4){transition-delay:.23s,.23s,0s}

/* ---------- page transition ----------
   Red wipe up + white wordmark on the way out, dissolve on the way in.
   pointer-events stay off in every state, so the overlay can never take a
   click even if it is somehow left on screen. */
.grt{position:fixed;inset:0;z-index:2000;pointer-events:none;overflow:hidden;
  display:grid;place-items:center}
.grt__fade,.grt__wipe{position:absolute;inset:0}
.grt__fade{background:var(--black);opacity:0}
.grt__wipe{background:var(--bold);opacity:1;transform:translateY(101%)}
.grt__logo{position:relative;width:min(43.5vw,285px);height:auto;opacity:0;   /* 25% smaller (was 58vw/380px) */
  transform:translateY(18px)}

/* out: wipe rises, ground dims under it, wordmark lifts in */
.grt.is-out .grt__fade{opacity:.88;transition:opacity .48s ease}
.grt.is-out .grt__wipe{transform:translateY(0);
  transition:transform .62s cubic-bezier(.62,0,.28,1)}
.grt.is-out .grt__logo{opacity:1;transform:none;
  transition:opacity .46s ease .14s,transform .56s cubic-bezier(.2,.7,.3,1) .12s}

/* in: the held cover dissolves. A CSS animation rather than JS, so the page
   uncovers itself even if site.js never loads — nobody can be sealed behind
   a red screen. The .06s delay with fill:both is what paints frame one
   already covered, so there is no flash of page before the reveal. */
.grt.is-enter .grt__wipe{animation:grt-in-wipe .78s cubic-bezier(.33,0,.2,1) .06s both}
.grt.is-enter .grt__fade{animation:grt-in-fade .6s ease .06s both}
.grt.is-enter .grt__logo{animation:grt-in-logo .5s cubic-bezier(.33,0,.2,1) .08s both}
@keyframes grt-in-wipe{from{transform:translateY(0);opacity:1}
  to{transform:translateY(0);opacity:0}}
@keyframes grt-in-fade{from{opacity:.88}to{opacity:0}}
@keyframes grt-in-logo{from{opacity:1;transform:translateY(0)}
  to{opacity:0;transform:translateY(-12px)}}

/* ---------- reduced motion ----------
   Same states, no travel: the nav swaps instantly and the transition overlay
   stays out of the way entirely (site.js also stops intercepting links, so
   navigation is exactly what the browser does on its own). */
@media(prefers-reduced-motion:reduce){
  .grn,.grn *,.grn *::before{
    transition-duration:.01ms!important;transition-delay:0s!important;
    animation-duration:.01ms!important;animation-delay:0s!important}
  .grt,.grt *{animation:none!important;transition:none!important}
  .grt__wipe{transform:translateY(101%)!important}
  .grt__fade,.grt__logo{opacity:0!important}
}


/* ======================================================================
   HERO GRW CHOREOGRAPHY + GLOBAL FEEL
   ====================================================================== */
/* ============================================================
   GRW hero choreography + global feel
   Appended to site.css. Later rules deliberately override the
   .nav, .hero__frame::after and .hero h1 declarations above.
   All new class names are namespaced grwx* / grw-*.
   ============================================================ */

/* ---------- (A) header: spelled-out wordmark ---------- */
/* 908x104 artwork; ~17-21px cap height in the bar, matching the old
   44px monogram optically. */
.nav__mark{width:clamp(138px,17vw,182px);height:auto}

/* ---------- (C) hard edges ---------- */
/* Gradient fade under the nav is gone; a barely-there drop shadow keeps the
   bar legible over bright footage without drawing a visible edge. */
.nav{background:none;}
/* Hero scrim is now flat, so the hero meets the next section on a hard edge.
   Kept as a uniform tint (not removed) so the headline stays legible. */
.hero__frame::after{background:rgba(3,3,3,.30)}   /* was .42: footage reads clearer */

/* ---------- (B) hero: monogram -> headline choreography ---------- */
:root{--grwx-gap:clamp(12px,1.8vh,26px);
  /* Shared by the mark's lift AND the copy's rise, so the two can never
     drift apart again — see .grwx-stage and .grwx-stage .hero__text. */
  --grwx-move:2.15s;
  --grwx-ease:cubic-bezier(.65,0,.35,1);   /* easeInOutCubic */
}

/* .hero__say keeps its existing rules; .grwx-stage is the positioning
   context. Stage height == monogram height, so at rest the monogram sits
   hard against the bottom of the video. */
.grwx-stage{position:relative;
  /* ONE curve for the whole reveal. The old cubic-bezier(.16,.9,.22,1) was
     49% travelled at 10% of its duration and 75% at 20%: the mark snapped
     into place in ~380ms and then crept through the remaining 1.5s, which is
     exactly why it read as a POP followed by a separate fade. easeInOutCubic
     is even -- slow off the mark, a gentle middle, a long settle. The copy
     below shares this duration and curve with NO delay, so the mark rising
     and the headline rising are literally the same motion. */
  transition:transform var(--grwx-move) var(--grwx-ease)}

/* 10% smaller than the old .hero__mono (420 -> 378px, 38vw -> 34.2vw). */
.grwx{position:relative;display:block;width:min(34.2vw,378px);
  margin:0 auto;padding:0;border:0;background:none;color:inherit;font:inherit;
  line-height:0;cursor:pointer;touch-action:manipulation;
  -webkit-tap-highlight-color:transparent}
.grwx:focus-visible{outline:2px solid var(--white);outline-offset:14px}
.grwx__base{display:block;width:100%;height:auto;opacity:.92;
  transition:opacity 1.2s cubic-bezier(.22,.72,.2,1)}
.grwx:hover .grwx__base,.grwx:focus-visible .grwx__base{opacity:1}

/* The sweep reads through the glyph, not behind it: the PNG's own alpha is
   the mask, and a soft-topped red wash slides up underneath it. Only a
   transform animates, so it stays on the compositor. */
.grwx__fill{position:absolute;inset:0;pointer-events:none;
  -webkit-mask-image:url("/assets/img/grw-logomark-light.png");
          mask-image:url("/assets/img/grw-logomark-light.png");
  -webkit-mask-size:100% 100%;mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:50% 50%;mask-position:50% 50%}
/* No mask support means no glyph-shaped clip, and the wash would paint as a
   plain red slab over the mark. Drop it; click still reveals the copy. */
@supports not ((mask-image:linear-gradient(#000,#000)) or
               (-webkit-mask-image:linear-gradient(#000,#000))){
  .grwx__fill{display:none}
}
/* The wash is twice the height of the mark and hangs a full mark-height
   above it, so its solid half is exactly the mark when --grwx-y is 0 and
   clears it entirely (soft edge included) at 65%. */
.grwx__wash{position:absolute;left:0;right:0;top:-100%;height:200%;
  background:linear-gradient(to top,var(--bold) 0,var(--bold) 50%,transparent 60%);
  transform:translate3d(0,var(--grwx-y,65%),0);will-change:transform}

/* (the discoverability hint was removed — the interaction is unlabelled
   by design) */

/* Headline + sub start hidden. Absolutely positioned just under the mark, so
   the mark can sit at the bottom of the frame with nothing reserved below it.
   Kept in the accessibility tree (opacity, not visibility) so the h1 is still
   announced and indexed before the reveal.
   SCOPED to .grwx-stage: if the stage markup is ever missing or renamed, the
   copy is simply a normal static block instead of an invisible one. */
.grwx-stage .hero__text{position:absolute;left:0;right:0;
  top:calc(100% + var(--grwx-gap));
  opacity:0;pointer-events:none;transform:translateY(26px);
  /* the flat .42 scrim is thin over bright footage; this keeps the grey sub
     legible without reintroducing the gradient */
  text-shadow:0 1px 22px rgba(3,3,3,.72);
  /* No delay, and the SAME duration and curve as the stage lift above: that
     .34s delay is what made the copy arrive as a second, separate beat once
     the mark had already moved. The 26px is the copy's own extra rise,
     riding the same curve, so the two travel in lockstep. The fade runs a
     little shorter so the words are legible as they land rather than still
     materialising. */
  transition:opacity 1.75s var(--grwx-ease),
             transform var(--grwx-move) var(--grwx-ease)}

/* Revealed: JS lifts .grwx-stage by exactly (gap + text height), so the mark
   slides up and the copy rises into the space it vacated. */
.grwx-stage.is-open .hero__text{opacity:1;transform:none;pointer-events:auto}
.grwx-stage.is-open .grwx{cursor:default}
/* Safety-net reveal (hero scrolled away un-revealed): land as a static state
   rather than animating a stack nobody is looking at. */
.grwx-stage.is-instant,
.grwx-stage.is-instant .hero__text,
.grwx-stage.is-instant .hero__text{transition:none}

/* h1 is 25% smaller than --d-l (7.5 -> 5.625rem, 7 -> 5.25vw). */
.hero h1{font-size:clamp(1.95rem,5.25vw,5.625rem)}

/* No JS, JS that never loaded, or a JS failure: the hero is simply the
   static, fully visible one. */
.no-js .grwx-stage .hero__text,
.grwx-fallback .grwx-stage .hero__text{position:static;opacity:1;
  transform:none;pointer-events:auto;margin-top:var(--grwx-gap);
  transition:none}
.no-js .grwx-stage,.grwx-fallback .grwx-stage{transform:none;transition:none}
.no-js .grwx,.grwx-fallback .grwx{cursor:default}
.no-js .grwx__hint,.grwx-fallback .grwx__hint{display:none}
.no-js .grwx__fill,.grwx-fallback .grwx__fill{display:none}

/* ---------- hero sizing ---------- */
@media(max-width:640px){.grwx{width:min(46.8vw,378px)}}
/* Short and landscape viewports: cap the mark by height so the revealed
   stack always clears the fold. Combined with the narrow rule so a short
   PHONE keeps the phone width and only picks up the height cap. */
@media(max-height:720px){.grwx{width:min(38vw,378px,34svh)}}
@media(max-width:640px) and (max-height:720px){.grwx{width:min(46.8vw,34svh)}}
/* Landscape phones: mark + gap + two-line h1 + two-line sub + the hero's
   bottom padding otherwise runs the stack up under the fixed nav. */
@media(max-height:560px){
  :root{--grwx-gap:10px}
  .hero__say{padding-block:0 clamp(20px,4vh,44px)}
  .grwx{width:min(30vw,26svh)}
  .hero h1{font-size:clamp(1.5rem,3.4vw,2.6rem)}
  .hero__sub{margin-top:.9rem}
  .grwx:focus-visible{outline-offset:8px}
}

@media(prefers-reduced-motion:reduce){
  .grwx-stage,.grwx-stage .hero__text,.grwx__base{transition:none}
}

/* (the SVG accent cursor was replaced by the .grwc red dot cursor below) */

/* ---------- (D) smooth scroll ---------- */
/* No scroll-behavior:smooth here on purpose: the JS glide drives the real
   scroll position frame by frame, and a CSS smooth behaviour would animate
   every one of those calls against it. */
html{scroll-padding-top:clamp(84px,12vh,112px)}


/* ======================================================================
   FAQ ACCORDION + PROCESS REVEAL
   ====================================================================== */
/* ============================================================
   FAQ accordion (.grw-acc) + process step reveal (.grw-steps)
   Appended to site.css. Every selector is grw-* namespaced except
   two scoped overrides (.grw-steps .step / .grw-steps .step__t),
   which only bite when the new class is present.

   NOTE: once build.py emits .grw-acc the old block at
   "/* ---------- faq ---------- *\/" (.faq, .faq details, .faq
   summary…, .faq__a) and the ".faq summary::after" line in the
   prefers-reduced-motion block are dead and can be deleted.

   Two build.py changes go with this file:
     1. the FAQ button ships aria-expanded="true" — that is the
        truth with JS off; site.js flips it to false as it parks.
     2. optional, kills the load flash: add
        <script>document.documentElement.className+=' js'</script>
        as the first line of <head> in head().
   ============================================================ */
:root{
  /* long, soft, no snap — one curve shared by both components */
  --grw-ease:cubic-bezier(.22,.72,.16,1);
  --grw-acc-dur:.68s;      /* site.js reads this back off the panel */
  --grw-step-dur:.9s;
  --grw-stagger:.3s;
}

/* ---------- FAQ accordion ---------- */
/* overflow-anchor:none — site.js pins the tapped question itself while the
   previous answer collapses above it; browser scroll anchoring would
   correct the same shift a second time and overshoot. */
.grw-acc{border-top:1px solid var(--black-soft);margin-top:clamp(30px,4vw,48px);
  overflow-anchor:none}
.grw-acc__item{border-bottom:1px solid var(--black-soft);
  transition:border-color var(--grw-acc-dur) var(--grw-ease)}
.grw-acc__item.is-open{border-bottom-color:var(--primary)}

/* the <h2> wrapper is structure only — the button carries the type */
.grw-acc__h{margin:0;font:inherit;font-weight:inherit;letter-spacing:normal;
  line-height:inherit}

.grw-acc__btn{display:flex;width:100%;align-items:center;justify-content:space-between;
  gap:1.25rem;min-height:56px;margin:0;padding:clamp(18px,2.2vw,26px) 0;
  background:none;border:0;border-radius:0;text-align:left;cursor:pointer;
  font-family:inherit;font-size:var(--b-xl);font-weight:400;line-height:1.3;
  color:var(--secondary);-webkit-tap-highlight-color:transparent;
  transition:color .45s var(--grw-ease)}
.grw-acc__btn[aria-expanded="true"]{color:var(--white)}
/* white, not --bold: #b00d23 on #030303 is 2.85:1, under the 3:1 that
   WCAG 1.4.11 asks of a focus indicator. This is the site's only real one. */
.grw-acc__btn:focus-visible{outline:2px solid var(--white);outline-offset:3px}
.grw-acc__q{display:block;min-width:0}

/* plus that melts into a minus while it turns */
.grw-acc__icon{position:relative;flex:0 0 auto;width:14px;height:14px;
  color:var(--grey-medium);
  transition:rotate .7s var(--grw-ease),color .5s var(--grw-ease)}
.grw-acc__icon::before,.grw-acc__icon::after{content:"";position:absolute;
  background:currentColor;
  transition:transform .7s var(--grw-ease),opacity .55s var(--grw-ease)}
.grw-acc__icon::before{left:0;right:0;top:50%;height:1.5px;margin-top:-.75px}
.grw-acc__icon::after{top:0;bottom:0;left:50%;width:1.5px;margin-left:-.75px}
.grw-acc__btn[aria-expanded="true"] .grw-acc__icon{rotate:180deg;color:var(--bold)}
.grw-acc__btn[aria-expanded="true"] .grw-acc__icon::after{transform:scaleY(0);opacity:0}

/* Hover latches on iOS after a tap and leaves a closed question wearing the
   open colour, so keep it to real pointers. */
@media(hover:hover){
  .grw-acc__btn:hover{color:var(--white)}
}

/* Default = every answer open. site.js adds .is-ready, so with JS off or
   broken the FAQ is still a readable list rather than five dead buttons.
   clip, not hidden, for the same reason body uses it: a hidden box is a
   scroll container, and focus landing inside a part-collapsed panel can
   scroll it internally and leave the content permanently offset. */
.grw-acc__panel{overflow:hidden;overflow:clip}
.grw-acc__inner{padding-bottom:clamp(20px,2.6vw,30px);max-width:74ch;
  font-size:var(--b-m);color:var(--grey-medium)}

/* Opt-in: with the one-line <head> snippet above, the FAQ paints collapsed on
   the first frame instead of painting five open answers and snapping shut
   when the deferred site.js finally lands. Inert if you skip the snippet. */
html.js .grw-acc:not(.is-ready) .grw-acc__panel{height:0}

.grw-acc.is-ready .grw-acc__panel{height:0;
  transition:height var(--grw-acc-dur) var(--grw-ease)}
.grw-acc.is-ready .grw-acc__inner{opacity:0;transform:translateY(-8px);
  transition:opacity .3s ease,transform .3s var(--grw-ease)}
.grw-acc.is-ready .grw-acc__item.is-open .grw-acc__inner{opacity:1;transform:none;
  transition:opacity .52s ease .12s,transform .66s var(--grw-ease) .06s}

/* ---------- process: thin icon between the number and the label ---------- */
.grw-steps .step{display:flex;flex-direction:column;
  min-height:clamp(200px,23vw,272px)}
.grw-steps .step__t{margin-top:0}
.grw-step-icon{margin-top:auto;padding-top:clamp(26px,6vw,44px);
  margin-bottom:clamp(16px,1.9vw,24px);line-height:0;
  color:var(--secondary-accent);transition:color .6s var(--grw-ease)}
.grw-step-icon svg{display:block;width:clamp(30px,3.2vw,38px);height:auto}
@media(hover:hover){
  .grw-steps .step:hover .grw-step-icon{color:var(--bold)}
}

/* Four cards need a 943px viewport to sit on one row under .steps'
   auto-fit minmax(220px,1fr); from 641px up to there you get 3 + a lone
   orphan, and min-height turns that orphan into a tall empty slab.
   Scoped to .grw-steps, so any other .steps grid is untouched. */
@media(min-width:641px) and (max-width:959px){
  .grw-steps{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---------- process: staggered fade-in ----------
   The card itself must not fade: .steps paints its 1px hairlines with a
   --black-soft background behind the black cards, so fading a .step would
   expose a grey slab. The three children move as one block instead.

   --grw-i is set inline by site.js from the position within the batch of
   cards that crossed the threshold together — NOT from :nth-child. On a
   phone the cards are stacked and enter one at a time, and an nth-child
   delay left card 4 blank on screen for 0.9s before it started to fade. */
html.grw-anim .grw-steps .step > *{opacity:0;transform:translateY(22px);
  transition:opacity var(--grw-step-dur) var(--grw-ease),
             transform var(--grw-step-dur) var(--grw-ease);
  transition-delay:calc(var(--grw-i,0) * var(--grw-stagger))}
html.grw-anim .grw-steps .grw-in > *{opacity:1;transform:none}

/* ---------- reduced motion: same states, no travel ---------- */
@media(prefers-reduced-motion:reduce){
  .grw-acc__item,.grw-acc__btn,.grw-acc__icon,
  .grw-acc__icon::before,.grw-acc__icon::after,
  .grw-acc.is-ready .grw-acc__panel,
  .grw-acc.is-ready .grw-acc__inner,
  .grw-acc.is-ready .grw-acc__item.is-open .grw-acc__inner,
  .grw-step-icon{transition:none}
  html.grw-anim .grw-steps .step > *{opacity:1;transform:none;transition:none}
}

/* ---------- narrow ---------- */
@media(max-width:640px){
  /* stacked cards: let each one be as short as its content */
  .grw-steps .step{min-height:0}
  .grw-step-icon{padding-top:clamp(22px,7vw,34px)}
  .grw-acc__btn{gap:1rem}
}


/* ======================================================================
   TESTIMONIAL CAROUSEL + COUNTERS
   ====================================================================== */
/* ============================================================
   Testimonial carousel + count-up stat tickers
   Append after the existing "Content additions" block.

   HOUSEKEEPING: once build.py emits the carousel, the old
   "---------- testimonials ----------" rules (.quotes, .quote,
   .quote__n, .quote__p, .quote__who) are dead — delete them.
   ============================================================ */

.grw-tcar{
  /* site.js mirrors this duration as DUR — change the two together */
  --grw-tcar-dur:.95s;
  --grw-tcar-ease:cubic-bezier(.16,1,.3,1);
  margin-top:clamp(40px,6vw,72px);
  display:grid;gap:clamp(26px,4vw,44px)}
@media(min-width:900px){
  .grw-tcar{grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    align-items:end;gap:clamp(40px,5vw,80px)}
}

/* screen-reader-only announcer, injected by site.js.
   position:absolute keeps it out of flow so it never becomes a grid item. */
.grw-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* ---------- the window the cards ride inside ----------
   Square at rest, but the cards are grid-STACKED in one cell rather than
   absolutely positioned, so the window grows when a card needs more room —
   a longer testimonial in build.py, or a visitor running text at 150%+ — and
   a quote can never be silently guillotined by the frame.

   overflow-x:CLIP, never hidden. overflow-x:hidden coerces overflow-y to auto
   and turns this into a scroll container; that is the same trap that cost this
   codebase its scroll events on <body>. clip has no such side effect. */
.grw-tcar__stage{position:relative;width:min(100%,560px);
  display:grid;grid-template-columns:100%;
  overflow-x:clip;overflow-y:visible;background:var(--black);
  /* pan-y AND pinch-zoom: we own horizontal drags only. Bare pan-y also takes
     pinch-to-zoom away from the visitor, which is a WCAG 1.4.4 problem. */
  touch-action:pan-y pinch-zoom;-webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent}
/* the square floor. align-self:start stops it stretching, so it SETS the row
   height instead of inheriting whatever the cards worked out. */
.grw-tcar__stage::before{content:"";grid-area:1/1;align-self:start;
  width:100%;aspect-ratio:1/1;pointer-events:none}
.grw-tcar__stage:focus-visible{outline:2px solid var(--secondary-accent);
  outline-offset:4px}

.grw-tcar__card{grid-area:1/1;position:relative;min-width:0;margin:0;
  display:flex;flex-direction:column;padding:clamp(24px,3.4vw,44px);
  background:var(--bold);color:var(--white);
  transform:translate3d(110%,0,0)}
/* before JS boots (and with JS off) card one rests in the window,
   the others sit outside it — never a stack of three on top of each other */
.grw-tcar__card:first-child{transform:translate3d(0,0,0);z-index:2}
.grw-tcar__stage.is-sliding .grw-tcar__card{
  transition:transform var(--grw-tcar-dur) var(--grw-tcar-ease)}
.grw-tcar__stage.is-sliding .grw-tcar__card,
.grw-tcar__stage.is-dragging .grw-tcar__card{will-change:transform}

.grw-tcar__n{font-size:var(--b-xs);letter-spacing:.04em;opacity:.62}
.grw-tcar__q{margin:clamp(26px,5vw,52px) 0 0;font-size:var(--b-xl);
  font-weight:400;line-height:1.35;letter-spacing:-.01em;text-wrap:pretty}
/* a 560px square wants more than body-copy scale — derived from the token,
   not a second hand-rolled ramp */
@media(min-width:900px){.grw-tcar__q{font-size:calc(var(--b-xl) * 1.3)}}
.grw-tcar__who{margin-top:auto;padding-top:1.4rem;font-size:var(--b-xs);
  line-height:1.5;letter-spacing:.05em;text-transform:uppercase;opacity:.62}

/* ---------- controls ---------- */
/* Hidden until site.js adds .is-live: the button does nothing without JS,
   and visibility (not just opacity) keeps it out of the tab order. */
.grw-tcar__ctrls{display:flex;align-items:center;justify-content:space-between;
  gap:clamp(16px,3vw,28px);width:min(100%,560px);
  opacity:0;visibility:hidden;
  transition:opacity .7s var(--grw-tcar-ease),visibility 0s .7s}
.grw-tcar.is-live .grw-tcar__ctrls{opacity:1;visibility:visible;
  transition:opacity .7s var(--grw-tcar-ease),visibility 0s 0s}
@media(min-width:900px){
  .grw-tcar__ctrls{flex-direction:column;align-items:flex-start;width:auto;
    gap:clamp(22px,3vw,34px)}
}

.grw-tcar__count{font-size:var(--b-xs);letter-spacing:.06em;
  text-transform:uppercase;color:var(--soft);font-variant-numeric:tabular-nums}
.grw-tcar__i{color:var(--white)}

.grw-tcar__next{position:relative;flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;
  width:clamp(58px,8vw,84px);aspect-ratio:1/1;padding:0;
  border:1px solid var(--white);border-radius:50%;background:transparent;
  color:var(--white);font-family:inherit;cursor:pointer;overflow:hidden;
  -webkit-tap-highlight-color:transparent}
/* the fill — a red disc that grows in, and eases back out on leave/release */
.grw-tcar__next::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:var(--bold);transform:scale(.25);opacity:0;
  transition:transform .75s var(--grw-tcar-ease),
             opacity .75s var(--grw-tcar-ease)}
.grw-tcar__next svg{position:relative;width:34%;height:auto;
  transition:transform .75s var(--grw-tcar-ease)}
/* hover is gated so a tap on a phone can never leave the fill stuck on */
@media(hover:hover){
  .grw-tcar__next:hover::before{transform:scale(1);opacity:1}
  .grw-tcar__next:hover svg{transform:translateX(16%)}
}
.grw-tcar__next:active::before,
.grw-tcar__next:focus-visible::before{transform:scale(1);opacity:1}
.grw-tcar__next:focus-visible{outline:2px solid var(--secondary-accent);
  outline-offset:5px}

/* ---------- count-up stat tickers ---------- */
/* site.js sets min-width in ch so the row cannot reflow while digits are
   still arriving. The 90% figure takes its red from .stat__n--accent. */
.grw-tick{display:inline-block;font-variant-numeric:tabular-nums}

@media(prefers-reduced-motion:reduce){
  /* the slide, the fill and the controls reveal all collapse to a state
     change — the carousel and the counters still work */
  .grw-tcar__stage.is-sliding .grw-tcar__card,
  .grw-tcar__ctrls,.grw-tcar.is-live .grw-tcar__ctrls,
  .grw-tcar__next::before,.grw-tcar__next svg{
    transition-duration:1ms;transition-delay:0s}
}


/* ======================================================================
   FILM HOVER PREVIEW + THEATER
   ====================================================================== */
/* ============================================================
   Film preview + theater player           (namespace: .grw-*)
   Mobile first: under 861px the player is a full-screen sheet
   with the controls in flow under the picture. The overlay-and-
   fade behaviour, the 4s dwell and the up-next crop are the
   desktop layer on top of that.

   Scroll safety: the only overflow this file sets outside its own
   boxes is html.grw-lock, which is the same lock the nav overlay
   already uses (.menu-open). Nothing touches overflow on <body>.
   ============================================================ */
:root{
  --grw-ease:cubic-bezier(.22,.61,.36,1);
  --grw-ease-both:cubic-bezier(.5,0,.2,1);
  --grw-fast:.45s;
  --grw-mid:.72s;
  --grw-slow:1.05s;
  --grw-rail:clamp(168px,20vw,272px);
  --grw-rail-gap:18px;
}

.grw-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
html.grw-lock{overflow:hidden}

/* ---------- film card ---------- */
.grw-fc{position:relative}
.grw-fc__link{display:block;text-decoration:none;color:inherit}
.grw-fc__link:focus-visible{outline:2px solid var(--bold);outline-offset:4px}
.grw-fc__media{position:relative;display:block;width:100%;aspect-ratio:3/2;
  overflow:hidden;background:var(--black-soft)}
.grw-fc__poster,.grw-fc__prev{position:absolute;inset:0;display:block;
  width:100%;height:100%;object-fit:cover}
.grw-fc__poster{transition:opacity var(--grw-mid) var(--grw-ease),
  transform 1.2s var(--grw-ease)}
.grw-fc__prev{opacity:0;pointer-events:none;
  transition:opacity var(--grw-mid) var(--grw-ease),transform 1.2s var(--grw-ease)}
/* Crossfade only ever runs when a preview file actually exists. */
.grw-fc.has-prev.is-hot .grw-fc__prev,
.grw-fc.has-prev.is-live .grw-fc__prev{opacity:1}
.grw-fc.has-prev.is-hot .grw-fc__poster,
.grw-fc.has-prev.is-live .grw-fc__poster{opacity:0}
.grw-fc.is-hot .grw-fc__poster,.grw-fc.is-hot .grw-fc__prev{transform:scale(1.035)}

.grw-fc__row{display:flex;justify-content:space-between;align-items:baseline;
  gap:1rem;margin-top:14px}
.grw-fc__t{font-size:var(--b-l);font-weight:400;color:var(--secondary);
  transition:color var(--grw-mid) var(--grw-ease)}
.grw-fc__y{font-size:var(--b-xs);color:var(--soft);letter-spacing:.04em}
.grw-fc.is-hot .grw-fc__t{color:var(--bold)}

/* Dwell meter — the 4s countdown into theater mode, drawn as a hairline. */
.grw-fc__dwell{position:absolute;left:0;right:0;bottom:0;height:2px;
  background:rgba(255,255,255,.14);opacity:0;
  transition:opacity var(--grw-fast) var(--grw-ease)}
.grw-fc.is-dwelling .grw-fc__dwell{opacity:1}
.grw-fc__dwellbar{display:block;height:100%;width:0;background:var(--bold);
  transition:width var(--grw-fast) var(--grw-ease)}
.grw-fc.is-dwelling .grw-fc__dwellbar{width:100%;transition:width 4s linear}

/* ---------- theater shell ---------- */
.grw-theater{position:fixed;inset:0;z-index:120;display:flex;
  align-items:center;justify-content:center;
  overscroll-behavior:contain;
  opacity:0;visibility:hidden;
  transition:opacity var(--grw-slow) var(--grw-ease),visibility 0s var(--grw-slow)}
.grw-theater.is-open{opacity:1;visibility:visible;
  transition:opacity var(--grw-slow) var(--grw-ease),visibility 0s 0s}
.grw-theater__veil{position:absolute;inset:0;background:rgba(3,3,3,.9)}
/* Desktop only: under 861px the stage is an opaque full-screen sheet, so a
   viewport-sized blur behind it is pure GPU cost for pixels nobody sees. */
@media(min-width:861px){
  @supports (backdrop-filter:blur(4px)) or (-webkit-backdrop-filter:blur(4px)){
    .grw-theater__veil{background:rgba(3,3,3,.84);
      -webkit-backdrop-filter:blur(8px) saturate(.8);backdrop-filter:blur(8px) saturate(.8)}
  }
}

.grw-theater__stage{position:relative;display:flex;flex-direction:column;
  width:100%;height:100vh;height:100svh;background:var(--black);
  opacity:0;transform:scale(.97);
  transition:opacity var(--grw-slow) var(--grw-ease),transform var(--grw-slow) var(--grw-ease)}
.grw-theater.is-open .grw-theater__stage{opacity:1;transform:none}
.grw-theater__stage:focus{outline:none}
.grw-theater__stage:focus-visible{outline:1px solid rgba(218,218,218,.35);outline-offset:-1px}

.grw-theater__frame{position:relative;display:flex;flex-direction:column;
  flex:1 1 auto;min-height:0;overflow:hidden}
.grw-theater__media{position:relative;flex:0 0 auto;width:100%;aspect-ratio:16/9;
  background:#000;overflow:hidden;
  /* A 16:9 box off a 100vw width is 475px tall on a 390px-tall landscape
     phone: without this cap it eats the whole sheet and every control is
     pushed out of the (overflow:hidden) frame. object-fit does the rest. */
  max-height:60vh;max-height:60svh}
.grw-theater__still,.grw-theater__video{position:absolute;inset:0;
  width:100%;height:100%;object-fit:contain}
.grw-theater__video{opacity:1;transition:opacity var(--grw-fast) var(--grw-ease)}
.grw-theater.is-swap .grw-theater__video,
.grw-theater.is-novideo .grw-theater__video{opacity:0}
/* Held slightly dark while the up-next rail is out. */
.grw-theater__scrim{position:absolute;inset:0;background:rgba(3,3,3,.45);
  opacity:0;pointer-events:none;transition:opacity var(--grw-mid) var(--grw-ease)}
.grw-theater.is-next .grw-theater__scrim{opacity:1}

.grw-theater__x{position:absolute;top:10px;right:10px;z-index:6;
  width:48px;height:48px;display:flex;align-items:center;justify-content:center;
  padding:0;border:0;border-radius:999px;background:rgba(3,3,3,.55);
  color:var(--secondary);cursor:pointer;
  transition:color var(--grw-fast) var(--grw-ease),
    background var(--grw-fast) var(--grw-ease),transform var(--grw-fast) var(--grw-ease)}
.grw-theater__x:hover{color:var(--bold);background:rgba(3,3,3,.8)}
.grw-theater__x:focus-visible{outline:2px solid var(--bold);outline-offset:2px}
.grw-theater__x svg{width:20px;height:20px}

.grw-theater__hint{position:absolute;top:0;right:0;bottom:0;width:74px;z-index:3;
  display:none;align-items:center;justify-content:flex-end;padding-right:10px;
  color:var(--secondary);pointer-events:none;opacity:0;
  background:linear-gradient(90deg,transparent,rgba(3,3,3,.5));
  transition:opacity var(--grw-mid) var(--grw-ease)}
.grw-theater__hint svg{width:22px;height:22px}

/* ---------- controls + copy ---------- */
.grw-theater__ui{position:relative;z-index:4;flex:1 1 auto;min-height:0;
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  display:flex;flex-direction:column;gap:clamp(16px,2.4vw,24px);
  padding:clamp(18px,4vw,32px) clamp(18px,4vw,34px) clamp(22px,5vw,34px)}
.grw-theater__meta{display:flex;flex-direction:column;gap:.7rem;
  transition:opacity var(--grw-fast) var(--grw-ease)}
.grw-theater.is-swap .grw-theater__meta{opacity:0}
.grw-theater__k{font-size:var(--b-xs);letter-spacing:.06em;color:var(--soft);
  text-transform:uppercase}
.grw-theater__t{font-size:clamp(1.6rem,4.4vw,2.4rem);font-weight:500;color:var(--white)}
.grw-theater__d{font-size:var(--b-s);color:var(--grey-medium);max-width:56ch;line-height:1.55}

.grw-cta{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:.5rem}

.grw-btn{display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  min-height:48px;padding:0 1.5rem;border:1px solid var(--grey-strong);
  background:transparent;color:var(--secondary);font-family:inherit;
  font-size:var(--b-xs);font-weight:500;letter-spacing:.08em;text-transform:uppercase;
  text-decoration:none;cursor:pointer;
  transition:color var(--grw-fast) var(--grw-ease),
    border-color var(--grw-fast) var(--grw-ease),
    background var(--grw-fast) var(--grw-ease),opacity var(--grw-mid) var(--grw-ease)}
.grw-btn:hover{color:var(--bold);border-color:var(--bold)}
.grw-btn:focus-visible{outline:2px solid var(--bold);outline-offset:3px}
.grw-btn--solid{background:var(--bold);border-color:var(--bold);color:var(--white)}
.grw-btn--solid:hover{background:#8d0a1c;border-color:#8d0a1c;color:var(--white)}
/* "Play film" has done its job once the sound is on — it fades, it never pops. */
.grw-theater.is-cta-done .grw-cta__play{opacity:0;visibility:hidden;
  transition:opacity var(--grw-mid) var(--grw-ease),visibility 0s var(--grw-mid)}

/* actor access: button -> input -> red download, all in one cell */
.grw-access{display:flex;flex-direction:column;gap:.5rem}
.grw-access__slot{display:grid}
.grw-access__slot > *{grid-area:1/1}
.grw-morph{opacity:0;visibility:hidden;transform:translateY(5px);
  transition:opacity var(--grw-mid) var(--grw-ease),
    transform var(--grw-mid) var(--grw-ease),visibility 0s var(--grw-mid)}
.grw-access[data-state="btn"] .grw-access__open,
.grw-access[data-state="form"] .grw-access__form,
.grw-access[data-state="dl"] .grw-access__dl{opacity:1;visibility:visible;transform:none;
  transition:opacity var(--grw-mid) var(--grw-ease),
    transform var(--grw-mid) var(--grw-ease),visibility 0s 0s}
.grw-access__form{display:flex;align-items:stretch;gap:0}
/* 11ch is the width of eleven zeros and ignores letter-spacing entirely, so
   a five-character code plus .34em tracking plus 1.8rem of padding scrolled
   out of view as it was typed. Sized off the real content instead. */
.grw-access__input{min-width:0;width:9.5rem;height:48px;padding:0 .9rem;
  background:transparent;border:1px solid var(--grey-strong);border-right:0;
  color:var(--white);font-family:inherit;font-size:var(--b-s);
  letter-spacing:.34em;text-transform:uppercase;
  transition:border-color var(--grw-fast) var(--grw-ease)}
.grw-access__input::placeholder{color:var(--soft);letter-spacing:.2em}
.grw-access__input:focus{outline:none;border-color:var(--bold)}
.grw-access__go{width:48px;height:48px;flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;padding:0;
  border:1px solid var(--grey-strong);background:transparent;color:var(--secondary);
  cursor:pointer;transition:color var(--grw-fast) var(--grw-ease),
    border-color var(--grw-fast) var(--grw-ease)}
.grw-access__go:hover{color:var(--bold);border-color:var(--bold)}
.grw-access__go:focus-visible{outline:2px solid var(--bold);outline-offset:2px}
.grw-access__go svg{width:18px;height:18px}
.grw-access__form.is-busy{opacity:.55;pointer-events:none}
.grw-access__msg{font-size:var(--b-xs);color:var(--soft);min-height:1.2em;
  transition:color var(--grw-fast) var(--grw-ease)}
.grw-access__msg.is-bad{color:var(--bold)}
.grw-access.is-nope .grw-access__form{animation:grw-nope .5s var(--grw-ease-both)}
@keyframes grw-nope{
  0%,100%{transform:translateX(0)}
  25%{transform:translateX(-5px)}
  60%{transform:translateX(4px)}
}

/* transport row */
.grw-theater__bar{display:flex;flex-direction:column;gap:14px;margin-top:auto}
.grw-ctl__line{position:relative;height:22px;display:flex;align-items:center;
  cursor:pointer;touch-action:none}
/* Pinned explicitly rather than leaning on the flex static-position rule for
   an abspos pseudo — the track and the fill must not drift apart. */
.grw-ctl__line::before{content:"";position:absolute;left:0;right:0;top:50%;
  margin-top:-1px;height:2px;background:rgba(218,218,218,.22)}
.grw-ctl__fill{position:relative;height:2px;width:0;background:var(--bold);
  transition:width .3s linear,height var(--grw-fast) var(--grw-ease)}
.grw-ctl__line:hover .grw-ctl__fill,
.grw-ctl__line:focus-visible .grw-ctl__fill{height:4px}
.grw-ctl__line:focus-visible{outline:2px solid var(--bold);outline-offset:4px}
.grw-ctl__btns{display:flex;align-items:center;flex-wrap:wrap;gap:10px}
.grw-ctl__gap{flex:1 1 auto}
.grw-ctl__time{font-size:var(--b-xs);color:var(--soft);letter-spacing:.06em;
  font-variant-numeric:tabular-nums}

.grw-ic{position:relative;width:52px;height:52px;flex:0 0 auto;
  display:inline-flex;align-items:center;justify-content:center;padding:0;
  border:1px solid rgba(218,218,218,.2);border-radius:999px;
  background:rgba(3,3,3,.3);color:var(--secondary);cursor:pointer;font-family:inherit;
  transition:color var(--grw-fast) var(--grw-ease),
    border-color var(--grw-fast) var(--grw-ease),
    background var(--grw-fast) var(--grw-ease),
    transform var(--grw-fast) var(--grw-ease)}
.grw-ic:hover{color:var(--bold);border-color:var(--bold)}
.grw-ic:active{transform:scale(.94)}
.grw-ic:focus-visible{outline:2px solid var(--bold);outline-offset:3px}
.grw-ic svg{position:absolute;width:24px;height:24px;
  transition:opacity var(--grw-fast) var(--grw-ease)}
.grw-ic__b{opacity:0}
.grw-theater.is-playing .grw-ic--play .grw-ic__a{opacity:0}
.grw-theater.is-playing .grw-ic--play .grw-ic__b{opacity:1}
.grw-ic--sound .grw-ic__b{opacity:1}
.grw-ic--sound .grw-ic__a{opacity:0}
.grw-ic--sound.is-muted .grw-ic__a{opacity:1}
.grw-ic--sound.is-muted .grw-ic__b{opacity:0}
.grw-ic--fs.is-on .grw-ic__a{opacity:0}
.grw-ic--fs.is-on .grw-ic__b{opacity:1}
/* seek feedback: a ring that expands away, never a flash */
.grw-ic::after{content:"";position:absolute;inset:-1px;border-radius:999px;
  border:1px solid var(--bold);opacity:0;pointer-events:none}
.grw-ic.is-bump::after{animation:grw-bump .8s var(--grw-ease)}
@keyframes grw-bump{
  from{opacity:.9;transform:scale(1)}
  to{opacity:0;transform:scale(1.42)}
}

.grw-ctl__next{width:auto;padding:0 1.1rem;gap:.55rem;font-size:var(--b-xs);
  letter-spacing:.08em;text-transform:uppercase}
.grw-ctl__next svg{position:relative;width:14px;height:14px;
  transition:transform var(--grw-mid) var(--grw-ease)}
.grw-theater.is-next .grw-ctl__next svg{transform:rotate(90deg)}

/* ---------- up next rail ---------- */
.grw-next{flex:0 0 auto;max-height:0;overflow:hidden;opacity:0;visibility:hidden;
  background:var(--black);border-top:1px solid var(--black-soft);
  transition:max-height var(--grw-slow) var(--grw-ease),
    opacity var(--grw-mid) var(--grw-ease),visibility 0s var(--grw-slow)}
.grw-theater.is-next .grw-next{max-height:min(46vh,380px);max-height:min(46svh,380px);
  opacity:1;visibility:visible;
  transition:max-height var(--grw-slow) var(--grw-ease),
    opacity var(--grw-mid) var(--grw-ease),visibility 0s 0s}
.grw-next__k{padding:14px 18px 8px;font-size:var(--b-xs);letter-spacing:.08em;
  text-transform:uppercase;color:var(--soft)}
.grw-next__list{display:flex;flex-direction:column;gap:8px;
  max-height:min(38vh,320px);max-height:min(38svh,320px);
  overflow-y:auto;overscroll-behavior:contain;padding:0 12px 14px}
.grw-next__item{display:flex;align-items:center;gap:12px;width:100%;padding:8px;
  background:none;border:1px solid transparent;color:var(--secondary);
  font-family:inherit;text-align:left;cursor:pointer;
  opacity:0;transform:translateY(-8px);
  transition:opacity var(--grw-fast) var(--grw-ease),
    transform var(--grw-fast) var(--grw-ease),
    border-color var(--grw-fast) var(--grw-ease),
    background var(--grw-fast) var(--grw-ease)}
.grw-theater.is-next .grw-next__item{opacity:1;transform:none}
.grw-theater.is-next .grw-next__item:nth-child(1){transition-delay:.06s}
.grw-theater.is-next .grw-next__item:nth-child(2){transition-delay:.13s}
.grw-theater.is-next .grw-next__item:nth-child(3){transition-delay:.2s}
.grw-theater.is-next .grw-next__item:nth-child(4){transition-delay:.27s}
.grw-theater.is-next .grw-next__item:nth-child(5){transition-delay:.34s}
.grw-theater.is-next .grw-next__item:nth-child(6){transition-delay:.41s}
.grw-theater.is-next .grw-next__item:nth-child(n+7){transition-delay:.48s}
.grw-next__item:hover{background:var(--black-soft);border-color:rgba(218,218,218,.16)}
.grw-next__item:focus-visible{outline:2px solid var(--bold);outline-offset:2px}
.grw-next__item.is-current{border-color:var(--bold);background:rgba(176,13,35,.09)}
.grw-next__shot{flex:0 0 auto;display:block;width:124px;aspect-ratio:16/9;
  overflow:hidden;background:var(--black-soft)}
.grw-next__shot img{width:100%;height:100%;object-fit:cover;
  transition:opacity var(--grw-mid) var(--grw-ease)}
.grw-next__item:hover .grw-next__shot img{opacity:.75}
.grw-next__meta{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.grw-next__t{font-size:var(--b-s);color:var(--secondary);
  transition:color var(--grw-fast) var(--grw-ease)}
.grw-next__item:hover .grw-next__t{color:var(--bold)}
.grw-next__y{font-size:var(--b-xs);color:var(--soft);letter-spacing:.04em}

/* ---------- short sheets: landscape phones, split-screen tablets ----------
   Everything below 861px shares the stacked sheet, and every phone held
   sideways lands here with 330-420px of height to spend. */
@media(max-width:860px) and (max-height:560px){
  .grw-theater__media{max-height:50vh;max-height:50svh}
  .grw-theater__ui{gap:10px;padding:10px 14px 14px}
  .grw-theater__meta{gap:.4rem}
  .grw-theater__t{font-size:1.25rem}
  .grw-theater__d{display:none}
  .grw-cta{gap:8px;margin-top:.2rem}
  .grw-btn{min-height:44px;padding:0 1.1rem}
  .grw-access__input,.grw-access__go{height:44px}
  .grw-ic{width:44px;height:44px}
  .grw-ic svg{width:20px;height:20px}
  .grw-theater__bar{gap:10px}
  .grw-theater.is-next .grw-next{max-height:44vh;max-height:44svh}
  .grw-next__k{padding:8px 14px 4px}
  .grw-next__list{max-height:34vh;max-height:34svh}
}

/* ---------- desktop: overlay ui, 90vw x 90vh, crop-for-rail ---------- */
@media(min-width:861px){
  .grw-theater__stage{display:block;width:min(90vw,1780px);
    height:90vh;height:90svh;background:transparent}
  .grw-theater__frame{position:absolute;inset:0;display:block;width:100%;
    background:#000;transition:width var(--grw-slow) var(--grw-ease)}
  .grw-theater__media{position:absolute;inset:0;width:100%;height:100%;
    max-height:none;aspect-ratio:auto;transition:width var(--grw-slow) var(--grw-ease)}
  /* The frame narrows; the picture keeps its width, so the right edge is
     cropped away rather than the whole film being scaled down. */
  .grw-theater.is-next .grw-theater__frame{
    width:calc(100% - var(--grw-rail) - var(--grw-rail-gap))}
  .grw-theater.is-next .grw-theater__media{
    width:calc(100% + var(--grw-rail) + var(--grw-rail-gap))}

  .grw-theater__ui{position:absolute;left:0;right:0;bottom:0;top:auto;
    flex:0 0 auto;overflow:visible;
    background:linear-gradient(transparent,rgba(3,3,3,.62) 38%,rgba(3,3,3,.93));
    opacity:0;transform:translateY(12px);pointer-events:none;
    transition:opacity var(--grw-mid) var(--grw-ease),
      transform var(--grw-mid) var(--grw-ease)}
  .grw-theater.is-ui .grw-theater__ui{opacity:1;transform:none;pointer-events:auto}
  .grw-theater__bar{margin-top:0}
  /* Never fades away with the rest of the UI — the exit is always visible. */
  .grw-theater__x{top:14px;right:14px;opacity:.75;
    transition:color var(--grw-fast) var(--grw-ease),
      background var(--grw-fast) var(--grw-ease),
      opacity var(--grw-fast) var(--grw-ease),
      right var(--grw-slow) var(--grw-ease)}
  .grw-theater__x:hover{opacity:1}
  .grw-theater.is-next .grw-theater__x{right:calc(var(--grw-rail) + var(--grw-rail-gap) + 14px)}
  .grw-theater__hint{display:flex}
  .grw-theater.is-ui .grw-theater__hint{opacity:.6}
  .grw-theater.is-next .grw-theater__hint{opacity:0}

  .grw-next{position:absolute;top:0;right:0;bottom:0;width:var(--grw-rail);
    max-height:none;overflow:hidden;border-top:0;background:transparent;
    display:flex;flex-direction:column;transform:translateX(16px);
    transition:opacity var(--grw-mid) var(--grw-ease),
      transform var(--grw-mid) var(--grw-ease),visibility 0s var(--grw-mid)}
  .grw-theater.is-next .grw-next{max-height:none;transform:none;
    transition:opacity var(--grw-mid) var(--grw-ease),
      transform var(--grw-mid) var(--grw-ease),visibility 0s 0s}
  .grw-next__k{padding:2px 0 12px}
  .grw-next__list{flex:1 1 auto;max-height:none;padding:0 0 4px;gap:12px}
  .grw-next__item{display:block;padding:0}
  .grw-next__shot{width:100%}
  .grw-next__meta{padding-top:8px}
}

/* Fullscreen: the stage becomes the screen. Separate rules — one unknown
   pseudo-element would otherwise invalidate the whole selector list. */
.grw-theater__stage:fullscreen{width:100vw;height:100vh;max-width:none}
.grw-theater__stage:-webkit-full-screen{width:100vw;height:100vh;max-width:none}

@media(prefers-reduced-motion:reduce){
  .grw-fc__poster,.grw-fc__prev,.grw-fc__t,.grw-fc__dwell,.grw-fc__dwellbar,
  .grw-theater,.grw-theater__stage,.grw-theater__frame,.grw-theater__media,
  .grw-theater__video,.grw-theater__ui,.grw-theater__meta,.grw-theater__scrim,
  .grw-theater__hint,.grw-theater__x,.grw-next,.grw-next__item,.grw-next__shot img,
  .grw-morph,.grw-access__form,.grw-access__input,.grw-access__go,.grw-access__msg,
  .grw-ic,.grw-ic::after,.grw-ic svg,.grw-btn,.grw-ctl__fill{
    transition-duration:1ms!important;transition-delay:0s!important;
    animation:none!important}
  .grw-fc.is-hot .grw-fc__poster,.grw-fc.is-hot .grw-fc__prev{transform:none}
  .grw-fc__dwell{display:none}
  /* The JS drops the preview element outright for these users; if the OS
     setting is flipped mid-session the element may still be in the DOM, so
     make sure an unplayed black <video> can never replace the poster. */
  .grw-fc__prev{display:none}
  .grw-fc.has-prev.is-hot .grw-fc__poster,
  .grw-fc.has-prev.is-live .grw-fc__poster{opacity:1}
}


/* ======================================================================
   WAITLIST GLOBE MODAL
   ====================================================================== */
/* ============================================================
   Waitlist globe modal  —  .wg / .wg__*  (namespaced; verified that
   site.css contains no "wg" token anywhere). APPEND AT THE END of
   site.css: .wg__btn only beats .btn{margin-top:1.8rem} on source
   order. Opens from [data-waitlist-open].
   ============================================================ */
.wg{
  /* Easing is the brand: long, soft, nothing snaps. */
  --wg-ease:cubic-bezier(.22,.61,.36,1);
  --wg-soft:cubic-bezier(.33,0,.15,1);
  --wg-in:.72s;
  --wg-slow:1.05s;
  --wg-size:clamp(232px,26vw,352px);   /* globe box; the sphere is 80% of it */
  --wg-shift:clamp(96px,13vw,190px);   /* how far left it glides at step 2 */
  --wg-row:0px;                        /* globe row height (phones) */

  position:fixed;inset:0;z-index:120;
  display:flex;align-items:center;justify-content:center;
  padding:var(--pad);
  overscroll-behavior:contain;
  visibility:hidden;pointer-events:none;
  transition:visibility 0s var(--wg-slow);
}
/* Stays display:none until the first open (site.js keeps [hidden] on at boot
   and restores it after the exit transition), so no page carries an idle
   fixed overlay or an idle backdrop-filter layer. */
.wg[hidden]{display:none}
.wg.is-open{visibility:visible;pointer-events:auto;transition:visibility 0s 0s}
/* On <html>, exactly the same trick as .menu-open. Deliberately NOT
   position:fixed on <body>: that resets scrollTop and would break the
   scrubbed letter-fill / photo-fan engine in site.js when the modal closes. */
.wg-lock{overflow:hidden}

.wg__scrim{position:absolute;inset:0;opacity:0;touch-action:none;
  background:rgba(3,3,3,.86);
  background:color-mix(in srgb,var(--black) 86%,transparent);
  -webkit-backdrop-filter:blur(14px) saturate(.8);backdrop-filter:blur(14px) saturate(.8);
  transition:opacity var(--wg-slow) var(--wg-soft)}
.wg.is-open .wg__scrim{opacity:1}

.wg__dialog{position:relative;display:flex;
  width:min(1040px,100%);height:min(660px,84svh);
  padding:clamp(28px,3.2vw,48px);
  background:var(--black);border:1px solid var(--black-soft);
  color-scheme:dark;overflow:hidden;
  opacity:0;transform:translateY(20px);
  transition:opacity var(--wg-in) var(--wg-soft),transform var(--wg-slow) var(--wg-ease)}
.wg.is-open .wg__dialog{opacity:1;transform:none}

/* ---------- globe stage ---------- */
/* The stage fills the dialog and only centres the orb; the orb is the thing
   that glides left, so the same transform serves phone and desktop. */
.wg__stage{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;pointer-events:none}
.wg__orb{position:relative;width:var(--wg-size);height:var(--wg-size);
  opacity:0;transform:translateX(0) scale(.88);
  transition:transform 1.15s var(--wg-ease),opacity var(--wg-slow) var(--wg-soft)}
.wg.is-open .wg__orb{opacity:1;transform:translateX(0) scale(1)}
.wg.is-shifted .wg__orb{transform:translateX(calc(-1 * var(--wg-shift))) scale(1)}
.wg__canvas{display:block;width:100%;height:100%}

/* The glowing dot is painted on the canvas; this is its hit target, so the
   city label is reachable by pointer, touch and keyboard alike.
   NO opacity transition: site.js writes pin.style.opacity every frame from
   the eased cityA/limb value, and a CSS transition here would restart on
   every write and leave the tap target permanently lagging the dot. */
.wg__pin{position:absolute;left:0;top:0;width:30px;height:30px;padding:0;
  border:0;border-radius:50%;background:transparent;cursor:pointer;
  opacity:0;pointer-events:none;transform:translate(-50%,-50%)}
.wg__pin:focus-visible{outline:2px solid var(--secondary-accent);outline-offset:1px}

.wg__tip{position:absolute;left:0;top:0;z-index:2;pointer-events:none;
  max-width:min(196px,58vw);padding:.42rem .68rem;
  background:var(--black-soft);border:1px solid var(--primary);
  color:var(--white);font-size:var(--b-xs);line-height:1.3;letter-spacing:.03em;
  text-transform:uppercase;white-space:normal;
  opacity:0;transition:opacity .55s var(--wg-soft)}
.wg__tip.is-on{opacity:1}

/* ---------- form side ----------
   Step 3: the panel is held back until the globe has taken its place, then the
   words and then the one input ease in. */
.wg__panel{opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .9s var(--wg-soft),transform 1.15s var(--wg-ease),
             visibility 0s .9s}
.wg.is-city .wg__panel{opacity:1;visibility:visible;transform:none;
  transition:opacity .9s var(--wg-soft),transform 1.15s var(--wg-ease),
             visibility 0s 0s}
.wg__field--city{opacity:0;transform:translateY(12px);
  transition:opacity .8s var(--wg-soft),transform var(--wg-slow) var(--wg-ease)}
.wg.is-city .wg__field--city{opacity:1;transform:none;transition-delay:.3s}

.wg__panel{position:relative;z-index:1;margin-left:auto;display:flex;
  width:min(50%,460px);max-height:100%;
  overflow-y:auto;overflow-x:hidden;   /* x:hidden so the -9999px honeypot can
                                          never open a horizontal scrollbar */
  overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
  scrollbar-width:thin}
/* auto margins centre the form beside the globe when it is short, and collapse
   to zero when it is tall (flexbox zeroes auto margins on negative free space,
   unlike justify-content:center, which would clip the top) */
.wg__panel-in{width:100%;margin-block:auto}
.wg__kicker{font-size:var(--b-xs);text-transform:uppercase;letter-spacing:.06em;
  color:var(--soft)}
.wg__title{margin-top:.7rem;font-size:var(--d-m);font-weight:500}
.wg__sub{margin-top:1rem;font-size:var(--b-s);color:var(--grey-medium);max-width:38ch}

/* The whole form lives in a collapsible box so that, once it is sent, it eases
   shut while the thank-you eases in — no reflow jump between the two. */
.wg__collapse{display:grid;grid-template-rows:1fr;
  transition:grid-template-rows var(--wg-slow) var(--wg-ease)}
.wg.is-sent .wg__collapse{grid-template-rows:0fr}
.wg__collapse-in{overflow:hidden;min-height:0;
  padding:clamp(22px,2.6vw,34px) 6px 0;margin-inline:-6px}
.wg__hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.wg__field{margin-bottom:clamp(16px,1.9vw,22px)}
.wg__label{display:block;margin-bottom:.55rem;font-size:var(--b-xs);
  text-transform:uppercase;letter-spacing:.05em;color:var(--soft)}
.wg__input{width:100%;padding:.9rem 1rem;background:transparent;color:var(--white);
  border:1px solid var(--black-soft);border-radius:0;font-family:inherit;
  font-size:var(--b-s);       /* 16px keeps iOS from zooming the page on focus */
  transition:border-color .45s var(--wg-soft),box-shadow .45s var(--wg-soft)}
.wg__input::placeholder{color:var(--soft)}
.wg__input:hover{border-color:var(--primary)}
.wg__input:focus{outline:none;border-color:var(--grey-strong)}
/* inset ring, so the overflow-clipped reveal box can never crop the focus state */
.wg__input:focus-visible{border-color:var(--secondary-accent);
  box-shadow:inset 0 0 0 1px var(--secondary-accent)}
textarea.wg__input{min-height:92px;resize:vertical;display:block}

.wg__city{position:relative;display:flex}
.wg__city .wg__input{padding-right:3.2rem}
.wg__go{position:absolute;right:1px;top:1px;bottom:1px;width:3rem;
  display:flex;align-items:center;justify-content:center;
  padding:0;border:0;background:transparent;cursor:pointer}
.wg__go span{width:11px;height:11px;border-right:1.5px solid var(--grey-medium);
  border-top:1.5px solid var(--grey-medium);transform:rotate(45deg);
  transition:border-color .4s var(--wg-soft),transform .5s var(--wg-ease)}
.wg__go:hover span{border-color:var(--bold);transform:rotate(45deg) translate(2px,-2px)}
.wg__go:focus-visible{outline:2px solid var(--secondary-accent);outline-offset:-2px}

/* --soft on --black is ~3.3:1; the hint carries real instructions, so it takes
   --grey-medium (~6:1). Labels stay on --soft to match the existing .form. */
.wg__hint{margin-top:.6rem;font-size:var(--b-xs);line-height:1.45;
  color:var(--grey-medium);opacity:1;transition:opacity .34s var(--wg-soft)}
.wg__hint.is-fading{opacity:0}
.wg__hint.is-warm{color:var(--secondary-accent)}

.wg__sel{position:relative;display:block}
.wg__sel select{appearance:none;-webkit-appearance:none;padding-right:2.6rem;cursor:pointer}
.wg__sel option{background:var(--black-soft);color:var(--white)}
.wg__sel::after{content:"";position:absolute;right:1.15rem;top:50%;
  width:9px;height:9px;margin-top:-7px;pointer-events:none;
  border-right:1.5px solid var(--grey-medium);border-bottom:1.5px solid var(--grey-medium);
  transform:rotate(45deg)}

/* Step 4: the rest of the form eases open. 0fr -> 1fr so the sheet grows with
   it instead of jumping, and visibility keeps the hidden fields out of Tab. */
.wg__rest{display:grid;grid-template-rows:0fr;opacity:0;visibility:hidden;
  transition:grid-template-rows var(--wg-slow) var(--wg-ease),
             opacity .8s var(--wg-soft) .12s,
             visibility 0s var(--wg-slow)}
.wg.is-rest .wg__rest{grid-template-rows:1fr;opacity:1;visibility:visible;
  transition:grid-template-rows var(--wg-slow) var(--wg-ease),
             opacity .8s var(--wg-soft) .12s,
             visibility 0s 0s}
.wg__rest-in{overflow:hidden;min-height:0;padding:6px;margin:-6px}
.wg__rest .wg__field{opacity:0;transform:translateY(12px);
  transition:opacity .7s var(--wg-soft),transform .9s var(--wg-ease)}
.wg.is-rest .wg__rest .wg__field{opacity:1;transform:none;
  transition-delay:calc(var(--i,0) * .09s + .18s)}

.wg__btn{margin-top:.4rem}
/* inset ring: the panel clips on x, and .wg__rest-in clips on y */
.wg__btn:focus-visible{outline:2px solid var(--secondary-accent);outline-offset:-3px}
.wg__note{margin-top:.85rem;font-size:var(--b-xs);color:var(--grey-medium);
  transition:color .4s var(--wg-soft)}
.wg__note.is-warn{color:var(--bold)}
.wg__live{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);
  white-space:nowrap}
.wg__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);
  white-space:nowrap}

/* ---------- sent ---------- */
.wg__form{opacity:1;visibility:visible;
  transition:opacity .6s var(--wg-soft),visibility 0s 0s}
.wg.is-sent .wg__form{opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity .6s var(--wg-soft),visibility 0s .6s}
.wg__done{margin-top:clamp(22px,2.6vw,34px);opacity:0;transform:translateY(10px);
  transition:opacity .8s var(--wg-soft) .25s,transform var(--wg-slow) var(--wg-ease) .25s}
.wg__done[hidden]{display:none}
.wg.is-sent .wg__done{opacity:1;transform:none}
.wg__done h3{margin:0;font-size:var(--b-xl);font-weight:500;color:var(--white)}
.wg__done p{margin-top:.9rem;font-size:var(--b-s);color:var(--grey-medium)}

/* ---------- chrome ---------- */
.wg__close{position:absolute;right:10px;top:10px;z-index:4;
  width:44px;height:44px;padding:0;border:0;background:transparent;cursor:pointer}
.wg__close span{position:absolute;left:13px;right:13px;top:21px;height:1.5px;
  background:var(--grey-medium);
  transition:background .4s var(--wg-soft),transform .5s var(--wg-ease)}
.wg__close span:nth-child(1){transform:rotate(45deg)}
.wg__close span:nth-child(2){transform:rotate(-45deg)}
.wg__close:hover span{background:var(--white)}
.wg__close:hover span:nth-child(1){transform:rotate(135deg)}
.wg__close:hover span:nth-child(2){transform:rotate(45deg)}
.wg__close:focus-visible{outline:2px solid var(--secondary-accent);outline-offset:-4px}
.wg__grip{display:none}

/* ---------- short desktop / landscape phone ----------
   860.02px, not 861px: 860.x is real at fractional DPR and at browser zoom,
   and 861 would leave that slice matching neither this nor the phone query. */
@media (min-width:860.02px) and (max-height:620px){
  .wg{--wg-size:min(190px,44svh);--wg-shift:clamp(80px,11vw,150px)}
  .wg__dialog{height:94svh;padding:22px 26px}
  .wg__title{font-size:clamp(1.6rem,3vw,2.2rem)}
}

/* ---------- phones and portrait tablets: a bottom sheet ----------
   The DIALOG must not scroll: .wg__close and .wg__grip are positioned against
   it, and an absolutely-positioned descendant of a scroll container scrolls
   away with the content. So the dialog stays a fixed frame, the globe row is a
   plain flex item at the top of it, and .wg__panel is the scroller. Same
   result as the sticky version — the globe never moves and never covers the
   form — without losing the close button the moment anyone scrolls. -------- */
@media (max-width:860px){
  .wg{--wg-size:min(52vw,190px);--wg-shift:7vw;--wg-row:calc(var(--wg-size) + 26px);
    align-items:flex-end;padding:0}
  .wg__dialog{flex-direction:column;width:100%;height:auto;max-height:94svh;
    padding:0;border-width:1px 0 0;overflow:hidden;
    transform:translateY(34px)}
  .wg.is-open .wg__dialog{transform:none}

  .wg__stage{position:relative;inset:auto;flex:0 0 auto;
    width:100%;height:var(--wg-row);
    background:linear-gradient(var(--black) 78%,rgba(3,3,3,0))}
  .wg__orb{margin-top:8px}

  .wg__panel{display:block;width:100%;margin-left:0;
    flex:1 1 auto;min-height:0;max-height:none;
    overflow-y:auto;overflow-x:hidden;
    padding:4px var(--pad) calc(var(--pad) + env(safe-area-inset-bottom,0px))}
  /* keeps the measure sane on a tablet-width sheet */
  .wg__panel-in{margin-block:0;max-width:560px;margin-inline:auto}
  .wg__title{font-size:clamp(1.9rem,7.4vw,2.6rem)}
  .wg__sub{max-width:46ch}
  .wg__grip{display:block;position:absolute;left:50%;top:9px;z-index:3;
    width:44px;height:3px;margin-left:-22px;background:var(--primary)}
  .wg__close{right:4px;top:6px}
  /* every tap target clears 44px on touch */
  .wg__pin{width:44px;height:44px}
  .wg__go{width:3.4rem}
}

@media (max-width:860px) and (max-height:560px){
  .wg{--wg-size:min(38vw,124px);--wg-row:calc(var(--wg-size) + 14px)}
}

/* ---------- reduced motion ----------
   Every step still happens and everything still works — it just arrives
   instantly, and the globe holds still instead of spinning (site.js). */
@media (prefers-reduced-motion:reduce){
  .wg,.wg *{transition-duration:.001ms !important;transition-delay:0s !important;
    animation-duration:.001ms !important;animation-delay:0s !important;
    animation-iteration-count:1 !important}
  .wg__go:hover span{transform:rotate(45deg)}
}


/* ======================================================================
   CONTACT FORM + TEAM CARDS + BTS BANNER
   ====================================================================== */
/* ==========================================================================
   GRW — contact flow · team plates · BTS banner
   Self-contained. Append to the end of assets/css/site.css. Nothing above
   is modified; every new name is grw- prefixed (checked against site.css).
   No overflow / position / transform is applied to html or body, so the
   scrubbed scroll engine in site.js keeps its scroll container.
   ========================================================================== */

:root{
  --grw-ease:cubic-bezier(.22,.61,.36,1);      /* soft out — the house feel */
  --grw-ease-io:cubic-bezier(.55,0,.2,1);
  --grw-slow:.72s;
  --grw-slower:.95s;
}

/* --------------------------------------------------------- centred column */
.grw-mid{max-width:660px;margin-inline:auto}
.grw-mid--wide{max-width:860px}

/* Everything centres; the form's own contents stay left-aligned. */
.grw-contact{text-align:center}
.grw-contact .display{max-width:none;margin-inline:auto}
.grw-contact__lede{max-width:46ch;margin-inline:auto}
.grw-form{max-width:none;width:100%;margin-inline:auto;text-align:left}
/* site.js replaces the form body with <p class="lede"> on a successful send;
   that message belongs on the centre line like everything else here. */
.grw-form .lede{text-align:center;margin-inline:auto}

/* ----------------------------------------------------- keyboard-flow hint */
/* Resting colour is grey-medium at .78, not soft at .7: soft over near-black
   at 70% composites to ~#464646, which is ~2.2:1 against the page and simply
   cannot be read at 14px. */
.grw-flow-hint{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:.55rem 1.1rem;margin-top:clamp(26px,3.4vw,38px);
  font-size:var(--b-xs);color:var(--grey-medium);letter-spacing:.03em;opacity:.78;
  transition:opacity var(--grw-slow) var(--grw-ease),color var(--grw-slow) var(--grw-ease)}
.grw-contact.is-flowing .grw-flow-hint{opacity:1;color:var(--secondary)}
.grw-flow-hint span{display:inline-flex;align-items:center;gap:.4rem;white-space:nowrap}
.grw-flow-hint kbd{font-family:inherit;font-size:.78em;line-height:1;padding:.36em .52em;
  border:1px solid var(--primary);background:rgba(255,255,255,.03);
  color:var(--grey-medium);letter-spacing:.06em;text-transform:uppercase;
  transition:border-color var(--grw-slow) var(--grw-ease),
             color var(--grw-slow) var(--grw-ease)}
.grw-flow-hint kbd + kbd{margin-left:-.2rem}
.grw-contact.is-flowing .grw-flow-hint kbd{border-color:var(--grey-strong);color:var(--white)}
/* No physical keyboard, no hint. */
@media (hover:none) and (pointer:coarse){.grw-flow-hint{display:none}}

/* ------------------------------------------------------------ form fields */
.grw-field{position:relative}
/* Current-field marker: a thin accent rule that eases down the left edge. */
.grw-field::before{content:"";position:absolute;left:calc(var(--pad) * -.5);top:2px;bottom:2px;
  width:2px;background:var(--bold);opacity:0;transform:scaleY(0);transform-origin:top center;
  transition:transform var(--grw-slow) var(--grw-ease),opacity var(--grw-slow) var(--grw-ease)}
.grw-field:focus-within::before,.grw-field.is-current::before{opacity:1;transform:scaleY(1)}
.grw-field--send::before{content:none}

.grw-field > label{transition:color var(--grw-slow) var(--grw-ease)}
.grw-field:focus-within > label,.grw-field.is-current > label{color:var(--secondary)}
.grw-opt{color:var(--grey-strong)}

.grw-field input,.grw-field textarea,.grw-select select{
  transition:border-color var(--grw-slow) var(--grw-ease),
             background-color var(--grw-slow) var(--grw-ease),
             color var(--grw-slow) var(--grw-ease)}
.grw-field input:focus,.grw-field textarea:focus,.grw-select select:focus{
  border-color:var(--secondary-accent);background-color:rgba(255,255,255,.025)}
.grw-field input:focus-visible,.grw-field textarea:focus-visible,
.grw-select select:focus-visible{outline:1px solid var(--secondary-accent);outline-offset:2px}

/* ------------------------------------------------------------ select ---- */
.grw-select{position:relative}
.grw-select select{-webkit-appearance:none;appearance:none;width:100%;
  padding:.95rem 2.8rem .95rem 1rem;background-color:transparent;color:var(--white);
  border:1px solid var(--black-soft);border-radius:0;font-family:inherit;
  font-size:var(--b-s);line-height:1.4;cursor:pointer;color-scheme:dark}
/* grey-medium, not grey-strong: #777 on #030303 is 3.8:1 and fails at 16px.
   The class is only applied to a genuine placeholder option (see site.js). */
.grw-select select.is-empty{color:var(--grey-medium)}
.grw-select option{background:var(--black-soft);color:var(--secondary)}
.grw-select::after{content:"";position:absolute;right:1.15rem;top:50%;margin-top:-5px;
  width:7px;height:7px;border-right:1.5px solid var(--grey-medium);
  border-bottom:1.5px solid var(--grey-medium);transform:rotate(45deg);pointer-events:none;
  transition:border-color var(--grw-slow) var(--grw-ease),
             transform var(--grw-slow) var(--grw-ease)}
.grw-field:focus-within .grw-select::after{border-color:var(--white);
  transform:rotate(45deg) translate(2px,2px)}

/* --------------------------------------- send: white outline, L→R RED fill
   The fill is a ::before, not a child element, on purpose: the Basin handler
   in site.js swaps the button's textContent while sending, which would wipe
   any child span. isolation + z-index:-1 keeps the fill behind the raw text
   node without needing one.

   The flood is --bold, matching "Join the Waitlist" and the theater play
   button, so the label stays WHITE the whole way through instead of flipping
   to black. Two things ride on that and are handled below: the focus ring
   can no longer be red (it would vanish into the fill), and the red dot
   cursor has to know this surface floods red or it sits invisible on it --
   see RED_SEL in site.js. */
.grw-send{display:flex;width:100%;justify-content:center;text-align:center;
  position:relative;isolation:isolate;overflow:hidden;margin-top:0;
  padding:1.15rem 2.1rem;background:transparent;border:1px solid var(--white);
  color:var(--white);
  transition:color .55s var(--grw-ease),border-color .55s var(--grw-ease),
             opacity .5s var(--grw-ease)}
.grw-send::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--bold);
  transform:scaleX(0);transform-origin:left center;
  transition:transform var(--grw-slower) var(--grw-ease)}
/* :hover is gated, the rest is not, and the split is deliberate.
   iOS/Android leave :hover stuck on the last-tapped element, so an ungated
   flood means a tap that fails HTML5 validation leaves the button solid red
   for the rest of the session. .is-filling is the touch press state (site.js
   adds it on a non-mouse pointerdown and drops it on pointerup) and it is
   what should flood there.
   The background arm stays UNGATED on purpose: .btn:hover{background:#8d0a1c}
   is also (0,2,0) and this button is class="btn grw-send", so removing
   .grw-send:hover{background:transparent} from the touch path would let that
   flat dark red paint through instead. */
.grw-send:hover{background:transparent}
.grw-send:focus-visible,.grw-send.is-filling{background:transparent;
  color:var(--white);border-color:var(--bold)}
.grw-send:focus-visible::before,.grw-send.is-filling::before{transform:scaleX(1)}
@media(hover:hover){
  .grw-send:hover{color:var(--white);border-color:var(--bold)}
  .grw-send:hover::before{transform:scaleX(1)}
}
/* white, not --bold: a red ring around a red fill is not a focus indicator */
.grw-send:focus-visible{outline:2px solid var(--white);outline-offset:3px}
/* Sending: the fill completes and holds, rather than the button just greying. */
.grw-send[disabled]{color:var(--white);border-color:var(--bold);
  opacity:.78;cursor:default}
.grw-send[disabled]::before{transform:scaleX(1)}

.grw-note{margin:.95rem 0 0;text-align:center}

/* --------------------------------------------------- about: team plates -- */
.grw-team{--grw-plate-x:clamp(12px,1.4vw,20px);--grw-plate-y:clamp(14px,1.6vw,22px)}
.grw-member{position:relative;-webkit-tap-highlight-color:transparent}
.grw-member > *:not(.grw-member__plate){position:relative;z-index:1}
.grw-member__plate{position:absolute;z-index:0;pointer-events:none;
  inset:calc(var(--grw-plate-y) * -1) calc(var(--grw-plate-x) * -1);
  background:var(--white);opacity:0;transform:scale(.988);
  transition:opacity var(--grw-slower) var(--grw-ease),
             transform var(--grw-slower) var(--grw-ease)}
.grw-member.is-lit .grw-member__plate{opacity:1;transform:scale(1);
  transition-duration:.62s,.62s}
/* Copy eases to dark for readability on the plate. */
.grw-member .member__t,.grw-member .member__r,
.grw-member .member__b,.grw-member .member__n{
  transition:color var(--grw-slower) var(--grw-ease)}
.grw-member.is-lit .member__t{color:var(--black)}
.grw-member.is-lit .member__r{color:var(--bold)}
.grw-member.is-lit .member__b{color:var(--primary)}
/* --soft, not --grey-strong: #777 on white is 4.48:1 and misses AA at 14px. */
.grw-member.is-lit .member__n{color:var(--soft)}
.grw-member:focus{outline:none}
.grw-member:focus-visible{outline:2px solid var(--bold);
  outline-offset:calc(var(--grw-plate-x) + 2px)}
@media (hover:none){.grw-member{cursor:pointer}}

/* ---------------------------------------------------- about: BTS banner -- */
.grw-bts{position:relative;margin-top:clamp(36px,5vw,60px)}
.grw-bts__frame{position:relative;overflow:hidden;background:var(--black-soft);
  height:clamp(110px,16vw,190px)}
.grw-bts__poster,.grw-bts__vid{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;filter:grayscale(1) contrast(1.06) brightness(.92)}
.grw-bts__poster{opacity:1;transition:opacity var(--grw-slower) var(--grw-ease)}
.grw-bts.is-live .grw-bts__poster{opacity:0}
.grw-bts__vid{opacity:0;transition:opacity .9s var(--grw-ease)}
.grw-bts__vid.is-on{opacity:1}
/* Melts the strip into the near-black ground and buys contrast for the label. */
.grw-bts__frame::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,var(--black),rgba(3,3,3,0) 15%,
             rgba(3,3,3,0) 85%,var(--black)),
             linear-gradient(180deg,rgba(3,3,3,.38),rgba(3,3,3,0) 45%,rgba(3,3,3,.6))}
.grw-bts__cap{position:absolute;z-index:2;pointer-events:none;
  left:clamp(12px,2vw,22px);bottom:clamp(10px,1.6vw,16px);
  font-size:var(--b-xs);text-transform:uppercase;letter-spacing:.06em;
  color:var(--secondary);opacity:.85}
.grw-bts__btn{position:absolute;z-index:3;right:clamp(10px,1.6vw,18px);
  bottom:clamp(10px,1.6vw,16px);width:40px;height:40px;padding:0;
  display:grid;place-items:center;cursor:pointer;font:inherit;
  -webkit-tap-highlight-color:transparent;
  background:rgba(3,3,3,.45);border:1px solid rgba(255,255,255,.28);color:var(--white);
  opacity:0;transition:opacity .6s var(--grw-ease),
             background-color .6s var(--grw-ease),border-color .6s var(--grw-ease)}
.grw-bts:hover .grw-bts__btn,.grw-bts:focus-within .grw-bts__btn{opacity:1}
.grw-bts__btn:hover{background:rgba(3,3,3,.72);border-color:var(--white)}
.grw-bts__btn:focus-visible{opacity:1;outline:2px solid var(--bold);outline-offset:2px}
/* No hover on touch: the control is always there, and at a real 44px target. */
@media (hover:none){.grw-bts__btn{opacity:1;width:44px;height:44px}}
/* display:grid above would otherwise beat the UA [hidden] rule. */
.grw-bts__btn[hidden]{display:none}
/* inset+margin:auto centres these outright. place-items on a grid container
   is only specified to reach its GRID ITEMS; an absolutely positioned child
   is out of flow, so relying on it to centre the icons is a coin flip. */
.grw-bts__i{position:absolute;inset:0;margin:auto;width:12px;height:12px;
  fill:currentColor;opacity:0;transform:scale(.8);
  transition:opacity .5s var(--grw-ease),transform .5s var(--grw-ease)}
.grw-bts[data-playing="true"] .grw-bts__i--pause{opacity:1;transform:none}
.grw-bts:not([data-playing="true"]) .grw-bts__i--play{opacity:1;transform:none}

/* ------------------------------------------------------------- narrow ---- */
@media (max-width:640px){
  .grw-field::before{left:-12px}
  .grw-team{--grw-plate-x:12px;--grw-plate-y:14px}
  .grw-send{padding:1.05rem 1.4rem}
}

/* ----------------------------------------------------- reduced motion ----
   State changes stay, the travel between states goes. */
@media (prefers-reduced-motion:reduce){
  .grw-flow-hint,.grw-flow-hint kbd,.grw-field::before,.grw-field > label,
  .grw-field input,.grw-field textarea,.grw-select select,.grw-select::after,
  .grw-send,.grw-send::before,
  .grw-member__plate,.grw-member .member__t,.grw-member .member__r,
  .grw-member .member__b,.grw-member .member__n,
  .grw-bts__poster,.grw-bts__vid,.grw-bts__btn,.grw-bts__i{
    transition-duration:1ms !important}
  .grw-member__plate{transform:none}
  .grw-bts__i{transform:none}
}


/* ============================================================
   Refinement pass — tints, hover fills, capture corners
   ============================================================ */

/* ---- scroll / load tints ------------------------------------------------
   A figure or word that eases into accent red. data-tint="view" repeats every
   time it enters the viewport; data-tint="load" fires once after load. */
.tint{color:inherit;transition:color 1.15s cubic-bezier(.22,.72,.2,1)}
.tint.is-lit{color:var(--bold)}
@media(prefers-reduced-motion:reduce){
  .tint{transition:none}
}

/* ---- "All Films" ghost button: outline and text bloom from the centre ---- */
.btn--ghost{position:relative;overflow:hidden;border-color:var(--grey-strong);
  transition:color .9s cubic-bezier(.22,.72,.2,1)}
.btn--ghost::before,.btn--ghost::after{content:"";position:absolute;
  left:50%;right:50%;height:1px;background:var(--bold);
  transition:left 1s cubic-bezier(.22,.72,.2,1),right 1s cubic-bezier(.22,.72,.2,1)}
.btn--ghost::before{top:-1px}
.btn--ghost::after{bottom:-1px}
/* the vertical edges arrive with the horizontals, so the outline closes as one */
.btn--ghost > span{position:absolute;top:0;bottom:0;width:1px;background:var(--bold);
  opacity:0;transition:opacity .5s ease .5s}
.btn--ghost > span:first-of-type{left:0}
.btn--ghost > span:last-of-type{right:0}
@media(hover:hover){
  .btn--ghost:hover{color:var(--bold);background:transparent}
  .btn--ghost:hover::before,.btn--ghost:hover::after{left:0;right:0}
  .btn--ghost:hover > span{opacity:1}
}
.btn--ghost:focus-visible{color:var(--bold)}
.btn--ghost:focus-visible::before,.btn--ghost:focus-visible::after{left:0;right:0}
.btn--ghost:focus-visible > span{opacity:1}

/* ---- "Join the Waitlist": white outline that floods accent red L->R ---- */
.join .btn,.grw-cta__play{position:relative;overflow:hidden;z-index:0;
  background:transparent;border:1px solid var(--white);color:var(--white);
  transition:color .9s cubic-bezier(.22,.72,.2,1),
             border-color .9s cubic-bezier(.22,.72,.2,1)}
.join .btn::before,.grw-cta__play::before{content:"";position:absolute;inset:0;
  z-index:-1;background:var(--bold);transform:scaleX(0);transform-origin:left center;
  transition:transform 1.05s cubic-bezier(.22,.72,.2,1)}
@media(hover:hover){
  .join .btn:hover,.grw-cta__play:hover{color:var(--white);border-color:var(--bold)}
  .join .btn:hover::before,.grw-cta__play:hover::before{transform:scaleX(1)}
}
.join .btn:focus-visible::before{transform:scaleX(1)}

/* ---- process steps: stagger left to right, once, on entry ---- */
.grw-steps .step{opacity:0;transform:translateY(18px);
  transition:opacity 1.05s cubic-bezier(.22,.72,.2,1),
             transform 1.15s cubic-bezier(.16,.9,.22,1)}
.grw-steps.is-in .step{opacity:1;transform:none}
.grw-steps.is-in .step:nth-child(1){transition-delay:0s}
.grw-steps.is-in .step:nth-child(2){transition-delay:.3s}
.grw-steps.is-in .step:nth-child(3){transition-delay:.6s}
.grw-steps.is-in .step:nth-child(4){transition-delay:.9s}
@media(prefers-reduced-motion:reduce){
  .grw-steps .step{opacity:1;transform:none;transition:none}
}

/* ---- testimonial: camera capture corners, bottom-left and top-right ---- */
.grw-tcar__stage{position:relative}
.grw-tcar__stage::before,.grw-tcar__stage::after{content:"";position:absolute;
  width:26px;height:26px;pointer-events:none;z-index:3;
  border-color:var(--secondary);border-style:solid;opacity:.85}
.grw-tcar__stage::before{top:14px;right:14px;border-width:1px 1px 0 0}
.grw-tcar__stage::after{bottom:14px;left:14px;border-width:0 0 1px 1px}

/* ---- crew card: tighter name/role lockup + hairline rule ---- */
.member__t{margin-bottom:0}
.member__r{margin-top:.23rem}           /* was .35rem — ~35% tighter */
.member__rule{display:block;width:26px;height:1px;background:var(--bold);
  margin:.9rem 0 0}
.member__b{margin-top:.7rem}

/* ---- BTS banner a touch taller ---- */
.grw-bts__frame{min-height:0}
.grw-bts{--grw-bts-h:1.13}              /* ~13% taller than the base ratio */

/* ---- FAQ accents: fade in with the answer, reset when it closes ---- */
.grw-acc__inner .hot{color:var(--secondary);
  transition:color 1.1s cubic-bezier(.22,.72,.2,1) .25s}
.grw-acc__item.is-open .grw-acc__inner .hot{color:var(--bold)}
@media(prefers-reduced-motion:reduce){
  .grw-acc__inner .hot{transition:none}
}


/* ==================================================================
   RED DOT CURSOR
   ================================================================== */
/* ======================================================================
   RED DOT CURSOR                                    (namespace: .grwc-*)
   Replaces block (D) "accent-red cursor" — delete site.css lines 578-613
   (the --cur-arrow / --cur-hand / --cur-text block, its
   @media(hover:hover) and (pointer:fine) rules, and the forced-colors
   override that resets those three variables). Verified: after that cut
   nothing in site.css or site.js reads --cur-* (the only other copies are
   in preview/getreel-preview.html, a generated standalone file).

   One node, two layers: .grwc is the positioner and only ever carries the
   per-frame transform site.js writes; .grwc__d is the visual and only ever
   carries eased state. Nothing animates the same property from both sides.

   .grwc-live is added by site.js on the FIRST REAL MOUSE MOVE, never at
   load, and is handed back at every moment the pointer might be over the
   page with no dot drawn. Every cursor-hiding rule below is gated on it, so
   "no cursor at all" is not a state this stylesheet can reach on its own.
   ====================================================================== */
:root{
  --grwc-box:32;                    /* unitless: the layout box, never animated */
  --grwc-dot:10;                    /* resting diameter */
  --grwc-ease:cubic-bezier(.22,.61,.36,1);
  --grwc-shape:.55s;                /* size + fade IN — eased, but it keeps up */
  --grwc-out:.22s;                  /* fade OUT — short, so a park never lingers */
  --grwc-tint:.45s;                 /* red <-> white */
}

/* Inert until site.js puts .grwc-live on <html>. pointer-events:none in every
   state, so it can never eat a click or a hover, and so elementFromPoint and
   the smooth-scroll engine's wheel target never see it; aria-hidden in the
   markup site.js builds, so it is not in the a11y tree. position:fixed with a
   0x0 box means it adds nothing to scrollable overflow — body's deliberate
   overflow-x:clip stays untouched and is not asked to clip anything. */
.grwc{position:fixed;left:0;top:0;width:0;height:0;
  z-index:2147483000;               /* over .grt (2000) and .grw-theater (120) */
  pointer-events:none;
  transform:translate3d(-9999px,-9999px,0);
  will-change:transform}
.grwc__d{position:absolute;left:0;top:0;box-sizing:border-box;
  width:calc(var(--grwc-box) * 1px);height:calc(var(--grwc-box) * 1px);
  margin:calc(var(--grwc-box) * -.5px) 0 0 calc(var(--grwc-box) * -.5px);
  border-radius:50%;
  background:var(--bold);
  border:1.5px solid transparent;
  box-shadow:0 1px 14px rgba(3,3,3,.5);   /* holds the dot on a film still */
  opacity:0;
  transform:scale(calc(var(--grwc-dot) / var(--grwc-box)));
  will-change:transform,opacity;
  transition:opacity var(--grwc-shape) var(--grwc-ease),
             transform var(--grwc-shape) var(--grwc-ease),
             background-color var(--grwc-tint) var(--grwc-ease),
             border-color var(--grwc-tint) var(--grwc-ease),
             box-shadow var(--grwc-tint) var(--grwc-ease)}

/* Arriving is floaty; leaving is not. A park means we have lost the pointer,
   and a dot that takes .95s to dissolve in the corner it was abandoned in is
   exactly what "stuck on screen" looks like to a client. Five durations, in
   the order of the list above. */
.grwc:not(.is-on) .grwc__d{
  transition-duration:var(--grwc-out),var(--grwc-out),
                      var(--grwc-tint),var(--grwc-tint),var(--grwc-tint)}

/* ---------- states (order matters: each block outranks the one above) ---- */
/* visible */
.grwc.is-on .grwc__d{opacity:1}

/* over anything focusable: opens into a ring, so interactive still reads
   as interactive without the OS hand */
.grwc.is-hit .grwc__d{transform:scale(1);background:transparent;
  border-color:var(--bold)}

/* over accent red: flips to white so it never disappears */
.grwc.is-red .grwc__d{background:var(--white);box-shadow:0 1px 14px rgba(3,3,3,.28)}
.grwc.is-red.is-hit .grwc__d{background:transparent;border-color:var(--white)}

/* over a text field the native I-beam takes back over (see the cursor rules
   below), so the dot eases away rather than fighting the caret */
.grwc.is-text .grwc__d{opacity:0;
  transform:scale(calc(var(--grwc-dot) / var(--grwc-box)))}

/* press — a small, soft compression */
.grwc.is-down .grwc__d{transform:scale(calc(var(--grwc-dot) / var(--grwc-box) * .72))}
.grwc.is-down.is-hit .grwc__d{transform:scale(.8)}

/* ---------- hiding the native cursor ------------------------------------
   Gated on BOTH the media query and the .grwc-live class site.js adds, so a
   coarse pointer can never lose its cursor even if the JS misfires, and a
   fine pointer only loses it once site.js is provably drawing a dot at it.
   !important is deliberate: dozens of class rules earlier in site.css set
   cursor:pointer at equal or higher specificity (.grwx-stage.is-open .grwx,
   .grw-tcar__next, .wg__sel select ...) and every one of them has to lose.
   The re-enabling rules below are ordered after, so they win in turn. */
@media(hover:hover) and (pointer:fine){
  html.grwc-live,html.grwc-live *,
  html.grwc-live *::before,html.grwc-live *::after{cursor:none!important}

  /* Usability floor 1 — a text field keeps its caret affordance. The dot
     fades out here (.is-text above) so there are never two cursors. The
     descendant arm covers a rich-text host, whose children would otherwise
     fall back through to cursor:none mid-paragraph. */
  html.grwc-live input:not([type=submit]):not([type=button]):not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]):not([type=image]),
  html.grwc-live textarea,
  html.grwc-live [contenteditable]:not([contenteditable=false]),
  html.grwc-live [contenteditable]:not([contenteditable=false]) *{cursor:text!important}

  /* Usability floor 2 — a child browsing context owns its own cursor. */
  html.grwc-live iframe,html.grwc-live embed,
  html.grwc-live object,html.grwc-live frame{cursor:auto!important}
}

/* ---------- reduced motion ---------------------------------------------
   The trailing easing is dropped in site.js (the dot is pinned to the
   pointer); here the size change stops animating too. The colour flip keeps
   a short cross-fade — that is a tint, not motion, and a hard cut would be
   the one jarring thing left. */
@media(prefers-reduced-motion:reduce){
  .grwc,.grwc__d{will-change:auto}
  .grwc__d{transition:opacity .2s linear,background-color .2s linear,
             border-color .2s linear,box-shadow .2s linear}
  /* one value, so it cannot mis-map onto the shorter list above */
  .grwc:not(.is-on) .grwc__d{transition-duration:.16s}
}

/* ---------- never run at all -------------------------------------------
   site.js also refuses to activate in each of these, so no cursor is ever
   hidden; the node is dropped here as the belt to that braces. */
@media(hover:none),(pointer:coarse){.grwc{display:none!important}}
@media(forced-colors:active),(prefers-contrast:more){.grwc{display:none!important}}
@media print{.grwc{display:none!important}}


/* ==================================================================
   TESTIMONIAL ARROW RING
   ================================================================== */
/* ======================================================================
   TESTIMONIAL NEXT-ARROW RING             (namespace: .grw-tring)
   Append to the end of site.css.
   ======================================================================

   The button's circular outline stops being a CSS border and becomes two
   concentric SVG circles sharing identical geometry:

     .grw-tring__track  white hairline, always visible — this is the
                        affordance, and it never depends on hover
     .grw-tring__arc    accent red, stroke-dasharray/dashoffset, rotated
                        -90deg on the shape so path position 0 sits at
                        12 o'clock and the arc grows CLOCKWISE

   Both carry fill:none, so the interior is transparent at every point of
   the sweep — this is an outline filling in, not a disc growing.

   Why dashoffset and not a conic-gradient mask: a conic mask can only be
   eased by animating an @property angle, and it cannot round the leading
   edge. dashoffset eases with a plain CSS transition in every engine,
   reverses on leave for free, and the repaint is a ~1.3px hairline
   inside an 84px box.

   ---------------------------------------------------------------------
   GATING. Every selector here is qualified with .has-grw-tring, a class
   site.js adds in the same function that injects the circles.

   This is not decoration. build.py emits no ring markup — the button is
   still <button class="grw-tcar__next"><svg>…arrow…</svg></button> — so
   an ungated "content:none" deletes the red disc the button has today
   against markup that does not exist, and the control is left with no
   hover, focus or press state at all. Gated, a blocked or throwing
   script simply leaves the disc in place.

   It also buys the specificity the ring needs anyway. The ring rules
   land at (0,3,0), which clears both
       .grw-tcar__next svg{width:34%;position:relative}       (0,1,1)
       .grw-tcar__next:hover svg{transform:translateX(16%)}   (0,2,1)
   the first of which would shrink the ring to arrow size, the second of
   which would slide the whole ring sideways with the arrow.

   ---------------------------------------------------------------------
   THE ARROW STAYS WHITE. Fading it to --bold puts #b00d23 on #030303 —
   2.85:1, the exact ratio site.css already refuses at .grw-acc__btn
   ("under the 3:1 that WCAG 1.4.11 asks"). Today the arrow is white on a
   filled red disc. Turning it red on black is a real regression, and
   because the arc is 0.5u wider than the track it covers the white
   hairline as it sweeps — so a red arrow would leave the hovered control
   with neither a boundary nor a glyph at 3:1. The ring goes red; the
   thing you have to read stays legible. No colour transition is needed
   on the button as a result.

   ---------------------------------------------------------------------
   HOUSEKEEPING — once this is settled, the "controls" block above can
   lose:
       .grw-tcar__next::before{ ... }
       @media(hover:hover){ .grw-tcar__next:hover::before{...} }
       .grw-tcar__next:active::before,
       .grw-tcar__next:focus-visible::before{ ... }
   and ".grw-tcar__next::before" comes out of the prefers-reduced-motion
   list at the end of it. Drop the .has-grw-tring gate at the same time,
   not before — until the disc is deleted it is the fallback.
   ====================================================================== */

.grw-tcar__next.has-grw-tring::before{content:none}

.grw-tcar__next.has-grw-tring{
  /* site.js mirrors --grw-tring-in as SWEEP — change the two together */
  --grw-tring-in:1.15s;          /* the sweep round */
  --grw-tring-out:1.05s;         /* the unwind back — never a snap */
  --grw-tring-e-in:cubic-bezier(.22,.61,.16,1);   /* drifts in, long settle */
  --grw-tring-e-out:cubic-bezier(.45,.03,.28,1);  /* soft release both ends */
  /* 308 is a hair over the 307.248 circumference of r=48.9, so offset 0
     closes the seam at 12 o'clock and offset 308 hides the arc completely */
  --grw-tring-dash:308;
  /* the 1px border stays for geometry only — removing it would grow the
     content box and resize the arrow, which is sized in %. The SVG paints
     the visible track. */
  border-color:transparent;
  /* the disc that needed clipping is gone, and visible keeps the rounded
     overflow clip off the hairline arc at the very edge */
  overflow:visible}

/* ---------- ring geometry ----------
   inset:-1px spans the border box (an absolute child is laid out against
   the PADDING box), so the arc lands exactly where the 1px border sat.
   transform:none and transition:none are here to shed what
   ".grw-tcar__next svg" and ":hover svg" would otherwise hand the ring. */
.grw-tcar__next.has-grw-tring .grw-tring{
  position:absolute;inset:-1px;width:auto;height:auto;display:block;
  overflow:visible;pointer-events:none;transform:none;transition:none}

.grw-tring__track,.grw-tring__arc{fill:none}
.grw-tring__track{stroke:var(--white);stroke-width:1.6}

/* The arc is drawn 0.5 user units wider than the track so it covers the
   track's antialiased fringe instead of compositing red over white and
   going pink. At rest dash and offset are equal: nothing is painted. */
.grw-tring__arc{
  stroke:var(--bold);stroke-width:2.1;stroke-linecap:round;
  stroke-dasharray:var(--grw-tring-dash);
  stroke-dashoffset:var(--grw-tring-dash);
  transition:stroke-dashoffset var(--grw-tring-out) var(--grw-tring-e-out)}

/* ---------- the swept state ----------
   :active is in this list on purpose. Deleting the ::before disc also
   deletes ".grw-tcar__next:active::before", which is the button's only
   press state, and the replacement one-shot fires on CLICK — after the
   finger has lifted. On touch that leaves the press itself dead, and
   under prefers-reduced-motion, where site.js suppresses the one-shot
   outright, it leaves a touch visitor with no feedback at any point:
   @media(hover:none) rules hover out, and iOS Safari does not focus
   buttons on tap so :focus-visible never fires either.

   :active starts the sweep the moment the finger lands. The one-shot
   class picks it up mid-travel on release — same property, same target
   value, so the arc simply keeps going and a tap reads as one continuous
   ring. A press that drags away loses :active and unwinds on its own.

   .is-grw-tring-on is the touch one-shot site.js adds on click. */
.grw-tcar__next.has-grw-tring:active .grw-tring__arc,
.grw-tcar__next.has-grw-tring:focus-visible .grw-tring__arc,
.grw-tcar__next.has-grw-tring.is-grw-tring-on .grw-tring__arc{
  stroke-dashoffset:0;
  transition:stroke-dashoffset var(--grw-tring-in) var(--grw-tring-e-in)}

/* press, keyboard focus and tap now get the arrow nudge hover has always
   had. (0,4,0) clears the (0,2,1) hover rule; the arrow's own transform
   transition still comes from ".grw-tcar__next svg", which the existing
   reduced-motion block already collapses to 1ms. */
.grw-tcar__next.has-grw-tring:active .grw-tarrow,
.grw-tcar__next.has-grw-tring:focus-visible .grw-tarrow,
.grw-tcar__next.has-grw-tring.is-grw-tring-on .grw-tarrow{
  transform:translateX(16%)}

/* hover stays gated so a tap on a phone can never leave the ring stuck on */
@media(hover:hover){
  .grw-tcar__next.has-grw-tring:hover .grw-tring__arc{
    stroke-dashoffset:0;
    transition:stroke-dashoffset var(--grw-tring-in) var(--grw-tring-e-in)}
}

/* ---------- touch ----------
   The button is at its smallest here (58px at 390px, so one user unit is
   0.58px and a 1.6 hairline lands at 0.93px CSS), and the ring is
   confirmation rather than decoration, so both strokes come up a little.
   2.4 reaches 50.1 of the 100-unit box — that rounding error past the
   edge is what overflow:visible on the button and the svg is for. */
@media(hover:none){
  .grw-tring__track{stroke-width:1.9}
  .grw-tring__arc{stroke-width:2.4}
}

@media(forced-colors:active){
  .grw-tring__track{stroke:CanvasText}
  .grw-tring__arc{stroke:Highlight}
}

/* The state still lands — red ring, nudged arrow — it just stops
   travelling. Every selector that carries a stroke-dashoffset transition
   is re-listed at matching specificity and later in source, or the
   (0,4,0) hover/active rules above would keep their 1.15s.
   site.js separately suppresses the tap one-shot here; :active is what
   confirms a press under reduced motion. */
@media(prefers-reduced-motion:reduce){
  .grw-tcar__next.has-grw-tring .grw-tarrow,
  .grw-tcar__next.has-grw-tring .grw-tring__arc,
  .grw-tcar__next.has-grw-tring:hover .grw-tring__arc,
  .grw-tcar__next.has-grw-tring:active .grw-tring__arc,
  .grw-tcar__next.has-grw-tring:focus-visible .grw-tring__arc,
  .grw-tcar__next.has-grw-tring.is-grw-tring-on .grw-tring__arc{
    transition-duration:1ms;transition-delay:0s}
}


/* ==================================================================
   CUSTOM FORM DROPDOWNS
   ================================================================== */
/* ============================================================
   custom form dropdowns — .grw-dd
   Appended to site.css. Scoped entirely under .grw-dd.is-ready.
   site.js adds BOTH classes once it has built the control, so the
   markup only ever carries the opt-in attribute:
     <div class="grw-select" data-grw-dd>
   With JS off not one rule below can match: the existing
   .grw-select native control is what renders, chevron and all.

   Two modes, set by site.js off (hover:hover) and (pointer:fine):
     .grw-dd--native   coarse pointer. The native <select> sits on
                       top at opacity 0 and takes the tap, so the
                       OS picker opens. .grw-dd__ctl is chrome.
     .grw-dd--custom   fine pointer. The <select> is inert chrome
                       (pointer-events:none) and the button +
                       listbox below are the control.
   ============================================================ */
.grw-dd{
  /* .form input is .95rem: the pickers sit a touch tighter on purpose so
     they read as pickers, not as another text field. Set --grw-dd-pad-y
     to .95rem here for pixel parity with the inputs. */
  --grw-dd-pad-y:.8rem;
  --grw-dd-pad-x:1rem;
  --grw-dd-gutter:2.15rem;     /* right inset that clears the chevron */
  --grw-dd-row:.62rem;
  --grw-dd-in:.66s;            /* open  */
  --grw-dd-out:.92s;           /* close — slower, nothing snaps shut */
  --grw-dd-stagger:.032s;
  position:relative}

/* The native select is the value that posts and the node the browser
   anchors its validation bubble to, so it keeps a real box: inset over the
   control at zero opacity, never display:none (which makes a required
   control unfocusable and throws in Chrome). color-scheme:dark and the
   option colours from .grw-select are deliberately left alone — they are
   what keep the OS picker dark in native mode. */
.grw-dd.is-ready > select{position:absolute;inset:0;width:100%;height:100%;
  margin:0;padding:0;border:0;background:transparent;opacity:0;
  font:inherit;cursor:pointer;z-index:2}
.grw-dd--custom.is-ready > select{pointer-events:none;cursor:default}
.grw-dd--native.is-ready > select{pointer-events:auto}
/* the .grw-select CSS chevron belongs to the un-enhanced control */
.grw-dd.is-ready::after{content:none}

/* ---------------------------------------------------------- the control */
.grw-dd__ctl{position:relative;z-index:1;display:block;width:100%;margin:0;
  padding:var(--grw-dd-pad-y) var(--grw-dd-gutter) var(--grw-dd-pad-y) var(--grw-dd-pad-x);
  background:transparent;color:var(--white);
  border:1px solid var(--black-soft);border-radius:0;
  font-family:inherit;font-size:var(--b-s);font-weight:inherit;line-height:1.4;
  text-align:left;cursor:pointer;-webkit-appearance:none;appearance:none;
  transition:border-color var(--grw-slow) var(--grw-ease),
             background-color var(--grw-slow) var(--grw-ease),
             color var(--grw-slow) var(--grw-ease)}
/* native mode: the select above it owns every pointer */
.grw-dd--native .grw-dd__ctl{pointer-events:none}

.grw-dd__val{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:color var(--grw-slow) var(--grw-ease)}
/* same reasoning as .grw-select select.is-empty: placeholder grey is
   grey-medium, never grey-strong, which fails contrast on near-black. */
.grw-dd.is-empty .grw-dd__val{color:var(--grey-medium)}

/* Focus reads the same as .grw-field input:focus. :focus-within covers both
   modes — in native mode the real focus is on the transparent select, and so
   it is in custom mode for the one beat where the browser has focused the
   select itself to report a constraint violation. */
.grw-dd:focus-within .grw-dd__ctl,
.grw-dd.is-open .grw-dd__ctl{border-color:var(--secondary-accent);
  background-color:rgba(255,255,255,.025)}
.grw-dd__ctl:focus-visible,
.grw-dd--native > select:focus-visible + .grw-dd__ctl{
  outline:1px solid var(--secondary-accent);outline-offset:2px}
.grw-dd.is-invalid .grw-dd__ctl{border-color:var(--bold)}

/* ------------------------------------------------------------- chevron */
.grw-dd__chev{position:absolute;right:var(--grw-dd-pad-x);top:50%;
  width:12px;height:12px;margin-top:-6px;color:var(--grey-medium);
  pointer-events:none;overflow:visible;
  transition:transform .78s var(--grw-ease),color var(--grw-slow) var(--grw-ease)}
.grw-dd__chev path{fill:none;stroke:currentColor;stroke-width:1.2;
  stroke-linecap:round;stroke-linejoin:round}
.grw-dd:focus-within .grw-dd__chev{color:var(--white)}
.grw-dd.is-open .grw-dd__chev{color:var(--white);transform:rotate(-180deg)}

/* ------------------------------------------------------------ the list
   Border is grey-strong, not primary. #262626 on the page's #030303 is
   1.4:1 and the drop shadow is black on black, so a --primary edge leaves
   the open panel with no visible boundary at all — it reads as loose text
   floating over the form. grey-strong is 4.6:1 against the page and clears
   SC 1.4.11 for the component boundary. Same reason the scrollbar thumb is
   --soft: a twelve-item genre list DOES overflow 288px, and a #262626 thumb
   on a #1a1a1a track is invisible. */
.grw-dd__list{position:absolute;z-index:30;left:0;right:0;top:calc(100% + 6px);
  max-height:min(46vh,288px);overflow-y:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;scrollbar-color:var(--soft) transparent;
  margin:0;padding:.3rem 0;list-style:none;text-align:left;
  background:var(--black-soft);border:1px solid var(--grey-strong);
  box-shadow:0 26px 64px rgba(0,0,0,.85);
  opacity:0;visibility:hidden;transform:translateY(-10px);
  /* visibility is delayed by the full duration so the panel FADES out —
     same idiom as the nav overlay further up this file. */
  transition:opacity var(--grw-dd-out) var(--grw-ease),
             transform var(--grw-dd-out) var(--grw-ease),
             visibility 0s var(--grw-dd-out)}
/* scrollbar-width/color is Chrome 121+ / Safari 18.2+; this is the rest. */
.grw-dd__list::-webkit-scrollbar{width:8px}
.grw-dd__list::-webkit-scrollbar-track{background:transparent}
.grw-dd__list::-webkit-scrollbar-thumb{background:var(--soft)}
.grw-dd.is-open .grw-dd__list{opacity:1;visibility:visible;transform:none;
  transition:opacity var(--grw-dd-in) var(--grw-ease),
             transform var(--grw-dd-in) var(--grw-ease),
             visibility 0s 0s}
/* flipped above the control when there is no room below. site.js only flips
   when the panel clears the FIXED .nav — that bar is transparent but it is
   a real box at z-index 90, above this one, and it would eat the clicks. */
.grw-dd.is-up .grw-dd__list{top:auto;bottom:calc(100% + 6px);transform:translateY(10px)}
.grw-dd.is-up.is-open .grw-dd__list{transform:none}

.grw-dd__opt{position:relative;display:block;
  padding:var(--grw-dd-row) var(--grw-dd-pad-x);
  font-size:var(--b-s);line-height:1.35;color:var(--grey-medium);
  cursor:pointer;-webkit-user-select:none;user-select:none;
  opacity:0;transform:translateY(-6px);
  transition:opacity .58s var(--grw-ease),transform .72s var(--grw-ease),
             color .45s var(--grw-ease),background-color .45s var(--grw-ease)}
/* --grw-i is set inline by site.js and capped at 8, so a twelve-item list
   does not drag its tail. The delay is declared per-property: hover colour
   must never inherit the entrance delay. */
.grw-dd.is-open .grw-dd__opt{opacity:1;transform:none;
  transition:opacity .58s var(--grw-ease) calc(var(--grw-i,0) * var(--grw-dd-stagger)),
             transform .72s var(--grw-ease) calc(var(--grw-i,0) * var(--grw-dd-stagger)),
             color .45s var(--grw-ease),
             background-color .45s var(--grw-ease)}

/* chosen row carries the same thin accent rule as .grw-field::before */
.grw-dd__opt::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;
  background:var(--bold);opacity:0;transform:scaleY(.25);
  transition:opacity .5s var(--grw-ease),transform .62s var(--grw-ease)}
.grw-dd__opt[aria-selected="true"]{color:var(--secondary)}
.grw-dd__opt[aria-selected="true"]::before{opacity:1;transform:scaleY(1)}
/* .is-active is the keyboard/pointer cursor (aria-activedescendant) */
.grw-dd__opt.is-active{color:var(--white);background-color:rgba(255,255,255,.055)}
@media (hover:hover){
  .grw-dd__opt:hover{color:var(--white);background-color:rgba(255,255,255,.055)}
}
/* a coarse pointer still gets 44px rows on the rare hybrid that runs custom */
@media (pointer:coarse){
  .grw-dd__opt{display:flex;align-items:center;min-height:44px}
}

@media (max-width:640px){
  .grw-dd{--grw-dd-pad-y:.86rem;--grw-dd-row:.78rem}
}

/* --------------------------------------------------- reduced motion ----
   Every state survives; only the travel between states goes. */
@media (prefers-reduced-motion:reduce){
  .grw-dd__ctl,.grw-dd__val,.grw-dd__chev,.grw-dd__list,
  .grw-dd__opt,.grw-dd__opt::before,
  .grw-dd.is-open .grw-dd__list,.grw-dd.is-open .grw-dd__opt{
    transition-duration:1ms !important;transition-delay:0s !important}
  .grw-dd__list,.grw-dd.is-up .grw-dd__list,.grw-dd__opt{transform:none}
  .grw-dd__chev{transform:none}
  .grw-dd.is-open .grw-dd__chev{transform:rotate(-180deg)}
}


/* ==================================================================
   THEATER KEYBOARD + CLICK CONTROLS
   ================================================================== */
/* ======================================================================
   THEATER — CTA BASELINE + KEY / TAP CONFIRMATION          (append-only)
   New name: .grw-kbi* (keyboard indicator). Checked against site.css —
   nothing above uses grw-kbi, grw-ctlh or is-back.
   No custom property is redefined here: --grw-fast / --grw-mid /
   --grw-ease / --grw-ease-both are read, never rewritten. (Note for the
   next person: the :root at site.css:643 re-declares --grw-ease for the
   FAQ/steps components. Same specificity, later in the file, so that is
   the value the whole theater already resolves to — reading it here just
   keeps this block on the same curve as everything around it. --grw-slow
   is declared once, at site.css:913.)
   ====================================================================== */

/* ---------------------------------------------------------------- (A)
   "Actor Access" sat ~12px HIGHER than "Play Film".

   Cause: .grw-cta is align-items:center, and .grw-access is not one
   control — it is a flex COLUMN of .grw-access__slot (48px) + .5rem gap
   + .grw-access__msg (min-height:1.2em = 14px at --b-xs). That column is
   ~72.8px tall against a 48px button, so centring pushed the button down
   (72.8-48)/2 = 12.4px and left the access control riding high. The slot
   itself was never the problem: its three states are grid-stacked in one
   cell, so button / input / download are already the same 48px box.

   Fix: align the row by the TOP of its controls instead of the centre of
   their boxes, and drive every control height off one variable so the
   row cannot shift as the slot morphs. align-self on the children as
   well as align-items on the row, so a later append to this file cannot
   quietly re-centre it. */
.grw-cta{--grw-ctlh:48px;align-items:flex-start}
.grw-cta > *{align-self:flex-start}
.grw-cta > .grw-btn{min-height:var(--grw-ctlh)}
/* The slot keeps its own width: a long status message must be free to be
   wider than the control without stretching the button under it. (.grw-access
   is a COLUMN, so align-self here is the cross axis = horizontal, i.e. it
   swaps the slot from stretch to fit-content. That is the intent.) */
.grw-cta .grw-access__slot{align-self:flex-start;min-height:var(--grw-ctlh)}
.grw-cta .grw-access__slot > .grw-btn,
.grw-cta .grw-access__form{min-height:var(--grw-ctlh)}
.grw-cta .grw-access__input,
.grw-cta .grw-access__go{height:var(--grw-ctlh)}
/* Short sheets already step the controls down to 44px — one variable. */
@media(max-width:860px) and (max-height:560px){
  .grw-cta{--grw-ctlh:44px}
}

/* ---------------------------------------------------------------- (B)
   Key / tap confirmation glyph. site.js injects it into
   .grw-theater__media, so it sits over the picture (z-index 3, same band
   as .grw-theater__hint, above the unlayered .grw-theater__scrim) and
   under the control layer (.grw-theater__ui is z-index 4) and the close
   button (6). Never interactive: the tap that summons it has to reach
   the video underneath. */
.grw-kbi{position:absolute;inset:0;z-index:3;display:flex;
  align-items:center;justify-content:center;pointer-events:none;
  opacity:0;visibility:hidden;transform:scale(1.08);
  transition:opacity 1.15s var(--grw-ease),transform 1.15s var(--grw-ease),
    visibility 0s 1.15s}
.grw-kbi.is-on{opacity:1;visibility:visible;transform:none;
  transition:opacity .62s var(--grw-ease-both),
    transform .78s var(--grw-ease-both),visibility 0s 0s}
.grw-kbi__box{position:relative;display:flex;align-items:center;
  justify-content:center;width:clamp(78px,17vw,104px);aspect-ratio:1;
  border-radius:999px;background:rgba(3,3,3,.55);
  border:1px solid rgba(218,218,218,.16);color:var(--secondary)}
.grw-kbi__gs{position:relative;display:block;
  width:clamp(26px,5.4vw,32px);aspect-ratio:1}
/* The three glyphs are stacked, so a pause following a play cross-fades
   inside the ring rather than cutting. */
.grw-kbi__g{position:absolute;inset:0;width:100%;height:100%;opacity:0;
  transition:opacity var(--grw-mid) var(--grw-ease),
    transform var(--grw-mid) var(--grw-ease)}
.grw-kbi[data-kind="play"] .grw-kbi__g--play,
.grw-kbi[data-kind="pause"] .grw-kbi__g--pause,
.grw-kbi[data-kind="seek"] .grw-kbi__g--seek{opacity:1}
.grw-kbi.is-back .grw-kbi__g--seek{transform:scaleX(-1)}
.grw-kbi__n{position:absolute;left:0;right:0;top:61%;text-align:center;
  font-size:var(--b-xs);letter-spacing:.06em;color:var(--secondary);
  font-variant-numeric:tabular-nums;opacity:0;
  transition:opacity var(--grw-mid) var(--grw-ease)}
.grw-kbi[data-kind="seek"] .grw-kbi__n{opacity:1}

/* The picture is a control now — say so where a cursor exists.
   NOT cursor:pointer. This site swaps every cursor for the accent-red set
   at site.css:584-613 under this exact query, and a class-level
   cursor:pointer outranks the html{cursor:var(--cur-arrow)} inheritance
   and hands back the OS hand — which is the whole reason the patch list
   at site.css:605 exists. --cur-hand already carries `pointer` as its own
   fallback and forced-colors/prefers-contrast remaps it to `pointer`. */
@media(hover:hover) and (pointer:fine){
  .grw-theater:not(.is-novideo) .grw-theater__media{cursor:var(--cur-hand,pointer)}
}

@media(prefers-reduced-motion:reduce){
  .grw-kbi,.grw-kbi.is-on,.grw-kbi__g,.grw-kbi__n{
    transition-duration:1ms!important;transition-delay:0s!important;
    animation:none!important}
  .grw-kbi{transform:none}
  .grw-kbi.is-back .grw-kbi__g--seek{transform:scaleX(-1)}
}

/* ==================================================================
   PRE-DEPLOY FIXES (2026-10-04 audit)
   ================================================================== */
/* Menu: the blurred backdrop reached 20px above the dropdown and painted
   over the lower half of the open X, so a tap on the X landed on the
   dropdown and the menu stayed open. The backdrop never takes taps now,
   and the burger sits above the dropdown. */
.grn__drop::before{pointer-events:none}
.grn__burger{z-index:2}

/* Join: the fanned photos lift up to 48px and rotate 18deg as they spread,
   which carried their corners over "Join the Waitlist" and swallowed taps.
   Keep the button above the fan. Page black behind it only shows where a
   photo passes underneath, so the label stays legible. */
.join .btn{z-index:2;background:var(--black)}

/* Team: auto-fit produced a 3 + 1 split between about 810px and 1090px,
   leaving the fourth card alone. Use 1, 2 or 4 columns only. */
.team{grid-template-columns:minmax(0,1fr)}
@media(min-width:560px){.team{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1100px){.team{grid-template-columns:repeat(4,minmax(0,1fr))}}

/* BTS strip: the poster is portrait inside a very wide, short frame, so the
   centre crop showed torsos. Heads run from about 40% to 47% down the photo; 43% centres them in the thin desktop strip. */
.grw-bts__poster{object-position:50% 43%}

/* Screen-reader-only text (films page <h1>) */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* BTS strip: 20% taller than before (was clamp(110px,16vw,190px)), and the
   photo slideshow layers. Slides cut, they do not fade: a hard change every
   0.6s reads as a contact sheet flipping, a fade would just look soft. */
.grw-bts__frame{height:clamp(132px,19.2vw,228px)}
.grw-bts__slide{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:grayscale(1) contrast(1.06) brightness(.92);opacity:0}
.grw-bts__slide.is-on{opacity:1}
.grw-bts.is-slides .grw-bts__poster{opacity:0}

/* Actor Access is switched off in build.py until the real code/link exist.
   .grw-access is display:flex, which would beat the UA [hidden] rule. */
.grw-access[hidden]{display:none}

/* Form helper line under a field, and shorter textareas for one-line-ish answers */
.grw-help{margin-top:.55rem;font-size:var(--b-xs);color:var(--grey-strong);line-height:1.5}
.grw-field textarea.grw-short{min-height:5.5em;height:5.5em}

/* Film card previews, Apple TV-style: no zoom on hover, and the clip fades in
   over the still only once it is really playing (site.js adds .is-prev-on).
   The still never fades out, so there is no dip to black mid-crossfade. */
.grw-fc.is-hot .grw-fc__poster,.grw-fc.is-hot .grw-fc__prev{transform:none}
.grw-fc__prev{transition:opacity 1.15s cubic-bezier(.33,0,.15,1)}
.grw-fc.has-prev.is-hot .grw-fc__prev,.grw-fc.has-prev.is-live .grw-fc__prev{opacity:0}
.grw-fc.has-prev.is-hot .grw-fc__poster,.grw-fc.has-prev.is-live .grw-fc__poster{opacity:1}
.grw-fc.has-prev.is-prev-on .grw-fc__prev{opacity:1}

/* BTS strip photo credit: bottom right, small and quiet, and vertically
   centred on the "/ Behind the scenes" caption. The caption gets an explicit
   line box; the credit is anchored at the caption's centre line and pulled
   down half its own height, so the two centres match at any size. */
.grw-bts__cap{line-height:1.6}
.grw-bts__credit{position:absolute;z-index:2;pointer-events:none;margin:0;
  right:calc(clamp(10px,1.6vw,18px) + 56px);
  bottom:calc(clamp(10px,1.6vw,16px) + var(--b-xs) * .8);transform:translateY(50%);
  font-size:.6875rem;line-height:1.3;letter-spacing:.04em;color:var(--secondary);
  opacity:.55;text-align:right}
/* Phones: caption + credit + button do not fit one row. The play/pause button
   moves to the top-right corner, and the credit wraps to two short lines
   that stay centred on the caption. */
@media (max-width:640px){
  .grw-bts__btn{top:clamp(10px,1.6vw,16px);bottom:auto}
  .grw-bts__credit{right:clamp(10px,1.6vw,18px);font-size:.625rem;max-width:9.5rem}
}

/* Actor Access sits about 20% smaller than Play Film: type and side padding
   scale down, while the height stays locked to Play Film through --grw-ctlh. */
.grw-cta .grw-access__open,.grw-cta .grw-access__dl{font-size:calc(var(--b-xs) * .86);
  letter-spacing:.07em;padding-left:1.3rem;padding-right:1.3rem}
/* The slot stacks button, code box and gallery link in one grid cell; without
   this the button stretched to the code box's width and looked oversized. */
.grw-cta .grw-access__slot{justify-items:start}
@media(max-width:860px) and (max-height:560px){
  .grw-cta .grw-access__open,.grw-cta .grw-access__dl{padding-left:.9rem;padding-right:.9rem}
}

/* Privacy page body copy */
.legal h2{margin:clamp(34px,4vw,48px) 0 .8rem;font-size:var(--b-xl);font-weight:500;color:var(--white)}
.legal p{max-width:68ch;color:var(--grey-medium);line-height:1.7}
.legal p a,.foot__legal{color:inherit;text-decoration:underline;text-underline-offset:3px}

/* Privacy choices switch (privacy page) */
.legal .choices{margin-top:1.2rem;display:flex;flex-wrap:wrap;align-items:center;gap:14px}
.legal .choices__state{color:var(--secondary);font-size:var(--b-s)}

/* Process steps: one thin, quiet line under each title */
.step__d{margin:.7rem 0 0;max-width:30ch;font-size:var(--b-xs);font-weight:300;line-height:1.55;
  color:var(--grey-medium)}

/* Film cards: genre and runtime under the title row, same quiet weight as the year */
.grw-fc__g{display:block;margin-top:.35rem;font-size:var(--b-xs);color:var(--soft);letter-spacing:.04em}

/* About "Who it's for": a pair of outline buttons (white line, red flood on hover) */
.cta-pair{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(28px,3.4vw,44px)}
.cta-pair .btn{margin-top:0}
.btn--line{position:relative;overflow:hidden;z-index:0;background:transparent;
  border:1px solid var(--white);color:var(--white);
  transition:color .9s cubic-bezier(.22,.72,.2,1),border-color .9s cubic-bezier(.22,.72,.2,1)}
.btn--line::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--bold);
  transform:scaleX(0);transform-origin:left center;transition:transform 1.05s cubic-bezier(.22,.72,.2,1)}
@media(hover:hover){.btn--line:hover{border-color:var(--bold)}.btn--line:hover::before{transform:scaleX(1)}}
.btn--line:focus-visible::before{transform:scaleX(1)}
/* Equal line boxes so the step titles stay level when one line wraps longer */
@media(min-width:600px){.step__d{min-height:calc(1.55em * 3)}}

/* Waitlist on phones: a panel that drops in from the top instead of a bottom
   sheet, so it sits high on the screen and stays clear of the keyboard. */
@media (max-width:860px){
  /* Opens centred (site.js sets --wg-top from the real sheet height). After
     the globe has flown to the visitor's city, the rest of the questions
     open and the whole sheet glides up to the top (--wg-top -> 10px). */
  .wg{align-items:flex-start;padding:0 10px}
  .wg__dialog{margin-top:max(calc(env(safe-area-inset-top,0px) + 10px),var(--wg-top,10px));
    max-height:calc(100svh - env(safe-area-inset-top,0px) - 20px);border-width:1px;
    transform:translateY(16px);
    transition:opacity var(--wg-in) var(--wg-soft),transform var(--wg-slow) var(--wg-ease),
      margin-top 1s cubic-bezier(.22,.61,.36,1)}
  .wg.is-open .wg__dialog{transform:none}
  .wg__grip{display:none}
}

/* Fullscreen (Play Film / the fullscreen button) AND a phone turned sideways
   (.is-land): the overlay layout at EVERY
   width. A phone on its side is still under 861px, where the copy and controls
   normally sit below the picture and never hide, so without this the title,
   description and buttons stayed on screen over the film. Here the picture
   fills the screen and everything else fades while it plays (site.js toggles
   .is-ui: a tap or mouse move brings it back, it never hides while paused). */
.grw-theater:is(.is-fs,.is-land) .grw-theater__stage{display:block;width:100vw;height:100vh;height:100dvh;background:#000}
.grw-theater:is(.is-fs,.is-land) .grw-theater__frame{position:absolute;inset:0;display:block;width:100%}
.grw-theater:is(.is-fs,.is-land) .grw-theater__media{position:absolute;inset:0;width:100%;height:100%;
  max-height:none;aspect-ratio:auto}
.grw-theater:is(.is-fs,.is-land) .grw-theater__ui{position:absolute;left:0;right:0;bottom:0;top:auto;
  flex:0 0 auto;overflow:visible;
  padding-left:max(clamp(18px,4vw,34px),env(safe-area-inset-left,0px));
  padding-right:max(clamp(18px,4vw,34px),env(safe-area-inset-right,0px));
  padding-bottom:max(clamp(16px,3vw,30px),env(safe-area-inset-bottom,0px));
  background:linear-gradient(transparent,rgba(3,3,3,.62) 38%,rgba(3,3,3,.93));
  opacity:0;transform:translateY(12px);pointer-events:none;
  transition:opacity .6s var(--grw-ease),transform .6s var(--grw-ease)}
.grw-theater:is(.is-fs,.is-land).is-ui .grw-theater__ui{opacity:1;transform:none;pointer-events:auto}
.grw-theater:is(.is-fs,.is-land) .grw-theater__x,.grw-theater:is(.is-fs,.is-land) .grw-theater__hint{transition:opacity .6s var(--grw-ease)}
.grw-theater:is(.is-fs,.is-land):not(.is-ui) .grw-theater__x,
.grw-theater:is(.is-fs,.is-land):not(.is-ui) .grw-theater__hint{opacity:0;pointer-events:none}
.grw-theater:is(.is-fs,.is-land):not(.is-ui) .grw-theater__stage{cursor:none}

/* Play Film stays put after it is pressed (it used to fade, which left Actor
   Access sitting alone in the row). Pressing it again restarts the film. */
.grw-theater.is-cta-done .grw-cta__play{opacity:1;visibility:visible}

/* Letterbox bands are black once the film is up (see site.js has-frame). */
.grw-theater.has-frame .grw-theater__video{background:#000}
