/* ============================================================
   CASE STUDY — /work/<client>
   Layered on css/home.css, which brings the tokens, the glass, the nav spine,
   the beacon, the sun and moon, the frames and the footer. Only what is
   specific to a case study lives here.
   ============================================================ */

/* ---------- the hero ----------
   The picture peeled off the phone on the way here and was held in the middle
   of the screen. It arrives at exactly that size and place, then travels into
   its frame as the page settles. js/work.js measures it; CSS carries the
   easing only. */
.case{padding-top:calc(var(--nav-h) + clamp(28px,5vh,64px))}
.case__hero{position:relative;display:block}
.case__head{display:flex;flex-direction:column;align-items:flex-start}
.case__eyebrow{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.case__title{
  font-size:clamp(52px,9vw,132px);font-weight:700;
  letter-spacing:-.045em;line-height:.94;text-wrap:balance;
}
.case__place{margin-top:16px;font-size:var(--fs-lede);opacity:.62;max-width:26ch}
/* the frame the hero settles into */
.case__shot{
  position:relative;width:100%;
  margin-top:clamp(28px,4.5vw,64px);
  transform-origin:50% 50%;will-change:transform;
}
.case__shot .frame{width:100%}
.case__shot img{display:block;width:100%;height:auto}
/* the one element the navigation morphs into */
.case__shot img{view-transition-name:work-hero}
/* a hero with a film (js/case-clip.js): the film fades in over its still */
.case__clip{position:relative;overflow:hidden}
.case__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .8s var(--ease-out)}
.case__clip.is-live .case__video{opacity:1}
/* .case--arriving: the hero is held over the viewport with no easing, because
   the browser is either about to photograph it for the morph, or we are one
   frame away from letting go. The page waits behind it. */
.case--arriving .case__body,.case--arriving .case__eyebrow,.case--arriving .case__title,.case--arriving .case__place{
  opacity:0;transform:translateY(14px);
}
/* .case--zoom: the easing is installed, ready for the trip back out */
.case--zoom .case__shot{transition:transform .9s var(--ease-out)}
.case__body,.case__eyebrow,.case__title,.case__place{
  transition:opacity .6s var(--ease) .3s,transform .6s var(--ease) .3s;
}
/* .case--landed: home, and the page arrives around it */
.case--landed .case__body,.case--landed .case__eyebrow,.case--landed .case__title,.case--landed .case__place{
  opacity:1;transform:none;
}

/* ---------- a film behind the hero ----------
   The photograph stays in charge of the frame: it sizes it, it is what the
   homepage morphs into and out of, and it is all anyone sees until the player
   underneath has a real video loaded (js/case-film.js). Then it fades, the way
   a poster gives way to its clip everywhere else on the site (.frame.is-live),
   and the player takes the clicks. */
.case__film iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:0}
.case__film img{position:relative;z-index:1;transition:opacity var(--t-slow) var(--ease)}
.case__film.is-live img{opacity:0;pointer-events:none}
/* leaving: the photograph is back at once, so the morph home has a picture */
.case__film.is-leaving img{opacity:1;transition:none}

/* ---------- the standfirst ----------
   The story is the biggest thing on the page after the title, so it is set as
   a statement rather than a paragraph. Three kinds of emphasis, each with one
   job, so the words that matter can be found at a glance:
     mark    the headline result, one per story
     strong  the specifics that back it up; the numbers, where there are any
     em      the "before", or the client's own words
   The highlight is the brand's one accent, used as a block the way the glyph
   quarter uses it. The ink on it stays near-black in both themes: white on
   that green would all but disappear. There is no italic cut of Helvetica
   Neue loaded, so em is the browser's slant of the upright; Helvetica's own
   italic is an oblique of the roman, so the two barely differ. */
/* It runs the full measure: a short story set large, not a narrow column
   with the right half of the page empty beside it. */
