/* ============================================================
   drobe.media — recreation
   Tokens lifted from the live site: ink #262626 (#1C1C1C on the
   original, lifted a step so it separates from --ink-deep), cream #F6EDE2,
   orange #FF7125. Display face is Area Variable on the original
   (Typekit); Bricolage Grotesque is the site's own declared
   fallback, so we use it here.
   ============================================================ */

:root{
  /* a touch off black: against --ink-deep the old #1c1c1c was 1.12:1,
     too close to read as a separate surface */
  --ink:        #262626;
  --ink-deep:   #101010;
  --cream:      #f6ede2;
  --cream-dim:  #ebe3d8;
  --orange:     #ff7125;
  --orange-dim: #ff8a4c;

  --line-light: rgba(246,237,226,.16);
  --line-dark:  rgba(38,38,38,.16);

  --display: "Bricolage Grotesque", "Helvetica Neue", Arial, sans-serif;
  --label:   "Barlow Semi Condensed", "Helvetica Neue", Arial, sans-serif;

  /* every contained box; full-bleed things (hero, section bands)
     stay square */
  --radius: 6px;

  /* the reading measure for a section heading and its paragraph */
  --measure: 32.8rem;

  --gutter: clamp(20px, 5vw, 64px);
  --maxw: 1240px;

  /* The width one cell WOULD have in a five-across row: the wrap's
     content less four gaps, over five. This is a size reference, not a
     description of the grid - a .step row is three across, and fewer
     than five in a row is still measured as though there were five, so
     the figures never inflate to fill a wider column. Kim's rule. */
  --step-cell: calc(
    (min(100vw, var(--maxw)) - 2 * var(--gutter) - 4 * clamp(12px, 1.6vw, 24px)) / 5
  );
  --nav-h: 76px;
}

*,*::before,*::after{box-sizing:border-box}

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}

body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:var(--display);
  font-size:20px;
  font-weight:400;
  line-height:1.5;
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased;
}

img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}

.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}

.skip{
  position:absolute;left:-9999px;top:0;z-index:999;
  background:var(--orange);color:var(--ink);padding:12px 20px;
}
.skip:focus{left:0}

:focus-visible{outline:2px solid var(--orange);outline-offset:3px}

/* ---------- type ---------- */

h1,h2,h3,h4{font-family:var(--display);font-weight:800;margin:0;letter-spacing:.01em}

.h-hero{
  font-size:clamp(2.64rem,7.04vw,4.84rem);   /* +10% */
  line-height:1.02;
  letter-spacing:.02em;
  color:var(--cream);
  max-width:15ch;
}
.h-1{font-size:clamp(2rem,4.6vw,3.4rem);line-height:1.06;max-width:var(--measure)}
/* weight and family of its own, for the same reason as .h-3 below: the
   only .h-2 on the site is a <p>, so with nothing declared it inherited
   body weight and rendered at 400 */
.h-2{font-family:var(--display);font-weight:800;font-size:clamp(1.6rem,3vw,2.35rem);line-height:1.12}
/* carries its own weight and family: the heading element supplied both,
   so on a <p class="h-3"> it used to come out at body weight */
.h-3{font-family:var(--display);font-weight:800;font-size:clamp(1.25rem,2vw,1.6rem);line-height:1.2}

.dot{color:var(--orange)}

.eyebrow{
  font-family:var(--label);
  font-weight:600;
  /* .82rem -> 1.23rem -> back a quarter -> up 15%. The rule and the gap
     are both in em, so they follow: the bar is 27.2px and still 2px. */
  font-size:1.0609rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  display:flex;
  align-items:center;
  gap:.7em;
  margin:0 0 .9rem;
}
.eyebrow::before{
  content:"";
  width:1.6em;height:2px;flex:none;
  background:var(--orange);
  /* radius is clamped to half the shorter side, so 6px on a 2px bar
     renders as a 1px cap - a rounded end, never a rounded rectangle.
     Using the token means the caps follow if the weight ever changes. */
  border-radius:var(--radius);
}
.eyebrow.is-plain::before{display:none}

/* The client's name above a case headline, at the top of the page. It
   used to be .eyebrow.is-plain - the shared eyebrow with its orange bar
   switched off - so it was defined by what it was not. It says what it
   is now, and owns every property rather than inheriting them, so
   changing the section eyebrow cannot move it. The CTA's "Let's work
   together" at the foot of the page is still .eyebrow.is-plain: a
   different line doing a different job. */
.case_client_eyebrow{
  font-family:var(--label);
  font-weight:600;
  /* 1.5x the .82rem it started at: the client's name reads as a line of
     its own above the headline rather than as a kicker on it, while
     still setting on one line on a phone - at 2.46rem "Ministry of
     Foreign Affairs Denmark" ran to four lines at 375px and pushed the
     headline off the first screen */
  font-size:1.23rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--orange);
  margin:0 0 1rem;
}

.lede{font-size:clamp(1.328rem,1.898vw,1.581rem);line-height:1.55;max-width:60ch}
p{margin:0 0 1rem}
p:last-child{margin-bottom:0}

/* ---------- buttons ---------- */

.btn{
  border-radius:var(--radius);
  display:inline-flex;align-items:center;justify-content:center;gap:.6em;
  font-family:var(--label);
  font-weight:600;
  font-size:.95rem;
  letter-spacing:.16em;
  text-transform:uppercase;
  padding:1rem 2.4rem;
  border:1px solid currentColor;
  /* quick, so the hover reads as a response rather than an animation */
  transition:background .18s ease,color .18s ease,border-color .18s ease;
}
.btn--light{color:var(--cream)}
.btn--light:hover{background:var(--cream);color:var(--ink)}
.btn--dark{color:var(--ink)}
/* ink on orange rather than cream or white: 6.4:1, against 2.37 and 2.75 */
.btn--dark:hover{background:var(--orange);border-color:var(--orange);color:var(--ink)}
.btn--solid{background:var(--orange);border-color:var(--orange);color:#fff}
.btn--solid:hover{background:var(--ink);border-color:var(--ink)}

/* ---------- logo ---------- */

.logo{
  display:inline-flex;align-items:baseline;
  font-family:var(--display);
  font-weight:800;
  font-size:1.6rem;
  letter-spacing:.06em;
  line-height:1;
  color:var(--cream);
  position:relative;
}
.logo .mark{position:relative;display:inline-block;padding-inline:.06em}
/* the wordmark on the original is cut by a diagonal stroke */
.logo .mark::after{
  content:"";
  position:absolute;
  left:-6%;right:-6%;top:50%;
  height:3px;
  background:currentColor;
  transform:translateY(-50%) rotate(-9deg);
}
.logo .dot{font-size:1.15em;line-height:0}
.logo--dark{color:var(--ink)}
.logo--lg{font-size:2.6rem}
/* once the real artwork lands the CSS-drawn wordmark gets out of the way */
.logo.has-logo img{height:1.5em;width:auto;display:block}
/* The animated wordmark (the GIF Kim supplied: 480x125, 91 frames).
   A tight crop - the mark fills all but a few pixels of the frame. */
.logo--lg.has-logo img{height:1em}

/* ---------- nav ---------- */

.nav{
  position:fixed;inset:0 0 auto 0;z-index:60;
  height:var(--nav-h);
  display:flex;align-items:center;
  transition:background .3s ease,box-shadow .3s ease;
}
.nav.is-stuck{background:rgba(16,16,16,.92);backdrop-filter:blur(10px)}
.nav__inner{
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
}
.nav__logo{grid-column:2}

.nav__toggle{
  grid-column:3;justify-self:end;
  position:relative;
  width:44px;height:44px;
  color:var(--cream);
}
/* stack the three bars on one centre point so they can fold into an X */
.nav__toggle span{
  position:absolute;
  left:50%;top:50%;
  width:24px;height:2px;
  margin-left:-12px;
  background:currentColor;
  border-radius:var(--radius);
  transition:transform .3s ease,opacity .2s ease;
}
.nav__toggle span:nth-child(1){transform:translateY(-8px)}
.nav__toggle span:nth-child(2){transform:translateY(0)}
.nav__toggle span:nth-child(3){transform:translateY(8px)}
.nav__toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(0) rotate(45deg)}
.nav__toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav__toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(0) rotate(-45deg)}

/* ---------- overlay menu ---------- */

.menu{
  position:fixed;inset:0;z-index:55;
  background:var(--ink-deep);
  /* dark container: give it a colour, or anything inside that does not
     set its own - the social icons did not - inherits the body's ink and
     goes invisible on the black */
  color:var(--cream);
  display:grid;place-items:center;
  opacity:0;visibility:hidden;
  transition:opacity .35s ease,visibility .35s ease;
}
.menu::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(70% 60% at 85% 100%, rgba(255,113,37,.34), transparent 70%);
}
.menu.is-open{opacity:1;visibility:visible}
.menu__list{
  list-style:none;margin:0;padding:0;
  position:relative;z-index:1;
  text-align:center;
}
.menu__list li{overflow:hidden}
.menu__list a{
  display:block;
  font-weight:800;
  font-size:clamp(2rem,7vw,3.6rem);
  line-height:1.24;
  letter-spacing:.02em;
  color:var(--cream);
  transform:translateY(110%);
  transition:transform .5s cubic-bezier(.22,1,.36,1),color .2s ease;
}
.menu.is-open .menu__list a{transform:translateY(0)}
.menu__list a:hover,.menu__list a[aria-current="page"]{color:var(--orange)}
.menu__social{
  position:absolute;bottom:clamp(24px,6vh,56px);left:0;right:0;
  z-index:1;display:flex;justify-content:center;gap:18px;
}

/* ---------- hero ---------- */

.hero{
  position:relative;
  /* dark container: text defaults to cream so nothing inside can
     silently inherit the body's ink and disappear into the image */
  color:var(--cream);
  min-height:clamp(340px,54vh,520px);
  display:flex;align-items:flex-end;
  padding:calc(var(--nav-h) + 40px) 0 clamp(48px,8vh,96px);
  background:var(--ink-deep);
  overflow:hidden;
  isolation:isolate;
}
/* the menu pages' heroes (We Do, Our Work, About, Book Session) take a
   fifth more of the screen than the shared size above, on Kim's call -
   every term of the clamp times 1.2. Case heroes keep the shared size;
   the front page sets its own further down, and wins by coming later. */
