
@import url('fonts/fonts.css');

:root{
  --bg:#FBFBF9;
  --bg-2:#F1F1ED;
  --ink:#0E0E10;
  --ink-2:#43434A;
  --ink-3:#6A6A74;
  --line:#E2E2DC;
  --line-d:#2A2A2F;
  --accent:#2B44FF;

  --ff-d:'Archivo',system-ui,sans-serif;
  --ff-b:'Public Sans',system-ui,sans-serif;
  --ff-m:'Martian Mono',ui-monospace,monospace;

  --gut:clamp(20px,4.4vw,72px);
  --maxw:1600px;
  --col-gap:clamp(18px,2.2vw,34px);

  /* ═══ TYPE SCALE ═══
     Every font-size resolves to a step below. Introducing an ad-hoc value is
     how this stylesheet previously ended up with six different label sizes and
     three different section-heading sizes on the same page.

     The ordering constraint that matters: --t-cta sits deliberately below
     --t-d2, because the closing CTA is a section heading and must never
     out-size the page title it sits under. It used to, on every inner page. */
  /* The display tier moves as a unit. It has to: d1 > d2 > cta > h1 is the
     hierarchy, so pulling the hero down without the rest would put the inner
     page titles and the closing CTA above it. */
  --t-d1:clamp(38px,5.9vw,92px);     /* home hero h1                        */
  --t-d2:clamp(35px,5.4vw,84px);     /* inner page h1 (.phero-h)            */
  --t-cta:clamp(32px,4.9vw,74px);    /* closing CTA, and big stat numerals  */
  --t-h1:clamp(32px,4.6vw,70px);     /* major section h2                    */
  --t-h2:clamp(28px,3.6vw,54px);     /* case-study titles                   */
  --t-h3:clamp(24px,3vw,42px);       /* section headings                    */
  --t-h4:clamp(20px,2.3vw,32px);     /* sub-item titles                     */
  --t-h5:clamp(17px,1.5vw,21px);     /* card and list-item titles           */

  --t-lede:clamp(16px,1.3vw,20px);   /* standfirst under a heading          */
  --t-body:15.5px;                   /* running copy                        */
  --t-sm:14px;                       /* secondary copy, dense lists         */
  --t-lab-l:12px;                    /* larger mono label                   */
  --t-lab:11px;                      /* mono eyebrow label — the floor      */
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--ink);font-family:var(--ff-b);
  font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}

/* ═══ OVERFLOW HARDENING ═══
   Structural guards against the ways a page bursts its container, applied
   regardless of whether a given cause is present. Grid and flex children
   default to min-width:auto, which refuses to shrink below their content and
   is the single most common cause of horizontal overflow. */
.hero-g>*,.hero-sub>*,.sec-hd>*,.w-item>*,.studio-g>*,.cta-g>*,
.srv-row>*,.stats>*,.slots>*,.legal-g>*,.nav-in>*,.cta-row>*{min-width:0}
/* Long unbreakable strings (URLs, emails, part codes) must wrap, not push */
.w-link,.founder-l,.cta-v,.cta-v a,.f-in,.f-in a,.plate-t,.plate-c,
.hero-p,.w-d,.srv-d,.studio-p,.sec-note,.cta-p,.legal-g p{overflow-wrap:anywhere}
h1,h2,.w-t,.srv-t,.cta-h,.stat-n{overflow-wrap:break-word}
/* Nothing may exceed the viewport regardless of its own sizing */
.w,.nav-in{width:100%}