.case__lede{
  margin-top:var(--s-sec);max-width:none;
  font-size:clamp(28px,3.3vw,50px);font-weight:300;
  letter-spacing:-.035em;line-height:1.12;text-wrap:pretty;
}
.case__lede strong{font-weight:700}
.case__lede em{font-style:italic}
.case__lede mark{
  background:var(--green);color:#0A0A0C;
  padding:0 .08em;margin:0 -.02em;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
.case__lede .fn{font-size:.42em}

/* ---------- who the client is, above the fold ----------
   Industry beside location, under the title. It keeps .case__place so it
   arrives with the rest of the head (work.js). */
/* Quieter than the title (Aston, 2026-09-30: "too bold and hard to
   read"): the values in a softer ink, not opacity, which the arrival above
   sets back to 1; and a clear gap under the title's descenders. */
.case__facts{display:flex;flex-wrap:wrap;gap:20px clamp(28px,4vw,56px);max-width:none;margin-top:clamp(28px,3.2vw,48px);font-size:clamp(16px,1.15vw,18px)}
.case__facts div{display:flex;flex-direction:column;gap:6px}
.case__facts dt{opacity:.62}
.case__facts dd{margin:0;color:rgba(var(--ink-rgb),.6)}

/* ---------- what we did ---------- */
/* A case page has no .sec__head, so its section labels miss the rule that
   sets the glyph beside the words rather than on top of them. */
.did > .label,.results > .label,.next .label{display:inline-flex;align-items:center;gap:12px}
.did{margin-top:var(--s-sec)}
.did__list{margin-top:var(--s-block);border-top:var(--hair)}
.did__row{
  display:grid;grid-template-columns:2.6em minmax(0,1.1fr) minmax(0,1.4fr);
  gap:clamp(16px,3vw,48px);align-items:start;
  padding:22px 0;border-bottom:var(--hair);
}
.did__row h3{font-size:var(--fs-h3);font-weight:400;letter-spacing:-.02em}
.did__row p{font-size:var(--fs-body);opacity:.7;line-height:1.6;max-width:44ch}

/* ---------- the work ---------- */
.shots{margin-top:var(--s-sec);display:flex;flex-direction:column;gap:clamp(40px,6vw,96px)}
.shot--wide{max-width:100%}
.shot--tall{width:min(100%,var(--tallw,340px))}
.shot--tall.shot--right{margin-left:auto}
.shot__cap{
  display:flex;justify-content:space-between;gap:16px;
  padding-top:12px;font-size:12px;opacity:.6;
}
.shots img:not(.mark){display:block;width:100%;height:auto}
/* Square feed ads, side by side at their own shape. A square in a wide frame
   loses the words printed on it; a square pair reads as the feed it ran in. */
.shots__pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,2.4vw,32px)}

/* ---------- results and words ----------
   Both stay hidden until real, attributable figures and a real quote exist.
   Remove the hidden attribute in the markup once they do — nothing here
   invents a number. */
.results{margin-top:var(--s-sec)}
.results__row{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  border-top:var(--hair);
}
/* a row with two real figures beats a row of three with one padded out; one
   figure gets the whole row, set large, with its note beneath */
.results__row--2{grid-template-columns:repeat(2,minmax(0,1fr))}
.results__row--1{grid-template-columns:minmax(0,1fr)}
.results__row--1 .results__n{font-size:var(--fs-num)}
.results__item{
  padding:28px clamp(16px,2vw,32px) 30px;
  border-left:var(--hair);display:flex;flex-direction:column;gap:12px;
  container-type:inline-size;
}
.results__item:first-child{border-left:0;padding-left:0}
.results__n{font-size:var(--fs-num);font-size:min(var(--fs-num),27cqw);font-weight:300;letter-spacing:-.05em;line-height:.9;white-space:nowrap}
/* The fine print: where the figures came from and over what period, kept
   out of the story and the numbers so neither has to carry a date. Small and
   faint, at the site's usual caption contrast, but still plain text to read. */
.case__notes{margin-top:var(--s-sec);max-width:72ch;font-size:12px;line-height:1.6;opacity:.62}
.case__notes p + p{margin-top:8px}
.fn{font-size:.55em;line-height:0;vertical-align:super;margin-left:.08em}
.fn a{color:inherit;text-decoration:none}


/* ---------- social pages (/social/<client>) ----------
   The work is vertical video, so the hero is three reels side by side, each
   in its own 9:16 frame with the poster giving way to the loop the way it
   does on the homepage wall, and the rest follow further down with their
   titles. The frames themselves (.reels, .reel, the sound pill and the
   hearts) are shared with the organic social service page and live in
   home.css. */
.case__shot--reels .frame{width:100%}
.shots--reels{display:block}
.shots--reels > .label{display:inline-flex;align-items:center;gap:12px}
.shot--reel{width:auto;margin:0}
.shot--reel .shot__cap{opacity:.7}
/* one morph target: the first poster is what the row on /digital-marketing
   turns into. Three imgs with the same view-transition-name would fight. */