.hero:not(.hero--case){min-height:clamp(408px,64.8vh,624px)}
.hero__bg{
  position:absolute;inset:0;z-index:-2;
  background:
    radial-gradient(90% 80% at 80% 110%, rgba(255,113,37,.55), transparent 62%),
    radial-gradient(70% 60% at 12% 0%, rgba(90,110,140,.38), transparent 64%),
    linear-gradient(170deg,#1f2227 0%,#141414 48%,#0d0b0a 100%);
}
/* faint film grain / scanline so the flat gradient reads as footage */
.hero__bg::after{
  content:"";position:absolute;inset:0;
  background-image:repeating-linear-gradient(0deg,rgba(255,255,255,.035) 0 1px,transparent 1px 3px);
  mix-blend-mode:overlay;
}
.hero__veil{
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(10,10,10,.72) 0%,rgba(10,10,10,.15) 55%,transparent 100%);
}

/* real photography / video sits behind the gradient, which then drops
   back to a tint so the warm grade still reads over the footage */
.hero__photo,.hero__video{
  position:absolute;inset:0;z-index:-3;
  width:100%;height:100%;
  object-fit:cover;
  background-size:cover;
  background-position:center;
}
.hero.has-media .hero__bg{opacity:.62}
.hero.has-media .hero__bg::after{opacity:.5}
.hero.has-video .hero__photo{display:none}
.hero__sub{
  margin:1.6rem 0 0;
  font-family:var(--label);
  /* 700 is a real Barlow cut, requested in every page's font link - asking
     for it without loading it would get a browser-faked bold */
  font-weight:700;
  font-size:1.32rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--cream);
  /* flex so the rule sits on the text's centre line, as on .eyebrow */
  display:flex;
  align-items:center;
  gap:.7em;
}
/* the same orange rule the eyebrows carry, at the same proportions - it
   is em-based, so it grows with the label rather than being pinned to a
   pixel width */
.hero__sub::before{
  content:"";
  width:1.6em;height:2px;flex:none;
  background:var(--orange);
  border-radius:var(--radius);
}
/* The front page opens on one full screen: the hero fills whatever is
   left once the stats bar has taken its height, so the bar always sits
   at the foot of the first screen rather than below the fold or
   floating. dvh follows mobile browser chrome as it hides and shows. */
.first-screen{
  min-height:100vh;
  min-height:100dvh;
  display:flex;
  flex-direction:column;
}
.first-screen > .hero{flex:1 0 auto;min-height:340px}
.first-screen > .sec{flex:0 0 auto}
/* The first screen is the hero AND the stats bar on a wide screen. On a
   phone the bar cannot sit beside the hero, so it stacked under it and
   took most of the first screen for itself - you scrolled past the
   headline to reach it. Below 760px, where the bar has already dropped
   to one column, the first screen is the hero alone. The counters still
   run; they are simply not on this page's first screen any more. */
@media (max-width:760px){
  .first-screen > .sec{display:none}
  /* the front page subline too, on Kim's call: on a phone the headline
     carries the first screen alone */
  .first-screen .hero__sub{display:none}
}
/* The front page headline runs larger than the shared hero type: 15% up
   on size, and a measure 25% wider than it renders elsewhere. Scoped to
   .first-screen, which only index.html carries, so the other fourteen
   heroes keep the streamlined size. The measure is 15ch * 1.25 / 1.15 -
   ch grows with the font, so dividing the type increase back out is what
   makes the rendered width exactly 25% wider rather than 44%. */
.first-screen .h-hero{
  /* Three lines since 2 October 2026 - "Communication / & marketing with
     / digital transformation." - and the last must hold on one line. That
     line is 10.5 times the font size at 100px but 11.1 at 50px - the face
     sets wider as it gets smaller, on its optical-size axis - and the
     hero's content width is 90vw up to 1280px (the gutter is 5vw there).
     8vw clears it with a little to spare from 600px up: measured at 600,
     760, 1024 and 1440. The cap is the size from before (6.41rem, reached
     at 1282px); above that the content is wide enough for it. The floor
     is low enough that the width term is still in charge at 600px, where
     the phone rule takes over. */
  font-size:clamp(2.9rem,8vw,6.41rem);
  max-width:none;
}
.first-screen .h-hero .nowrap{white-space:nowrap}
/* On a phone the gutter is a fixed 20px rather than 5vw, so the room for
   "Digital transformation." is less than 90vw, and the face is at its
   widest here (11.6 times the size at 30px): 7.5vw keeps the line inside
   the gutters down to a 320px screen, where the floor of 1.5rem is also
   exactly what fits. The two rules land 3px apart at 600px. */
@media (max-width:600px){
  /* the cap meets the rule above at 600px so crossing the breakpoint does
     not jump; below about 589px the width term takes over anyway, which is
     what keeps "transformation" inside the gutters down to a 320px screen */
  .first-screen .h-hero{font-size:clamp(1.5rem,7.5vw,3.5rem)}
}
/* On a short screen — a laptop with the dock and a couple of toolbars
   eating into it — the hero's padding and the stats bar's own padding
   together outrun the viewport and push the bar below the fold. The
   stats padding is vw-based, so width alone never catches this. Tighten
   both against height so the first screen still ends where the screen does. */
@media (max-height:760px){
  .first-screen > .hero{
    min-height:0;
    padding-top:calc(var(--nav-h) + 16px);
    padding-bottom:clamp(24px,4vh,48px);
  }
  .first-screen > .sec--tight{padding-block:clamp(24px,4vh,40px)}
}

.hero--warm .hero__bg{
  background:
    radial-gradient(85% 75% at 88% 105%, rgba(255,113,37,.6), transparent 60%),
    linear-gradient(165deg,#241d19 0%,#171311 55%,#0e0b09 100%);
}
.hero--cool .hero__bg{
  background:
    radial-gradient(80% 70% at 78% 108%, rgba(255,113,37,.4), transparent 62%),
    radial-gradient(60% 55% at 20% 10%, rgba(120,140,170,.32), transparent 66%),
    linear-gradient(175deg,#1b1e22 0%,#131313 60%,#0c0a09 100%);
}

/* ---------- sections ---------- */

.sec{padding:clamp(56px,9vw,120px) 0}
.sec--ink{background:var(--ink);color:var(--cream)}
.sec--deep{background:var(--ink-deep);color:var(--cream)}
.sec--cream{background:var(--cream);color:var(--ink)}
.sec--tight{padding-block:clamp(40px,6vw,72px)}

/* Section headings sit a fifth narrower than the hero headline's measure
   - 41rem less 20%. The lede takes the same column rather than a
   narrower one of its own, so the two share a right edge. */
.sec-head{max-width:var(--measure);margin-bottom:clamp(32px,5vw,64px)}
.sec-head .lede,.sec-head .h-3{margin-top:1.1rem;max-width:none}

/* ---------- stats ---------- */

.stats{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(24px,4vw,48px);
  text-align:center;
}
.stat__num{
  font-size:clamp(2.4rem,5vw,3.6rem);
  font-weight:800;
  line-height:1;
  color:var(--orange);
}
/* The label wears .h-2 in the markup - display type, 800 - and keeps
   only what .h-2 does not say: the capitals, the tracking, the spacing
   and the colour. Nothing here restates a .h-2 property, so the two
   cannot drift apart. */
.stat__label{
  letter-spacing:.18em;
  text-transform:uppercase;
  margin-top:.5rem;
  color:var(--cream);
}

/* ---------- service columns ---------- */

.cols-3{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2.4vw,32px)}
.cols-2{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(24px,4vw,64px)}
/* heading on the left, a pair of columns on the right */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.5fr);gap:clamp(24px,4vw,64px)}
.split > .cols-2{gap:clamp(20px,2.6vw,40px)}

.card{
  border-radius:var(--radius);
  background:var(--cream);
  color:var(--ink);
  border:1px solid var(--line-dark);
  padding:clamp(24px,3vw,40px);
  display:flex;flex-direction:column;
}
/* no hover lift: the cards are not links, so nothing should suggest they
   respond to the pointer (removed on Kim's call, 2 October 2026) */
.card__title{display:flex;align-items:center;gap:.5rem;margin-bottom:1rem}
/* the orange dash before a card title is drawn here, not typed: it used
   to be a "-" in a <span class="dash">, which read aloud as a hyphen and
   set at whatever the font gave it */
.card__title::before{
  content:"";flex:none;
  width:.6em;height:3px;
  background:var(--orange);
  border-radius:var(--radius);
}
.card p{font-size:1rem;line-height:1.55}
/* on a dark band the card goes transparent and keeps the band's text,
   as the front page's track cards do */
.sec--ink .card,.sec--deep .card{background:transparent;color:inherit;border-color:var(--line-light)}

.ticks{list-style:none;margin:1.5rem 0 0;padding:0;font-size:1rem}
.ticks li{
  padding:.55rem 0 .55rem 1.6rem;
  border-top:1px solid var(--line-dark);
  position:relative;
}
/* a round dot, echoing the orange dot that ends every headline */
.ticks li::before{
  content:"";position:absolute;left:0;top:1.15rem;
  width:8px;height:8px;border-radius:50%;background:var(--orange);
}
.sec--ink .ticks li,.sec--deep .ticks li{border-color:var(--line-light)}

/* ---------- process ---------- */

.steps{
  display:grid;
  /* three at most on a row - five across left each one too narrow to
     read. The circle of trust is five steps, so it wraps to 3 + 2. */
  grid-template-columns:repeat(3,1fr);
  gap:clamp(12px,1.6vw,24px);
  row-gap:clamp(32px,4vw,56px);
  counter-reset:step;
}
.step{
  /* no rule across the top: the figure is the marker for these */
  padding-top:.4rem;
}
/* The figure is the marker for a .step, so it is sized to fill a cell of
   a five-across row - --step-cell - whatever the row it actually sits in.
   min() against 100% is for the collapsed layouts, where a cell is
   narrower than --step-cell. */
.step .icon{
  /* max() keeps the old 95px floor: on a phone --step-cell alone works
     out to a 57px shape. min() against 100% is the other end. */
  width:min(max(var(--step-cell),95px),100%);
  height:auto;
  aspect-ratio:1;
  /* every mark sits centred on its shared canvas, so centring the box in
     the column puts them all on one centre line - left-aligning the box
     instead leaves the single circle looking indented against the text */
  margin:0 auto 1.6rem;
}
.step__num{
  font-family:var(--label);
  font-weight:600;
  font-size:1.1rem;
  letter-spacing:.12em;
  color:var(--orange);
  display:block;
  margin-bottom:.6rem;      /* it now sits under the figure, above the name */
}
.step h3{margin-bottom:.7rem}
.step p{font-size:.95rem;line-height:1.5;opacity:.82}

/* ---------- pillars ---------- */

.pillar{border-top:2px solid var(--line-dark);padding-top:1.4rem}
/* A pillar's heading is a label, not display type - it is the kicker above
   the stat, which is the thing meant to carry weight. Named rather than
   keyed off h3, so "h3" does not mean two different looks on the site. */