:focus{outline:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.inv :focus-visible{outline-color:#fff}
@media (forced-colors:active){:focus-visible{outline:3px solid Highlight}}
::selection{background:var(--accent);color:#fff}
html{scrollbar-color:#B9B9B2 var(--bg-2);scrollbar-width:thin}
::-webkit-scrollbar{width:12px}
::-webkit-scrollbar-track{background:var(--bg-2)}
::-webkit-scrollbar-thumb{background:#B9B9B2;border:3px solid var(--bg-2)}

.skip{position:fixed;top:0;left:50%;transform:translate(-50%,-130%);z-index:999;
  background:var(--accent);color:#fff;padding:13px 26px;font-family:var(--ff-m);
  font-size:var(--t-lab-l);letter-spacing:.05em;transition:transform .2s}
.skip:focus{transform:translate(-50%,0)}

.w{max-width:var(--maxw);margin:0 auto;padding:0 var(--gut)}
.lab{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-3)}
.lab-a{color:var(--accent)}
/* On the dark sections the accent drops to 3.1:1 against #0E0E10, which fails
   WCAG AA for 11px text. This lighter tint is already in the palette (it is
   what .inv .more:hover uses) and clears AA at 5.6:1. */
.inv .lab-a,.inv .srv-n,.inv .w-idx,.inv .cs-role{color:#6E7FFF}

/* ═══ NAV ═══ */
.nav{position:fixed;inset:0 0 auto;z-index:100;padding:20px 0;
  transition:background .35s,padding .35s,border-color .35s;border-bottom:1px solid transparent}
.nav.stuck{background:rgba(251,251,249,.86);backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);padding:13px 0;border-bottom-color:var(--line)}
.nav-in{display:flex;align-items:center;justify-content:space-between;gap:20px;
  max-width:var(--maxw);margin:0 auto;padding:0 var(--gut)}
.brand{font-family:var(--ff-d);font-weight:700;font-size:16px;letter-spacing:-.02em}
.brand span{color:var(--accent)}
.nav-r{display:flex;align-items:center;gap:clamp(16px,2.2vw,34px)}
.nav-r a{font-size:var(--t-sm);color:var(--ink-2);transition:color .2s}
.nav-r a:hover{color:var(--ink)}
.nav-cta{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.06em;text-transform:uppercase;
  border:1px solid var(--ink);padding:11px 20px;color:var(--ink)!important;
  display:inline-flex;position:relative;isolation:isolate;overflow:hidden}
.nav-cta::before{background:var(--ink)}
.nav-cta .bt-on{color:#fff}

/* ── Services mega-menu ──
   Opens on hover and on :focus-within, so it works from the keyboard with no
   JavaScript. The trigger stays a real link to the hub: on touch, where hover
   never fires, tapping navigates instead of dead-ending.

   The panel is positioned against .nav-r, not the trigger — anchored to the
   Services link it would be far too narrow for five columns, or would hang
   off the right edge of the viewport. */
.nav-d{position:static;display:inline-flex}
.nav-r{position:relative}
.nav-d>a{display:inline-flex;align-items:center;gap:6px}
.chev{width:9px;height:6px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .22s}
.nav-d:hover .chev,.nav-d:focus-within .chev{transform:rotate(180deg)}

.nav-m{position:absolute;top:100%;right:0;margin-top:14px;
  width:min(1180px,calc(100vw - 2*var(--gut)));
  background:var(--bg);border:1px solid var(--line);
  box-shadow:0 26px 60px rgba(14,14,16,.10);
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .24s ease,transform .24s ease,visibility .24s}
.nav-d:hover .nav-m,.nav-d:focus-within .nav-m{opacity:1;visibility:visible;transform:none}
/* bridges the gap so the pointer can travel into the panel without closing it */
.nav-m::before{content:;position:absolute;inset:-16px 0 auto;height:16px}

.nav-cols{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:0;padding:6px}
.nav-col{display:flex;flex-direction:column;padding:18px 16px;min-width:0}
.nav-col+.nav-col{border-left:1px solid var(--line)}
.nav-ct{font-family:var(--ff-d);font-weight:700;font-size:14px;letter-spacing:-.015em;
  color:var(--ink);margin-bottom:12px;line-height:1.25}
.nav-ct:hover{color:var(--accent)}
.nav-cl{font-size:13px;line-height:1.35;color:var(--ink-2);padding:6px 0;
  transition:color .18s,padding-left .18s}
.nav-cl:hover{color:var(--accent);padding-left:5px}
/* no page yet in this language — shown, but not a link */
.nav-cl-off{color:var(--ink-3);opacity:.62;cursor:default}
.nav-all{display:flex;align-items:center;justify-content:flex-end;gap:9px;
  border-top:1px solid var(--line);padding:13px 22px;
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-2)}
.nav-all:hover{color:var(--accent)}

/* ═══ HERO ═══ */
/* padding-block, never the shorthand: these elements also carry .w, and a
   `padding: X 0` shorthand silently overwrote .w's horizontal gutter, putting
   every section flush against the screen edges. */
.hero{padding-block:clamp(112px,13vh,150px) clamp(52px,7vw,96px)}
/* stretch, not end: the plate matches the text column's height instead of a
   tall fixed ratio dictating the row and leaving dead space above the headline */
/* 50/50: copy left, 3D right. The old 1.34/.56 split left the animation
   column too narrow to carry a hero object. */
.hero-g{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(24px,3.4vw,60px);align-items:center}
.hero-copy{display:flex;flex-direction:column;align-items:flex-start}
.hero-copy h1{margin-top:clamp(14px,1.6vw,24px)}
.hero-g>.w-media{display:flex;flex-direction:column;justify-content:center}
.hero-meta{list-style:none;display:flex;flex-wrap:wrap;gap:clamp(16px,2.4vw,38px);
  margin-top:clamp(28px,3.4vw,46px);padding-top:clamp(18px,2.2vw,26px);
  border-top:1px solid var(--line);width:100%}
.hero-meta li{font-size:var(--t-sm);color:var(--ink-3);line-height:1.4}
.hero-meta b{display:block;font-family:var(--ff-d);font-weight:700;font-size:var(--t-h5);
  color:var(--ink);letter-spacing:-.02em;margin-bottom:3px}
/* portrait ratio lives here, not inline — an inline style outranks every
   media query and pinned the plate to 4/5 on phones */
.hero-plate{width:100%;aspect-ratio:4/5;min-height:clamp(300px,46vh,520px)}

/* ═══ HERO 3D ═══
   The animation column. An SVG solid is rendered into the HTML as the
   baseline, so the hero is never an empty half — no JS, no WebGL, or reduced
   motion all still show a shape. hero3d.js replaces it with real geometry
   when it can, and marks the container .live so the baseline steps aside. */
.hero-3d{position:relative;width:100%;aspect-ratio:1/1;
  max-height:min(72vh,640px);display:grid;place-items:center}
.hero-3d-base{width:74%;height:auto;transition:opacity .5s ease}
.hero-3d.live .hero-3d-base{opacity:0}
.hero-3d canvas{position:absolute;inset:0;width:100%;height:100%}
/* Stacked under the copy on phones, so a square pushes it well below the fold.
   Shorter and wider brings it back into reach. */
@media(max-width:760px){
  .hero-3d{aspect-ratio:4/3;max-height:42vh}
  .hero-3d-base{width:58%}
}

/* the baseline turns gently on its own where motion is welcome */
@media (prefers-reduced-motion:no-preference){
  .hero-3d:not(.live) .hero-3d-base{animation:heroTurn 22s linear infinite}
}
@keyframes heroTurn{
  from{transform:rotate(0deg) scale(1)}
  50%{transform:rotate(180deg) scale(.94)}
  to{transform:rotate(360deg) scale(1)}
}
.mask{overflow:hidden;display:block}
h1{font-family:var(--ff-d);font-weight:800;letter-spacing:-.042em;line-height:.9;
  font-size:var(--t-d1)}

.hero-p{font-size:var(--t-lede);line-height:1.6;color:var(--ink-2);
  max-width:44ch;margin-top:clamp(20px,2.2vw,30px)}
.hero-p b{color:var(--ink);font-weight:600}
.hero-act{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:clamp(24px,2.8vw,36px)}

/* ═══ BUTTONS ═══
   Hover colour wipes in from the left.

   Two moving parts, sharing one easing and duration so they stay locked:
     ::before  the fill, scaleX(0) → scaleX(1) from the left edge
     .bt-on    a duplicate of the label in the hover colour, clipped from the
               left by the same amount

   The duplicate exists because cross-fading the label colour instead makes it
   wash out mid-hover: the text ahead of the fill edge turns white while its
   background is still white. Clipping a second copy means the colour boundary
   IS the wipe edge on every frame.

   inset:0 resolves against the padding box, so the fill stops short of the 1px
   border; the border animates separately to land with the wipe.
   prefers-reduced-motion is handled by the global transition:none rule, which
   makes both layers apply instantly rather than sweeping. */
.btn{display:inline-flex;align-items:center;gap:11px;font-family:var(--ff-m);font-size:var(--t-lab);
  letter-spacing:.07em;text-transform:uppercase;padding:17px 30px;border:1px solid var(--ink);
  background:var(--ink);color:#fff;position:relative;isolation:isolate;overflow:hidden;
  transition:border-color .44s cubic-bezier(.65,0,.35,1)}

.btn::before,.nav-cta::before{content:'';position:absolute;inset:0;z-index:0;
  transform:scaleX(0);transform-origin:left center;
  transition:transform .44s cubic-bezier(.65,0,.35,1)}
.btn:hover::before,.nav-cta:hover::before{transform:scaleX(1)}

/* label layers */
.bt{position:relative;z-index:1;display:inline-flex;align-items:center;gap:inherit;
  white-space:nowrap}
.bt-on{position:absolute;inset:0;z-index:2;padding:inherit;
  clip-path:inset(0 100% 0 0);
  transition:clip-path .44s cubic-bezier(.65,0,.35,1)}
.btn:hover .bt-on,.nav-cta:hover .bt-on{clip-path:inset(0 0 0 0)}

.btn::before{background:var(--accent)}
.btn .bt-on{color:#fff}
.btn:hover{border-color:var(--accent)}

.btn-o{background:transparent;color:var(--ink)}
.btn-o::before{background:var(--ink)}
.btn-o .bt-on{color:#fff}
.btn-o:hover{border-color:var(--ink)}

.inv .btn{background:#fff;border-color:#fff;color:var(--ink)}
.inv .btn::before{background:var(--accent)}
.inv .btn .bt-on{color:#fff}
.inv .btn:hover{border-color:var(--accent)}
.arw{width:13px;height:13px;stroke:currentColor;stroke-width:1.7;fill:none;flex:none}

/* ═══ PLATE (image placeholder) ═══ */
.plate{position:relative;overflow:hidden;background:var(--bg-2);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center}
.plate-in{position:absolute;inset:-8% 0;background:
  repeating-linear-gradient(135deg,transparent,transparent 11px,rgba(14,14,16,.032) 11px,rgba(14,14,16,.032) 22px);
  will-change:transform}
.plate-t{position:relative;text-align:center;font-family:var(--ff-m);font-size:var(--t-lab);
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);line-height:2;
  background:var(--bg);border:1px solid var(--line);padding:11px 18px}
.plate-t b{display:block;font-size:var(--t-lab);color:var(--ink);font-weight:600;letter-spacing:.06em}
.plate-c{margin-top:11px;font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-3)}
.inv .plate{background:#1A1A1E;border-color:var(--line-d)}
.inv .plate-in{background:repeating-linear-gradient(135deg,transparent,transparent 11px,rgba(255,255,255,.038) 11px,rgba(255,255,255,.038) 22px)}
.inv .plate-t{background:var(--ink);border-color:var(--line-d);color:#8B8B92}
.inv .plate-t b{color:#fff}
.inv .plate-c{color:#8B8B92}
/* A plate holding a real screenshot: dark like the product UI it frames. */
.plate-shot{background:#13161E;border-color:#2A2F3A}
/* A shot plate takes its media's own ratio (--ar), whatever ratio the slot
   would give a placeholder, so the whole product screen stays in view. */
.plate.plate-shot,.cs .plate.plate-shot{aspect-ratio:var(--ar,16/10)}
/* A vertical clip at full column width towers over the text beside it. */
.plate.plate-tall{width:100%;max-width:340px;margin-inline:auto}
.plate-shot img,.plate-shot video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:left top}
.plate-play{position:absolute;right:12px;bottom:12px;z-index:1;font-family:var(--ff-m);
  font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;color:#fff;cursor:pointer;
  background:rgba(14,14,16,.78);border:1px solid rgba(255,255,255,.22);padding:8px 12px;
  transition:border-color .2s}
.plate-play:hover{border-color:var(--accent)}
.plate-play[hidden]{display:none}
.plate-snd{position:absolute;left:12px;bottom:12px;z-index:1;font-family:var(--ff-m);
  font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;color:#fff;cursor:pointer;
  background:rgba(14,14,16,.78);border:1px solid rgba(255,255,255,.22);padding:8px 12px;
  transition:border-color .2s}
.plate-snd:hover{border-color:var(--accent)}
.plate-snd[hidden]{display:none}
.plate-badge{position:absolute;left:12px;top:12px;z-index:1;font-family:var(--ff-m);
  font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;color:#fff;
  background:rgba(14,14,16,.72);padding:6px 10px}

/* ═══ MARQUEE STRIP ═══ */
.strip{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:17px 0;overflow:hidden;background:var(--bg)}
/* ── marquee wordmarks ──
   Original brand colours, not recoloured: forcing one grey fills PostgreSQL's
   white inner detail solid, and recolouring is what most brand guidelines
   restrict.

   Heights are set PER MARK rather than uniformly. Equal pixel height does not
   mean equal visual weight — Stripe's wordmark is short and heavy, PostgreSQL's
   is long and fine, so at one height the row reads lumpy. These are eyeballed
   to match optically, which is the only way this works. */
.wm{display:block;width:auto;flex:none}
.wm-next{height:21px}
.wm-ts{height:22px}
.wm-prisma{height:22px}
.wm-vercel{height:21px}
.wm-pg{height:30px}
.wm-stripe{height:25px}
.wm-wa{height:25px}
.dv{color:var(--accent);font-style:normal;font-size:9px;line-height:1}   /* no margin: the flex gap on .strip-t span already spaces these */
.strip-t{display:flex;gap:52px;white-space:nowrap;font-family:var(--ff-m);font-size:var(--t-lab);
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);width:max-content}
.strip-t span{display:inline-flex;align-items:center;gap:clamp(26px,2.6vw,40px)}
.strip-t i{font-style:normal}   /* colour is set per role below: .nm muted, .dv accent */

/* ═══ SECTION ═══ */
.sec{padding-block:clamp(66px,9vw,150px)}
.sec-hd{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.9fr);gap:var(--col-gap);
  align-items:end;padding-bottom:clamp(26px,3vw,44px);border-bottom:1px solid var(--line);
  margin-bottom:clamp(34px,4.4vw,64px)}
.inv .sec-hd{border-bottom-color:var(--line-d)}
h2{font-family:var(--ff-d);font-weight:700;letter-spacing:-.036em;line-height:.98;
  font-size:var(--t-h1);margin-top:14px}
.sec-note{font-size:var(--t-body);line-height:1.62;color:var(--ink-2);max-width:48ch}
.inv .sec-note{color:#A0A0A8}

/* ═══ WORK ═══ */
.work{display:grid;gap:clamp(48px,6.5vw,110px)}
.w-item{display:grid;grid-template-columns:minmax(0,1.18fr) minmax(0,1fr);
  gap:clamp(24px,3.4vw,64px);align-items:center}
.w-item:nth-child(even) .w-media{order:2}
.w-media{position:relative}
.w-plate{aspect-ratio:4/3}
.w-idx{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.1em;color:var(--accent);
  margin-bottom:16px;display:block}
.w-t{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h2);
  letter-spacing:-.032em;line-height:1}
.w-role{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin-top:12px}
.w-d{color:var(--ink-2);margin-top:18px;font-size:var(--t-body);line-height:1.66;max-width:46ch}
.w-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:22px}
.tag{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.05em;text-transform:uppercase;
  border:1px solid var(--line);padding:7px 12px;color:var(--ink-2)}
.w-link{display:inline-flex;align-items:center;gap:10px;margin-top:26px;font-family:var(--ff-m);
  font-size:var(--t-lab);letter-spacing:.07em;text-transform:uppercase;border-bottom:1px solid var(--ink);
  padding-bottom:5px;transition:color .2s,border-color .2s}
.w-link:hover{color:var(--accent);border-color:var(--accent)}

/* reserved slots */
.slots{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--col-gap);
  margin-top:clamp(48px,6vw,96px)}
.slot{border:1px dashed var(--line);background:var(--bg-2);padding:26px 22px;min-height:170px;
  display:flex;flex-direction:column;justify-content:space-between}
.slot-n{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;color:var(--ink-3)}
.slot-t{font-family:var(--ff-d);font-weight:600;font-size:var(--t-h5);color:var(--ink-3);letter-spacing:-.018em}
.slot-c{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}

/* ═══ SERVICES ═══ */
.srv{border-top:1px solid var(--line)}
.inv .srv{border-top-color:var(--line-d)}
.srv-row{display:grid;grid-template-columns:64px minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(16px,2.4vw,44px);padding:clamp(26px,3.2vw,44px) 0;border-bottom:1px solid var(--line);
  align-items:start;transition:padding-left .3s}
.inv .srv-row{border-bottom-color:var(--line-d)}
.srv-row:hover{padding-left:14px}
.srv-n{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.08em;color:var(--accent);padding-top:9px}
.srv-t{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h4);letter-spacing:-.028em;line-height:1.08}
.srv-d{color:var(--ink-2);font-size:var(--t-body);line-height:1.64}
.inv .srv-d{color:#A0A0A8}
.srv-tags{display:flex;flex-wrap:wrap;gap:7px;margin-top:15px}
.inv .tag{border-color:var(--line-d);color:#A0A0A8}

/* ═══ STATS ═══ */
.stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--col-gap);
  padding:clamp(40px,5vw,76px) 0;border-top:1px solid var(--line-d);border-bottom:1px solid var(--line-d)}
.stat-n{font-family:var(--ff-d);font-weight:800;font-size:var(--t-cta);
  letter-spacing:-.045em;line-height:.9}
.stat-l{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;text-transform:uppercase;
  color:#8B8B92;margin-top:14px}

/* ═══ INVERTED CHAPTER ═══ */
.inv{background:var(--ink);color:#fff}
.inv h2,.inv .w-t,.inv .srv-t,.inv .stat-n{color:#fff}

/* ═══ STUDIO ═══ */
.studio-g{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.82fr);gap:clamp(28px,4vw,80px);align-items:start}
.studio-p{font-size:var(--t-lede);line-height:1.7;color:var(--ink-2);margin-bottom:18px;max-width:52ch}
.studio-p:last-of-type{margin-bottom:0}
.studio-p strong{color:var(--ink);font-weight:600}
.founder{margin-top:clamp(30px,3.6vw,52px);padding-top:26px;border-top:1px solid var(--line)}
.founder-n{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h5);letter-spacing:-.02em}
.founder-r{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-top:7px}
.founder-l{display:inline-flex;align-items:center;gap:9px;margin-top:16px;font-size:var(--t-sm);
  border-bottom:1px solid var(--ink);padding-bottom:3px}
.founder-l:hover{color:var(--accent);border-color:var(--accent)}
.studio-plate{aspect-ratio:4/5}

/* ═══ CONTACT ═══ */
.cta{padding-block:clamp(70px,9.5vw,160px)}
.cta-h{font-family:var(--ff-d);font-weight:800;letter-spacing:-.042em;line-height:.92;
  font-size:var(--t-cta);max-width:15ch}
.cta-g{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.72fr);gap:var(--col-gap);
  align-items:end;margin-top:clamp(34px,4.4vw,64px)}
.cta-p{color:#A0A0A8;font-size:var(--t-body);line-height:1.66;max-width:44ch}
.cta-rows{margin-top:26px}
.cta-row{display:grid;grid-template-columns:118px 1fr;gap:16px;padding:13px 0;
  border-bottom:1px solid var(--line-d);font-size:var(--t-sm)}
.cta-k{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;text-transform:uppercase;
  color:#8B8B92;padding-top:4px}
.cta-v a{border-bottom:1px solid #43434A;padding-bottom:2px}
.cta-v a:hover{border-color:var(--accent);color:#9AA6FF}

/* Contact form, on the dark CTA band. Fields are underlined rather than boxed
   so the form reads as part of the section, not a widget dropped onto it. */
.cf{display:grid;gap:20px;margin-top:30px;max-width:640px}
.cf-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px}
.cf-f{display:grid;gap:8px}
.cf-k{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;text-transform:uppercase;
  color:#8B8B92}
.cf input,.cf textarea{width:100%;font:inherit;font-size:var(--t-body);color:#fff;
  background:transparent;border:0;border-bottom:1px solid #43434A;border-radius:0;padding:9px 0;
  transition:border-color .2s}
.cf textarea{resize:vertical;min-height:128px;line-height:1.55}
.cf input:hover,.cf textarea:hover{border-bottom-color:#6A6A74}
.cf input:focus,.cf textarea:focus{border-bottom-color:var(--accent)}
.cf-go{display:flex;flex-wrap:wrap;align-items:center;gap:14px 24px;margin-top:6px}
.cf-note{font-size:var(--t-sm);color:#8B8B92;max-width:34ch}
.cf-status{font-size:var(--t-sm);line-height:1.5}
.cf-status:empty{display:none}
.cf-status.is-ok{color:#9AA6FF}
.cf-status.is-err{color:#FF9B8F}
.cf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
button.btn{cursor:pointer}
button.btn:disabled{opacity:.6;cursor:progress}
@media(max-width:760px){.cf-row{grid-template-columns:1fr}}

/* Home service headings link to their category page. */
.srv-t a{transition:color .2s}
.srv-t a:hover{color:var(--accent)}
.inv .srv-t a:hover{color:#9AA6FF}

footer{border-top:1px solid var(--line-d);padding:26px 0;background:var(--ink);color:#8B8B92}
.f-in{display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;align-items:center;
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.06em;text-transform:uppercase}
.f-in a:hover{color:#fff}
.legal{background:var(--ink);color:#8B8B92;padding-bottom:clamp(40px,5vw,72px)}
.legal-g{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(20px,2.6vw,44px);
  padding-top:clamp(34px,4vw,60px);border-top:1px solid var(--line-d)}
.legal-g h3{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.1em;text-transform:uppercase;
  color:#fff;margin-bottom:13px}
.legal-g p{font-size:var(--t-sm);line-height:1.6;margin-bottom:9px}
.ph{background:#2A2233;border:1px solid var(--accent);color:#B9C2FF;font-family:var(--ff-m);
  font-size:var(--t-lab);letter-spacing:.04em;padding:3px 7px;display:inline-block}

/* ═══ RESPONSIVE ═══ */
@media(max-width:1080px){
  .hero-g{grid-template-columns:1fr;gap:clamp(28px,4vw,44px);align-items:start}
  .hero-plate{aspect-ratio:16/9;min-height:0}
  .hero-meta{margin-top:clamp(24px,3vw,34px)}
  .w-item{grid-template-columns:1fr;gap:24px}
  .w-item:nth-child(even) .w-media{order:0}
  .studio-g{grid-template-columns:1fr;gap:34px}
  .studio-plate{aspect-ratio:16/10}
  .cta-g{grid-template-columns:1fr;gap:28px;align-items:start}
  .sec-hd{grid-template-columns:1fr;gap:16px;align-items:start}
  .stats{grid-template-columns:1fr 1fr;gap:26px}
  .legal-g{grid-template-columns:1fr 1fr}
}
/* ═══ MOBILE DISCLOSURE MENU (hidden above 760px) ═══
   A full-width panel rather than the narrow dropdown it used to be: at 216px
   the category names wrapped to two lines and the whole thing read as an
   afterthought over the page.

   Positioned against .nav-in so it aligns to the same gutters as the content
   below it. Each category is a <details>, so all twenty-six service links are
   reachable without a twenty-six-item wall — and with no JavaScript. */
.mnav{display:none;position:static}
.nav-in{position:relative}
.mnav summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.07em;text-transform:uppercase;
  border:1px solid var(--ink);padding:0 16px;min-height:44px}
.mnav>summary::-webkit-details-marker{display:none}
.mnav-bars{width:15px;height:9px;border-top:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor;position:relative}
.mnav-bars::after{content:;position:absolute;left:0;right:0;top:3px;
  border-top:1.5px solid currentColor}

.mnav-panel{position:absolute;top:calc(100% + 16px);left:0;right:0;
  background:var(--bg);border:1px solid var(--ink);
  box-shadow:0 24px 60px rgba(14,14,16,.16);
  max-height:calc(100vh - 130px);overflow-y:auto;overscroll-behavior:contain}

/* top-level destinations */
.mnav-top{display:flex;align-items:center;min-height:54px;padding:0 20px;
  font-family:var(--ff-d);font-weight:600;font-size:19px;letter-spacing:-.02em;
  border-bottom:1px solid var(--line)}
.mnav-top:active{background:var(--bg-2)}

/* a service category, collapsed by default */
.mnav-cat{border-bottom:1px solid var(--line);background:var(--bg-2)}
.mnav-cat>summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  justify-content:space-between;gap:14px;min-height:50px;padding:0 20px;
  border:0;font-family:var(--ff-b);font-weight:500;font-size:15px;
  letter-spacing:0;text-transform:none;color:var(--ink-2)}
.mnav-cat>summary::-webkit-details-marker{display:none}
.mnav-cat[open]>summary{color:var(--ink)}
.mnav-cat[open] .mnav-plus{color:var(--accent)}
.mnav-plus{position:relative;width:13px;height:13px;flex:none;color:var(--ink-3)}
.mnav-plus::before,.mnav-plus::after{content:;position:absolute;background:currentColor;
  transition:transform .22s,opacity .22s}
.mnav-plus::before{inset:6px 0 auto;height:1.8px}
.mnav-plus::after{inset:0 6px auto;width:1.8px;height:13px}
.mnav-cat[open] .mnav-plus::after{transform:scaleY(0);opacity:0}

.mnav-leaves{display:flex;flex-direction:column;background:var(--bg);
  border-top:1px solid var(--line)}
.mnav-leaves a{padding:12px 20px 12px 34px;font-size:14px;color:var(--ink-2);
  border-bottom:1px solid var(--line)}
.mnav-leaves a:last-child{border-bottom:0}
.mnav-leaves a:active{background:var(--bg-2)}
.mnav-all{font-family:var(--ff-m)!important;font-size:10.5px!important;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)!important}

/* utility row and the closing action */
.mnav-panel>a:not(.mnav-top):not(.mnav-cta){display:flex;align-items:center;min-height:48px;
  padding:0 20px;font-size:15px;color:var(--ink-2);border-bottom:1px solid var(--line)}
.mnav-cta{display:flex;align-items:center;justify-content:center;min-height:56px;
  background:var(--ink);color:var(--bg)!important;font-family:var(--ff-m);
  font-size:12px;letter-spacing:.07em;text-transform:uppercase}

/* Below 760 the inline nav is replaced by the disclosure menu. This rule was
   lost when the menu was restyled, which hid the toggle entirely and left the
   site with no navigation at all on phones. */
@media(max-width:760px){
  .nav-r{display:none}
  .mnav{display:block}
}

@media(max-width:380px){
  :root{--gut:18px}
  :root{--t-d1:clamp(30px,8.8vw,38px)}
}

/* ═══ REDUCED MOTION ═══
   Nothing is hidden by CSS. Start states are set by GSAP only inside the
   no-preference branch, so with reduced motion — or with JS disabled — the
   page renders complete and static.                                        */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ═══════════════ INNER PAGES ═══════════════ */
.phero{padding-block:clamp(120px,15vh,190px) clamp(30px,4vw,54px)}
.phero-h{font-family:var(--ff-d);font-weight:800;letter-spacing:-.04em;line-height:.94;
  font-size:var(--t-d2);margin-top:clamp(14px,1.6vw,22px)}
.phero-l{font-size:var(--t-lede);line-height:1.6;color:var(--ink-2);
  max-width:56ch;margin-top:clamp(20px,2.4vw,32px)}
.sec-solo{font-family:var(--ff-d);font-weight:700;letter-spacing:-.032em;
  font-size:var(--t-h3);margin-bottom:clamp(26px,3vw,44px);
  padding-bottom:18px;border-bottom:1px solid var(--line)}

/* case studies */
.cs-wrap>.cs{padding-block:clamp(44px,6vw,90px);border-top:1px solid var(--line)}
.cs-hd{display:grid;grid-template-columns:64px minmax(0,1fr) minmax(0,1fr);
  gap:clamp(18px,2.6vw,44px);align-items:start;margin-bottom:clamp(26px,3vw,44px)}
.cs-n{font-family:var(--ff-m);font-size:var(--t-lab-l);letter-spacing:.08em;color:var(--accent);padding-top:10px}
.cs-t{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h2);
  letter-spacing:-.034em;line-height:1}
.cs-role{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-top:12px}
.cs-lede{font-size:var(--t-lede);line-height:1.58;color:var(--ink-2);padding-top:6px}
.cs .plate{aspect-ratio:16/9}
.cs-body{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(20px,2.8vw,48px);
  margin-top:clamp(26px,3vw,44px)}
.cs-col p{color:var(--ink-2);font-size:var(--t-body);line-height:1.62}
.cs-h{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);padding-bottom:9px;border-bottom:1px solid var(--line);margin-bottom:13px}
.cs-list{list-style:none;counter-reset:s}
.cs-list li{counter-increment:s;position:relative;padding-left:30px;margin-bottom:11px;
  font-size:var(--t-body);color:var(--ink-2);line-height:1.5}
.cs-list li::before{font-size:var(--t-lab);content:counter(s,decimal-leading-zero);position:absolute;left:0;top:1px;
  font-family:var(--ff-m);color:var(--accent)}
.cs-foot{display:flex;flex-wrap:wrap;gap:18px;justify-content:space-between;align-items:center;
  margin-top:clamp(24px,3vw,40px);padding-top:22px;border-top:1px solid var(--line)}

/* services page */
.srv-wrap>.srvp{padding-block:clamp(44px,6vw,88px);border-top:1px solid var(--line)}
.srvp-hd{display:grid;grid-template-columns:64px minmax(0,1fr) minmax(0,1fr);
  gap:clamp(18px,2.6vw,44px);align-items:start}
.srvp-n{font-family:var(--ff-m);font-size:var(--t-lab-l);letter-spacing:.08em;color:var(--accent);padding-top:9px}
.srvp-t{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h3);
  letter-spacing:-.032em;line-height:1.02}
.srvp-l{font-size:var(--t-lede);line-height:1.58;color:var(--ink-2);padding-top:6px}
.srvp-body{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(22px,3vw,52px);margin-top:clamp(24px,3vw,40px);padding-left:calc(64px + clamp(18px,2.6vw,44px))}
.srvp-p{color:var(--ink-2);font-size:var(--t-body);line-height:1.66}
.srvp-lists{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,2.4vw,36px)}
.tick{list-style:none}
.tick li{position:relative;padding-left:20px;margin-bottom:9px;font-size:var(--t-sm);
  color:var(--ink-2);line-height:1.5}
.tick li::before{content:'';position:absolute;left:0;top:8px;width:8px;height:8px;
  border-left:1.6px solid var(--accent);border-bottom:1.6px solid var(--accent);
  transform:rotate(-45deg)}
.tick-no li::before{border:0;top:10px;width:9px;height:1.6px;background:var(--ink-3);transform:none}

/* process */
.proc{padding-block:clamp(44px,6vw,88px);border-top:1px solid var(--line)}
.proc-h{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h3);
  letter-spacing:-.03em;margin-bottom:clamp(24px,3vw,40px)}
.proc-l{list-style:none;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(18px,2.4vw,36px)}
.proc-l li{border-top:2px solid var(--ink);padding-top:16px}
.proc-l b{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h5);letter-spacing:-.02em;display:block}
.proc-l span{display:block;margin-top:9px;font-size:var(--t-sm);color:var(--ink-2);line-height:1.55}

/* studio page */
.prin{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(22px,3vw,52px)}
.prin-i{border-top:1px solid var(--line);padding-top:18px}
.prin-i b{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h5);
  letter-spacing:-.022em;display:block}
.prin-i p{margin-top:10px;color:var(--ink-2);font-size:var(--t-body);line-height:1.62}
.founder-g{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);
  gap:clamp(26px,3.6vw,64px);align-items:start}
.founder-h{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h3);
  letter-spacing:-.032em;line-height:1.04}
.founder-r2{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-top:11px}
.facts2{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line);
  border:1px solid var(--line)}
.facts2>div{background:var(--bg);padding:20px 18px}
.facts2 b{font-family:var(--ff-d);font-weight:700;font-size:var(--t-h5);
  letter-spacing:-.024em;display:block}
.facts2 span{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-top:8px;display:block;line-height:1.5}

/* home: section links to inner pages */
.more{display:inline-flex;align-items:center;gap:10px;margin-top:clamp(28px,3.4vw,48px);
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.07em;text-transform:uppercase;
  border-bottom:1px solid var(--ink);padding-bottom:5px;min-height:44px}
.more:hover{color:var(--accent);border-color:var(--accent)}
.inv .more{border-bottom-color:#fff}
.inv .more:hover{color:#9AA6FF;border-color:#9AA6FF}

@media(max-width:1080px){
  .cs-hd,.srvp-hd{grid-template-columns:48px minmax(0,1fr)}
  /* .hcat-l is the hub/summary lede and must follow .srvp-l into column 2 —
     without it the lede auto-places into the 48px number column. */
  .cs-lede,.srvp-l,.hcat-l{grid-column:2}
  .srvp-body{grid-template-columns:1fr;padding-left:calc(48px + clamp(18px,2.6vw,44px))}
  .cs-body{grid-template-columns:1fr}
  .founder-g{grid-template-columns:1fr}
  .proc-l{grid-template-columns:1fr 1fr}
}
@media(max-width:760px){
  .phero{padding-block:100px clamp(24px,4vw,40px)}
  .cs-hd,.srvp-hd{grid-template-columns:1fr;gap:12px}
  .cs-lede,.srvp-l,.hcat-l{grid-column:1}
  .cs-n,.srvp-n{padding-top:0}
  .srvp-body{padding-left:0}
  .srvp-lists,.prin,.facts2{grid-template-columns:1fr}
  .proc-l{grid-template-columns:1fr}
  .facts2>div{padding:16px 14px}
  .cs .plate{aspect-ratio:3/2}
}

/* ═══ SERVICE HUB ═══
   Category block reuses .srvp-hd / .srvp-n / .srvp-t / .srvp-l so the hub and
   the category pages share one header rhythm and one set of breakpoints. */
.hub-wrap>.hcat{padding-block:clamp(40px,5vw,78px);border-top:1px solid var(--line)}
.hcat-l{display:flex;flex-wrap:wrap;align-items:baseline;gap:14px 22px;
  padding-top:6px;font-size:var(--t-lede);line-height:1.58;color:var(--ink-2)}
.hcat-more{flex:none;font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.07em;
  text-transform:uppercase;display:inline-flex;align-items:center;gap:9px;
  border-bottom:1px solid var(--ink);padding-bottom:4px;transition:color .2s,border-color .2s}
.hcat-more:hover{color:var(--accent);border-color:var(--accent)}

.cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--col-gap);
  margin-top:clamp(24px,3vw,40px);
  padding-left:calc(64px + clamp(18px,2.6vw,44px))}
.cards>*{min-width:0}
/* full-bleed 3-up, used where the grid is not hanging off a category number */
.cards-3{grid-template-columns:repeat(3,minmax(0,1fr));padding-left:0}
/* full-bleed 4-up, for the "other services" row when four categories remain */
.cards-4{padding-left:0}
/* leaf pages have no number in the gutter, so the body should not hang off one */
.srvp-body.flush{padding-left:0}

/* ═══ LEAF SUMMARY ROWS (category page) ═══
   A summary row holds one heading and one line, so it must NOT inherit .srvp's
   padding, which was sized for a full section with body copy and lists. At 1440
   that padding left ~176px of dead space between every row. */
.lsum-wrap>.lsum{padding-block:clamp(22px,2.6vw,38px);border-top:1px solid var(--line)}
.lsum .srvp-t{font-size:var(--t-h4)}
.lsum .hcat-l{padding-top:3px}
.lsum .srvp-n{padding-top:6px}

/* Section that follows another already-padded block. Full .sec padding on top
   of .faq or .proc padding stacks into a void. */
.sec-tight{padding-block:clamp(36px,4.4vw,76px)}
.card{display:flex;flex-direction:column;gap:9px;min-height:158px;
  border:1px solid var(--line);background:var(--bg);padding:20px 20px 18px;
  transition:border-color .22s,background .22s,transform .22s}
.card:hover{border-color:var(--ink);background:var(--bg-2);transform:translateY(-3px)}
.card-n{font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.09em;color:var(--ink-3)}
.card-t{font-family:var(--ff-d);font-weight:600;font-size:var(--t-h5);letter-spacing:-.02em;
  line-height:1.18;overflow-wrap:break-word}
.card-d{font-size:var(--t-sm);line-height:1.5;color:var(--ink-2);overflow-wrap:anywhere}
.card .arw{margin-top:auto;color:var(--ink-3);transition:color .22s,transform .22s}
.card:hover .arw{color:var(--accent);transform:translate(3px,-3px)}

/* ═══ FLOATING 3D OBJECTS ═══
   A transparent WebGL canvas pinned to the viewport, holding lit geometry
   that drifts and turns on scroll. Injected by floats3d.js.

   No blend mode. An earlier version put the canvas over the content with
   mix-blend-mode:multiply to guarantee it could not veil text. That composites
   correctly in software rendering but is unreliable on GPU-composited canvas
   layers, which made the objects invisible on real hardware while every
   automated check still passed.

   Behind the content instead: no blending, nothing to fail. The objects show
   against the page background, and the opaque hero plate and the dark .inv
   sections occlude them, which reads as depth. Text is never touched because
   nothing is ever drawn on top of it. */
.gl{position:fixed;inset:0;z-index:0;pointer-events:none;
  opacity:0;transition:opacity 1.2s ease}
.gl.on{opacity:1}
/* content composites above the canvas */
main,.cta,.legal,footer{position:relative;z-index:1}

/* ── No-GPU fallback (floats2d.js) ──
   Shaded SVG solids for machines where WebGL is unavailable. These go ABOVE
   the content with multiply: DOM blending composites reliably where canvas
   blending does not, and multiply can only darken, so text contrast is never
   reduced. */
.f2{position:fixed;inset:0;z-index:2;pointer-events:none;overflow:hidden;
  mix-blend-mode:multiply;opacity:0;transition:opacity 1.1s ease}
.f2.on{opacity:.9}
.f2-i{position:absolute;top:0;left:0;will-change:transform}
.f2-i svg{display:block;width:100%;height:100%}

/* ═══ LANGUAGE SWITCHER ═══
   Globe plus the code of the language you would switch TO, which is the
   convention that reads correctly in either direction: on the English page it
   says ES, on the Spanish page EN. A globe alone is ambiguous about which way
   it goes. */
.lang{display:inline-flex;align-items:center;gap:7px;
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.06em;
  color:var(--ink-2)!important;border:1px solid var(--line);padding:9px 12px;
  transition:color .2s,border-color .2s}
.lang:hover{color:var(--ink)!important;border-color:var(--ink)}
.globe{width:15px;height:15px;flex:none;stroke:currentColor;stroke-width:1.25;fill:none}
.lang-c{line-height:1}

/* A card with no destination yet — same shell, no hover, no pointer */
.card-flat{cursor:default}
.card-flat:hover{border-color:var(--line);background:var(--bg);transform:none}

/* ═══ CURSOR FOLLOWER ═══
   A ring that trails the pointer across the screen, lagging behind it.

   Created in JS and only where a real pointer exists, so touch devices and
   no-JS pages never carry it. The native cursor deliberately stays visible:
   hiding it is the usual move here and it costs more in usability — text
   selection, resize handles, the OS wait state — than the effect returns.

   Painted with transform only (GSAP writes x/y), so it never triggers layout.
   The centring offset is a margin rather than a translate, leaving the
   transform channel free for position and scale. */
.cur{position:fixed;top:0;left:0;width:34px;height:34px;margin:-17px 0 0 -17px;
  border:1.5px solid var(--accent);border-radius:50%;
  pointer-events:none;z-index:500;opacity:0;will-change:transform;
  transition:opacity .28s ease}
.cur.on{opacity:1}

/* ═══ BREADCRUMB ═══
   On every page below /. The separator is a CSS ::before rather than markup, so
   it stays out of the accessibility tree — a screen reader announces the list,
   not a run of slashes. */
.bc{list-style:none;display:flex;flex-wrap:wrap;align-items:center;gap:9px;
  margin-bottom:18px;
  font-family:var(--ff-m);font-size:var(--t-lab);letter-spacing:.1em;text-transform:uppercase}
.bc li{display:flex;align-items:center;gap:9px;min-width:0}
.bc li+li::before{content:'/';color:var(--line);flex:none}
.bc a{color:var(--ink-3);transition:color .2s}
.bc a:hover{color:var(--accent)}
.bc [aria-current]{color:var(--accent)}
/* the trail is long on leaf pages; let it wrap rather than push the page wide */
.bc li:last-child{overflow-wrap:anywhere}

/* ═══ FAQ ═══ */
.faq{padding-block:clamp(44px,6vw,88px);border-top:1px solid var(--line)}
.faq-g{display:grid;grid-template-columns:minmax(0,.72fr) minmax(0,1fr);
  gap:clamp(22px,3vw,52px);align-items:start}
.faq-g>*{min-width:0}
.faq-l{list-style:none;border-top:1px solid var(--line)}
.faq-i{border-bottom:1px solid var(--line)}
.faq-q{cursor:pointer;list-style:none;display:flex;align-items:flex-start;
  justify-content:space-between;gap:18px;padding:19px 0;
  font-family:var(--ff-d);font-weight:600;font-size:var(--t-h5);
  letter-spacing:-.018em;line-height:1.3;transition:color .2s}
.faq-q::-webkit-details-marker{display:none}
.faq-q:hover{color:var(--accent)}
.faq-s{flex:none;position:relative;width:13px;height:13px;margin-top:5px}
.faq-s::before,.faq-s::after{content:'';position:absolute;background:currentColor;
  transition:transform .26s,opacity .26s}
.faq-s::before{inset:6px 0 auto;height:1.6px}
.faq-s::after{inset:0 6px auto;width:1.6px;height:13px}
.faq-i[open] .faq-s::after{transform:scaleY(0);opacity:0}
.faq-i[open] .faq-q{color:var(--accent)}
.faq-a{padding:0 clamp(24px,3vw,44px) 22px 0;font-size:var(--t-body);line-height:1.62;
  color:var(--ink-2);max-width:64ch}
.faq-a a{border-bottom:1px solid var(--line);transition:border-color .2s,color .2s}
.faq-a a:hover{color:var(--accent);border-color:var(--accent)}

@media(max-width:1080px){
  .cards{grid-template-columns:repeat(2,minmax(0,1fr));
    padding-left:calc(48px + clamp(18px,2.6vw,44px))}
  .cards-3,.cards-4{padding-left:0}
  .faq-g{grid-template-columns:1fr}
}
@media(max-width:760px){
  .cards{grid-template-columns:1fr;padding-left:0}
  .card{min-height:0}
  .hcat-l{padding-top:0}
  .faq-a{padding-right:0}
}
@media (prefers-reduced-motion:reduce){
  .card,.card:hover,.card .arw,.card:hover .arw,
  .faq-s::before,.faq-s::after{transition:none;transform:none}
}

/* ═══════════ CENTRED SINGLE-COLUMN LAYOUT ═══════════
   At 1080px and below every two-column grid on the site collapses to one —
   hero, work items, studio, contact, section headers. That is the point where
   the display blocks read better
   centred: hero, page headers, section intros, the closing CTA and the footer.

   Running copy, bullet lists, FAQ answers and card bodies stay left-aligned.
   Centred prose is harder to read — the eye loses the start of each line — and
   a centred bullet list has no consistent left edge at all. Mixing the two
   deliberately is the point, not an oversight. */
@media(max-width:1080px){
  /* hero */
  .hero-copy{align-items:center;text-align:center}
  .hero-p{margin-left:auto;margin-right:auto}
  .hero-act{justify-content:center}
  .hero-meta{justify-content:center;text-align:center}
  .hero-meta li{flex:0 0 auto}

  /* inner page headers */
  .phero{text-align:center}
  .phero-l{margin-left:auto;margin-right:auto}
  .bc{justify-content:center}

  /* section headers and standalone headings */
  .sec-hd{text-align:center}
  .sec-note{margin-left:auto;margin-right:auto}
  .sec-solo,.proc-h{text-align:center}
  .strip-t{text-align:left}          /* marquee must not re-centre mid-scroll */

  /* Services hub and category headers. The index number moves above the
     title instead of hanging in a left gutter — a left-aligned numeral beside
     a centred title reads as a mistake rather than a device. */
  .cs-hd,.srvp-hd{grid-template-columns:1fr;gap:10px}
  .cs-n,.srvp-n{padding-top:0}
  .cs-lede,.srvp-l,.hcat-l{grid-column:1}
  .srvp-hd,.hcat .srvp-hd{text-align:center}
  .hcat-l{justify-content:center;text-align:center}
  .srvp-l{text-align:center}

  /* closing CTA */
  .cta .lab,.cta-h{text-align:center}
  .cta-p{margin-left:auto;margin-right:auto;text-align:center}
  .cf{margin-left:auto;margin-right:auto}       /* block centred, fields stay left */
  .cf-go{justify-content:center;text-align:center}

  /* studio principles and facts read as a centred stack */
  .prin-i,.facts2>div{text-align:center}

  /* footer and legal */
  .f-in{text-align:center;justify-items:center}
  .legal-g{text-align:center}

  /* Homepage services list. Its own class set, separate from the services
     page — it kept a three-column grid up to 1080px, which was both cramped
     and left-anchored while everything around it centred. */
  .srv-row{grid-template-columns:1fr;gap:10px;text-align:center}
  .srv-n{padding-top:0}
  .srv-d{grid-column:1}
  .srv-tags{justify-content:center}
  .srv-row:hover{padding-left:0}      /* the hover indent reads as a wobble when centred */
  .stats{text-align:center}
  .more{margin-left:auto;margin-right:auto}

  /* left-aligned on purpose — see note above */
  .cs-col p,.cs-list,.tick,.faq-a,.card,.srvp-p,.studio-p,.w-d{text-align:left}
}