.case__shot--reels img{view-transition-name:none}
.case__shot--reels .frame:first-child img{view-transition-name:work-hero}
.next__shot--tall{width:clamp(110px,13vw,180px)}
@media (max-width:620px){
  .next__shot--tall{width:min(48vw,200px)}
}

/* ---------- next case ----------
   Its image carries the same morph onward, so the effect chains. */
.next{margin-top:var(--s-sec);padding-top:var(--s-block);border-top:var(--hair)}
.next__link{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(20px,4vw,64px);align-items:center;
}
.next__client{display:block;font-size:var(--fs-h2);font-weight:700;letter-spacing:-.04em;line-height:1;margin-top:14px}
.next__shot{width:clamp(150px,20vw,260px);flex:none}
/* without this the thumbnail renders at its intrinsic 1800px and the frame
   clips a random sliver out of the left edge */
.next__shot img{display:block;width:100%;height:auto}
.next__link:hover .next__client,.next__link:focus-visible .next__client{opacity:.62}
.next__client{transition:opacity var(--t-fast) var(--ease)}

/* ---------- narrow ---------- */
@media (max-width:900px){
  .case__shot{margin-top:clamp(22px,5vw,36px)}
  .did__row{grid-template-columns:2.2em minmax(0,1fr);row-gap:8px}
  .did__row p{grid-column:2}
  .shot--tall{width:min(100%,300px)}
}
@media (max-width:620px){
  /* two squares at half a phone's width would shrink the ads' own words too
     far to read, so they stack */
  .shots__pair{grid-template-columns:1fr}
  .results__row{grid-template-columns:1fr}
  .results__item{border-left:0;padding-left:0;padding-right:0;border-top:var(--hair)}
  .results__item:first-child{border-top:0}
  .next__link{grid-template-columns:1fr;gap:22px}
  .next__shot{width:min(72vw,320px)}
}

/* ---------- reduced motion ----------
   No zoom-out: the hero is simply where it belongs from the first frame. */
@media (prefers-reduced-motion:reduce){
  .case__shot{transition:none!important;transform:none!important}
  .case__body,.case__eyebrow,.case__title,.case__place{
    opacity:1!important;transform:none!important;transition:none!important;
  }
}

/* ---------- a paid media case study: the searches ----------
   An illustration of the search a client's ad appears for: the query types
   itself into the bar and the client's ad sits first, marked Sponsored.
   The searches are real (from the account), and so are the ads where we
   have them, one per search; otherwise the listing is drawn from the
   client's own site. Never invented ad copy, and the note says so. Under
   the ad two competitors fade away, as placeholders with no words. No brand
   of Google's is drawn: a neutral bar, a neutral page. js/serp.js cycles the
   queries; without it (or with reduced motion) the first query stands. */