.pillar__name{
  font-family:var(--label);
  font-weight:600;
  font-size:1rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  margin-bottom:.9rem;
}
.pillar p{font-size:1rem;line-height:1.55}
.sec--ink .pillar,.sec--deep .pillar{border-color:var(--line-light)}

.pillar__stat{
  font-size:clamp(2rem,4vw,2.8rem);
  font-weight:800;
  line-height:1;
  color:var(--orange);
  display:block;
  margin-bottom:.8rem;
}

/* ---------- ai block ---------- */

.hash{
  font-family:var(--label);
  font-weight:600;
  letter-spacing:.1em;
  color:var(--orange);
  font-size:.95rem;
  margin-top:1.4rem;
  display:block;
}

/* ---------- work grid ---------- */

.filters{
  display:flex;flex-wrap:wrap;gap:10px;
  margin-bottom:clamp(28px,4vw,48px);
}
.filter{
  border-radius:var(--radius);
  font-family:var(--label);
  font-weight:600;
  font-size:.85rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:.6rem 1.3rem;
  border:1px solid var(--line-dark);
  transition:background .2s ease,color .2s ease,border-color .2s ease;
}
.filter[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--cream)}
/* orange outline on hover - never on the chip that is already selected */
.filter:not([aria-pressed="true"]):hover{border-color:var(--orange)}

.work-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(12px,1.8vw,24px);
}
.case{
  border-radius:var(--radius);
  position:relative;
  display:block;
  aspect-ratio:4/3;
  overflow:hidden;
  background:var(--ink);
  color:var(--cream);
}
.case[hidden]{display:none}
.case__bg{
  position:absolute;inset:0;
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
.case:hover .case__bg{transform:scale(1.06)}
.case__bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(8,8,8,.85) 0%,rgba(8,8,8,.15) 60%,transparent 100%);
}
.case__body{
  position:absolute;inset:auto 0 0 0;
  padding:clamp(18px,2vw,28px);
  z-index:1;
}
.case__cat{
  font-family:var(--label);
  font-weight:600;
  font-size:.75rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--orange);
  display:block;
  margin-bottom:.4rem;
}
.case__name{font-size:clamp(1.05rem,1.6vw,1.35rem);font-weight:800;line-height:1.16}

/* six generated cover treatments, so no two cases look alike */
.cv-1{background:linear-gradient(145deg,#2a2f38,#0e1014)}
.cv-2{background:linear-gradient(145deg,#3a2418,#120c08)}
.cv-3{background:linear-gradient(145deg,#1f2a2a,#0b1010)}
.cv-4{background:linear-gradient(145deg,#31232e,#120d11)}
.cv-5{background:linear-gradient(145deg,#2c2a1d,#111008)}
.cv-6{background:linear-gradient(145deg,#1d2733,#0a0e13)}
.case__bg::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(60% 60% at 75% 95%, rgba(255,113,37,.45), transparent 65%);
}
.case__bg.has-media{background-size:cover;background-position:center}
/* with a real photo the orange wash would muddy it, so it steps back */
.case__bg.has-media::before{opacity:.28}

/* ---------- client wall ----------
   Logo-wall convention: no boxes, every mark capped to one optical
   size so wide wordmarks and square marks read as equals, monochrome
   at rest and full colour on hover, generous air between them. */

.clients{
  display:grid;
  /* six to a line, so twelve marks fall into two even rows */
  grid-template-columns:repeat(6,1fr);
  gap:clamp(40px,5vw,72px) clamp(24px,3vw,48px);
  align-items:center;
  justify-items:center;
}
@media (max-width:900px){ .clients{grid-template-columns:repeat(3,1fr)} }
@media (max-width:560px){ .clients{grid-template-columns:repeat(2,1fr)} }
.client{
  /* tall enough for the 72px mark plus air; see tools/logo-prep.py for why
     the display box is 1.75:1 rather than the wider box it used to be */
  width:100%;height:90px;
  display:grid;place-items:center;
  /* text fallback while the mark is still loading */
  font-family:var(--label);font-weight:600;font-size:.8rem;
  letter-spacing:.14em;text-transform:uppercase;text-align:center;line-height:1.3;
  color:rgba(38,38,38,.4);
}
.client.has-logo img{
  /* the cell is 152x90, so this takes the room that was going spare while
     still leaving each mark 8px of air on every side */
  max-height:82px;max-width:144px;width:auto;height:auto;
  object-fit:contain;
  filter:grayscale(1);opacity:.55;
  transition:filter .3s ease,opacity .3s ease,transform .3s ease;
}
.client.has-logo:hover img{filter:none;opacity:1;transform:scale(1.04)}
/* on a dark section the marks are inverted to light */
.sec--ink .client,.sec--deep .client{color:rgba(246,237,226,.4)}
.sec--ink .client.has-logo img,.sec--deep .client.has-logo img{filter:grayscale(1) invert(1) brightness(1.4);opacity:.6}
.sec--ink .client.has-logo:hover img,.sec--deep .client.has-logo:hover img{filter:invert(1) brightness(1.4);opacity:1}

/* ---------- brand icons ---------- */
/* The shapes from the brand set, used as CSS masks. One file per shape
   serves every colour on the site: the icon paints in currentColor, so
   it inherits whatever the container already sets - cream on the dark
   bands, ink on cream - and the modifiers below are for when it should
   differ from the text around it. */
.icon{
  display:block;
  width:clamp(56px,7vw,104px);
  height:clamp(56px,7vw,104px);
  background:currentColor;
  flex:none;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
}
.icon--orange{color:var(--orange)}
.icon--cream {color:var(--cream)}
.icon--ink   {color:var(--ink)}
.icon--deep  {color:var(--ink-deep)}
.icon--dim   {opacity:.55}

.icon--circle-solid{-webkit-mask-image:url("../img/figures/circle-solid.png");mask-image:url("../img/figures/circle-solid.png")}
.icon--circle-ring {-webkit-mask-image:url("../img/figures/circle-ring.png");mask-image:url("../img/figures/circle-ring.png")}
.icon--circle-star {-webkit-mask-image:url("../img/figures/circle-star.png");mask-image:url("../img/figures/circle-star.png")}
.icon--cross       {-webkit-mask-image:url("../img/figures/cross.png");mask-image:url("../img/figures/cross.png")}
.icon--asterisk    {-webkit-mask-image:url("../img/figures/asterisk.svg");mask-image:url("../img/figures/asterisk.svg")}
.icon--circles-1   {-webkit-mask-image:url("../img/figures/circles-1.png");mask-image:url("../img/figures/circles-1.png")}
.icon--circles-2   {-webkit-mask-image:url("../img/figures/circles-2.png");mask-image:url("../img/figures/circles-2.png")}
.icon--circles-3   {-webkit-mask-image:url("../img/figures/circles-3.png");mask-image:url("../img/figures/circles-3.png")}
.icon--circles-4   {-webkit-mask-image:url("../img/figures/circles-4.png");mask-image:url("../img/figures/circles-4.png")}
/* the three SVG ones, from the brand export. Their own fill is #FF7326,
   a shade off the site's #FF7125 - as masks that never shows, because
   the colour comes from the stylesheet either way. */
.icon--eye         {-webkit-mask-image:url("../img/figures/eye.svg");mask-image:url("../img/figures/eye.svg")}
.icon--sliders     {-webkit-mask-image:url("../img/figures/sliders.svg");mask-image:url("../img/figures/sliders.svg")}
.icon--users       {-webkit-mask-image:url("../img/figures/users.svg");mask-image:url("../img/figures/users.svg")}

/* Padded variants. Same artwork, centred on a canvas that gives it air,
   so the mark paints at 0.516 of its box - the share one circle takes on
   a circle-of-trust figure. The tight originals above stay as they are:
   they fill their box, which is what you want anywhere the box IS the
   mark. Use these where a figure sits next to a circle-of-trust one, or
   it will read twice the size for the same box. */
.icon--circle-solid-pad{-webkit-mask-image:url("../img/figures/circle-solid-pad.png");mask-image:url("../img/figures/circle-solid-pad.png")}
.icon--circle-ring-pad {-webkit-mask-image:url("../img/figures/circle-ring-pad.png");mask-image:url("../img/figures/circle-ring-pad.png")}
.icon--cross-pad       {-webkit-mask-image:url("../img/figures/cross-pad.png");mask-image:url("../img/figures/cross-pad.png")}
.icon--eye-pad         {-webkit-mask-image:url("../img/figures/eye-pad.svg");mask-image:url("../img/figures/eye-pad.svg")}
.icon--sliders-pad     {-webkit-mask-image:url("../img/figures/sliders-pad.svg");mask-image:url("../img/figures/sliders-pad.svg")}
.icon--users-pad       {-webkit-mask-image:url("../img/figures/users-pad.svg");mask-image:url("../img/figures/users-pad.svg")}

/* without mask support the icon would paint as a plain coloured block,
   so hide it instead - same guard the scroll figure uses */
@supports not ((-webkit-mask-image:url("x.png")) or (mask-image:url("x.png"))){
  .icon{display:none}
}

/* the process steps and the pillars lead with one */
.step .icon{margin-bottom:1.1rem}
.pillar .icon{margin-bottom:1.2rem}

/* ---------- contact ---------- */

.info{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(24px,4vw,48px)}
.info__label{
  font-family:var(--label);
  font-weight:600;
  font-size:.85rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--orange);
  margin-bottom:.6rem;
}
.info__value{font-size:1.15rem;line-height:1.45;font-weight:500}
.info a:hover{color:var(--orange)}

.map{
  border-radius:var(--radius);
  aspect-ratio:16/7;
  background:
    radial-gradient(48% 62% at 50% 50%, rgba(255,113,37,.3), transparent 62%),
    repeating-linear-gradient(0deg,rgba(246,237,226,.07) 0 1px,transparent 1px 44px),
    repeating-linear-gradient(90deg,rgba(246,237,226,.07) 0 1px,transparent 1px 44px),
    var(--ink-deep);
  display:grid;place-items:center;
  position:relative;
}
.map__pin{
  width:18px;height:18px;border-radius:50%;
  background:var(--orange);
  box-shadow:0 0 0 8px rgba(255,113,37,.22),0 0 0 18px rgba(255,113,37,.1);
}

/* ---------- job rows ---------- */

.rows{border-top:1px solid var(--line-dark)}
.sec--ink .rows,.sec--deep .rows{border-color:var(--line-light)}
.row{
  display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:clamp(18px,2.4vw,30px) 0;
  border-bottom:1px solid var(--line-dark);
  transition:padding-inline .3s ease,color .3s ease;
}
.sec--ink .row,.sec--deep .row{border-color:var(--line-light)}
.row:hover{padding-inline:12px;color:var(--orange)}
.row__title{
  font-family:var(--label);
  font-weight:600;
  font-size:clamp(1rem,1.6vw,1.2rem);
  letter-spacing:.16em;
  text-transform:uppercase;
}
.row__arrow{font-size:1.4rem;line-height:1}

/* ---------- footer ---------- */

.footer{
  position:relative;
  /* --ink-deep, matching the .sec--deep sections that close most pages -
     on #1c1c1c the footer read as a step up from them */
  background:var(--ink-deep);
  color:var(--cream);
  text-align:center;
  padding:clamp(56px,8vw,96px) 0 clamp(32px,4vw,48px);
  overflow:hidden;
}
.footer::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  /* dimmed from .4 - enough warmth to read as the brand accent, close
     enough to flat #101010 that the footer sits with the .sec--deep
     sections above it */
  background:radial-gradient(60% 70% at 85% 110%, rgba(255,113,37,.18), transparent 65%);
}
.footer > *{position:relative;z-index:1}
/* the footer column runs 20% narrower than the page measure, so the rule
   above the meta line pulls in rather than spanning the full page */
.footer .wrap{max-width:calc(var(--maxw) * .8)}
/* .7rem each side - both margins apply here, they do not collapse, so
   the gap to the wordmark is 22px rather than the 64px it started at */
.footer .logo{margin-bottom:.7rem}
.socials{display:flex;justify-content:center;gap:16px;margin-top:.7rem}
.social{
  width:40px;height:40px;border-radius:50%;
  border:1px solid var(--line-light);
  display:grid;place-items:center;
  transition:background .25s ease,color .25s ease,border-color .25s ease;
}
.social:hover{background:var(--cream);color:var(--ink);border-color:var(--cream)}
.social svg{width:16px;height:16px;fill:currentColor}
.footer__meta{
  margin-top:clamp(32px,5vw,56px);
  padding-top:1.6rem;
  border-top:1px solid var(--line-light);
  font-family:var(--label);
  font-size:.85rem;
  letter-spacing:.12em;
  text-transform:uppercase;
  opacity:.6;
  display:flex;justify-content:center;gap:1.5rem;flex-wrap:wrap;
}

/* ---------- reveal ---------- */

.rv{opacity:0;transform:translateY(22px);transition:opacity .7s ease,transform .7s cubic-bezier(.22,1,.36,1)}
.rv.is-in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .rv{opacity:1;transform:none}
  .menu__list a{transform:none}
}

/* ---------- responsive ---------- */

@media (max-width:1040px){
  .split{grid-template-columns:1fr;gap:clamp(20px,3vw,32px)}
}

@media (max-width:960px){
  .steps{grid-template-columns:repeat(2,1fr);row-gap:32px}
  .work-grid{grid-template-columns:repeat(2,1fr)}
}

@media (max-width:760px){
  body{font-size:18px}
  .cols-3,.cols-2,.info,.split{grid-template-columns:1fr}
  .stats{grid-template-columns:1fr;gap:28px}
  .h-hero{max-width:none}
}

@media (max-width:520px){
  .steps,.work-grid{grid-template-columns:1fr}
  .footer__meta{gap:.8rem}
}

/* ============================================================
   Case pages
   Two templates on the live site: a structured case study
   (challenge / solution / results / products) and a long-form
   showcase (section after section of films and galleries).
   Both share the chrome below.
   ============================================================ */

/* Vimeo in background mode, sized to cover like a photo would.

   The player letterboxes the film inside its own iframe, so the iframe
   must itself be over-sized to the film's 16:9 and cropped by the
   wrapper - otherwise the black bands show through as bars.

   Measured against the hero box, not the viewport: vh/vw only agreed
   while the hero happened to be viewport-height, and the full-screen
   hero broke that, putting a 66px black band above and below the film.
   (The old 128vh was wrong arithmetic too - 16:9 is 177.78vh.) */
.hero__embed{
  position:absolute;inset:0;z-index:-3;
  overflow:hidden;pointer-events:none;background:#000;
  container-type:size;
}
.hero__embed iframe{
  position:absolute;top:50%;left:50%;
  width:max(100%,177.78vh);height:max(100%,56.25vw);
  transform:translate(-50%,-50%);
  border:0;
}
@supports (width:1cqw){
  .hero__embed iframe{
    width:max(100cqw,177.78cqh);
    height:max(100cqh,56.25cqw);
  }
}
/* A film with black bars baked into it: the picture is a 2.37:1 strip
   inside a 16:9 frame (measured on Book Session's 246705037, 541 of 720
   rows). Covering the hero with the frame still showed the bars, so this
   covers it with the picture instead and lets the bars fall outside: the
   frame is sized so its picture strip is at least the hero's height. 2%
   over, so the bars' uneven last row never shows. */
.hero__embed--letterbox iframe{
  width:max(102%,240vh);height:max(57.4vw,135vh);
}
@supports (width:1cqw){
  .hero__embed--letterbox iframe{
    width:max(102cqw,240cqh);
    height:max(57.4cqw,135cqh);
  }
}

.case-head{max-width:none}
/* .case-head .eyebrow used to colour the client line orange here. That
   line is .case_client_eyebrow now and carries its own colour, and no
   .eyebrow is left inside a .case-head, so the rule matched nothing. */
.case-head .h-hero{max-width:18ch}
.case-head__sub{
  font-weight:700;
  font-size:clamp(1.05rem,1.8vw,1.35rem);
  line-height:1.35;
  color:var(--cream);
  margin:1rem 0 0;
  max-width:44ch;
}
.back{
  display:inline-block;
  font-family:var(--label);font-weight:600;
  /* .78rem at 60% opacity over a hero photo was barely there - it is the
     only way back to Our Work from a case, so it reads at full strength
     now, a size up, and still under the client line above the headline */
  font-size:1rem;
  letter-spacing:.18em;text-transform:uppercase;
  color:var(--cream);margin-bottom:1.4rem;
  transition:opacity .2s ease,color .2s ease;
}
.back:hover{opacity:1;color:var(--orange)}

/* The case hero's play button sits on the seam between the hero and the
   section under it, half in each, as on the live site. The hero clips its
   overflow (the film is over-sized inside it), so the button cannot live
   in there: it gets a zero-height strip of its own between the two
   sections, lifted above the next one, and pulls itself up by half its
   height. That is `top`, not a negative margin: the margin collapsed
   through the empty strip and dragged the next section up with it.
   84px is the old 64px plus 30%. Never captioned. */
.case-play-seam{position:relative;z-index:2;height:0}
.case-play{
  --size:84px;
  position:relative;top:calc(var(--size) / -2);
  display:grid;place-items:center;
  width:var(--size);height:var(--size);border-radius:50%;
  border:2px solid var(--cream);color:var(--cream);
  transition:background .25s ease,color .25s ease,transform .25s ease;
}
.case-play::before{
  content:"";margin-left:7px;
  border-left:21px solid currentColor;
  border-top:13px solid transparent;border-bottom:13px solid transparent;
}
.case-play:hover{background:var(--cream);color:var(--ink);transform:scale(1.06)}

.slash-list{
  list-style:none;padding:0;margin:1.6rem auto 0;
  font-weight:700;font-size:clamp(1rem,1.6vw,1.2rem);line-height:1.5;
  text-align:left;display:inline-block;
}
.slash-list b{color:var(--orange);font-family:var(--label);letter-spacing:-.05em;margin-right:.5em}

.h-orange{color:var(--orange)}

/* client / year on the left, the challenge on the right */
.meta-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2.2fr);gap:clamp(24px,4vw,64px);align-items:start}
.meta{margin:0;display:grid;gap:1.2rem;align-content:start}
.meta div{margin:0}
.meta__k{
  font-family:var(--label);font-weight:600;font-size:.72rem;
  letter-spacing:.22em;text-transform:uppercase;opacity:.55;
}
.meta__v{margin:.25rem 0 0;font-size:1rem}
/* the client's own mark under the case facts. Same treatment as the
   client wall: greyed back so it sits with the type rather than
   shouting, and inverted on the dark grounds the case pages use. */
.case-logo{margin:2.2rem 0 0}
.case-logo img{
  display:block;
  /* twice the size it started at. The file comes from img/case-logos/,
     cut at 532x304 so this is still 2x on a retina screen - the wall's
     own 252x144 files would have been 1:1 here, and soft. */
  max-width:266px;max-height:152px;width:auto;height:auto;
  object-fit:contain;
  /* greyed at rest, its own colours on hover - the same deal the dark
     grounds get below, which used to be the only place it held. CBS sits
     on cream and would otherwise have been the one mark in full colour
     at rest. */
  filter:grayscale(1);
  opacity:.75;
  transition:filter .3s ease,opacity .3s ease;
}
/* grey it BEFORE inverting, exactly as the client wall does - inverting a
   colour straight gives its complement, which turned the emblem cyan */
.sec--ink .case-logo img,.sec--deep .case-logo img{filter:grayscale(1) invert(1) brightness(1.4);opacity:.7}
/* hover hands the mark back its own colours. These sit after the rules
   above because they match at the same specificity and would otherwise
   lose to them. */
/* artwork already cut for a dark ground: inverting it would turn it black,
   so it greys back at rest like the others but is never inverted */
.sec--ink .case-logo--light img,.sec--deep .case-logo--light img{filter:grayscale(1);opacity:.75}
.case-logo img:hover,
.sec--ink .case-logo img:hover,
.sec--deep .case-logo img:hover,
.sec--ink .case-logo--light img:hover,
.sec--deep .case-logo--light img:hover{filter:none;opacity:1}

/* ---- a mark painted rather than shown ----
   Pandora's file is a pure black silhouette, so the filter:none above
   handed hover a black logo on a dark ground - the one case where
   "its own colours back" meant invisible. Painted as a mask it takes
   currentColor, so hover can give it the brand's actual pink.

   #FF93A0 is not a guess: it is what pandora.net's own stylesheet
   declares, as --chakra-colors-pandoraPink and --chakra-colors-
   primaryColor. Re-read it there if the brand moves.

   Same @supports guard as the brand icons: without mask support the
   ::after would paint as a plain block, so the <img> stays instead. */
@supports ((-webkit-mask-image:url("")) or (mask-image:url(""))){
  .case-logo--tint img{display:none}
  .case-logo--tint::after{
    content:"";display:block;
    width:266px;height:152px;
    background:currentColor;
    opacity:.7;
    -webkit-mask-size:contain;mask-size:contain;
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    -webkit-mask-position:left center;mask-position:left center;
    transition:color .3s ease,opacity .3s ease;
  }
  .case-logo--tint:hover::after{color:#FF93A0;opacity:1}
  .case-logo--pandora::after{
    -webkit-mask-image:url("../img/case-logos/pandora.png");
    mask-image:url("../img/case-logos/pandora.png");
  }
}

.question{font-weight:700;font-size:clamp(1.15rem,2vw,1.5rem);line-height:1.38;margin:0}
.question em{font-style:normal;color:var(--orange)}

.pull{margin-top:clamp(36px,5vw,64px);max-width:64ch}
/* the top margin exists to part it from whatever it follows; standing on
   its own in a section, the section's padding already does that */
.wrap > .pull:first-child{margin-top:0}
.pull__mark{display:block;font-size:4.2rem;line-height:.55;color:var(--orange);font-weight:800;margin-bottom:1.2rem}
.pull p{
  font-family:var(--label);font-weight:600;font-size:.95rem;
  letter-spacing:.07em;text-transform:uppercase;line-height:1.55;margin:0;
}

.split--case{grid-template-columns:minmax(0,1fr) minmax(0,2.4fr)}
.prose p{font-size:1rem;line-height:1.6;opacity:.9}
.prose p strong{opacity:1;color:var(--cream)}
.sec--cream .prose p strong{color:var(--ink)}
.num-h{
  font-family:var(--label);font-weight:600;font-size:.88rem;
  letter-spacing:.16em;text-transform:uppercase;margin:0 0 .7rem;
}
.block + .block{margin-top:clamp(28px,4vw,48px)}
.block .video,.block .mosaic{margin-top:1.2rem}
.block .h-3{margin-bottom:.4rem}
.block .lede{margin:.4rem 0 1rem;font-size:1.328rem}

/* results */
.results-ticks{margin-top:2rem}
.pillar--tick h3::before{content:"\2714\00a0";color:var(--orange)}
.pillar--big h3{
  font-family:var(--display);font-weight:800;font-size:1.45rem;
  letter-spacing:0;text-transform:none;
  display:flex;align-items:center;gap:.6em;
}
.pillar--big h3::after{content:"";width:2em;height:2px;background:var(--orange);flex:none;border-radius:var(--radius)}
.stats-row{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,40px);margin-top:2rem}
.rstat{border-top:2px solid var(--line-light);padding-top:1.2rem}
.rstat__num{font-size:clamp(2.4rem,5vw,3.6rem);font-weight:800;line-height:1;color:var(--orange)}
.rstat__label{margin-top:.6rem;font-size:1rem;line-height:1.4;opacity:.85}

/* films */
.video{border-radius:var(--radius);
  position:relative;aspect-ratio:16/9;background:#000;overflow:hidden}
.video iframe,.video video{position:absolute;inset:0;width:100%;height:100%;border:0;object-fit:cover}
.video--portrait{aspect-ratio:9/16}
.video--slot{
  display:grid;place-items:center;
  background:linear-gradient(145deg,#1f2227,#0e1014);
  border:1px dashed var(--line-light);
}
.video__hint{font-family:var(--label);font-size:.75rem;letter-spacing:.2em;text-transform:uppercase;opacity:.5}
.video.has-media{border:0}
.video.has-media .video__hint{display:none}
.vcap{
  font-family:var(--label);font-weight:600;font-size:.78rem;
  letter-spacing:.12em;text-transform:uppercase;
  margin:.7rem 0 0;opacity:.75;line-height:1.4;
}

/* client on the left, the film on the right */
.vlist{border-top:1px solid var(--line-light);margin-top:1.6rem}
.sec--cream .vlist{border-color:var(--line-dark)}
.vlist__row{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.6fr);
  gap:clamp(20px,3vw,48px);align-items:center;
  padding:clamp(18px,2.4vw,28px) 0;
  border-bottom:1px solid var(--line-light);
}
.sec--cream .vlist__row{border-color:var(--line-dark)}
.vlist__row .eyebrow{margin:0}
.vlist__row p{margin:.5rem 0 0;font-size:1rem;opacity:.85}

/* ---------- .mosaic: every album, photos and films ----------
   Nothing is cropped. Each item carries its own width/height as --r,
   written from the file itself by tools/album-ratios.py, and keeps that
   shape at every size - a 2.19 letterbox, a 0.56 phone film and a square
   sit side by side as they are.

   js/site.js decides which items share a row: it tries every way of
   breaking the album into rows and keeps the one whose rows come closest
   to --mosaic-row, with each row filling the width exactly at one shared
   height. Set --mosaic-row on one album to make its rows taller or
   shorter; it is registered as a length so the script can read it back
   in pixels.

   Without the script the same rows come from flexbox alone: each item
   asks for --r x --mosaic-row and grows in proportion to --r, which keeps
   a line at one height but lets the browser choose the breaks. */
@property --mosaic-row{syntax:'<length>';inherits:true;initial-value:280px}
.mosaic{
  --mosaic-row:clamp(170px,22vw,290px);
  --mosaic-gap:clamp(10px,1.5vw,18px);
  display:flex;flex-wrap:wrap;align-items:flex-start;
  gap:var(--mosaic-gap);
}
.mosaic > *{
  flex:var(--r,1.5) 1 calc(var(--r,1.5) * var(--mosaic-row));
  min-width:0;margin:0;
}
/* the photo, or the film inside a cell that also holds its caption */
.mosaic .shot,.mosaic .video{aspect-ratio:var(--r,1.5)}
/* a row capped at 85% of the screen (see site.js) sits centred */
.mosaic > .is-capped{margin-inline:auto}

/* ---------- .h-vertical: the word running down an album ----------
   The live site's "IMPRESSIONS" - there an SVG of outlined letters
   (yootheme/heading-09.svg), here real type, so the word is editable and
   the section has a heading a screen reader can find. Set as the first
   child of a section's .wrap, directly before the album: it lies over the
   album's left edge, above the photos, and reads top to bottom.

   It is taller than most albums. js/site.js slides it up as the section
   scrolls by, so every letter crosses the screen once and the last one
   arrives as the section leaves; the section clips it at both ends.
   Under reduced motion it stays put, showing as much as fits.

   To remove one: delete the <h2>. Nothing else refers to it. */
.wrap:has(> .h-vertical){position:relative}
.sec:has(> .wrap > .h-vertical){overflow:clip}
.h-vertical{
  /* no top: an absolute box left at top:auto stays where it would have
     been in the flow, which is level with the album that follows it */
  position:absolute;z-index:2;
  left:-.12em;
  margin:0;
  writing-mode:vertical-rl;
  font-family:var(--display);font-weight:800;
  font-size:clamp(4.2rem,13.9vw,13rem);
  line-height:.74;letter-spacing:-.01em;
  text-transform:uppercase;
  color:var(--orange);
  pointer-events:none;
  will-change:transform;
}

/* shots keep the case-cover placeholders (cv-1..6) until real photos
   are dropped in */
.shot{border-radius:var(--radius);
  position:relative;margin:0;aspect-ratio:4/3;overflow:hidden}
.shot--wide{aspect-ratio:16/9}
/* Every loaded shot opens in the lightbox, so every loaded shot has to
   look like it does. A slot still on its placeholder has nothing to
   enlarge, hence .has-media rather than .shot. */
.shot.has-media{cursor:zoom-in;transition:transform .35s ease}
.shot.has-media:hover{transform:scale(1.02)}
.shot.has-media:focus-visible{outline:3px solid var(--orange);outline-offset:3px}
.shot--tall{aspect-ratio:3/4}
.shot--square{aspect-ratio:1}
.shot::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(60% 60% at 70% 92%,rgba(255,113,37,.28),transparent 65%);
}
.shot.has-media{background-size:cover;background-position:center}
.shot.has-media::after{opacity:.3}

/* partner / client marks inside a case */
.plogos{display:flex;justify-content:center;gap:1.2rem;flex-wrap:wrap;margin-top:1.8rem}
.plogo{
  border-radius:var(--radius);
  width:110px;height:62px;display:grid;place-items:center;
  border:1px solid var(--line-light);
  font-family:var(--label);font-weight:600;font-size:.7rem;
  letter-spacing:.16em;text-transform:uppercase;opacity:.7;
}
.plogo img{max-height:44px;max-width:88px;object-fit:contain}
.plogo.has-logo{opacity:1}

/* team */
.team{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:clamp(28px,4vw,56px)}
.member__halo{
  padding:18px;
  background-image:radial-gradient(rgba(246,237,226,.22) 1px,transparent 1.6px);
  background-size:12px 12px;
}
.member__pic{aspect-ratio:1;background:linear-gradient(160deg,#2a2d33,#0f1114)}
.member__name{text-align:center;font-size:1.4rem;font-weight:800;margin-top:1.1rem}
.member__exp{
  text-align:center;margin:.3rem 0 0;
  font-family:var(--label);font-weight:600;font-size:.72rem;
  letter-spacing:.22em;text-transform:uppercase;color:var(--orange);
}
.member__role{color:var(--orange);font-weight:700;margin:1.2rem 0 .4rem;font-size:1.05rem}
.member__bio p{font-size:.95rem;line-height:1.55;opacity:.85}

/* closing call */
.cta-case{text-align:center}
.cta-case .eyebrow{justify-content:center;opacity:.6}
.cta-case h2{font-size:clamp(2rem,4.6vw,3.2rem);line-height:1.08}
.cta-case h2 span{display:block;color:var(--orange)}

@media (max-width:900px){
  .stats-row{grid-template-columns:1fr;gap:20px}
}
@media (max-width:760px){
  .hero--case{height:auto;min-height:min(78vh,640px)}
  .meta-grid,.split--case,.vlist__row{grid-template-columns:1fr}
}

/* ---------- vimeo facades ----------
   A poster and a play button stand in for the player until it is
   clicked; a long case carries thirty films, and thirty live players
   would stall the page for everyone. */
.video[data-vimeo]{
  cursor:pointer;
  background:linear-gradient(145deg,#1f2227,#0e1014) center/cover no-repeat;
}
.video[data-vimeo]::after{content:"";position:absolute;inset:0;background:rgba(0,0,0,.18);transition:background .25s ease}
.video[data-vimeo]:hover::after{background:rgba(0,0,0,.05)}
.video__play{
  position:absolute;inset:0;margin:auto;z-index:1;
  width:64px;height:64px;border-radius:50%;
  background:rgba(16,16,16,.55);
  border:2px solid var(--cream);color:var(--cream);
  display:grid;place-items:center;
  backdrop-filter:blur(4px);
  transition:background .25s ease,border-color .25s ease,transform .25s ease;
}
.video__play::before{
  content:"";margin-left:5px;
  border-left:16px solid currentColor;
  border-top:10px solid transparent;border-bottom:10px solid transparent;
}
.video--portrait .video__play{width:52px;height:52px}
.video[data-vimeo]:hover .video__play{background:var(--orange);border-color:var(--orange);transform:scale(1.06)}
.video.is-playing{cursor:default}
.video.is-playing::after,.video.is-playing .video__play{display:none}

/* ---------- careers + album (About) ----------
   Headline left, Apply right; two roles as bullet headings over films;
   then a masonry album of behind-the-scenes shots with a lightbox. */
.careers-head{display:flex;justify-content:space-between;align-items:flex-start;gap:2rem;flex-wrap:wrap}
/* takes --measure like every other section heading */
.btn .ico{width:1.1em;height:1.1em;fill:none;stroke:currentColor;stroke-width:2;stroke-linejoin:round}
.h-bullet{
  font-family:var(--display);font-weight:800;
  font-size:clamp(1.25rem,2.2vw,1.7rem);line-height:1.15;
  text-transform:uppercase;letter-spacing:.02em;
  display:flex;align-items:center;gap:.5em;margin-bottom:1rem;
}
.h-bullet::before{content:"";width:.9em;height:3px;background:var(--orange);flex:none;border-radius:var(--radius)}

.album{background:#efe6da;color:var(--ink)}
.masonry{columns:5;column-gap:clamp(10px,1.4vw,16px)}
.masonry .shot{break-inside:avoid;margin:0 0 clamp(10px,1.4vw,16px);display:block}
.masonry .shot::after{opacity:.12}
@media (max-width:1100px){.masonry{columns:4}}
@media (max-width:900px){.masonry{columns:3}}
@media (max-width:600px){.masonry{columns:2}}

.lightbox{
  position:fixed;inset:0;z-index:80;
  background:rgba(10,10,10,.94);
  display:grid;place-items:center;padding:4vw;
  cursor:zoom-out;
  opacity:0;visibility:hidden;
  transition:opacity .25s ease,visibility .25s ease;
}
.lightbox.is-open{opacity:1;visibility:visible}
/* one stage, holding either a photo or a film */
.lightbox__stage{width:min(1120px,92vw);display:grid;place-items:center}
.lightbox__stage img{
  max-width:100%;max-height:86vh;object-fit:contain;
  border-radius:var(--radius);box-shadow:0 24px 64px rgba(0,0,0,.5);
}
.lightbox__film{
  position:relative;width:100%;aspect-ratio:16/9;
  background:#000;border-radius:var(--radius);overflow:hidden;
  box-shadow:0 24px 64px rgba(0,0,0,.5);
}
.lightbox__film.is-portrait{aspect-ratio:9/16;width:auto;height:86vh}
.lightbox__film iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.lightbox__x{position:absolute;top:14px;right:20px;color:var(--cream);font-size:2.2rem;line-height:1;opacity:.7}
.lightbox__x:hover{opacity:1}

/* ===== SCROLL FIGURE — START =========================================
   One brand asterisk drifting behind BOTH cream sections. They are
   wrapped in .deco-field, which carries the cream and lets the figure
   cross the boundary between them - the sections themselves go
   transparent so it shows through, and their content sits above it.

   js/figure.js stops the travel just short of the client logos and
   fades the figure out before it gets there, so it is never cut and
   never lands on the logos.

   Self-contained - delete this fenced block, js/figure.js, the .deco
   markup and unwrap .deco-field to remove entirely.
   ==================================================================== */
.deco-field{position:relative;overflow:hidden;background:var(--cream)}
.deco-field > .sec{position:relative;z-index:1;background:transparent}

.deco{
  --x:0px; --y:0px; --r:0deg; --fade:0;
  position:absolute;
  top:0;
  left:0;                              /* JS places it; see figure.js */
  width:clamp(300px,52vw,760px);
  aspect-ratio:407/408;
  background:var(--orange);
  -webkit-mask:url("../img/figures/asterisk.svg") center/contain no-repeat;
  mask:url("../img/figures/asterisk.svg") center/contain no-repeat;
  opacity:calc(var(--fade) * .13);
  transform:translate3d(var(--x),var(--y),0) rotate(var(--r));
  pointer-events:none;
  z-index:0;
  will-change:transform,opacity;
  backface-visibility:hidden;
}

@media (max-width:760px){ .deco{width:78vw} }

@media (prefers-reduced-motion:reduce){
  .deco{transform:none;opacity:.07}
}

/* Without mask support the background would paint as a plain orange
   rectangle drifting across the page - worse than showing nothing. */
@supports not ((-webkit-mask-image: url("x.svg")) or (mask-image: url("x.svg"))) {
  .deco{display:none}
}
/* ===== SCROLL FIGURE — END =========================================== */

/* ===== FRONT PAGE: tracks, flow line, ecosystems =======================
   index.html only. Sections 3 and 4 sit inside .flow, one dark band, and
   js/flow.js draws a single orange line through it: down from each track
   card, together in #merge, then straight on to the ecosystems eyebrow.
   js/ecosystems.js builds the network and the phone rows from one list.
   No type of its own: every size, weight and tracking here is a class
   that already exists (.h-1, .h-3, .lede, .eyebrow, .case__cat,
   .row__title, .plogo, .card p).
   ==================================================================== */

/* the wrapper carries the band's ink itself: two sections of the same
   colour can leave a hairline of the page behind them at a fractional
   scroll position, and this is meant to read as one band */
.flow{position:relative;background:var(--ink)}
.flow > .sec{position:relative}
.flow__svg{
  position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:1;overflow:visible;
}
.flow__path{
  fill:none;stroke:var(--orange);stroke-width:3;stroke-linecap:round;
  stroke-dasharray:1;stroke-dashoffset:1;
  /* hidden until there is something to draw: with nothing drawn the
     round cap still paints a dot at the start. js/flow.js adds is-drawing */
  visibility:hidden;
}
.flow__path.is-drawing{visibility:visible}
/* the label on the trunk: the line passes behind it, so it carries the
   band's own ink as a background. js/flow.js sets top; it shows once the
   drawing tip has reached it */
.flowtag{
  position:absolute;left:50%;top:0;z-index:3;
  transform:translate(-50%,-50%) scale(.96);
  margin:0;padding:.6rem 1.1rem;
  white-space:nowrap;
  color:var(--cream);background:var(--ink);
  border:1px solid var(--orange);border-radius:var(--radius);
  opacity:0;
  transition:opacity .4s ease,transform .4s ease;
}
.flowtag.is-on{opacity:1;transform:translate(-50%,-50%) scale(1)}
/* on a phone the label is wider than the screen on one line, so it
   takes two there, centred, inside the gutters */
@media (max-width:520px){
  .flowtag{white-space:normal;text-align:center;justify-content:center;max-width:calc(100% - 2 * var(--gutter))}
}

/* ---- two tracks ---- */
.tracks{padding-bottom:0;overflow:hidden}
.tracks > .wrap{position:relative;z-index:1}
/* the brand asterisk, once, still, top right behind the cards. .deco is
   the scroll figure's element; without js/figure.js its vars stay at
   rest, and this keeps it from the fade that would hide it */
.deco--still{
  left:auto;right:-6%;top:-4%;
  width:clamp(260px,38vw,560px);
  opacity:.08;
  transform:rotate(-22deg);
}
@media (prefers-reduced-motion:reduce){ .deco--still{opacity:.08;transform:rotate(-22deg)} }
/* the brand cross, the same way, bottom left - but on the band wrapper
   rather than inside the ecosystems section, which clips. It sits at the
   band's foot and its lower edge, plus the corner the turn swings down,
   runs over into the client wall, so the dark band and the cream section
   read as joined. Turned 20 degrees right. */
.deco--cross{
  -webkit-mask-image:url("../img/figures/cross.png");mask-image:url("../img/figures/cross.png");
  aspect-ratio:411/412;
  top:auto;right:auto;left:-6%;bottom:-4%;
  transform:rotate(20deg);
}
@media (prefers-reduced-motion:reduce){ .deco--cross{transform:rotate(20deg)} }
.eco > .wrap{position:relative;z-index:1}
/* the section after the band: its content lifted above the cross, its
   background left below it. The section itself must stay unpositioned -
   positioned, it would paint its cream over the figure */
.flow + .sec > .wrap{position:relative;z-index:1}
/* the part of the cross outside the left edge must not widen the page */
main{overflow-x:clip}
.tracks__head{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:clamp(20px,3vw,40px);
  margin-bottom:clamp(32px,5vw,64px);
}
.tracks__head .sec-head{flex:1 1 0;min-width:0;margin-bottom:0}
.tracks__head > p{flex:none;margin:0 0 .35rem}
.tracks__cards{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(16px,2.4vw,32px)}
/* on the dark band the cards go transparent and keep the band's text */
.tracks .card{background:transparent;color:inherit;border-color:var(--line-light)}
/* the track kicker runs 15% over .case__cat (.75rem), on Kim's call -
   the two cards only, the case grid keeps its size */
.tracks .card .case__cat{font-size:.8625rem;margin-bottom:.8rem}
/* where the two lines merge, under the cards */
.merge{height:clamp(120px,15vw,200px)}
@media (max-width:760px){
  .tracks__head{flex-direction:column;align-items:flex-start}
  .tracks__cards{grid-template-columns:1fr}
}

/* ---- ecosystems ---- */
.eco{padding-top:0}
.lead{height:clamp(64px,8vw,104px)}
.eco__head{margin-inline:auto;text-align:center}
.eco__head .lede{margin-inline:auto}
.eco__eyebrow{justify-content:center;color:var(--orange)}

/* the network: four quadrants round a hub, lines drawn behind them by
   js/ecosystems.js into .net__svg */
.net{
  position:relative;
  display:grid;
  grid-template-columns:1fr clamp(100px,12vw,160px) 1fr;
  grid-template-rows:auto auto;
  row-gap:clamp(56px,8vw,112px);
  align-items:start;
}
.net__svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.net__line{fill:none;stroke:var(--line-light);stroke-width:1.5;transition:stroke .25s ease,stroke-width .25s ease}
.net__line.is-active{stroke:var(--orange);stroke-width:3}
.hub{
  grid-column:2;grid-row:1 / 3;
  align-self:center;justify-self:center;
  width:22px;height:22px;border-radius:50%;
  background:var(--orange);
  box-shadow:0 0 0 10px rgba(255,113,37,.14),0 0 0 22px rgba(255,113,37,.06);
  /* a slow breath: the two rings swell and thin out, the disc stays */
  animation:hub-pulse 3.6s ease-in-out infinite;
}
@keyframes hub-pulse{
  0%,100%{box-shadow:0 0 0 10px rgba(255,113,37,.14),0 0 0 22px rgba(255,113,37,.06)}
  50%{box-shadow:0 0 0 16px rgba(255,113,37,.10),0 0 0 34px rgba(255,113,37,.035)}
}
.quad{
  position:relative;z-index:1;
  display:flex;flex-direction:column;gap:1rem;
  transition:opacity .25s ease;
}
.quad--tl{grid-column:1;grid-row:1}
.quad--tr{grid-column:3;grid-row:1}
.quad--bl{grid-column:1;grid-row:2}
.quad--br{grid-column:3;grid-row:2}
/* the lower row mirrors the upper: logos nearest the hub, the name and
   its dot on the outer edge, and the quadrant pinned to the row's foot.
   Dots then sit at the top edge of row one and the bottom edge of row
   two, so the hub at the grid's centre is the same distance from all
   four and the four lines come out the same length */
.quad--bl,.quad--br{flex-direction:column-reverse;align-self:end}
/* the left quadrants face the hub: dot on the inner side, boxes ranged right */
.quad--tl,.quad--bl{align-items:flex-end;text-align:right}
.quad--tl .node,.quad--bl .node{flex-direction:row-reverse}
.quad--tl .quad__logos,.quad--bl .quad__logos{justify-content:flex-end}
.net.has-active .quad:not(.is-active){opacity:.25}
.node{
  display:inline-flex;align-items:center;gap:.8rem;
  padding:0;text-align:inherit;
  color:inherit;
  transition:color .25s ease;
}
.node__dot{
  flex:none;width:14px;height:14px;border-radius:50%;
  border:2px solid var(--cream);
  transition:background .25s ease,border-color .25s ease;
}
/* the ecosystem names run 10% over .row__title, on Kim's call
   (2 October 2026): clamp(1rem,1.6vw,1.2rem) scaled, desktop and phone alike */
.node{--name:clamp(1.1rem,1.76vw,1.32rem)}
.node__name,.eco__row .row__title{font-size:clamp(1.1rem,1.76vw,1.32rem)}
.node__name{line-height:1.25}
/* a long name wraps, and a dot centred on the block would then sit a
   half line further from the hub than its neighbour's. The dot goes on
   the line nearest the hub instead - the first line in the upper row,
   the last in the lower - centred on that line's height, so the four
   dots keep their distance from the hub whatever the line count */
.node__dot{align-self:flex-start;margin-top:calc(var(--name) * 1.25 / 2 - 7px)}
.quad--bl .node__dot,.quad--br .node__dot{align-self:flex-end;margin-top:0;margin-bottom:calc(var(--name) * 1.25 / 2 - 7px)}
.quad.is-active .node{color:var(--orange)}
.quad.is-active .node__dot{background:var(--orange);border-color:var(--orange)}
.node:focus-visible{outline:2px solid var(--orange);outline-offset:6px;border-radius:var(--radius)}
.quad__logos{display:flex;flex-wrap:wrap;gap:.7rem;max-width:460px}
.quad .plogo{opacity:.5;transition:opacity .25s ease}
.quad.is-active .plogo{opacity:1}
.eco .plogo img{filter:grayscale(1) invert(1) brightness(1.4)}

/* under the network: the active ecosystem's description, or the hint */
.eco__desc{
  margin:clamp(32px,5vw,64px) auto 0;
  /* the measure plus the padding, so the words still get their 40ch;
     the height of two lines plus the padding, so the hint and a
     two-line description hold the same box */
  max-width:calc(40ch + 2 * clamp(20px,2.6vw,36px));text-align:center;
  min-height:calc(2lh + 2 * clamp(16px,2vw,28px));
  /* boxed while it carries a description, like the "AI first" label:
     the band's ink as a solid ground so the cross behind never runs
     through the words, and an orange rule. The padding and the border
     are always there, only coloured in, so the box does not change
     height between the hint and the text */
  padding:clamp(16px,2vw,28px) clamp(20px,2.6vw,36px);
  border:1px solid transparent;border-radius:var(--radius);
  transition:border-color .25s ease,background-color .25s ease;
}
.eco__desc.is-on{background:var(--ink);border-color:var(--orange)}
.eco__hint{justify-content:center;margin:0;color:var(--orange)}

/* the button under the network, and under the rows on a phone */
.eco__cta{text-align:center;margin:clamp(32px,5vw,64px) 0 0}

/* the phone layout: rows instead of the network */
.eco__rows{display:none}
.eco__row{padding:clamp(20px,3vw,32px) 0;text-align:center}
.eco__row .quad__logos{justify-content:center;margin-inline:auto}
.eco__row .row__title{color:var(--orange);margin:0 0 .6rem}
.eco__row p{margin:0 0 1rem}
@media (max-width:759px){
  .net,.eco__desc{display:none}
  .eco__rows{display:block}
}
@media (prefers-reduced-motion:reduce){
  .hub{animation:none}
  .flow__path{stroke-dashoffset:0 !important;visibility:visible}
  .flowtag{opacity:1;transform:translate(-50%,-50%);transition:none}
}
/* ===== FRONT PAGE — END ============================================== */

/* ===== BOOK SESSION: discovery form ===================================
   book-session.html only; js/discovery-form.js opens it as a popup and
   sends it to HubSpot. On a dark panel, so the fields are outlined in the
   light line and
   take the cream text. Labels wear .info__label, the contact band's own
   label type, so no new type is introduced here.
   ==================================================================== */
.dform{
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(16px,2vw,24px) clamp(16px,2vw,24px);
  align-content:start;
}
.dform__field{display:flex;flex-direction:column;gap:.5rem;min-width:0}
.dform__field--wide{grid-column:1 / -1}
.dform__field .info__label{margin:0}
.dform__opt{color:var(--cream);opacity:.55;margin-left:.4em}
.dform input,.dform textarea{
  font:inherit;font-size:1rem;color:var(--cream);
  background:transparent;
  border:1px solid var(--line-light);border-radius:var(--radius);
  padding:.85rem 1rem;width:100%;
  transition:border-color .18s ease;
}
.dform textarea{resize:vertical;min-height:8.5rem;line-height:1.5}
.dform input:focus,.dform textarea:focus{outline:none;border-color:var(--orange)}
.dform input:focus-visible,.dform textarea:focus-visible{box-shadow:0 0 0 1px var(--orange)}
.dform__foot{display:flex;align-items:center;flex-wrap:wrap;gap:1rem 1.6rem;margin-top:.4rem}
.dform__note{margin:0;font-size:.9rem;opacity:.7}
.dform__status{margin:0;min-height:1.5em;font-size:1rem}
.dform__status.is-error{color:var(--orange)}
@media (max-width:760px){
  .dform{grid-template-columns:1fr}
}
/* the popup the form lives in: the deep ink panel over a dimmed page */
.dmodal{
  padding:0;border:1px solid var(--line-light);border-radius:var(--radius);
  background:var(--ink-deep);color:var(--cream);
  width:min(760px,calc(100% - 2 * var(--gutter)));
  max-height:calc(100dvh - 32px);overflow:auto;
}
.dmodal::backdrop{background:rgba(16,16,16,.72);backdrop-filter:blur(3px)}
.dmodal[open]{animation:dmodal-in .25s ease}
@keyframes dmodal-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.dmodal[open]{animation:none}}
html:has(.dmodal[open]){overflow:hidden}
.dmodal__panel{position:relative;padding:clamp(28px,4vw,48px)}
.dmodal__panel .h-2{margin:0 0 .6rem;padding-right:2.5rem}
.dmodal__lede{margin:0 0 clamp(24px,3vw,36px);max-width:52ch;opacity:.85}
/* the close button: a cross drawn in CSS, cream, orange on hover */
.dmodal__close{
  position:absolute;top:clamp(16px,2.4vw,24px);right:clamp(16px,2.4vw,24px);
  width:40px;height:40px;border-radius:50%;
  border:1px solid var(--line-light);color:var(--cream);
  transition:color .18s ease,border-color .18s ease;
}
.dmodal__close::before,.dmodal__close::after{
  content:"";position:absolute;left:50%;top:50%;
  width:16px;height:2px;background:currentColor;border-radius:var(--radius);
}
.dmodal__close::before{transform:translate(-50%,-50%) rotate(45deg)}
.dmodal__close::after{transform:translate(-50%,-50%) rotate(-45deg)}
.dmodal__close:hover,.dmodal__close:focus-visible{color:var(--orange);border-color:var(--orange);outline:none}
/* the solid button's hover is ink, which would vanish on this panel */
.dform .btn--solid:hover{background:var(--cream);border-color:var(--cream);color:var(--ink)}
/* ===== BOOK SESSION — END ============================================ */

/* ===== WE DO: the lap dog =============================================
   The animation from the original site's service page, beside the
   "AI is our lap dog" heading. 864x576 is the file's own size and it is
   never shown larger, so it stays sharp. */
.lapdog{align-items:center;margin-bottom:clamp(32px,5vw,64px)}
.lapdog .sec-head{margin-bottom:0}
.lapdog__pic{margin:0;max-width:864px}
.lapdog__pic img{width:100%;height:auto;border-radius:var(--radius)}
/* The three ways under the lap dog: the figure small and on the heading's
   own line, before the name, instead of large above it. The tight crop of
   each figure is used here, since at this size the box is the mark. */
.step--inline .step__head{display:flex;align-items:center;gap:.8rem;margin-bottom:.6rem}
.step--inline .step__head .icon{width:2.6rem;height:2.6rem;margin:0}
.step--inline .step__head .h-3{margin:0}
/* ===== WE DO — END ==================================================== */

/* ===== WE DO: the two tracks as toggles ===============================
   we-do.html; js/tracks.js opens and closes the panels. Every font size
   here is one the site already uses. */
  /* cards on row one, the open panel across row two; on a phone the
     markup order takes over, so each panel opens under its own card */
  .wdt-tracks{display:grid;grid-template-columns:1fr 1fr;gap:clamp(16px,2.4vw,32px)}
  #track-1{grid-column:1;grid-row:1}
  #track-2{grid-column:2;grid-row:1}
  .wdt-panel{grid-column:1 / -1;grid-row:2}
  .wdt-track{position:relative;transition:border-color .2s ease,box-shadow .2s ease}
  /* the open card's liner is 3px, the weight of the circle of trust's
     orange stroke (.cot__progress). The border stays 1px and an inset
     shadow adds the other 2px, so opening a card does not move its
     content by the difference. */
  .wdt-track.is-open{border-color:var(--orange);box-shadow:inset 0 0 0 2px var(--orange)}
  .wdt-track .case__cat{font-size:.8625rem;margin-bottom:.8rem}
  .wdt-more{
    margin-top:auto;padding:1.4rem 0 0;text-align:left;
    font-family:var(--label);font-weight:600;font-size:.95rem;
    letter-spacing:.16em;text-transform:uppercase;
    display:inline-flex;align-items:center;gap:.6em;
    transition:color .18s ease;
  }
  /* the whole card is the click target, through the button */
  .wdt-more::before{content:"";position:absolute;inset:0;border-radius:var(--radius)}
  .wdt-more::after{
    content:"";width:.5em;height:.5em;flex:none;
    border-right:2px solid var(--orange);border-bottom:2px solid var(--orange);
    transform:translateY(-.15em) rotate(45deg);transition:transform .25s ease;
  }
  .wdt-more[aria-expanded="true"]::after{transform:translateY(.15em) rotate(-135deg)}
  .wdt-track:hover .wdt-more,.wdt-more:focus-visible{color:var(--orange)}
  .wdt-more:focus-visible{outline:none}
  .wdt-more:focus-visible::before{outline:2px solid var(--orange);outline-offset:4px}
  .wdt-panel{padding-top:clamp(16px,2.4vw,32px)}
  .wdt-panel[hidden]{display:none}
  .wdt-panel.is-in{animation:wdt-in .35s ease}
  @keyframes wdt-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
  @media (prefers-reduced-motion:reduce){.wdt-panel.is-in{animation:none}}
  .wdt-panel__lede{margin:0 0 clamp(24px,3vw,40px);max-width:60ch}
  .wdt-groups{row-gap:clamp(32px,4vw,48px)}
  .wdt-group p{font-size:1rem;line-height:1.55}
  @media (max-width:760px){
    .wdt-tracks{grid-template-columns:1fr}
    #track-1,#track-2,.wdt-panel{grid-column:auto;grid-row:auto}
    .wdt-panel{padding-top:0;padding-bottom:clamp(16px,2.4vw,32px)}
    /* on a phone it is only the boxes: the "See what is included" line
       and its arrow are not shown. The button stays, at no size, because
       it is still what makes the whole card clickable and what a screen
       reader announces; the orange border marks the open card. */
    .wdt-more{font-size:0;padding:0;margin:0;gap:0;height:0}
    .wdt-more::after{display:none}
  }
/* ===== WE DO TRACKS — END ============================================= */

/* ===== WE DO: circle of trust ring, percentage rings ==================
   we-do.html. js/circle.js builds the ring from the list of steps; the
   percentage rings are CSS alone, filled when their row reveals, with
   the site's counter running the numbers. */
/* ---- the circle of trust as a ring ---- */
.cot{
  position:relative;
  width:min(540px,100%);aspect-ratio:1;
  margin:clamp(56px,7vw,88px) auto clamp(64px,8vw,104px);
}
.cot[hidden]{display:none}
.cot__ring{position:absolute;inset:0;width:100%;height:100%;overflow:visible;transform:rotate(-90deg)}
/* stroke widths are in the drawing's own units: the ring is 540px
   across a 100-unit box, so .56 is 3px. (non-scaling-stroke would let
   them be pixels, but it measures the dashes in pixels too, which broke
   the progress stroke into fragments.) */
.cot__ring circle{fill:none}
.cot__track{stroke:var(--line-light);stroke-width:.28}
.cot__progress{
  stroke:var(--orange);stroke-width:.56;stroke-linecap:round;
  stroke-dasharray:0 100;transition:stroke-dasharray .7s cubic-bezier(.22,1,.36,1);
}
/* ---- Bridge: the circle closes, lights up and breathes ----
   At step 05 the stroke has gone all the way round, at one even
   weight. Two things then say "bridge": the whole ring glows and
   breathes, and rings ripple outward from the circle, the next round
   growing out of this one. Both wait for the stroke to finish closing
   first. (A thicker closing stretch from Bridge to Plan was tried and
   dropped: Kim wants the circle equally thick all the way round.) */
.cot__ripple{
  stroke:var(--orange);stroke-width:.28;opacity:0;
  transform-box:fill-box;transform-origin:center;
}
.cot.is-bridged .cot__progress{animation:cot-breathe 2.8s ease-in-out .7s infinite}
.cot.is-bridged .cot__ripple{animation:cot-ripple 2.8s ease-out .7s infinite}
.cot.is-bridged .cot__ripple--2{animation-delay:2.1s}
@keyframes cot-breathe{
  0%,100%{stroke-width:.56;filter:drop-shadow(0 0 0 rgba(255,113,37,0))}
  50%{stroke-width:.93;filter:drop-shadow(0 0 2px rgba(255,113,37,.75))}
}
@keyframes cot-ripple{
  0%{transform:scale(1);opacity:.55}
  100%{transform:scale(1.22);opacity:0}
}
/* every dot is lit, and Plan - where the bridge lands - gets the halo too */
.cot.is-bridged .cot__node::before{background:var(--orange);border-color:var(--orange)}
.cot.is-bridged .cot__node--t::before{
  box-shadow:0 0 0 8px rgba(255,113,37,.14),0 0 0 18px rgba(255,113,37,.06);
  transition-delay:.6s;
}
.cot.is-bridged .cot__centre .icon{animation:cot-star 2.8s ease-in-out .7s infinite}
@keyframes cot-star{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}

/* a node: a 44px hit area centred on its point of the ring, the dot
   drawn in the middle of it, the label hung on the outer side */
.cot__node{
  position:absolute;width:44px;height:44px;padding:0;
  transform:translate(-50%,-50%);
  color:var(--cream);transition:color .25s ease;
}
.cot__node::before{
  content:"";position:absolute;left:50%;top:50%;
  width:14px;height:14px;border-radius:50%;
  transform:translate(-50%,-50%);
  background:var(--ink);border:2px solid var(--cream);
  transition:background .25s ease,border-color .25s ease,box-shadow .25s ease;
}
.cot__node.is-done::before{background:var(--orange);border-color:var(--orange)}
.cot__node.is-active{color:var(--orange)}
.cot__node.is-active::before{
  background:var(--orange);border-color:var(--orange);
  box-shadow:0 0 0 8px rgba(255,113,37,.14),0 0 0 18px rgba(255,113,37,.06);
}
.cot__node:focus-visible{outline:2px solid var(--orange);outline-offset:2px;border-radius:50%}
.cot__label{
  position:absolute;white-space:nowrap;
  font-family:var(--label);font-weight:600;
  font-size:clamp(1rem,1.6vw,1.2rem);letter-spacing:.16em;text-transform:uppercase;
}
.cot__label b{font-weight:600;color:var(--orange);margin-right:.6em}
.cot__node--t .cot__label{bottom:100%;left:50%;transform:translateX(-50%)}
.cot__node--r .cot__label{left:100%;top:50%;transform:translateY(-50%)}
.cot__node--l .cot__label{right:100%;top:50%;transform:translateY(-50%)}
.cot__node--br .cot__label{top:100%;left:50%}
.cot__node--bl .cot__label{top:100%;right:50%}
/* the middle: the active step */
.cot__centre{
  position:absolute;inset:17%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;
}
.cot__centre .icon{width:clamp(72px,9vw,112px);height:clamp(72px,9vw,112px);margin-bottom:.8rem}
.cot__centre .h-3{margin:0 0 .5rem}
.cot__centre p{margin:0;font-size:1rem;line-height:1.55;max-width:26ch}
.cot__centre.is-swap > *{animation:cot-in .4s ease}
@keyframes cot-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .cot__centre.is-swap > *{animation:none}
  .cot__progress{transition:none}
  /* Bridge still reads without motion: the lit ring stays, the
     breathing and the ripples do not run */
  .cot.is-bridged .cot__progress,.cot.is-bridged .cot__ripple,.cot.is-bridged .cot__centre .icon{animation:none}

}
/* the list: the timeline a phone gets, and the fallback everywhere */
.cot-list{list-style:none;margin:0;padding:0;position:relative}
.cot-list.is-ringed{display:none}
.cot-step{position:relative;padding:0 0 clamp(28px,4vw,40px) 2.4rem}
.cot-step:last-child{padding-bottom:0}
.cot-step::before{
  content:"";position:absolute;left:0;top:.35rem;
  width:14px;height:14px;border-radius:50%;background:var(--orange);
}
.cot-step::after{
  content:"";position:absolute;left:6px;top:calc(.35rem + 18px);bottom:-.1rem;
  width:2px;background:var(--orange);opacity:.45;border-radius:var(--radius);
}
.cot-step:last-child::after{display:none}
.cot-step .step__num{margin-bottom:.2rem}
.cot-step .h-3{margin:0 0 .4rem}
.cot-step p{margin:0;font-size:1rem;line-height:1.55;max-width:52ch}
@media (max-width:760px){
  .cot{display:none !important}
  .cot-list.is-ringed{display:block}
}

/* ---- why honest brands win: three percentage rings ---- */
.gauge{
  position:relative;display:grid;place-items:center;
  /* smaller, and centred in its column like the site's other figures */
  width:clamp(104px,10.5vw,132px);aspect-ratio:1;margin:0 auto 1.6rem;
}
.gauge svg{position:absolute;inset:0;width:100%;height:100%;transform:rotate(-90deg);overflow:visible}
.gauge circle{fill:none}
.gauge__track{stroke:var(--line-dark);stroke-width:.8}
.gauge__arc{
  stroke:var(--orange);stroke-width:2.4;stroke-linecap:round;
  stroke-dasharray:0 100;
  /* the same 2.8s the number takes to count up, so they land together */
  transition:stroke-dasharray 2.8s cubic-bezier(.22,1,.36,1);
}
.rv.is-in .gauge__arc{stroke-dasharray:var(--p) 100}
/* the number at the .h-2 size, to sit inside the smaller ring */
.gauge .stat__num{position:relative;font-size:clamp(1.6rem,3vw,2.35rem)}
@media (prefers-reduced-motion:reduce){.gauge__arc{transition:none}}
/* ===== WE DO RINGS — END ============================================== */

/* ===== WE DO: who we do it for ========================================
   we-do.html, after the tracks. */
/* The four ecosystems as plain rows: name, one sentence, three logos,
   all visible. The rows themselves are the ones js/ecosystems.js
   already builds for the front page's phone layout, so the names, the
   sentences and the clients come from that one list. Here they show at
   every width, and on a wide screen each row runs left to right. */
.who .net,.who .eco__desc{display:none}
.who .eco__rows{display:block;border-top:1px solid var(--line-light)}
.who .eco__row{border-bottom:1px solid var(--line-light)}
@media (min-width:900px){
  .who .eco__row{
    display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr) auto;
    align-items:center;gap:clamp(24px,3vw,48px);
    text-align:left;padding:clamp(20px,2.4vw,30px) 0;
  }
  .who .eco__row .row__title,.who .eco__row p{margin:0}
  .who .eco__row .quad__logos{flex-wrap:nowrap;margin:0;max-width:none}
}
.who .plogo{opacity:1}
/* light on the dark band, as on the front page */
.who .plogo img{filter:grayscale(1) invert(1) brightness(1.4)}
/* ===== WE DO WHO — END ================================================ */