.serp,.gallery{margin-top:var(--s-sec)}
.serp > .label,.gallery > .label{display:inline-flex;align-items:center;gap:12px}
.serp .h2,.gallery .h2{margin-top:var(--s-block)}
.serp__grid{margin-top:var(--s-block);display:grid;gap:clamp(28px,4vw,64px);align-items:center}
@media (min-width:900px){.serp__grid{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}}
.serp__card{
  margin:0;padding:clamp(18px,2.4vw,32px);border-radius:22px;
  background:#fff;color:#1f1f23;border:1px solid rgba(10,10,12,.08);
  box-shadow:0 40px 80px -48px rgba(var(--shadow-rgb),.45),0 8px 24px -18px rgba(var(--shadow-rgb),.3);
  font-family:inherit;
}
.serp__bar{
  display:flex;align-items:center;gap:12px;min-height:52px;padding:0 20px;
  border-radius:999px;border:1px solid rgba(10,10,12,.12);
  box-shadow:0 2px 8px -4px rgba(10,10,12,.25);
  font-size:clamp(15px,1.3vw,18px);letter-spacing:-.005em;
}
.serp__icon{width:18px;height:18px;flex:none;fill:none;stroke:#70757a;stroke-width:2;stroke-linecap:round}
.serp__q{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.serp__caret{width:1.5px;height:1.2em;background:#1f1f23;flex:none;margin-left:-8px;animation:serp-caret 1s steps(1) infinite}
@keyframes serp-caret{50%{opacity:0}}
/* every ad in one cell, so the card is as tall as the longest and never
   jumps; the one for the search on screen shows */
.serp__ads{display:grid;margin-top:clamp(20px,2.4vw,30px);transition:opacity .35s var(--ease)}
.serp__card.is-typing .serp__ads{opacity:.25}
.serp__ad{grid-area:1/1;align-self:start;padding:clamp(14px,1.6vw,20px);border-radius:14px;background:rgba(0,255,72,.07);box-shadow:inset 0 0 0 1px rgba(0,160,50,.22);opacity:0;visibility:hidden;transition:opacity .3s var(--ease),visibility 0s linear .3s}
.serp__ad.is-on{opacity:1;visibility:visible;transition:opacity .3s var(--ease),visibility 0s}
.serp__spons{display:block;font-size:12px;font-weight:600;letter-spacing:.01em;color:#1f1f23}
.serp__site{display:flex;align-items:center;gap:10px;margin-top:10px;min-width:0}
.serp__fav{width:28px;height:28px;border-radius:50%;flex:none;display:grid;place-items:center;background:#0a0a0c;color:#fff;font-size:12px;font-weight:600}
.serp__who{display:flex;flex-direction:column;line-height:1.25;font-size:13px;min-width:0}
.serp__who span{opacity:.62;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.serp__title{margin-top:8px;font-size:clamp(18px,1.7vw,22px);line-height:1.3;color:#1a0dab}
.serp__sep{color:#70757a}
.serp__desc{margin-top:6px;font-size:14px;line-height:1.5;color:#4d5156}
/* the competitors: the same listing, drawn in placeholders and fading
   out down the page (Aston, 2026-09-30) */
.serp__rivals{
  display:flex;flex-direction:column;gap:clamp(16px,1.8vw,22px);
  margin-top:clamp(16px,1.8vw,22px);padding:0 clamp(14px,1.6vw,20px);
  -webkit-mask-image:linear-gradient(to bottom,#000,rgba(0,0,0,.45) 50%,transparent 96%);
  mask-image:linear-gradient(to bottom,#000,rgba(0,0,0,.45) 50%,transparent 96%);
}
.serp__rival{opacity:.6}
.serp__rival .serp__fav{background:#dadce0;color:#5f6368}
.serp__rival .serp__who i{display:block;width:9em;height:.62em;margin-top:5px;border-radius:4px;background:rgba(10,10,12,.1)}
.serp__rival .serp__title i{display:block;width:74%;height:.72em;margin-top:.4em;border-radius:5px;background:rgba(26,13,171,.16)}
.serp__rival .serp__desc i{display:block;height:.62em;margin-top:.6em;border-radius:4px;background:rgba(10,10,12,.08)}
.serp__rival .serp__desc i + i{width:58%}
.serp__say{font-size:clamp(21px,2vw,30px);font-weight:300;line-height:1.3;letter-spacing:-.02em;max-width:34ch}
.serp__say strong{font-weight:600}
.serp__list{margin:clamp(20px,2.4vw,30px) 0 0;padding:0;list-style:none;border-top:var(--hair)}
.serp__list li{padding:11px 0;border-bottom:var(--hair);font-size:var(--fs-body);transition:opacity var(--t-fast) var(--ease)}
.serp__list li::before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;margin:0 12px 2px 0;background:currentColor;opacity:.25;vertical-align:middle}
.serp__list li.is-on::before{background:var(--green);opacity:1}
.serp__note{margin-top:16px;opacity:.62}
@media (prefers-reduced-motion:reduce){.serp__caret{animation:none}}

/* ---------- their work ----------
   Photographs from the client's own site, with their permission: what the
   ads are selling. Two across, a tall one allowed. */
.gallery__grid{margin-top:var(--s-block);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,2.4vw,32px);align-items:start}
.gallery__item{margin:0}
.gallery__item img{display:block;width:100%;height:auto}
.gallery__item figcaption{padding-top:12px;opacity:.6}
.gallery__item--tall{grid-row:span 2}
@media (max-width:620px){.gallery__grid{grid-template-columns:1fr}.gallery__item--tall{grid-row:auto}}
/* a store's range (Sea Storm, Sea Weeds): packshots in a shop's grid, four across, two on a phone */
.gallery__grid--products{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:900px){.gallery__grid--products{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* three across (an ad carousel's cards, in order) */
@media (min-width:621px){.gallery__grid--three{grid-template-columns:repeat(3,minmax(0,1fr))}}

/* ---------- a cut-out hero ----------
   A product photographed on transparency (Triple H's lockers) stands on the
   page rather than in a box, and the page draws its shadow, as it does for
   the gold pieces. */
.case__shot--cutout{display:grid;place-items:center;padding:clamp(28px,5vw,72px) 0 clamp(36px,5vw,72px)}
.case__shot--cutout img{width:min(100%,1000px);height:auto;position:relative;z-index:1;view-transition-name:none}
.case__shot--cutout::after{
  content:"";position:absolute;left:18%;right:18%;bottom:clamp(20px,3.4vw,52px);height:clamp(18px,2.4vw,36px);border-radius:50%;
  background:radial-gradient(ellipse at 50% 50%,rgba(var(--shadow-rgb),.4),rgba(var(--shadow-rgb),.12) 50%,rgba(var(--shadow-rgb),0) 72%);
}

/* ---------- a client with more than one service ----------
   One page per client (Aston, 2026-09-28). Each service is a chapter, the
   biggest first: its count ("02 / 03"), its name set large, and, after the
   first, the service's own standfirst, a size down from the page's. The head
   draws no rule: the first block inside it has its own. */
.chapter{margin-top:var(--s-sec);scroll-margin-top:calc(var(--nav-h) + 24px)}
.chapter__head > .label{display:inline-flex;align-items:center;gap:12px}
.chapter__title{
  margin-top:clamp(12px,1.4vw,22px);
  font-size:clamp(44px,7vw,112px);font-weight:700;
  letter-spacing:-.045em;line-height:.94;text-wrap:balance;
}
.case__lede.case__lede--chapter{margin-top:clamp(24px,3vw,44px);font-size:clamp(24px,2.6vw,40px)}
/* the first block of a chapter follows its head closely; the chapters
   themselves keep the page's long pause between them */
.chapter__head + section,.chapter__head + aside{margin-top:var(--s-block)}
/* no "What we did" label in a chapter: its line sits right under the name
   as the name's subheading, and the rows follow at the usual distance */
.chapter__head + .did--in{margin-top:clamp(20px,2.4vw,36px)}
.did--in > .h2{margin-top:0}
/* the services in the facts under the title jump to their chapters */
.case__facts dd a{text-decoration:underline;text-underline-offset:.2em;text-decoration-thickness:1px;text-decoration-color:rgba(var(--ink-rgb),.28);transition:color .2s var(--ease),text-decoration-color .2s var(--ease)}
.case__facts dd a:hover,.case__facts dd a:focus-visible{color:var(--ink);text-decoration-color:currentColor}

/* ---------- the Google Partner badge ----------
   Beside every Google search a case study shows (Aston, 2026-09-29). It is
   Google's mark, so it keeps its own colours on a white plate in both
   themes, as it does on /paid-media. */
.serp__partner{display:inline-flex;margin:clamp(22px,2.6vw,32px) 0 0;background:#fff;border:var(--hair);border-radius:10px;padding:7px 11px}
.serp__partner img{display:block;width:auto;height:42px}
@media (max-width:640px){.serp__partner img{height:36px}}

/* ---------- a row about a part of the site ----------
   Aston (2026-09-29): a screenshot belongs beside the words about that part
   of the site, not on its own at the foot of a section. The heading and the
   words share the middle column; the screenshot of the live page takes the
   right, where a plain row has its paragraph, so the list keeps one grid. */
.did__row--shot{align-items:start}
.did__text p{margin-top:12px}
.did__shot{margin:0}
.did__shot img{display:block;width:100%;height:auto}
.did__shot figcaption{padding-top:10px;opacity:.62}
@media (max-width:900px){.did__row--shot .did__shot{grid-column:2;margin-top:10px}}

/* ---------- the Next link names the next client's industry ---------- */
.next__industry{display:block;margin-top:12px;font-size:var(--fs-body);opacity:.62}

/* ---------- a free 15-minute consult ----------
   On every case study (Aston, 2026-09-29): a band across the whole page in
   its colours turned over, dark in light mode and light in dark mode, as the
   price band on /social-media-management is. The tokens are swapped inside
   it, so everything in the band follows. It reaches out of the case's
   column to the edges of the window; the page clips sideways overflow. */
.consult{
  --paper:#0A0A0C; --ink:#F6F5F8;
  --paper-rgb:10,10,12; --ink-rgb:246,245,248;
  --line:rgba(246,245,248,.2);
  margin:var(--s-sec) calc(50% - 50vw) 0;
  padding-block:clamp(64px,8vw,120px);
  background:var(--paper);color:var(--ink);
}
:root[data-theme="dark"] .consult{--paper:#F6F5F8;--ink:#0A0A0C;--paper-rgb:246,245,248;--ink-rgb:10,10,12;--line:rgba(10,10,12,.2)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .consult{--paper:#F6F5F8;--ink:#0A0A0C;--paper-rgb:246,245,248;--ink-rgb:10,10,12;--line:rgba(10,10,12,.2)}
}
.consult__in > .label{display:inline-flex;align-items:center;gap:12px}
.consult__say{
  margin-top:clamp(22px,2.6vw,36px);max-width:24ch;
  font-size:clamp(30px,3.6vw,56px);font-weight:300;
  letter-spacing:-.035em;line-height:1.1;text-wrap:balance;
}
.consult__say strong{font-weight:700}
.consult__more{margin-top:clamp(18px,2vw,28px);max-width:52ch;font-size:clamp(17px,1.4vw,21px);line-height:1.5;opacity:.8}
.consult__more strong{font-weight:600}
/* the button and its calendar dialog are in home.css: the homepage books too */
@media (min-width:900px){
  .consult__in{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);column-gap:clamp(48px,6vw,120px);align-items:end}
  .consult__in > .label{grid-column:1 / -1;justify-self:start}
  .consult__say{grid-column:1;grid-row:2 / span 2;max-width:none}
  .consult__more{grid-column:2;grid-row:2;max-width:none}
  .consult__btn{grid-column:2;grid-row:3;justify-self:start}
}


/* ---------- a carousel ----------
   More than three pictures of the work in one row that scrolls sideways
   (scripts/work/build.js, carouselBlock; Aston, 2026-09-29: a wall of ads
   "gets cluttered and is overwhelming"). Every picture at one height and
   its own shape, a wide one capped so the next always shows at the edge.
   The count and the arrows sit on the label's line (js/carousel.js); the
   row scrolls by itself too, by trackpad, swipe or the arrow keys. */
.carousel{margin-top:var(--s-sec)}
.carousel__head{display:flex;justify-content:space-between;align-items:center;gap:16px}
.carousel__head > .label{display:inline-flex;align-items:center;gap:12px}
.carousel .h2{margin-top:var(--s-block)}
.carousel__nav{display:flex;align-items:center;gap:10px;visibility:hidden}
.carousel.is-ready .carousel__nav{visibility:visible}
.carousel.is-static .carousel__nav{visibility:hidden}
.carousel__count{min-width:5.5em;text-align:right;font-variant-numeric:tabular-nums;opacity:.62}
.carousel__count b{font-weight:inherit;opacity:1}
.carousel__btn{
  width:44px;height:44px;border-radius:50%;display:grid;place-items:center;flex:none;
  border:0;padding:0;background:rgba(var(--ink-rgb),.07);color:var(--ink);cursor:pointer;
  transition:background var(--t-fast) var(--ease),opacity var(--t-fast) var(--ease);
}
.carousel__btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.carousel__btn:disabled{opacity:.28;cursor:default}
.carousel__btn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
@media (hover:hover){.carousel__btn:not(:disabled):hover{background:rgba(var(--ink-rgb),.14)}}
.carousel__track{
  --h:clamp(320px,34vw,500px);
  position:relative;margin-top:var(--s-block);
  display:flex;align-items:flex-start;gap:clamp(12px,1.6vw,24px);
  overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;scrollbar-width:none;
}
.carousel__track::-webkit-scrollbar{display:none}
.carousel__track:focus-visible{outline:2px solid var(--ink);outline-offset:6px}
.carousel__track.is-dragging{scroll-snap-type:none;cursor:grabbing}
.carousel__track.is-dragging *{pointer-events:none}
@media (hover:hover) and (pointer:fine){.carousel__track{cursor:grab}}
.carousel__item{flex:none;margin:0;scroll-snap-align:start;width:min(calc(var(--h) * (var(--ar))),86%)}
.carousel__item > .frame{width:100%;aspect-ratio:var(--ar);height:auto}
.carousel__item > .frame img{display:block;width:100%;height:100%;object-fit:cover;-webkit-user-drag:none}
.carousel__item.shot--reel .shot__cap{opacity:.7}
@media (max-width:620px){
  .carousel__track{--h:min(118vw,420px)}
  .carousel__btn{width:38px;height:38px}
  .carousel__count{min-width:4.5em}
}

/* "Free 15-minute" in the consult band's label, highlighted green (Aston,
   2026-09-29), as the story voice's highlighter is */
.consult .label mark{background:var(--green);color:#0A0A0C;padding:.12em .3em;margin:0 .05em 0 -.05em}
