/* ============================================================
   BROWSER.AE — Global stylesheet
   Three colours only, and nothing else:
     red   #F00030   blue  #1C2473   black #000000
   Plus white, and a short scale of near-white / near-black SURFACES
   (bands, cards) which carry no hue. Grey as a text colour is gone:
   on white the copy is black, on black it is white.
   ============================================================ */

:root{
  /* Type — two faces, split by job.
     Space Grotesk is a display grotesque: its character earns its keep in
     headings and in the small wide-tracked labels, and costs nothing there.
     Inter Tight carries the running copy, which is ~90% of the words on a
     service page and the part that actually has to be read.
     --font-mono names a role (breadcrumbs, kickers, counters, step numbers),
     not a third face; it rides with the display cut. */
  --font-display: "Space Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-sans:    "Inter Tight", "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono:    var(--font-display);

  /* Palette — near-black, greys, and one red used sparingly.
     The red is reserved for display type, marks and rules; it
     measures 4.42:1 on white, which carries large text but not
     body copy, so it never sets a paragraph. */
  --ink:        #000000;   /* true black — was #221F1F, which read as dark grey */
  --paper:      #ffffff;
  --paper-2:    #f3f3f3;   /* header */
  --paper-3:    #e7e7e7;   /* menu + footer */
  --band:       #f1f1f1;   /* the alternating section band */
  --error:      #F00030;   /* form validation only; was #c0392b */
  /* the greys now resolve to black: secondary copy sits at the same
     weight of colour as everything else, per the three-colour palette */
  --grey:       #000000;   /* was #6d6d6d */
  --grey-light: #000000;   /* was #9a9a9a */
  --accent:     #F00030;
  --accent-deep:#F00030;   /* was #c40028 - one red only now */
  --logo-red:   #F00030;   /* was #db0032 - folded into the one brand red */
  --hover:      #1C2473;   /* what used to go black on hover; 13.6:1 on white */
  --line:       rgba(0,0,0,.14);
  --line-strong:rgba(0,0,0,.28);

  /* The shared list bullet: the same arrow the buttons use. Carried as a mask
     rather than a background image so the colour still comes from a token —
     a data URI would otherwise bake the red in. */
  --arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E");

  /* Selected Work caps at native art size: two 800px cards + the 30px
     gap. Past this the 800x600 sources upscale and go soft. */
  --work-cap: 1630px;

  /* The projects grid sits narrower than the page cap so the
     thumbnails stay small; the masthead follows it to keep the
     left edges aligned. */
  --work-grid: 1180px;

  --header-h: 80px;
  /* breathing room between the fixed header and whatever opens the page */
  --header-gap: clamp(14px,1.6vw,30px);
  /* half a gap: every section carries this top and bottom, so the space
     between any two of them is the same 2x value */
  --sec-pad:    clamp(56px,6.2vw,104px);
  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-io: cubic-bezier(.76,0,.24,1);
  --ease-quart: cubic-bezier(.77,0,.175,1);      /* inOutQuart */
  --ease-out-quart: cubic-bezier(.165,.84,.44,1); /* outQuart  */
  --ease-soft: cubic-bezier(.16,1,.3,1);          /* outExpo — long, gentle settle */
}

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

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

body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-sans);
  font-size:16px;
  line-height:1.6;
  font-weight:400;
  /* No -webkit-font-smoothing:antialiased here. It switches Chrome from
     subpixel (ClearType) to grayscale antialiasing, which looks fine on a
     Retina Mac but renders small text thin and fuzzy on a 1x Windows
     display - which is most of this site's audience. Browser default wins. */
}

/* form controls do not inherit type from the document — without this the
   browser default (Arial) leaks back in wherever a control is not styled */
input, textarea, select, button{ font-family:inherit; }

/* Headings take the display cut. Everything else inherits the body face from
   `body`, so only the exceptions are named — here, and wherever a rule asks
   for --font-mono. */
h1, h2, h3, h4, h5, h6{ font-family:var(--font-display); }

/* Buttons and the big menu links are display type doing a job, not copy —
   they keep the same cut as the headings they sit under. */
.pill,
.menu-line{ font-family:var(--font-display); }

/* Scroll lock. Hiding the scrollbar widens the viewport, so everything
   anchored to it shifts sideways — that sideways jump is the "shake".
   --sbw is the real scrollbar width, measured once in main.js, and is
   handed back as padding to every box that touches the viewport edge.
   The lock is held until the closing panel has left the screen, so the
   scrollbar never appears or disappears mid-animation. */
body.scroll-lock{
  overflow:hidden;
  padding-right:var(--sbw,0px);
}
body.scroll-lock .site-header,
body.scroll-lock .menu-overlay{ padding-right:var(--sbw,0px); }

img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; }
address{ font-style:normal; }

/* Shared micro-label (mono, uppercase, tracked out) */
.menu-label{
  display:block;
  font-family:var(--font-mono);
  font-size:12px;
  font-weight:400;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--grey);
  margin-bottom:34px;
}

/* ============================================================
   MASKED LINE REVEAL
   Real line boxes are measured and wrapped by JS:
   <span class="ln"><span class="ln-i">one line of text</span></span>
   Used by the hero headline and the about paragraph.
   ============================================================ */
.ln{
  display:block;
  overflow:clip;
  padding-bottom:.14em;      /* room for descenders inside the mask */
  margin-bottom:-.14em;
}
.ln-i{
  display:block;
  transform:translateY(105%);
  opacity:0;
  transition:transform 1.15s var(--ease-soft), opacity .8s var(--ease-soft);
  will-change:transform;
}
.is-split.in .ln-i{ transform:translateY(0); opacity:1; }
.is-split.out .ln-i{
  transform:translateY(-105%);
  opacity:0;
  transition:transform .55s var(--ease-out-quart), opacity .38s linear;
}

/* ============================================================
   MASKED WORD REVEAL  (menu links)
   Words are wrapped by JS: <span class="w"><i>word</i></span>
   ============================================================ */
.split .w{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  padding-bottom:.16em;
  margin-bottom:-.16em;
}
.split .w i{
  display:inline-block;
  font-style:normal;
  transform:translateY(105%);
  opacity:0;
  /* long outExpo settle, with the fade running shorter than the move so
     the word is already solid while it is still easing into place */
  transition:transform 1.15s var(--ease-soft), opacity .75s var(--ease-soft);
  will-change:transform;
}
.split.in .w i{ transform:translateY(0); opacity:1; }
.split.out .w i{
  transform:translateY(-105%);
  opacity:0;
  transition:transform .55s var(--ease-out-quart), opacity .38s linear;
}

/* ============================================================
   SECTION HEADINGS — the same reveal, on the scroll
   The hero plays its headline on load; the home page's section
   headings play the same move when they come into view, so the
   .is-in the reveal system hands out is what starts them. The
   heading may be the block that gets .is-in, or sit inside one.
   ============================================================ */
.is-in .rv--lines .w i,
.rv--lines.is-in .w i,
.is-in .rv--lines .ln-i,
.rv--lines.is-in .ln-i{ transform:translateY(0); opacity:1; }

/* whatever could not be masked — the project count's superscript — only fades,
   a beat behind the words it follows */
.rv--lines .w-keep{
  opacity:0;
  transition:opacity .8s var(--ease-soft) .3s;
}
.is-in .rv--lines .w-keep,
.rv--lines.is-in .w-keep{ opacity:1; }

/* the block around a split heading only fades: the travel is the words' own */
.rv:has(.rv--lines){ transform:none; }

@media (prefers-reduced-motion:reduce){
  .rv--lines .w i,
  .rv--lines .ln-i{ transform:none; }
}

/* ============================================================
   PILL BUTTON — label + circular arrow
   ============================================================ */
.pill{
  display:inline-flex;
  align-items:center;
  gap:18px;
  padding:7px 7px 7px 28px;
  border-radius:0;  /* was 999px */
  border:1px solid transparent;
  font-size:15.5px;
  font-weight:500;
  letter-spacing:-.01em;
  white-space:nowrap;
  transition:background-color .4s var(--ease), color .4s var(--ease),
             border-color .4s var(--ease);
}
.pill-arrow{
  width:46px; height:46px;
  border-radius:0;  /* was 50% */
  display:grid; place-items:center;
  flex:none;
  overflow:hidden;
  transition:background-color .4s var(--ease), color .4s var(--ease),
             box-shadow .4s var(--ease);
}
.pill-arrow svg{ width:19px; height:19px; }
/* A button that came in from the old site sometimes carries the arrow box
   without the arrow drawn inside it, which shows as an empty square. Where
   there is no drawing, one is painted here from the same mark the bulleted
   lists use, in the button’s own colour. */
.pill-arrow:not(:has(svg))::before{
  content:"";
  width:19px; height:19px;
  background:currentColor;
  -webkit-mask:var(--arrow) center / contain no-repeat;
          mask:var(--arrow) center / contain no-repeat;
}
.pill:hover .pill-arrow svg{ animation:arrow-cycle .55s var(--ease-io); }
@keyframes arrow-cycle{
  0%{ transform:translateX(0); opacity:1; }
  45%{ transform:translateX(150%); opacity:0; }
  55%{ transform:translateX(-150%); opacity:0; }
  100%{ transform:translateX(0); opacity:1; }
}

/* on light surfaces — filled black */
.pill--solid{ background:var(--ink); color:var(--paper); }
.pill--solid .pill-arrow{ background:var(--paper); color:var(--ink); }
.pill--solid:hover{ background:transparent; color:var(--ink); border-color:var(--ink); }
.pill--solid:hover .pill-arrow{ background:var(--ink); color:var(--paper); }

/* on light surfaces — outlined */
.pill--outline{ background:transparent; color:var(--ink); border-color:var(--ink); }
.pill--outline .pill-arrow{ background:var(--ink); color:var(--paper); }
.pill--outline:hover{ background:var(--ink); color:var(--paper); }
.pill--outline:hover .pill-arrow{ background:var(--paper); color:var(--ink); }

/* on dark surfaces — frosted */
.pill--light{
  background:rgba(255,255,255,.16);
  color:#ffffff;                     /* never var(--paper): it is #141414 in .inv */
  border-color:rgba(255,255,255,.55);
}
.pill--light .pill-arrow{ background:var(--paper); color:var(--ink); }
.pill--light:hover{ background:var(--paper); color:var(--ink); }
.pill--light:hover .pill-arrow{ background:var(--ink); color:var(--paper); }

/* compact variant (header) */
.pill--sm{
  gap:12px;
  padding:5px 5px 5px 22px;
  font-size:13.5px;
}
.pill--sm .pill-arrow{ width:38px; height:38px; }
.pill--sm .pill-arrow svg{ width:16px; height:16px; }

/* ============================================================
   HEADER
   ============================================================ */
/* Where a page opens on a banner set a little way under the header (the
   --header-gap strip), the header grows to fill that white strip while
   the page is at the top, so the menu sits with equal room above and
   below it. Once the page scrolls, the script adds .is-scrolled and the
   header settles back to its usual height. Tall is the default, so it is
   already right before the script runs. */
:root{ --header-now:var(--header-h); }
html:has(main > :is(.hero,.ibn,.pj-top):first-child):not(.is-scrolled){
  --header-now:calc(var(--header-h) + var(--header-gap));
}
.site-header{
  position:fixed;
  top:0; left:0; right:0;
  z-index:120;
  height:var(--header-now);
  background:var(--paper);           /* white, no dividing rule */
  transition:background-color .5s var(--ease), height .35s var(--ease);
}
.header-inner{
  position:relative;                 /* the nav centres against this box */
  height:100%;
  max-width:1920px;
  margin:0 auto;
  padding:0 clamp(16px,3.4vw,54px);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:clamp(14px,2vw,36px);
}
.brand{ display:inline-flex; align-items:center; min-height:44px; }
.brand img{
  height:46px; width:auto;
  transition:opacity .3s var(--ease);
}
.brand:hover img{ opacity:.7; }

.hdr-right{
  display:flex;
  align-items:center;
  gap:clamp(14px,1.9vw,34px);
}

/* --- inline nav (desktop only) --- */
.hdr-nav{
  /* Centred on the header itself, not on whatever space the logo leaves.
     Done with auto margins rather than translateX(-50%): a percentage
     translate of an odd-width box lands on a half pixel, and a fractional
     transform is applied at paint time without snapping, which softens the
     type. Auto margins are a layout offset, so the engine snaps it. */
  position:absolute;
  left:0;
  right:0;
  width:max-content;
  margin-inline:auto;
  display:flex;
  align-items:center;
  /* caps run wider than the old sentence case, so the items sit closer */
  gap:clamp(11px,1.35vw,26px);
}
.hdr-nav > a,
.hdr-drop-btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:5px;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  /* the display face, as the headings and the overlay menu use, set in
     caps: caps need positive tracking and a touch more weight to hold */
  font-family:var(--font-display);
  font-size:13.5px;
  font-weight:500;
  line-height:1;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--ink);
  white-space:nowrap;
  transition:color .28s var(--ease);
}
/* the rule sits below the baseline rather than underlining the text, so a
   two-word item does not jump when it grows */
.hdr-nav > a::after,
.hdr-drop-btn::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:-7px;
  height:1.5px;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .3s var(--ease-io);
}
.hdr-nav > a:hover,
.hdr-drop-btn:hover,
.hdr-nav a[aria-current="page"]{ color:var(--accent); }
.hdr-nav > a:hover::after,
.hdr-drop-btn:hover::after,
.hdr-nav a[aria-current="page"]::after{ transform:scaleX(1); }

/* --- services dropdown --- */
.hdr-drop{ position:relative; }
.hdr-chev{
  width:13px; height:13px;
  transition:transform .3s var(--ease-io);
}
.hdr-drop:hover .hdr-chev,
.hdr-drop.is-open .hdr-chev{ transform:rotate(180deg); }


/* --- call / whatsapp round buttons --- */
.hdr-actions{
  display:flex;
  align-items:center;
  gap:10px;
}
.hdr-icon{
  flex:none;
  width:50px; height:50px;           /* = .pill--sm height: 38 + 5+5 + 1+1 */
  border-radius:0;  /* was 50% */
  display:grid;
  place-items:center;
  background:var(--ink);
  color:#ffffff;                     /* 21:1 on black */
  transition:background-color .3s var(--ease);
}
.hdr-icon svg{ width:18px; height:18px; }
/* --accent-deep, not --accent: white on #F00030 is 4.42:1, which misses the
   3:1 needed for an icon far less comfortably than #c40028's 6.17:1 */
.hdr-icon:hover{ background:var(--accent-deep); }

/* --- 3-line hamburger (mobile only) --- */
.burger{
  width:56px; height:56px;
  display:grid; place-items:center;
  background:none; border:0; padding:0;
  cursor:pointer;
}
.burger-lines{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:7px;
  width:34px;
}
.burger-lines i{
  display:block;
  height:2px;
  background:var(--ink);
  border-radius:0;  /* was 2px */
  transition:width .4s var(--ease-io), transform .45s var(--ease-io),
             opacity .25s var(--ease);
}
.burger-lines i:nth-child(1){ width:34px; }
.burger-lines i:nth-child(2){ width:22px; align-self:flex-start; }
.burger-lines i:nth-child(3){ width:28px; }
.burger:hover .burger-lines i{ width:34px; }

/* open state → X */
.burger.is-open .burger-lines i:nth-child(1){ width:34px; transform:translateY(9px) rotate(45deg); }
.burger.is-open .burger-lines i:nth-child(2){ width:34px; opacity:0; transform:scaleX(.2); }
.burger.is-open .burger-lines i:nth-child(3){ width:34px; transform:translateY(-9px) rotate(-45deg); }

/* header tone while the menu is open */
.site-header.on-menu{ background:var(--paper-3); border-color:transparent; }

/* ============================================================
   FULL SCREEN MENU — drops in from above
   ============================================================ */
/* the page dims behind the descending panel */
.menu-backdrop{
  position:fixed;
  inset:0;
  z-index:105;
  background:rgba(0,0,0,.59);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .2s linear, visibility 0s linear .2s;
}
body.menu-open .menu-backdrop{
  opacity:1;
  visibility:visible;
  transition:opacity .2s linear, visibility 0s linear 0s;
}

/* Panel motion, matched to the Fleet reference:
   open  — slides down 1200ms inOutQuart, fades in over 300ms
   close — waits 300ms (while the links drop out), then slides up 1200ms */
.menu-overlay{
  position:fixed;
  inset:0;
  z-index:110;
  background:var(--paper);      /* white, unlike the footer it mirrors */
  overflow-y:auto;
  overscroll-behavior:contain;
  transform:translateY(-100%);
  opacity:0;
  visibility:hidden;
  transition:transform 1.2s var(--ease-quart) .3s,
             opacity 0s linear 1.5s,
             visibility 0s linear 1.5s;
  will-change:transform;
}
.menu-overlay.is-open{
  transform:translateY(0);
  opacity:1;
  visibility:visible;
  transition:transform 1.2s var(--ease-quart) 0s,
             opacity .3s var(--ease-out-quart) 0s,
             visibility 0s linear 0s;
}
.menu-inner{
  max-width:1920px;
  margin:0 auto;
  min-height:100%;
  padding:calc(var(--header-h) + clamp(46px,6.5vw,104px)) clamp(20px,3.4vw,54px) clamp(46px,5vw,70px);
  display:flex;
  flex-direction:column;
}
.menu-top{
  display:grid;
  /* services carries nine links in two sub-columns, so it takes
     the wider share of the row */
  grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);
  gap:clamp(28px,4vw,70px);
  flex:1;
}
.menu-split{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(14px,2vw,34px);
}
.menu-rule{
  height:1px;
  background:var(--line);
  margin:clamp(34px,4.5vw,64px) 0 clamp(28px,3.4vw,46px);
}
.menu-bottom{
  display:grid;
  grid-template-columns:1fr 1fr 1fr;
  gap:clamp(24px,3vw,40px);
  align-items:stretch;
}

/* --- nav links: smaller than before, so two columns sit side by
   side without the second wrapping --- */
.menu-nav{ display:flex; flex-direction:column; align-items:flex-start; }
.menu-nav a{
  font-size:clamp(24px,2.7vw,42px);
  text-wrap:balance;
  font-weight:500;
  letter-spacing:-.035em;
  line-height:1.24;
  transition:opacity .4s var(--ease), color .3s var(--ease);
}
.menu-nav:hover a{ opacity:.3; }
.menu-nav a:hover{ opacity:1; color:var(--accent); }

/* links ride up out of their masks once the panel has landed —
   one block, 1000ms inOutQuart after a 500ms delay; on close they
   drop back down in 800ms outQuart before the panel leaves */
.menu-overlay .menu-nav a .w i{
  transform:translateY(100%);
  opacity:1;                       /* menu links mask only, they do not fade */
  transition:transform .8s var(--ease-out-quart) 0s;
}
.menu-overlay.is-open .menu-nav a .w i{
  transform:translateY(0);
  opacity:1;
  transition:transform 1s var(--ease-quart) .5s;
}

/* --- menu buttons --- */
.menu-actions{ display:flex; flex-direction:column; align-items:flex-start; gap:14px; }

/* --- contact rows, socials and address: the footer treatment
   inverted for a light ground --- */
.menu-line{
  display:flex;
  align-items:center;
  gap:11px;
  color:var(--ink);
  text-decoration:none;
  font-size:clamp(15px,1.15vw,19px);
  font-weight:500;
  letter-spacing:-.02em;
  transition:color .3s var(--ease);
}
.menu-line + .menu-line{ margin-top:10px; }
.menu-line svg{ width:.95em; height:.95em; flex:none; opacity:.55; transition:opacity .3s var(--ease); }
.menu-line:hover{ color:var(--accent); }
.menu-line:hover svg{ opacity:1; }

.menu-socials{ margin:0; padding:0; list-style:none; }
.menu-socials li + li{ margin-top:10px; }
.menu-socials a{
  display:inline-flex;
  align-items:center;
  gap:11px;
  color:var(--ink);
  text-decoration:none;
  font-size:clamp(15px,1.05vw,17px);
  transition:color .3s var(--ease);
}
.menu-socials svg{ width:17px; height:17px; flex:none; }
.menu-socials a:hover{ color:var(--accent); }

.menu-address{ font-style:normal; font-size:clamp(14.5px,1.05vw,17px); line-height:1.7; color:var(--grey); }

/* ============================================================
   HERO
   ============================================================ */
.hero{ padding-top:calc(var(--header-h) + var(--header-gap)); }
.hero-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  /* fixed height, not viewport height — the section ends at the same
     place on every screen and the next one starts on cue */
  min-height:720px;
}

/* --- left: copy panel --- */
.hero-copy{
  background:var(--ink);
  color:var(--paper);
  padding:clamp(56px,6vw,96px) clamp(24px,4.4vw,86px);
  display:flex;
  flex-direction:column;
  justify-content:center;
}
/* same setting as the menu links — lighter weight, wider tracking */
.hero h1{
  margin:0;
  font-size:clamp(38px,4.4vw,74px);
  font-weight:500;
  line-height:1.12;
  letter-spacing:-.035em;
  max-width:15ch;
}
/* The marked word in the headline stays white rather than turning red. The
   mark still does its job in the admin — it is simply not coloured here, so
   the headline reads as one voice against the black. */
.hero h1 .hl{ color:inherit; }
.hero-text{
  margin:28px 0 0;
  max-width:46ch;
  font-size:clamp(15px,1.1vw,17.5px);
  line-height:1.65;
  color:rgba(255,255,255,.66);
  font-weight:300;
}
.hero-actions{ display:flex; flex-wrap:wrap; gap:14px; margin-top:44px; }

/* paragraph + button ride in behind the headline */
.hero-copy .fade-up{
  opacity:0;
  transform:translateY(20px);
  transition:opacity 1s var(--ease-soft), transform 1s var(--ease-soft);
}
.hero-copy.in .hero-text{ transition-delay:.5s; }
.hero-copy.in .hero-actions{ transition-delay:.64s; }
.hero-copy.in .fade-up{ opacity:1; transform:translateY(0); }
.hero-copy.out .fade-up{
  opacity:0;
  transform:translateY(-16px);
  transition-duration:.45s;
  transition-delay:0s;
}

/* --- right: slider --- */
.hero-visual{
  position:relative;
  overflow:hidden;
  background:var(--paper);
  min-height:420px;
}
.hero-slider{ position:absolute; inset:0; }
/* Slides cross-fade over one second, on the same easing as the words beside
   them. Nothing is scaled or moved, so the picture that is uploaded is the
   picture that shows — the only cropping is the frame's own shape. */
.hero-slider img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  object-position:center;
  opacity:0;
  transition:opacity 1s var(--ease-soft);
  will-change:opacity;
}
.hero-slider img.active{ opacity:1; }
/* Logo and packshot slides show whole instead of cropping: paper fills either
   side when the picture's shape differs from the frame's. Prepare these at 4:3
   (1600x1200 is plenty) with their own breathing space built in. */
.hero-slider img.fit-contain{
  object-fit:contain;
  background:var(--paper);
}

/* No dark wash over the foot of the picture: the counter and the dots carry
   their own paper chips instead, the same way the arrows do, so they stay
   legible on light and dark artwork alike without shading the work. */

.slider-nav{
  position:absolute;
  top:50%;
  transform:translateY(-50%);
  z-index:3;
  width:54px; height:54px;
  border-radius:0;  /* was 50% */
  border:0;
  cursor:pointer;
  background:var(--paper);
  color:var(--ink);
  box-shadow:0 2px 10px rgba(0,0,0,.20);   /* it sits on a photo, so it needs an edge */
  display:grid; place-items:center;
  transition:background-color .3s var(--ease), color .3s var(--ease), transform .3s var(--ease);
}
.slider-nav svg{ width:20px; height:20px; }
.slider-nav:hover{ background:var(--ink); color:var(--paper); transform:translateY(-50%); }
.slider-nav.prev{ left:clamp(14px,1.6vw,26px); }
.slider-nav.next{ right:clamp(14px,1.6vw,26px); }

.slider-count{
  position:absolute;
  left:clamp(14px,1.6vw,26px); bottom:22px;
  z-index:3;
  padding:7px 10px;
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.14em;
  color:var(--ink);
  background:var(--paper);
  box-shadow:0 2px 10px rgba(0,0,0,.20);
}
.slider-count b{ font-weight:500; }

/* ============================================================
   ABOUT
   ============================================================ */
.sr-only{
  position:absolute; width:1px; height:1px;
  padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.about{ background:var(--paper); overflow:hidden; }
.about-inner{
  max-width:1920px;
  margin:0 auto;
  padding:clamp(48px,5vw,92px) clamp(20px,3.4vw,54px) 0;
}
/* copy takes the width; the picture column is deliberately narrow so the
   whole section — copy, shots and strip — lands inside one screen */
.about-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) clamp(210px,24vw,470px);
  gap:clamp(30px,5vw,110px);
  align-items:stretch;
}

/* --- copy --- */
/* the bottom padding matches the strip's negative pull, so the lettering
   only ever crosses the photographs — never the copy or the button */
.about-copy{
  position:relative;
  padding-right:clamp(0px,4vw,90px);
  padding-bottom:calc(clamp(24px,6vw,90px) + 22px);
}
.about-heading{ margin:0 0 clamp(20px,2.4vw,38px); }
/* type ratios lifted from the reference: 3.6vw, 1.09 leading, -.038em.
   The first line runs flush now that the label is a heading above
   it rather than a mark sitting in the margin. */
.about-lede{
  margin:0;
  font-size:clamp(20px,3.2vw,54px);
  font-weight:500;
  line-height:1.09;
  letter-spacing:-.038em;
}
.ln-indent{ display:inline-block; }

.about-heading,
.about-cta{
  opacity:0;
  transform:translateY(14px);
  transition:opacity .8s var(--ease-soft), transform .8s var(--ease-soft);
}
.about-copy.is-in .about-heading{ opacity:1; transform:none; }
.about-copy.is-in .about-cta{ opacity:1; transform:none; transition-delay:.45s; }
.about-cta{ margin-top:clamp(30px,3.4vw,54px); }

/* --- overlapping shots --- */
.about-shots{
  position:relative;
  z-index:1;                       /* the strip below paints over these */
  align-self:stretch;              /* run down to the bottom of the row */
}
.shot{ margin:0; overflow:hidden; background:var(--paper-3); }
.shot img{ width:100%; height:100%; object-fit:cover; }
/* 5:7 like the reference, but never shorter than the row — that overhang
   is what lets the lettering cross the photograph */
.shot--main{
  width:100%;
  aspect-ratio:5 / 7;
  min-height:100%;
  border-radius:0;  /* was 5px */
}

/* --- scrolling strip --- */
/* the lettering runs over the photographs, as in the reference */
.marquee{
  position:relative;
  z-index:2;
  overflow:hidden;
  margin-top:clamp(-90px,-6vw,-24px);
  padding-bottom:clamp(10px,1.4vw,22px);
  user-select:none;
}
.marquee-track{
  display:flex;
  align-items:center;
  gap:clamp(18px,2vw,40px);
  width:max-content;
  animation:marquee 62s linear infinite;   /* reference runs 62s per pass */
}
.marquee-track span{
  font-size:clamp(30px,6.5vw,110px);       /* readable, still full-bleed */
  font-weight:600;
  line-height:1;
  letter-spacing:-.03em;
  text-transform:uppercase;
  white-space:nowrap;
}
.marquee-track i{
  font-family:var(--font-mono);
  font-style:normal;
  font-weight:400;
  font-size:clamp(16px,2.4vw,42px);
  line-height:1;
  color:var(--grey);
  transform:translateY(-.14em);
}
@keyframes marquee{
  from{ transform:translateX(0); }
  to{ transform:translateX(-50%); }
}
.marquee:hover .marquee-track{ animation-play-state:paused; }

@media (max-width:900px){
  .about-grid{ grid-template-columns:1fr; gap:44px; }
  .about-copy{ padding-right:0; }
  .about-shots{ width:min(330px,62vw); margin:0 auto; }

}
@media (max-width:560px){
  .about-cta{ width:100%; justify-content:space-between; }
}

/* ============================================================
   SERVICES — stacked cards, copy left, one shot right
   Proportions and tones taken from the reference:
   section #EDE6E0, cards #FAF9F7, 44px radius at 1600, 9px gap,
   heading column 17% and cards 76% of the screen.
   ============================================================ */
/* Soft grey "silk" backdrop: a gradient base with blurred wave forms
   drifting slowly over it. No overflow:hidden here — it would stop the
   heading column sticking; the artwork is clipped by the SVG instead. */
.services{
  position:relative;
  isolation:isolate;
  color:var(--ink);
  background:var(--band);
}
.services-inner{
  position:relative;
  z-index:1;
  max-width:1920px;
  margin:0 auto;
  padding:clamp(56px,6vw,110px) clamp(18px,3.4vw,55px) clamp(60px,7vw,130px);
}
.services-layout{
  display:grid;
  grid-template-columns:18% 82%;   /* reference: 271px / 1220px */
  gap:0;
  align-items:stretch;
}

/* --- left: heading and strapline stay put while the cards pass --- */
/* heading at the top of the sticky column, strapline pinned at its foot */
.services-head{
  position:sticky;
  top:calc(var(--header-h) + 40px);
  height:calc(100vh - var(--header-h) - 110px);
  display:flex;
  flex-direction:column;
  justify-content:space-between;
}
.services-heading{ margin:0; }
.services-note{
  margin:clamp(22px,2.6vw,44px) 0 0;   /* only matters once the column is static */
  max-width:22ch;
  font-size:clamp(14px,1.05vw,18px);
  line-height:1.45;
  font-weight:500;
  color:var(--grey);
}

/* --- right: the cards --- */
.services-cards{
  display:flex;
  flex-direction:column;
  gap:clamp(16px,1.8vw,30px);
}
.svc-card{
  display:grid;
  /* The picture is held to a share of the card rather than half of it, and
     capped: at 4:3 a half-width picture on a wide monitor stands over 550px
     tall, which drags the whole card down with it and leaves the words
     stranded at the top of a tall empty column. Capped, the card stays the
     height of its own content. */
  grid-template-columns:minmax(0,1fr) minmax(0,clamp(260px,53%,565px));
  align-items:stretch;
  background:var(--paper);
  border-radius:0;                   /* squared off - try it and see */
  overflow:hidden;
  min-height:clamp(220px,18vw,330px);
  /* flat: no shadow, no outline, and nothing reacts to the pointer.
     The card reads as white against the grey band on its own. */
}

.svc-body{
  display:flex;
  flex-direction:column;
  padding:clamp(22px,2.2vw,40px);
}
.svc-title{
  margin:0 0 clamp(10px,1vw,18px);
  font-size:clamp(21px,2.1vw,36px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.025em;
}
.svc-text{
  margin:0;
  max-width:42ch;
  font-size:clamp(14px,1vw,16.5px);
  line-height:1.6;
  color:var(--grey);
}

/* what you get — small pills under the copy */
/* Held to two rows on purpose. Left to run the full width of the card, six
   labels fit on one line in some cards and spill onto a second in others, so
   the cards came out different heights and the picture beside the taller ones
   was left with a margin above and below it. Two rows everywhere means every
   card is the same height and every picture fills its side. */
.svc-tags{
  list-style:none;
  margin:clamp(12px,1.1vw,17px) 0 0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  max-width:min(100%, 640px);
}
.svc-tags li{
  padding:7px 15px;
  border-radius:0;  /* was 999px */
  background:var(--paper);
  border:1px solid rgba(0,0,0,.08);
  font-size:clamp(12px,.85vw,13.5px);
  font-weight:500;
  line-height:1.25;
  letter-spacing:-.005em;
  color:var(--ink);
  white-space:nowrap;
}
/* margin, never padding — padding here stretches the pill and drops its
   label and arrow off centre */
.svc-cta{
  margin-top:clamp(18px,1.7vw,26px);
  align-self:flex-start;
}

/* Side by side, the picture takes the full height of the card, and the column
   it sits in is capped near four thirds of that height — so an 800x600 upload
   lands edge to edge with nothing left over. The card's height comes from the
   words, which stay much the same at any screen width, so a fixed cap holds
   that shape better than a ratio would.
   The picture is fitted rather than cropped, so a file that is not 4:3 is
   shown whole instead of having its edges cut off. */
.svc-shot{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--paper);
  aspect-ratio:4 / 3;
  align-self:center;
  min-height:180px;
}
.svc-shot img{
  position:absolute;
  inset:0;
  width:100%; height:100%;
  object-fit:contain;
  object-position:center;
}

/* ------------------------------------------------------------
   The drawn mark, in place of a picture
   The brand blue, a fine grid of dots, a soft light from the top
   corner, and the service's mark drawn large in a single white
   line. A second copy of the same mark, far bigger and barely
   there, runs off the bottom corner to give the panel depth; the
   card's number sits top left over a short red rule.
   The panel takes the picture's exact frame, so the cards keep
   their size whichever of the two is showing.
   ------------------------------------------------------------ */
/* the brand blue exactly, #1C2473, with nothing laid over it, at rest and on
   hover alike */
.svc-shot--mark{ background:#1C2473; }

.svc-mark{
  --mark-w:clamp(92px,32%,168px);   /* how wide the drawing is */
  position:absolute;
  inset:0;
  display:grid;
  place-items:center;
  overflow:hidden;
  color:#ffffff;
}
.svc-mark-icon{
  position:relative;
  z-index:1;
  width:var(--mark-w);
}
/* Fine lines, the way an engraving or a technical drawing is fine: the
   drawings are 24 units across but shown anywhere from 90 to 170 pixels, so a
   width set in their own units would thicken as they grow. The script works
   out, for each one, the width that lands at the same hairline on screen and
   hands it over as --sw; the figures after it are only the fallback for a
   page with no script. */
.svc-mark-icon svg{
  display:block;
  width:100%;
  height:auto;
  stroke-width:var(--sw, .75);
}

.svc-mark-ghost{
  position:absolute;
  right:-14%;
  bottom:-22%;
  width:80%;
  /* a hairline needs more presence than the old heavy line to be seen at all */
  opacity:.18;
  transform:rotate(-9deg);
  transition:transform 1.1s var(--ease-soft), opacity 1.1s var(--ease-soft);
}
.svc-mark-ghost svg{
  display:block;
  width:100%;
  height:auto;
  stroke-width:var(--sw, .45);
}
/* the one thing that answers the pointer: the faint copy turns a little —
   on the service cards and the goal cards alike */
.svc-card:hover .svc-mark-ghost,
.goal-card:hover .svc-mark-ghost,
.goal-card:focus-visible .svc-mark-ghost{ transform:rotate(-3deg) scale(1.04); opacity:.26; }

.svc-mark-num{
  position:absolute;
  left:clamp(16px,2vw,28px);
  top:clamp(14px,1.8vw,26px);
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.16em;
  color:rgba(255,255,255,.72);
}
.svc-mark-num::after{
  content:"";
  display:block;
  width:22px;
  height:2px;
  margin-top:8px;
  background:var(--accent);
}

/* The mark draws itself in, line by line, once it reaches the middle of the
   screen — not as soon as the card peeks in at the bottom. Every stroke is
   marked out as one unit long, so an offset of 1 hides it and 0 shows it
   whole. The script arms each card and says when to draw; with no script, the
   mark is simply there. */
.svc-mark-icon svg *{
  /* a dash the length of the line, then a gap twice as long: an offset of 1
     with a gap of only 1 would still leave a dot — the rounded cap of a dash
     shrunk to nothing — at the start of every line before it draws. The dash
     is a touch longer than the line (1.1): Chrome measures a circle a little
     short, and a dash of exactly 1 left a notch where small circles close */
  stroke-dasharray:1.1 2;
  stroke-dashoffset:0;
}
.mark-armed:not(.mark-drawn) .svc-mark-icon svg *{ stroke-dashoffset:1.12; }
/* the draw runs one way only — in. Put on the drawn state rather than the
   resting one, so an armed card hides its mark at once instead of visibly
   un-drawing it first */
.mark-drawn .svc-mark-icon svg *{ transition:stroke-dashoffset 1s var(--ease-soft); }

@media (max-width:760px){
  .svc-mark-icon{ width:clamp(84px,30%,132px); }
  .svc-mark-icon svg{ stroke-width:var(--sw, .9); }
}

@media (prefers-reduced-motion:reduce){
  .svc-mark-icon svg *{ transition:none; stroke-dashoffset:0 !important; }
  .svc-mark-ghost{ transition:none; }
  .svc-card:hover .svc-mark-ghost,
  .goal-card:hover .svc-mark-ghost,
  .goal-card:focus-visible .svc-mark-ghost{ transform:rotate(-9deg); opacity:.18; }
}

@media (max-width:1100px){
  .services-layout{ grid-template-columns:1fr; gap:32px; }
  .services-head{ position:static; height:auto; display:block; }
}
@media (max-width:760px){
  .svc-card{ grid-template-columns:1fr; min-height:0; }
  /* stacked, there is no card height to fill, so the picture sets its own:
     4:3, the shape they are exported at, edge to edge */
  .svc-shot{ order:1; aspect-ratio:4 / 3; min-height:0; }
  .svc-body{ order:2; }
  .svc-cta{ margin-top:20px; width:100%; justify-content:space-between; }
}

/* ============================================================
   PROJECTS — image, then the label beneath it
   Nothing sits on the artwork except the category chip: titles
   over photographs fight the image and lose. The two actions
   fade in over the frame on hover only.
   ============================================================ */
.work{ background:var(--paper); color:var(--ink); }
.work-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(64px,7vw,120px) clamp(18px,3.4vw,55px) clamp(70px,8vw,140px);
}

/* --- masthead: oversized word left, standfirst right --- */
.work-head{
  max-width:var(--work-grid);
  margin-inline:auto;
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:clamp(24px,4vw,80px);
  margin-bottom:clamp(34px,4vw,68px);
}
.work-title{ margin:0; text-transform:uppercase; }
/* inner pages set the same heading in sentence case */
.work-title--plain{ text-transform:none; }
.work-count{
  font-size:.2em;
  font-weight:500;
  letter-spacing:0;
  vertical-align:super;
  margin-left:.1em;
}
.work-intro{
  margin:.6em 0 0;
  max-width:26ch;
  flex:none;
  text-align:right;
  color:var(--ink);
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.5;
}

.work-grid{
  max-width:var(--work-grid);
  margin-inline:auto;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(26px,2.6vw,44px) clamp(16px,1.8vw,30px);
}
.work-more{
  display:flex;
  justify-content:center;
  margin-top:clamp(40px,4.6vw,76px);
}

.wk-card{ display:flex; flex-direction:column; }

/* --- the frame holds the image, chip and hover actions --- */
.wk-frame{
  position:relative;
  overflow:hidden;
  border:1px solid var(--line);
  border-radius:0;  /* was clamp(18px,1.6vw,26px) */   /* matches the process cards */
  aspect-ratio:4 / 3;      /* the sources are 800x600 */
  background:var(--paper-2);
  isolation:isolate;
}
.wk-shot{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
}

/* category chip, bottom right of the artwork */
.wk-tag{
  position:absolute;
  right:clamp(10px,1vw,18px);
  bottom:clamp(10px,1vw,18px);
  z-index:2;
  padding:6px 14px;
  border-radius:0;  /* was 999px */
  background:rgba(0,0,0,.78);
  /* the scrim above is a fixed dark, so this stays a literal — the token
     would follow an inverted section and disappear into it */
  color:#fff;
  font-family:var(--font-mono);
  font-size:12px;
  font-weight:500;
  letter-spacing:.09em;
  text-transform:uppercase;
  line-height:1.25;
  white-space:nowrap;
  transition:opacity .4s var(--ease);
}
.wk-card:hover .wk-tag{ opacity:0; }

/* --- hover actions, centred over the frame --- */
.wk-actions{
  position:absolute;
  inset:0;
  z-index:3;
  display:flex;
  align-items:center;
  justify-content:center;
  flex-wrap:wrap;
  gap:10px;
  padding:0 clamp(14px,1.6vw,28px);
  background:rgba(0,0,0,.45);
  opacity:0;
  visibility:hidden;
  transition:opacity .45s var(--ease-out-quart), visibility 0s linear .45s;
}
.wk-card:hover .wk-actions,
.wk-card:focus-within .wk-actions{
  opacity:1;
  visibility:visible;
  transition:opacity .45s var(--ease-out-quart), visibility 0s linear 0s;
}
.wk-btn{
  appearance:none;
  border:0;
  cursor:pointer;
  padding:11px 20px;
  border-radius:0;  /* was 999px */
  background:var(--paper);
  color:var(--ink);
  font-family:inherit;
  font-size:clamp(12px,.9vw,14.5px);
  font-weight:500;
  line-height:1.2;
  letter-spacing:-.01em;
  white-space:nowrap;
  text-decoration:none;
  transition:background-color .3s var(--ease), color .3s var(--ease);
}
.wk-btn:hover{ background:var(--ink); color:var(--paper); }

/* --- caption under the frame --- */
.wk-name{
  margin:clamp(12px,1.1vw,18px) 0 0;
  padding-bottom:clamp(12px,1.1vw,18px);
  border-bottom:1px solid var(--line);
  font-size:clamp(16px,1.25vw,21px);
  font-weight:500;
  line-height:1.2;
  letter-spacing:-.015em;
}

@media (max-width:860px){
  .work-head{ flex-direction:column; align-items:flex-start; gap:14px; }
  .work-intro{ text-align:left; margin-top:0; }
}
@media (max-width:640px){
  .work-grid{ grid-template-columns:1fr; }
}
/* Phones, and any screen without a pointer that can hover (tablets, phones
   turned sideways): there is no hover on touch, so the overlay had to sit
   permanently over the artwork - a dark scrim across every thumbnail - or
   never show at all. Instead the frame stops being a fixed-ratio window and
   becomes a plain column: picture, then the two buttons underneath in
   normal flow. */
@media (max-width:640px), (hover:none){
  .wk-frame{
    aspect-ratio:auto;
    overflow:visible;
    border:0;
    background:none;
    display:flex;
    flex-direction:column;
  }
  .wk-shot{
    position:static;
    width:100%;
    height:auto;
    aspect-ratio:4 / 3;
    border:1px solid var(--line);
  }
  .wk-tag{ display:none; }          /* the caption below already names it */

  .wk-actions{
    position:static;
    opacity:1;
    visibility:visible;
    background:none;
    padding:0;
    margin-top:10px;
    gap:8px;
    justify-content:stretch;
  }
  .wk-btn{
    flex:1 1 0;
    min-width:0;
    padding:13px 14px;              /* >=44px tall: a real touch target */
    border:1px solid var(--ink);
  }
}

/* ============================================================
   IMAGE LIGHTBOX
   ============================================================ */
.lb{
  position:fixed;
  inset:0;
  z-index:220;
  display:grid;
  place-items:center;
  padding:clamp(14px,3vw,48px);
  visibility:hidden;
  transition:visibility 0s linear .45s;
}
.lb.is-open{ visibility:visible; transition:visibility 0s linear 0s; }
.lb-backdrop{
  position:absolute; inset:0;
  background:rgba(0,0,0,.85);
  opacity:0;
  transition:opacity .45s var(--ease);
}
.lb.is-open .lb-backdrop{ opacity:1; }
.lb-panel{
  position:relative;
  max-width:min(1400px,100%);
  max-height:100%;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:14px;
  opacity:0;
  transform:scale(.97);
  transition:opacity .45s var(--ease-out-quart), transform .55s var(--ease-out-quart);
}
.lb.is-open .lb-panel{ opacity:1; transform:none; }
.lb-img{
  max-width:100%;
  max-height:calc(100vh - clamp(90px,12vw,190px));
  width:auto; height:auto;
  border-radius:0;  /* was 10px */
  background:var(--ink);
}
.lb-caption{
  margin:0;
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:rgba(255,255,255,.72);
  text-align:center;
}
.lb-close{
  position:absolute;
  top:-52px; right:0;
  width:44px; height:44px;
  border-radius:0;  /* was 50% */
  border:1px solid rgba(255,255,255,.3);
  background:transparent;
  color:var(--paper);
  cursor:pointer;
  display:grid; place-items:center;
  transition:background-color .3s var(--ease), color .3s var(--ease);
}
.lb-close svg{ width:20px; height:20px; }
.lb-close:hover{ background:var(--paper); color:var(--ink); }
@media (max-width:760px){
  .lb-close{ top:auto; bottom:-54px; right:50%; transform:translateX(50%); }
}
/* ============================================================
   GET A QUOTE — LIGHTBOX
   ============================================================ */
.quote-modal{
  position:fixed;
  inset:0;
  z-index:200;                       /* above the fixed header */
  display:grid;
  place-items:center;
  padding:clamp(12px,3vw,40px);
  visibility:hidden;
  transition:visibility 0s linear .5s;
}
.quote-modal.is-open{
  visibility:visible;
  transition:visibility 0s linear 0s;
}
.quote-backdrop{
  position:absolute;
  inset:0;
  background:rgba(0,0,0,.62);
  opacity:0;
  transition:opacity .45s var(--ease);
}
.quote-modal.is-open .quote-backdrop{ opacity:1; }

.quote-panel{
  position:relative;
  width:100%;
  max-width:1180px;
  max-height:calc(100vh - clamp(24px,6vw,80px));
  overflow-y:auto;
  overscroll-behavior:contain;
  background:var(--paper);
  padding:clamp(28px,3.4vw,58px);
  opacity:0;
  transform:translateY(34px) scale(.985);
  transition:opacity .5s var(--ease-soft), transform .7s var(--ease-soft);
}
.quote-modal.is-open .quote-panel{ opacity:1; transform:none; }

.quote-close{
  position:absolute;
  top:clamp(14px,1.6vw,22px);
  right:clamp(14px,1.6vw,22px);
  z-index:2;
  width:44px; height:44px;
  border-radius:0;  /* was 50% */
  border:1px solid var(--line);
  background:var(--paper);
  cursor:pointer;
  display:grid; place-items:center;
  transition:background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.quote-close svg{ width:20px; height:20px; }
.quote-close:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }

.quote-grid{
  display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(30px,4vw,64px);
}

/* --- left column --- */
.quote-aside{ display:flex; flex-direction:column; align-items:flex-start; }
.quote-kicker{
  margin:0 0 clamp(20px,2.4vw,34px);
  font-size:14.5px;
  font-weight:500;
  line-height:1.5;
  max-width:34ch;
}
.quote-title{
  margin:0;
  font-size:clamp(32px,3.4vw,56px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.035em;
  max-width:12ch;
}
.quote-or{
  margin:clamp(26px,3vw,46px) 0 16px;
  font-size:17px;
  color:var(--grey);
}
.quote-direct{ display:flex; flex-wrap:wrap; gap:12px; }
.quote-direct .pill-arrow svg{ width:17px; height:17px; }

/* --- form --- */
.quote-form{
  border-left:1px solid var(--line);
  padding-left:clamp(24px,3vw,54px);
}
.qf-row{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(18px,2vw,30px);
  margin-bottom:clamp(20px,2.2vw,32px);
}
.qf-field{ display:block; }
.qf-label{
  display:block;
  margin-bottom:10px;
  font-size:14px;
  font-weight:500;
  letter-spacing:-.005em;
  color:var(--ink);
}
.quote-form input[type="text"],
.quote-form input[type="email"],
.quote-form input[type="tel"],
.quote-form textarea{
  width:100%;
  border:0;
  border-bottom:1px solid var(--line);
  background:transparent;
  padding:8px 0 12px;
  font-family:inherit;
  font-size:15.5px;
  color:var(--ink);
  border-radius:0;                   /* iOS rounds inputs by default */
  transition:border-color .3s var(--ease);
}
.quote-form textarea{ resize:vertical; min-height:74px; }
/* black at partial opacity: still the palette black, but a typed value and
   an empty field have to look different */
.quote-form ::placeholder{ color:#000000; opacity:.42; }
.quote-form input:focus,
.quote-form textarea:focus{ outline:none; border-bottom-color:var(--ink); }
.quote-form input.is-invalid,
.quote-form textarea.is-invalid{ border-bottom-color:var(--error); }

.qf-block{ margin-bottom:clamp(20px,2.2vw,32px); }
fieldset.qf-block{ border:0; padding:0; margin-inline:0; }
fieldset.qf-block legend{ padding:0; }

/* --- service chips --- */
.qf-chips{ display:flex; flex-wrap:wrap; gap:9px; }
.chip{ display:inline-flex; cursor:pointer; }
.chip input{
  position:absolute;
  opacity:0;
  width:1px; height:1px;
  pointer-events:none;
}
.chip span{
  display:inline-flex;
  align-items:center;
  padding:9px 17px;
  border:1px solid var(--line);
  border-radius:0;  /* was 999px */
  font-size:13.5px;
  font-weight:500;
  line-height:1.2;
  white-space:nowrap;
  transition:background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.chip:hover span{ border-color:var(--ink); }
.chip input:checked + span{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.chip input:focus-visible + span{ outline:2px solid var(--ink); outline-offset:2px; }

.qf-hp{ position:absolute; left:-9999px; width:1px; height:1px; opacity:0; }

.qf-foot{
  display:flex;
  align-items:center;
  gap:18px;
  flex-wrap:wrap;
  margin-top:clamp(24px,2.6vw,36px);
}
.quote-form button.pill{ border:1px solid transparent; cursor:pointer; }
.quote-form button.pill:disabled{ opacity:.55; pointer-events:none; }
.qf-status{
  margin:0;
  font-size:14px;
  line-height:1.45;
  color:var(--grey);
}
.qf-status.is-ok{ color:var(--ink); font-weight:500; }
.qf-status.is-error{ color:var(--error); }

@media (max-width:900px){
  .quote-grid{ grid-template-columns:1fr; gap:30px; }
  .quote-form{ border-left:0; border-top:1px solid var(--line); padding-left:0; padding-top:30px; }
  .quote-title{ max-width:100%; }
}
@media (max-width:560px){
  .qf-row{ grid-template-columns:1fr; }
  /* 44px, not 38: this is the only way out of the modal on a phone */
  .quote-close{ width:44px; height:44px; }
  .quote-direct{ width:100%; }
  .quote-direct .pill{ flex:1 1 100%; justify-content:space-between; }
  .qf-foot .pill{ width:100%; justify-content:space-between; }
}

/* --- the modal on a phone --- */
@media (max-width:760px){
  /* the close button sits over this line at narrow widths and was cutting
     the sentence in half - hold the text clear of it */
  .quote-kicker{ padding-right:60px; }

  /* iOS Safari zooms the whole page when a focused field is under 16px,
     and never zooms back out. 16px exactly is the threshold. */
  .quote-form input[type="text"],
  .quote-form input[type="email"],
  .quote-form input[type="tel"],
  .quote-form textarea{ font-size:16px; }   /* both forms carry .quote-form */

  /* service chips are tapped, not clicked */
  .chip span{ min-height:44px; padding:11px 16px; }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
/* step the hero down on narrower desktops so the image slot stays close to
   square instead of turning tall and portrait — keeps the crop predictable */
@media (max-width:1400px){ .hero-grid{ min-height:640px; } }
@media (max-width:1150px){ .hero-grid{ min-height:560px; } }
@media (max-width:1000px){ .hero-grid{ min-height:480px; } }

@media (max-width:900px){
  /* one nav column, and the contact blocks stack under it */
  .menu-top{ grid-template-columns:1fr; row-gap:38px; }
  .menu-bottom{ grid-template-columns:1fr; row-gap:30px; }
}

@media (max-width:900px){
  :root{ --header-h:70px; }
  .brand img{ height:36px; }
  .hero-grid{ grid-template-columns:1fr; min-height:0; }
  .hero-visual{ min-height:0; height:min(72vw,520px); order:-1; }
  .hero-copy{ padding:56px 24px 66px; }
  .hero h1{ max-width:100%; }
  .menu-nav a{ font-size:clamp(26px,5.4vw,36px); }
}

@media (max-width:640px){
  .pill--sm{ padding-left:16px; gap:9px; font-size:12px; }
  .pill--sm .pill-arrow{ width:32px; height:32px; }
  .pill--sm .pill-arrow svg{ width:14px; height:14px; }
  .burger{ width:44px; }
  .menu-top{ grid-template-columns:1fr; row-gap:44px; }
  .menu-bottom{ grid-template-columns:1fr; }
  .menu-label{ margin-bottom:20px; }
  .menu-actions{ width:100%; }
  .menu-actions .pill{ width:100%; justify-content:space-between; }
  .hero-actions .pill{ width:100%; justify-content:space-between; }
  .slider-nav{ width:44px; height:44px; }
}

@media (max-width:400px){
  .header-inner{ padding:0 12px; }
  .brand img{ height:30px; }
  .burger{ width:44px; }
  .burger-lines{ width:28px; gap:6px; }
  .burger-lines i:nth-child(1){ width:28px; }
  .burger-lines i:nth-child(2){ width:18px; }
  .burger-lines i:nth-child(3){ width:23px; }
  .burger:hover .burger-lines i,
  .burger.is-open .burger-lines i{ width:28px; }
  .burger.is-open .burger-lines i:nth-child(1){ transform:translateY(8px) rotate(45deg); }
  .burger.is-open .burger-lines i:nth-child(3){ transform:translateY(-8px) rotate(-45deg); }
}

/* Reduced motion: drop the ambient, self-starting motion — the slow image
   push, the on-load reveal, looping hover art. The menu transition stays:
   it is a direct response to a click, and it is the whole interaction. */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  .hero-slider img{ transition:opacity .5s linear !important; }
  .pill:hover .pill-arrow svg{ animation:none !important; }
}

/* ============================================================
   HOW WE WORK — fanned process cards
   Four cards overlap on one rail, each tilted by its own --rot.
   They sit flat and low until the block scrolls in, then settle
   into the fan — the tilt is the animation, so the reveal is
   handled here rather than by the shared .rv treatment.
   ============================================================ */
.flow{ background:var(--band); color:var(--ink); }
.flow-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(64px,7vw,120px) clamp(18px,3.4vw,55px);
}

/* --- head --- */
.flow-headline{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:clamp(24px,4vw,70px);
}
.flow-cta{ flex:none; margin-bottom:.4em; }

/* --- the fan --- */
.flow-fan{
  display:flex;
  justify-content:center;
  align-items:flex-start;
  gap:clamp(10px,1.1vw,18px);
  margin-top:clamp(46px,5.4vw,90px);
  padding:clamp(16px,2vw,34px) 0;
}

.flow-card{
  flex:0 0 clamp(215px,20vw,290px);
  min-height:clamp(280px,25vw,330px);
  padding:clamp(20px,1.9vw,28px);
  border-radius:0;  /* was clamp(18px,1.6vw,26px) */   /* fully round — no cut corner */
  background:var(--paper);
  color:var(--ink);
  border:1px solid var(--line);
  display:flex;
  flex-direction:column;

  /* --f is the fan amount, driven by main.js from the section's
     scroll progress: 1 while the block is entering (tilted and
     pulled together) easing to 0 once it is fully in view, where
     the cards stand square-on in an evenly spaced row. */
  transform:
    translateX(calc(var(--tx,0px) * var(--f,1)))
    rotate(calc(var(--rot,0deg) * var(--f,1)));
}

/* the outer cards ride in front as they overlap */
.flow-card:nth-child(1){ z-index:4; }
.flow-card:nth-child(2){ z-index:3; }
.flow-card:nth-child(3){ z-index:2; }
.flow-card:nth-child(4){ z-index:1; }
/* the two filled cards */
.flow-card--red,
.flow-card--blue{
  color:var(--paper);
  border-color:transparent;
}
.flow-card--red{ background:var(--accent); }
.flow-card--blue{ background:var(--hover); }

/* --- icon and step number share the top row --- */
.flow-top{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:14px;
}
.flow-icon{
  display:block;
  width:clamp(46px,4vw,62px);
  height:clamp(46px,4vw,62px);
  flex:none;
  color:var(--ink);            /* black on the two light cards */
}
.flow-card--red .flow-icon,
.flow-card--blue .flow-icon{ color:var(--paper); }
.flow-icon svg{ width:100%; height:100%; display:block; }

.flow-num{
  font-family:var(--font-mono);
  font-size:clamp(13px,1.05vw,17px);
  font-weight:500;
  letter-spacing:.04em;
  line-height:1;
  color:var(--grey-light);
}
.flow-card--red .flow-num,
.flow-card--blue .flow-num{ color:rgba(255,255,255,.72); }

.flow-title{
  margin:auto 0 0;                 /* pinned to the foot, above the copy */
  font-size:clamp(16px,1.25vw,20px);
  font-weight:500;
  line-height:1.25;
  letter-spacing:-.02em;
}
.flow-text{
  margin:clamp(9px,.9vw,13px) 0 0;
  font-size:clamp(13.5px,.98vw,15px);
  line-height:1.55;
  color:var(--grey);
}
.flow-card--blue .flow-text{ color:rgba(255,255,255,.78); }
/* white on #F00030 is 4.42:1, so the copy stays near-solid */
.flow-card--red .flow-text{ color:rgba(255,255,255,.94); }

@media (max-width:1100px){
  .flow-headline{ flex-direction:column; align-items:flex-start; gap:26px; }
  .flow-cta{ margin-bottom:0; }
}
@media (max-width:900px){
  /* the fan needs width; below this the cards stack square-on */
  .flow-fan{ flex-wrap:wrap; justify-content:flex-start; gap:16px; }
  .flow-card{ flex:1 1 240px; min-height:0; }
  .flow-card + .flow-card{ margin-left:0; }
  /* no room to fan; --f is forced flat and the row just wraps */
  .flow-card{ --f:0; transform:none; }
}
@media (max-width:560px){
  .flow-card{ flex:1 1 100%; }
  .flow-cta{ width:100%; justify-content:space-between; }
}
/* Note: the fan is scroll-linked rather than a timed transition,
   so it follows the reader either way and needs no reduced-motion
   opt-out; the icon disc keeps its own hover colour change. */
.flow-card:hover{ z-index:5; }
/* ============================================================
   WHAT WE DO — keyword carousel
   Artwork left, copy centred beside it, and a sliver of the
   next slide cut off at the right edge. Slides are stacked in
   one grid cell so the row sizes to the tallest block and the
   copy never clips — the text is long on purpose, it is what
   the section is for.
   ============================================================ */
.seo{ background:var(--paper); color:var(--ink); }
.seo-stage{
  display:grid;
  grid-template-columns:minmax(0,1.02fr) minmax(0,1fr) clamp(38px,7vw,150px);
  align-items:stretch;
  gap:0;
  min-height:clamp(360px,30vw,520px);
}

/* --- left: the artwork, flush to the section edge --- */
.seo-main{
  position:relative;
  overflow:hidden;
  background:var(--paper-3);
}
.seo-frame{
  /* out of flow, or the 1024px-square sources would set the row
     height from their own aspect ratio instead of the copy */
  position:absolute;
  inset:0;
  margin:0;
  /* JS parks each frame at (index - current) * 100%, so the active
     one sits at 0 and its neighbours wait just off each edge. */
  transform:translateX(100%);
  transition:transform .9s var(--ease-soft);
  will-change:transform;
}
.seo-frame img{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
}

/* --- centre: the copy --- */
.seo-panel{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:clamp(18px,2vw,34px);
  padding:clamp(36px,3.6vw,64px) clamp(22px,3.2vw,58px);
}
.seo-copywrap{ display:grid; width:100%; }
.seo-copy{
  grid-area:1 / 1;
  text-align:center;
  opacity:0;
  visibility:hidden;
  transform:translateY(10px);
  transition:opacity .55s var(--ease-soft), transform .7s var(--ease-soft),
             visibility 0s linear .55s;
}
.seo-copy.is-active{
  opacity:1;
  visibility:visible;
  transform:none;
  transition:opacity .55s var(--ease-soft) .12s, transform .7s var(--ease-soft) .12s,
             visibility 0s linear 0s;
}
.seo-count{
  display:block;
  font-family:var(--font-mono);
  font-size:clamp(12px,.85vw,13px);
  letter-spacing:.22em;
  color:var(--grey-light);
}
.seo-count b{ font-weight:500; color:var(--ink); }
.seo-heading{
  margin:clamp(12px,1.4vw,22px) 0 0;
  font-size:clamp(23px,2.25vw,38px);
  font-weight:500;
  line-height:1.12;
  letter-spacing:-.03em;
}
.seo-text{
  margin:clamp(14px,1.4vw,22px) auto 0;
  max-width:44ch;
  color:var(--grey);
  font-size:clamp(13.5px,.95vw,15.5px);
  line-height:1.68;
}

/* --- arrows, under the copy --- */
.seo-nav{ display:flex; gap:12px; flex:none; }
.seo-arrow{
  appearance:none;
  cursor:pointer;
  width:clamp(42px,3.2vw,54px);
  height:clamp(42px,3.2vw,54px);
  border-radius:0;  /* was 50% */
  display:grid; place-items:center;
  border:1px solid var(--line);
  background:var(--paper);
  color:var(--ink);
  transition:background-color .35s var(--ease), color .35s var(--ease),
             border-color .35s var(--ease);
}
.seo-arrow svg{ width:40%; height:40%; }
.seo-arrow:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }

/* --- right: the cut-off sliver of the next slide --- */
.seo-peek{
  position:relative;
  overflow:hidden;
  background:var(--paper-3);
}
.seo-peek-frame{
  position:absolute;
  inset:0;
  margin:0;
  /* same rail as the main stack, offset one slide ahead */
  transform:translateX(100%);
  transition:transform .9s var(--ease-soft);
  will-change:transform;
}
.seo-peek-frame img{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
}

@media (max-width:900px){
  /* the sliver is decoration — drop it before it squeezes the copy */
  .seo-stage{ grid-template-columns:1fr; min-height:0; }
  .seo-main{ aspect-ratio:16 / 10; }
  .seo-peek{ display:none; }
  .seo-panel{ padding:clamp(34px,7vw,60px) clamp(20px,5vw,44px); }
  .seo-text{ max-width:60ch; }
}
@media (prefers-reduced-motion:reduce){
  .seo-frame,
  .seo-peek-frame{ transition:none; }
  .seo-copy{ transform:none; }
}

/* ============================================================
   HOW CAN WE HELP — goal picker
   Oversized question, then a 4-across grid of goals. Each card
   is an anchor to #quote, which main.js delegates into the
   quote modal, so the whole tile is the hit area.
   ============================================================ */
.goals{ background:var(--paper); color:var(--ink); }
.goals-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(64px,7vw,120px) clamp(18px,3.4vw,55px);
}

.goals-heading{ margin:0; }
.goals-intro{
  margin:clamp(20px,2.2vw,34px) 0 0;
  max-width:62ch;
  color:var(--grey);
  font-size:clamp(15px,1.15vw,19px);
  line-height:1.6;
}
.goals-ask{
  margin:clamp(18px,1.8vw,28px) 0 clamp(26px,3vw,46px);
  font-size:clamp(15px,1.1vw,18px);
  font-weight:600;
  letter-spacing:-.01em;
}

.goals-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(12px,1.2vw,20px);
}

.goal-card{
  display:flex;
  flex-direction:column;
  padding:0;
  overflow:hidden;                  /* holds the picture to the frame */
  border:1px solid var(--line);
  border-radius:0;  /* was clamp(10px,.9vw,14px) */
  background:var(--paper);
  color:inherit;
  text-decoration:none;
  transition:border-color .3s var(--ease);
}

/* the picture well - a fixed 800x600 frame, whatever the source */
.goal-shot{
  margin:0;
  aspect-ratio:4 / 3;
  overflow:hidden;
  background:var(--band);
}
.goal-shot img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
}

.goal-title{
  /* the band caps the card: every picture is the same height and every
     card stretches to the row, so the bands come out identical and the
     label is centred in whatever height is left */
  flex:1;
  display:flex;
  align-items:center;
  margin:0;
  padding:clamp(13px,1.15vw,17px) clamp(14px,1.25vw,18px);
  background:var(--band);
  font-size:clamp(16px,1.15vw,19px);
  font-weight:500;
  line-height:1.3;
  letter-spacing:-.02em;
  transition:background-color .3s var(--ease), color .3s var(--ease);
}

/* Hovering the tile takes its label band to the brand blue and the words to
   white — the picture is left alone, so the work stays the work. Keyboard
   focus gets the same answer as the mouse. */
.goal-card:hover,
.goal-card:focus-visible{ border-color:var(--hover); }
.goal-card:hover .goal-title,
.goal-card:focus-visible .goal-title{
  background:var(--hover);
  color:var(--paper);
}

/* ------------------------------------------------------------
   The drawn mark, in place of a picture
   The same plain panel the service cards use — flat #1C2473, the
   goal's mark drawn large in a single white line, and a faint
   oversized copy cut off by the corner — so the two sections read
   as one set. Those styles live with the service cards
   (.svc-mark); this only colours the frame and positions it, so
   the panel stays inside the picture's 4:3 frame rather than
   spreading over the card's title.
   ------------------------------------------------------------ */
.goal-shot--mark{ position:relative; background:#1C2473; }

@media (max-width:1100px){
  .goals-grid{ grid-template-columns:repeat(3,minmax(0,1fr)); }
}
@media (max-width:820px){
  .goals-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:460px){
  .goals-grid{ grid-template-columns:1fr; }
}

/* ============================================================
   SECTION HEADINGS
   One type treatment for every section heading, taken from the
   original "Our Services" mark, plus a short accent bar beneath
   it — a fixed stub at the left edge rather than a rule running
   the width of the words.
   ============================================================ */
.about-heading,
.steps-heading,
.duo-heading,
.wdsvc-heading,
.services-heading,
.work-title,
.flow-heading,
.goals-heading,
.faq-heading{
  position:relative;
  width:fit-content;
  max-width:100%;
  padding-bottom:.55em;
  font-size:clamp(26px,2.6vw,44px);
  font-weight:500;
  line-height:1.1;
  letter-spacing:-.035em;
}
.about-heading::after,
.duo-heading::after,
.steps-heading::after,
.wdsvc-heading::after,
.services-heading::after,
.work-title::after,
.flow-heading::after,
.goals-heading::after,
.faq-heading::after{
  content:"";
  position:absolute;
  left:0;
  bottom:0;
  width:clamp(34px,3vw,52px);
  height:3px;
  background:currentColor;
}

/* ============================================================
   FAQS — two columns of disclosures
   Each answer is a grid row animated 0fr -> 1fr, which gives a
   real height transition without measuring anything in JS. The
   inner wrapper carries the overflow and the visibility flip so
   collapsed answers stay out of the accessibility tree.
   ============================================================ */
.faq{ background:var(--band); color:var(--ink); }
.faq-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(64px,7vw,120px) clamp(18px,3.4vw,55px);
}
.faq-head{ margin-bottom:clamp(30px,3.4vw,56px); }
.faq-sub{
  margin:clamp(14px,1.4vw,22px) 0 0;
  max-width:56ch;
  color:var(--grey);
  font-size:clamp(14.5px,1.05vw,17px);
  line-height:1.6;
}

.faq-grid{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(12px,1.2vw,20px);
  align-items:stretch;
}
/* each column is its own flow, so opening an answer on the left
   never pushes the right-hand column around */
.faq-col{
  display:flex;
  flex-direction:column;
  gap:clamp(12px,1.2vw,20px);
}

.faq-item{
  background:var(--paper);
  border:1px solid var(--line);
  overflow:hidden;
  border-radius:0;  /* was clamp(12px,1.1vw,18px) */
  transition:border-color .35s var(--ease);
}
/* .rv sets its own `transition` further down the file, and at equal
   specificity the later rule replaces this list wholesale — which would leave
   the open card's border snapping. The compound selector outranks
   it and carries both sets. */
.faq-item.rv{
  transition:border-color .35s var(--ease),
             opacity .9s var(--ease-soft), transform .9s var(--ease-soft);
}
.faq-item.is-open{
  border-color:rgba(0,0,0,.24);
}

.faq-q{ margin:0; font-size:inherit; font-weight:inherit; }
.faq-btn{
  appearance:none;
  border:0;
  background:none;
  cursor:pointer;
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:18px;
  padding:clamp(17px,1.6vw,24px) clamp(18px,1.7vw,26px);
  text-align:left;
  font-family:inherit;
  font-size:clamp(14.5px,1.05vw,17px);
  font-weight:500;
  line-height:1.35;
  letter-spacing:-.015em;
  color:var(--ink);
}

/* the plus, which rotates into a minus when the answer is open */
.faq-mark{
  position:relative;
  flex:none;
  width:clamp(14px,1.1vw,17px);
  height:clamp(14px,1.1vw,17px);
  color:var(--accent);
  /* the whole mark turns as it opens, which carries the eye
     through the change instead of the bar simply vanishing */
  transition:transform .5s var(--ease-soft);
}
.faq-item.is-open .faq-mark{ transform:rotate(180deg); }

.faq-mark::before,
.faq-mark::after{
  content:"";
  position:absolute;
  top:50%; left:50%;
  width:100%;
  height:2.5px;                   /* ~15% of the mark, so it stays bold as it shrinks */
  border-radius:0;  /* was 2px */              /* rounded ends, not cut off */
  background:currentColor;
  transform:translate(-50%,-50%);
  transition:transform .5s var(--ease-soft), opacity .3s var(--ease);
}
.faq-mark::after{ transform:translate(-50%,-50%) rotate(90deg); }

/* the upright bar retracts into the horizontal one */
.faq-item.is-open .faq-mark::after{
  transform:translate(-50%,-50%) rotate(90deg) scaleX(0);
  opacity:0;
}

/* --- the answer --- */
.faq-a{
  height:0;
  overflow:hidden;
  visibility:hidden;
  transition:height .48s var(--ease-soft), visibility 0s linear .48s;
}
.faq-item.is-open .faq-a{
  visibility:visible;
  transition:height .48s var(--ease-soft), visibility 0s linear 0s;
}
.faq-a-in p{
  margin:0;
  padding:0 clamp(18px,1.7vw,26px) clamp(19px,1.7vw,26px);
  color:var(--grey);
  font-size:clamp(13.5px,.98vw,15.5px);
  line-height:1.68;
  /* the answer catches up with the box rather than snapping in */
  opacity:0;
  transform:translateY(6px);
  transition:opacity .34s var(--ease-soft), transform .34s var(--ease-soft);
}

@media (max-width:760px){
  .faq-grid{ grid-template-columns:1fr; }
}
/* Note: the disclosure itself keeps its easing under reduced
   motion. A local height change and an opacity fade are not the
   vestibular triggers the setting exists to stop; the scroll-in
   movement below is, so that one is still suppressed. */

.faq-item.is-open .faq-a-in p{
  opacity:1;
  transform:none;
  transition-delay:.14s;
}

/* ============================================================
   SECTION REVEAL
   One entrance for the whole page, in the spirit of the hero's
   line animation: content rises out from under a mask on the
   site's outExpo curve, staggered block by block. Delays are
   set by main.js so the order follows the DOM rather than a
   pile of nth-child rules.

   Under reduced motion the rise is dropped but the fade stays —
   a plain opacity change is not what that setting guards
   against, and it keeps the page from snapping into place.
   ============================================================ */
.rv{
  opacity:0;
  transform:translateY(24px);
  transition:opacity .9s var(--ease-soft), transform .9s var(--ease-soft);
  will-change:opacity, transform;
}
.rv.is-in{
  opacity:1;
  transform:none;
}
/* the mask: headings and copy wipe up from their own baseline */
.rv--mask{
  clip-path:inset(0 0 -20% 0);
}

@media (prefers-reduced-motion:reduce){
  /* keep the fade, drop the travel. Overriding `transform` alone rather than
     re-declaring `transition` leaves each component's own transition list
     intact — a second shorthand here would replace it outright. */
  .rv,
  .rv.is-in{ transform:none; }
}

/* ============================================================
   BY THE NUMBERS
   Oversized figure, a rule beneath it, then the explanation set
   in bold underneath — the layout from the reference. Sits on
   the grey band so it also breaks up the run of white sections
   either side of it.
   ============================================================ */
.stats{ background:var(--accent); color:var(--paper); }
.stats-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(58px,6.4vw,110px) clamp(18px,3.4vw,55px);
}
.stats-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(24px,3vw,62px);
}
.stat{ display:flex; flex-direction:column; }

.stat-num{
  margin:0 0 clamp(14px,1.4vw,22px);
  padding-bottom:clamp(12px,1.3vw,22px);
  border-bottom:1px solid rgba(255,255,255,.4);
  font-size:clamp(46px,5.6vw,92px);
  font-weight:500;
  line-height:.92;
  letter-spacing:-.045em;
  font-variant-numeric:tabular-nums;
}
.stat-label{
  margin:0;
  /* held at 19px+ so the white sits in the large-text band, where
     4.42:1 on this red is comfortably inside the 3:1 threshold */
  font-size:clamp(16px,1.2vw,20px);
  font-weight:600;
  line-height:1.25;
  letter-spacing:-.02em;
}

@media (max-width:900px){
  .stats-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:460px){
  .stats-grid{ grid-template-columns:1fr; gap:clamp(26px,6vw,40px); }
}

/* ============================================================
   ACCENT
   The red earns its place on display type, section marks and
   state changes — never on running copy, where #F00030 falls
   short of the 4.5:1 body-text threshold on white.
   ============================================================ */

/* the rule under every section heading */
.wdsvc-heading::after,
.duo-heading::after,
.steps-heading::after,
.about-heading::after,
.services-heading::after,
.work-title::after,
.flow-heading::after,
.goals-heading::after,
.faq-heading::after{ background:var(--accent); }

/* a single word carried in red inside a heading */
.hl{ color:var(--accent); font-style:normal; }

/* the figures sit on the red band, so they invert to white */
.stat-num{ color:var(--paper); }

/* carousel counter: the live number only */
.seo-count b{ color:var(--accent); }

/* the marquee slashes, which were pure punctuation before */
.marquee i{ color:var(--accent); }

/* FAQ: the mark is red throughout; only the card edge reacts */
.faq-item.is-open{ border-color:var(--line-strong); }

/* projects: the category chip on hover, and the work count */
.work-count{ color:var(--accent); }

/* the one solid call to action, and text selection */
/* The brand red, as specified. White on it is 4.42:1 — fine for
   large text, a shade under the 4.5:1 wanted at button size, so
   the label runs at 600 to hold its weight. Swap in
   --accent-deep (6.17:1) if that margin ever matters. */
/* white on red is right on every ground, so these two are literals rather
   than tokens — an inverted section would otherwise darken the label */
.pill--accent{ background:var(--accent); color:#fff; font-weight:600; }
.pill--accent .pill-arrow{ background:#fff; color:var(--accent); }
.pill--accent:hover{ background:var(--ink); color:var(--paper); }
.pill--accent:hover .pill-arrow{ background:var(--paper); color:var(--ink); }

::selection{ background:var(--accent); color:var(--paper); }

/* On hover the arrow disc turns red across every pill variant.
   Placed after the variant rules so it wins without !important;
   the glyph is a stroked icon, not text, so white on #F00030
   sits well inside the 3:1 asked of non-text UI. */
.pill:hover .pill-arrow,
.pill--solid:hover .pill-arrow,
.pill--outline:hover .pill-arrow,
.pill--light:hover .pill-arrow,
.pill--accent:hover .pill-arrow,
.wk-btn:hover .pill-arrow{
  background:var(--accent);
  color:var(--paper);
}

/* ============================================================
   HOVER BLUE
   Everything that previously resolved to black on hover now
   lands on #1C2473. White on it measures 13.6:1, so the filled
   states are more legible than the black they replace. Applied
   here, after the originals, rather than editing each rule in
   place — one block to find, one block to change.
   ============================================================ */
.pill--solid:hover{ color:var(--hover); border-color:var(--hover); }
.pill--outline:hover{ background:var(--hover); }
.pill--light:hover{ color:var(--hover); }
.pill--accent:hover{ background:var(--hover); }

.wk-btn:hover{ background:var(--hover); }
.seo-arrow:hover{ background:var(--hover); border-color:var(--hover); }
.slider-nav:hover{ background:var(--hover); }
.quote-close:hover{ background:var(--hover); border-color:var(--hover); }
.chip:hover span{ border-color:var(--hover); }
.lb-close:hover{ color:var(--hover); }

/* ============================================================
   CLOSING CTA
   Full-bleed photograph, desaturated and darkened so the type
   carries. Two display lines — the second in the accent — then
   a short line of copy and two plain text links.
   ============================================================ */
.cta{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  background:var(--ink);
  color:var(--paper);
}
/* <picture> is the positioned box; the inner img does the covering */
.cta-bg{
  position:absolute;
  inset:0;
  z-index:-2;
  display:block;
}
.cta-bg img{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
  /* the page is monochrome apart from the red, so the photograph
     is drained to match */
  filter:grayscale(1) contrast(1.05);
}
.cta-veil{
  position:absolute;
  inset:0;
  z-index:-1;
  background:
    linear-gradient(to bottom, rgba(0,0,0,.82), rgba(0,0,0,.66) 45%, rgba(0,0,0,.88));
}

.cta-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(84px,11vw,190px) clamp(20px,4vw,60px);
  text-align:center;
  display:flex;
  flex-direction:column;
  align-items:center;
}

.cta-heading{
  margin:0;
  font-size:clamp(28px,3.9vw,64px);
  font-weight:500;
  line-height:1.06;
  letter-spacing:-.04em;
}
.cta-line{ display:block; }
.cta-line--accent{ color:var(--accent); }

.cta-sub{
  margin:clamp(18px,2vw,32px) 0 0;
  max-width:46ch;
  color:rgba(255,255,255,.78);
  font-size:clamp(14.5px,1.05vw,18px);
  line-height:1.6;
}

/* --- the two text links --- */
.cta-links{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:clamp(12px,1.2vw,18px);
  margin-top:clamp(28px,3.4vw,52px);
}

/* --- or: the team on the left, the words and the ways to get in touch on
   the right. Two halves, edge to edge like the slider at the top of the
   page: the photo fills its half to the very edges, and the words sit on
   the brand blue in the other */
.cta--split{ --ci-gap:#1C2473; background:#1C2473; }
.cta-split{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  align-items:stretch;
  min-height:clamp(360px,30vw,540px);
}
.cta-photo{
  position:relative;
  margin:0;
  overflow:hidden;
}
.cta-photo img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
}
.cta-panel{
  display:flex;
  flex-direction:column;
  justify-content:center;
  text-align:left;
  background:#1C2473;
  padding:clamp(32px,3.2vw,60px) clamp(22px,4.4vw,96px);
}
.cta-panel > *{ max-width:680px; }
.cta--split .cta-sub{ margin-top:clamp(12px,1.2vw,18px); color:rgba(255,255,255,.82); }
.cta--split .cta-contacts{ border-top-color:rgba(255,255,255,.22); }
/* small red type is hard to read on the blue: the labels go soft white */
.cta--split .cta-contact-label{ color:rgba(255,255,255,.66); }
.cta--split .cta-heading{ font-size:clamp(26px,2.4vw,42px); }
.cta--split .cta-line--accent{ color:var(--paper); }
.cta--split .cta-sub{ max-width:52ch; }
.cta--split .cta-links{ justify-content:flex-start; margin-top:clamp(20px,2vw,30px); }
.cta--split .cta-contacts{ margin-top:clamp(18px,1.8vw,28px); padding-top:clamp(16px,1.6vw,24px); gap:clamp(14px,1.4vw,20px) clamp(18px,2.4vw,36px); }

.cta-contacts{
  list-style:none;
  margin:clamp(26px,2.8vw,40px) 0 0;
  padding:clamp(22px,2.2vw,32px) 0 0;
  border-top:1px solid rgba(255,255,255,.18);
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(18px,2vw,28px) clamp(18px,2.4vw,36px);
}
.cta-contacts li{
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  column-gap:14px;
  align-items:start;
  align-content:start;   /* a taller neighbour must not pull the label and its line apart */
}
.cta-contacts .cnt-icon{
  grid-row:span 2;
  width:34px;
  height:34px;
  margin:0;
  color:var(--paper);
}
.cta-contact-label{
  font-family:var(--font-mono);
  font-size:11.5px;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--accent);
}
.cta-contacts a,
.cta-contacts address{
  margin-top:4px;
  color:var(--paper);
  font-style:normal;
  font-size:clamp(14px,1vw,16px);
  line-height:1.45;
  text-decoration:none;
  overflow-wrap:anywhere;
}
.cta-contacts a:hover{ color:var(--accent); }
/* a moment of its own for each mark, so the four never move together */
.cta-contacts li:nth-child(2) .cnt-icon *{ animation-delay:.9s; }
.cta-contacts li:nth-child(3) .cnt-icon *{ animation-delay:1.8s; }
.cta-contacts li:nth-child(4) .cnt-icon *{ animation-delay:2.7s; }

@media (max-width:900px){
  .cta-split{ grid-template-columns:minmax(0,1fr); }
  .cta-split{ min-height:0; }
  .cta-photo{ aspect-ratio:16 / 10; }
}
@media (max-width:520px){
  .cta-contacts{ grid-template-columns:minmax(0,1fr); }
}

/* ============================================================
   FOOTER
   Black ground. The wordmark is sized in vw so it spans the
   column at any width — cqw would be neater but vw matches the
   fixed side padding closely enough and needs no container.
   ============================================================ */
.site-footer{
  background:var(--ink);
  color:var(--paper);
}
.ft-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(52px,6vw,96px) clamp(18px,3.4vw,55px) clamp(28px,3vw,46px);
}

/* the divider above the closing row */
.ft-rule--plain{
  display:block;
  margin-top:clamp(32px,3.6vw,60px);
  border-top:1px solid rgba(255,255,255,.18);
}

/* --- the four columns --- */
.ft-top{
  display:grid;
  /* the services column is doubled up, so it takes more room */
  grid-template-columns:1.35fr .8fr 1.5fr .9fr;
  gap:clamp(28px,3vw,56px);
  margin-top:clamp(40px,4.6vw,78px);
}
.ft-label{
  display:block;
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--paper);
  margin-bottom:clamp(16px,1.6vw,24px);
}
.ft-label--spaced{ margin-top:clamp(28px,3vw,42px); }

.ft-actions{ display:flex; flex-wrap:wrap; gap:10px; }

.ft-address{
  font-style:normal;
  font-size:clamp(14px,1vw,16px);
  line-height:1.7;
  color:var(--paper);
}

.ft-list{ margin:0; padding:0; list-style:none; }
.ft-list li + li{ margin-top:clamp(8px,.8vw,13px); }
.ft-list a{
  color:var(--paper);
  text-decoration:none;
  font-size:clamp(14px,1.05vw,17px);
  transition:color .3s var(--ease);
}
.ft-list a:hover{ color:var(--accent); }

/* --- socials, brand marks at their real proportions --- */
.ft-socials{ margin:0; padding:0; list-style:none; }
.ft-socials li + li{ margin-top:clamp(10px,1vw,15px); }
.ft-socials a{
  display:inline-flex;
  align-items:center;
  gap:11px;
  color:var(--paper);
  text-decoration:none;
  font-size:clamp(14px,1.05vw,17px);
  transition:color .3s var(--ease);
}
.ft-socials svg{ width:18px; height:18px; flex:none; }
.ft-socials a:hover{ color:var(--accent); }

/* --- bottom row --- */
.ft-bottom{
  display:grid;
  grid-template-columns:1.1fr 1fr auto;
  align-items:stretch;
  gap:clamp(24px,3vw,56px);
  margin-top:clamp(26px,3vw,44px);
}
.ft-who{
  margin:0;
  max-width:34ch;
  font-size:clamp(16px,1.5vw,25px);
  font-weight:500;
  line-height:1.3;
  letter-spacing:-.02em;
}
/* red on the black footer is 3.7:1 — bold lifts it into the large-text
   threshold (3:1) rather than dulling the brand colour */
.ft-who em{ font-style:normal; font-weight:700; color:var(--accent); }

.ft-contact{ display:flex; flex-direction:column; gap:clamp(8px,.9vw,14px); }
.ft-mail,
.ft-phone{
  display:inline-flex;
  align-items:center;
  gap:clamp(10px,.9vw,14px);
  color:var(--paper);          /* the address reads as one colour */
  text-decoration:none;
  font-size:clamp(18px,1.9vw,32px);
  font-weight:500;
  letter-spacing:-.03em;
  transition:color .3s var(--ease);
}
/* the mark is sized off the type, so it tracks it at every width */
.ft-mail svg,
.ft-phone svg{
  width:.82em;
  height:.82em;
  flex:none;
  opacity:1;
  transition:opacity .3s var(--ease);
}
.ft-mail:hover svg,
.ft-phone:hover svg{ opacity:1; }
.ft-mail:hover,
.ft-phone:hover{ color:var(--accent); }

.ft-mark{ justify-self:end; }
.ft-mark img{ width:clamp(112px,9vw,150px); height:auto; display:block; }

.ft-legal{
  margin:clamp(26px,3vw,44px) 0 0;
  font-size:12.5px;
  color:var(--paper);
}

@media (max-width:1000px){
  .ft-top{ grid-template-columns:1fr 1fr; }
  .ft-bottom{ grid-template-columns:1fr; }
  .ft-mark{ justify-self:start; }
}
@media (max-width:560px){
  .ft-top{ grid-template-columns:1fr; }
  .ft-actions .pill{ width:100%; justify-content:space-between; }
}

/* --- nine services need a smaller setting than the four main
   links beside them, and they run in two sub-columns --- */
.menu-col--svc .menu-nav a{ font-size:clamp(16px,1.5vw,24px); line-height:1.35; }

/* the same split in the footer, where the type is already small */
.ft-split{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(14px,1.6vw,30px);
  align-items:stretch;
}
.ft-block--svc{ grid-column:span 1; }

/* --- touch targets ---------------------------------------------------
   The nine service links in the overlay and the eleven in the footer are
   set small and stacked tight, which leaves a 22px hit area -- under half a
   thumb. Padding opens the target without touching the type size; the
   li margin comes off so the visible rhythm barely moves. --- */
@media (max-width:820px){
  .menu-col--svc .menu-nav a{ display:block; padding-block:9px; }
  .ft-list a{ display:block; padding-block:7px; }
  .ft-list li + li{ margin-top:0; }

  /* the same for the contact and social lines, which run at 24px */
  .menu-line,
  .menu-socials a,
  .ft-mail, .ft-phone,
  .ft-socials a{ padding-block:8px; }
  .menu-line + .menu-line,
  .menu-socials li + li,
  .ft-socials li + li{ margin-top:0; }
}


/* ============================================================
   BREADCRUMB
   Sits under the page banner on inner pages.
   ============================================================ */
/* white through, with a hairline marking where the crumb ends */
.crumb{ background:var(--paper); }
.crumb-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  /* the banner above clears the fixed header now, so this is plain spacing */
  padding:clamp(11px,1.1vw,16px) clamp(18px,3.4vw,55px) 0;
}
/* one rule, not two: the pair that stood here set padding-bottom and then
   immediately reset it with the `padding` shorthand, so the rule below the
   trail was drawn tight against the type */
.crumb ol{
  margin:0;
  padding:0 0 clamp(9px,.95vw,14px);
  border-bottom:1px solid rgba(0,0,0,.08);
  list-style:none;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:8px;
  /* the breadcrumb reads as copy, not as a display label, so it takes the
     body face rather than the tracked display cut the other labels use */
  font-family:var(--font-sans);
  font-size:12px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--grey);
}
/* the separator is drawn, so it never lands in copied text */
.crumb li + li::before{
  content:"";
  display:inline-block;
  width:5px; height:5px;
  margin-right:8px;
  border-top:1px solid var(--grey-light);
  border-right:1px solid var(--grey-light);
  transform:rotate(45deg) translateY(-1px);
}
.crumb a{ color:var(--grey); text-decoration:none; transition:color .3s var(--ease); }
.crumb a:hover{ color:var(--accent); }
.crumb [aria-current]{ color:var(--ink); }

/* ============================================================
   WEB DESIGN SERVICES  (web-design.html)
   Reuses the homepage .svc-card, so the two pages stay in step;
   only the wrapper and the heading block are new.
   ============================================================ */
.wdsvc{ background:var(--band); color:var(--ink); }
.wdsvc-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(58px,6.4vw,110px) clamp(18px,3.4vw,55px);
}
.wdsvc-head{ margin-bottom:clamp(30px,3.4vw,56px); }
.wdsvc-lede{
  margin:clamp(14px,1.4vw,22px) 0 0;
  max-width:62ch;
  color:var(--grey);
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.6;
}

/* ============================================================
   ALTERNATING DETAIL BLOCKS  (web-design.html)
   Image one side, copy the other, flipping row by row. The
   order is set with grid placement rather than row-reverse, so
   the image always follows the copy in the source and screen
   readers get a consistent reading order.
   ============================================================ */
.duos{ background:var(--band); color:var(--ink); }
/* about page carries this block on white; the service pages keep the band,
   where it separates the section from the white work grid above it */
.duos--light{ background:var(--paper); }
.duos-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(56px,6.2vw,104px) clamp(18px,3.4vw,55px);
  display:flex;
  flex-direction:column;
  gap:clamp(48px,6vw,104px);
}

.duo{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(28px,4vw,80px);
  align-items:center;
}
/* row is pinned as well as column: without it, placing the copy
   in column 1 after the image has taken column 2 makes grid
   auto-placement drop it to a second row */
.duo-shot{ margin:0; grid-column:1; grid-row:1; }
.duo-copy{ grid-column:2; grid-row:1; }
.duo--flip .duo-shot{ grid-column:2; grid-row:1; }
.duo--flip .duo-copy{ grid-column:1; grid-row:1; }

.duo-shot img{
  display:block;
  width:100%;
  height:auto;               /* or the height attribute pins the box */
  aspect-ratio:4 / 3;
  object-fit:cover;
  border-radius:0;  /* was clamp(14px,1.3vw,22px) */
}

.duo-copy p{
  margin:clamp(16px,1.6vw,26px) 0 0;
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.65;
  color:var(--grey);
}
.duo-copy strong{ color:var(--ink); font-weight:600; }

/* --- the marked list --- */
.duo-list{
  margin:clamp(18px,1.8vw,28px) 0 0;
  padding:0;
  list-style:none;
}
.duo-list li{
  position:relative;
  /* the gutter is set with the marker, below */
  margin-top:clamp(9px,.9vw,14px);
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.55;
  color:var(--grey);
}

/* --- the pull quote --- */
.duo-quote{
  margin:clamp(22px,2.2vw,34px) 0 0;
  padding-left:clamp(16px,1.4vw,22px);
  border-left:2px solid var(--accent);
}
.duo-quote p{
  margin:0;
  font-style:italic;
  font-size:clamp(14.5px,1.1vw,18px);
  line-height:1.5;
  color:var(--ink);
}

@media (max-width:860px){
  /* stacked: image first in both directions */
  .duo{ grid-template-columns:1fr; gap:clamp(20px,4vw,30px); }
  .duo-shot,
  .duo--flip .duo-shot{ grid-column:1; grid-row:1; }
  .duo-copy,
  .duo--flip .duo-copy{ grid-column:1; grid-row:2; }
}
/* ============================================================
   WORDPRESS PROCESS  (web-design.html)
   A centred spine with the six stages alternating either side:
   card on one flank, its ghost number facing it across the line,
   and a ringed dot marking the stage on the spine itself.
   Below 820px the spine moves to the left edge and every card
   lines up to the right of it.
   ============================================================ */
.steps{ background:var(--band); color:var(--ink); }
.steps-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(58px,6.4vw,110px) clamp(18px,3.4vw,55px);
}
/* the timeline is a centred composition, so the heading is centred over it
   rather than flush left like the rest of the page */
.steps-head{
  margin:0 auto clamp(40px,4.6vw,74px);
  text-align:center;
}
.steps-heading{ margin-inline:auto; }
.steps-heading::after{ left:50%; transform:translateX(-50%); }
.steps-lede{ margin-inline:auto; }

.steps-line{
  --spine: 3px;            /* the line itself */
  --dot:   22px;           /* the marker on the spine */
  --gap:   clamp(26px,3.2vw,58px);   /* card / number to the spine */
  position:relative;
  max-width:1120px;
  margin:0 auto;
  padding:0;
  list-style:none;
  display:grid;
  gap:clamp(20px,2.4vw,40px);
}
/* The spine is two lines stacked: a static track, and a red fill whose height
   is driven by --p (0 to 1) written on the list by main.js as the block
   scrolls. Height is animated rather than transform so the fill grows from
   the top edge without needing a transform-origin.  */
.steps-line::before,
.steps-line::after{
  content:"";
  position:absolute;
  top:0;
  left:50%;
  transform:translateX(-50%);
  width:var(--spine);
}
.steps-line::before{
  bottom:0;
  background:var(--line-strong);
}
.steps-line::after{
  height:calc(var(--p,0) * 100%);
  background:var(--accent);
  transition:height .18s linear;   /* smooths the per-frame steps */
}

/* only the fill colour changes now that the dot is a solid disc */
.step::before{ transition:background-color .35s var(--ease); }

.step{
  position:relative;
  display:grid;
  grid-template-columns:1fr 1fr;
  align-items:center;
  column-gap:calc(var(--gap) * 2);
}

/* One solid disc, no ring. The band-coloured outer shadow is the only extra:
   it punches a clean gap through the track running behind the dot. */
.step::before{
  content:"";
  position:absolute;
  left:50%; top:50%;
  transform:translate(-50%,-50%);
  z-index:2;
  width:var(--dot); height:var(--dot);
  border-radius:0;  /* was 50% */
  /* solid, not the translucent rule colour it used to share with the track:
     rgba(0,0,0,.28) read as a washed-out square rather than a marker */
  background:var(--ink);
  box-shadow:0 0 0 5px var(--band);
}
/* the fill has reached this stage */
.step.is-on::before{ background:var(--accent); }

.step-card{
  position:relative;
  padding:clamp(18px,1.8vw,28px) clamp(20px,2vw,30px);
  background:var(--paper);
  border-radius:0;  /* was 14px */
}
/* the little tail pointing back at the spine */
.step-card::after{
  content:"";
  position:absolute;
  top:50%;
  width:14px; height:14px;
  background:var(--paper);
}

.step-num{
  font-size:clamp(38px,4.4vw,64px);
  font-weight:600;
  line-height:1;
  letter-spacing:-.04em;
  font-variant-numeric:tabular-nums;
  color:var(--line-strong);   /* a ghost figure, not a label */
}

.step-label{
  margin:0 0 6px;
  font-size:clamp(15px,1.2vw,19px);
  font-weight:600;
  letter-spacing:-.02em;
  color:var(--ink);
}
.step-text{
  margin:0;
  font-size:clamp(13.5px,.98vw,15.5px);
  line-height:1.6;
  color:var(--grey);
}

/* --- odd stages: card right, number left --- */
/* both children are pinned to row 1. Grid auto-placement only moves
   forward, so putting the even card in column 1 after its number has taken
   column 2 would drop the card to a second row — which is what left 02
   floating above its own dot. */
.step:nth-child(odd) .step-num{ grid-column:1; grid-row:1; text-align:right; }
.step:nth-child(odd) .step-card{ grid-column:2; grid-row:1; }
.step:nth-child(odd) .step-card::after{
  left:-8px;
  border-right:0; border-top:0;
  transform:translateY(-50%) rotate(45deg);
}

/* --- even stages: card left, number right --- */
.step:nth-child(even) .step-num{ grid-column:2; grid-row:1; text-align:left; }
.step:nth-child(even) .step-card{
  grid-column:1;
  grid-row:1;
  text-align:right;
}
.step:nth-child(even) .step-card::after{
  right:-8px;
  border-left:0; border-bottom:0;
  transform:translateY(-50%) rotate(45deg);
}

@media (max-width:820px){
  /* spine to the left, every card to the right of it, numbers inline */
  .steps-line{ --gap:22px; }
  /* both layers, not just the track — the fill would otherwise stay centred
     while the grey line moved left */
  .steps-line::before,
  .steps-line::after{ left:8px; }
  .step{ grid-template-columns:1fr; column-gap:0; padding-left:44px; }
  .step::before{ left:8px; transform:translate(-50%,-50%); }
  .step:nth-child(odd) .step-num,
  .step:nth-child(even) .step-num{
    grid-column:1;
    text-align:left;
    font-size:clamp(26px,7vw,36px);
    margin-bottom:6px;
  }
  .step:nth-child(odd) .step-card,
  .step:nth-child(even) .step-card{ grid-column:1; text-align:left; }
  .step:nth-child(odd) .step-card::after{ left:-8px; }
  .step:nth-child(even) .step-card::after{
    right:auto; left:-8px;
    border:1px solid var(--line);
    border-right:0; border-top:0;
  }
}


/* ==========================================================================
   SERVICE TABS  (web-design.html)
   A dark break between the light .duos band and the white .steps section.
   Vertical button rail on the left, one panel visible on the right.
   Every panel ships in the HTML so the copy is crawlable.
   ========================================================================== */
.wtab{
  background:var(--ink);
  color:var(--paper);

}
.wtab-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(58px,6.4vw,110px) clamp(18px,3.4vw,55px);
}

.wtab-head{ margin-bottom:clamp(30px,3.6vw,56px); }
.wtab-heading{
  position:relative;
  width:fit-content; max-width:100%;
  margin:0;
  padding-bottom:.55em;
  font-size:clamp(26px,2.6vw,44px);
  font-weight:500;
  line-height:1.1;
  letter-spacing:-.035em;
  color:var(--paper);
}
.wtab-heading span{ color:rgba(255,255,255,.55); }
.wtab-heading::after{
  content:"";
  position:absolute; left:0; bottom:0;
  width:clamp(34px,3vw,52px); height:3px;
  background:var(--accent);
}

.wtab-body{
  display:grid;
  grid-template-columns:minmax(230px,300px) minmax(0,1fr);
  gap:clamp(28px,3.4vw,64px);
  align-items:stretch;
}

/* --- the rail --- */
.wtab-rail{ display:flex; flex-direction:column; gap:6px; }

.wtab-btn{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  width:100%;
  padding:clamp(13px,1.15vw,17px) clamp(15px,1.3vw,20px);
  border:1px solid transparent;
  border-radius:0;  /* was 12px */
  background:rgba(255,255,255,.04);
  color:rgba(255,255,255,.72);   /* on the black .wtab panel: --grey-light is #000 */
  font:inherit;
  font-size:clamp(13.5px,1vw,15.5px);
  font-weight:500;
  letter-spacing:-.01em;
  text-align:left;
  cursor:pointer;
  /* the reveal's opacity/transform are repeated here for the same reason as
     .faq-item: a second `transition` shorthand would drop them entirely */
  transition:background .3s var(--ease-soft), color .3s var(--ease-soft),
             border-color .3s var(--ease-soft),
             opacity .9s var(--ease-soft), transform .9s var(--ease-soft);
}
.wtab-btn:hover{ background:rgba(255,255,255,.09); color:var(--paper); }
.wtab-btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

.wtab-btn.is-active{
  background:var(--paper);
  border-color:var(--paper);
  color:var(--ink);
  font-weight:600;
}

/* the trailing dash: a short rule that grows into an arrow-length line
   when its tab is the live one */
.wtab-btn-d{
  flex:none;
  width:14px; height:2px;
  border-radius:0;  /* was 2px */
  background:currentColor;
  opacity:.35;
  transition:width .4s var(--ease-soft), opacity .4s var(--ease-soft),
             background-color .3s var(--ease-soft);
}
.wtab-btn.is-active .wtab-btn-d{ width:26px; opacity:1; background:var(--accent); }

/* --- the stage --- */
.wtab-stage{ position:relative; }
.wtab-panel[hidden]{ display:none; }

.wtab-panel{
  display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1fr);
  gap:clamp(22px,2.6vw,48px);
  align-items:stretch;
  height:100%;
}
.wtab-copy{ align-self:center; }
/* fresh panels ease in rather than snapping */
.wtab-panel.is-entering{ animation:wtab-in .5s var(--ease-soft) both; }
@keyframes wtab-in{
  from{ opacity:0; transform:translateY(14px); }
  to  { opacity:1; transform:none; }
}

/* the shot fills the row, whose height comes from the tab rail beside it.
   absolute positioning is what makes height:100% resolve here — an img left
   in flow falls back to its intrinsic ratio instead */
/* A 4:3 frame that stays 4:3: it used to stretch down to fill the row beside
   it, which turned a landscape screenshot into a tall crop with its sides cut
   off. Now the frame keeps the shape the pictures are exported at — 800x600 —
   and sits at the top of the column when the words beside it run longer. */
.wtab-shot{
  position:relative;
  margin:0;
  width:100%;
  align-self:start;
  aspect-ratio:4/3;
  overflow:hidden;
  border-radius:0;  /* was 14px */
  background:rgba(255,255,255,.06);
}
.wtab-shot img{
  position:absolute;
  inset:0;
  display:block;
  width:100%; height:100%;
  /* the whole picture, not a crop of it: an 800x600 upload fills this frame
     exactly, and anything else is fitted inside rather than trimmed */
  object-fit:contain;
  object-position:center;
}

.wtab-title{
  margin:0 0 clamp(10px,1vw,16px);
  font-size:clamp(20px,1.75vw,29px);
  font-weight:500;
  line-height:1.15;
  letter-spacing:-.03em;
  color:var(--paper);
}
.wtab-text{
  margin:0 0 clamp(14px,1.4vw,22px);
  font-size:clamp(13.5px,.98vw,15.5px);
  line-height:1.65;
  color:rgba(255,255,255,.74);   /* on the black .wtab panel: --grey-light is #000 */
}
.wtab-list{
  margin:0 0 clamp(18px,1.9vw,28px);
  padding:0;
  list-style:none;
  display:grid;
  gap:9px;
}
.wtab-list li{
  position:relative;
  /* the gutter is set with the marker, below */
  font-size:clamp(13px,.94vw,15px);
  line-height:1.5;
  color:var(--paper);
}

/* the outline pill has to invert against the dark ground */
.wtab-cta{ align-self:start; }

@media (max-width:980px){
  .wtab-body{ grid-template-columns:1fr; }
  /* the rail turns into a horizontal, scrollable strip of buttons */
  .wtab-rail{
    flex-direction:row;
    flex-wrap:nowrap;
    overflow-x:auto;
    padding-bottom:4px;
    scrollbar-width:none;
  }
  .wtab-rail::-webkit-scrollbar{ display:none; }
  .wtab-btn{ width:auto; flex:none; }
  .wtab-btn-d{ display:none; }
}
@media (max-width:720px){
  .wtab-panel{ grid-template-columns:1fr; }
}

/* ==========================================================================
   WHY BROWSER  (web-design.html)
   Oversized statement heading over a staggered three-tile collage, with the
   supporting copy set to the right. Sits on the band so it does not run into
   the white .steps section below it.
   ========================================================================== */
.why{ background:var(--band); color:var(--ink); }
.why-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(58px,6.4vw,110px) clamp(18px,3.4vw,55px);
}

.why-kicker{
  display:flex;
  align-items:center;
  gap:11px;
  margin:0 0 clamp(16px,1.8vw,28px);
  font-size:clamp(12.5px,.9vw,14.5px);
  color:var(--grey);
}
.why-kicker i{
  flex:none;
  width:10px; height:10px;
  border-radius:0;  /* was 50% */
  background:var(--accent);
}

/* the statement line: larger than the standard section heading, and with no
   red rule under it — the dot in the kicker carries the accent instead */
.why-heading{
  max-width:22ch;
  margin:0;
  font-size:clamp(27px,3vw,46px);
  font-weight:500;
  line-height:1.06;
  letter-spacing:-.04em;
}

.why-body{
  display:grid;
  grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  gap:clamp(28px,4vw,80px);
  align-items:center;
  margin-top:clamp(36px,4.4vw,76px);
}

/* --- the collage --- */
.why-art{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(14px,1.6vw,26px);
}
.why-tile{
  position:relative;
  margin:0;
  overflow:hidden;
  border-radius:0;  /* was clamp(12px,1.2vw,20px) */
  background:#e2e2e2;
}
.why-tile img{
  display:block;
  width:100%; height:100%;
  object-fit:cover;
}

/* placed explicitly — auto-placement would drop the third tile into the
   empty cell under the first one instead of stacking it in column two.
   The left tile spans both rows and centres against that stack, which is
   what gives the group its scattered look. */
.why-tile--a{ grid-column:1; grid-row:1 / span 2; align-self:center; aspect-ratio:1/1; }
.why-tile--b{ grid-column:2; grid-row:1; aspect-ratio:1/1.02; }
.why-tile--c{ grid-column:2; grid-row:2; aspect-ratio:1/1.08; }

/* the black card, carrying the wordmark rather than a photograph */
.why-tile--b{
  display:grid;
  place-items:center;
  background:var(--ink);
}
.why-mark{
  font-size:clamp(20px,2.2vw,38px);
  font-weight:600;
  letter-spacing:-.04em;
  color:var(--paper);
}
.why-mark i{ font-style:normal; color:var(--accent); }

/* --- the copy --- */
.why-copy p{
  margin:0 0 clamp(14px,1.4vw,22px);
  font-size:clamp(14px,1.02vw,16.5px);
  line-height:1.75;
  color:var(--grey);
}
.why-copy p:last-child{ margin-bottom:0; }

@media (max-width:900px){
  .why-body{ grid-template-columns:1fr; gap:clamp(28px,4vw,44px); }
  .why-heading{ max-width:none; }
}

/* ==========================================================================
   INDUSTRIES  (web-design.html)
   Three full-bleed rows of pills drifting in alternating directions, faded
   out at both edges. Each row carries its pills twice so the track can loop;
   the duplicate is aria-hidden. With reduced motion the rows stop and wrap
   into a centred cloud instead.
   ========================================================================== */
.ind{
  background:var(--band);
  color:var(--ink);
  overflow:hidden;   /* the rows run wider than the page on purpose */
}
.ind-inner{
  /* no cap here: the rows run edge to edge, the head sets its own width */
  max-width:none;
  margin:0 auto;
  padding:var(--sec-pad) 0;
}
.ind-head{
  max-width:var(--work-cap);
  margin:0 auto clamp(34px,4vw,64px);
  padding:0 clamp(18px,3.4vw,55px);
}
.ind-heading{
  position:relative;
  width:fit-content; max-width:100%;
  margin:0;
  padding-bottom:.55em;
  font-size:clamp(26px,2.6vw,44px);
  font-weight:500;
  line-height:1.1;
  letter-spacing:-.035em;
}
.ind-heading::after{
  content:"";
  position:absolute; left:0; bottom:0;
  width:clamp(34px,3vw,52px); height:3px;
  background:var(--accent);
}
.ind-lede{
  max-width:62ch;
  margin:clamp(14px,1.4vw,22px) 0 0;
  font-size:clamp(14px,1.02vw,16.5px);
  line-height:1.7;
  color:var(--grey);
}

.ind-rows{
  display:flex;
  flex-direction:column;
  gap:clamp(10px,1.1vw,16px);
  /* the rows bleed past the page edges and fade out rather than being cut */
  -webkit-mask-image:linear-gradient(to right,transparent,#000 7%,#000 93%,transparent);
          mask-image:linear-gradient(to right,transparent,#000 7%,#000 93%,transparent);
}

.ind-row{ overflow:hidden; }
.ind-track{
  display:flex;
  width:max-content;
  animation:ind-drift 46s linear infinite;
}
.ind-row--rev .ind-track{ animation-direction:reverse; }
.ind-rows:hover .ind-track{ animation-play-state:paused; }

/* each copy sits exactly one set-plus-gap along, so shifting the track by a
   third of its width lands the next copy where the first one started. Three
   copies rather than two: with only two, the far side of the row runs dry on
   any viewport wider than a single set. */
@keyframes ind-drift{
  from{ transform:translate3d(0,0,0); }
  to  { transform:translate3d(-33.3333%,0,0); }
}

.ind-set{
  display:flex;
  gap:clamp(10px,1.1vw,16px);
  margin:0 clamp(10px,1.1vw,16px) 0 0;
  padding:0;
  list-style:none;
}

.ind-pill{
  display:flex;
  align-items:center;
  gap:9px;
  flex:none;
  padding:clamp(11px,1vw,15px) clamp(18px,1.6vw,26px);
  border:1px solid var(--line);
  border-radius:0;  /* was 999px */
  background:var(--paper);
  color:var(--ink);
  font-size:clamp(13.5px,1vw,16px);
  font-weight:500;
  letter-spacing:-.015em;
  white-space:nowrap;
}
.ind-pill i{
  flex:none;
  width:7px; height:7px;
  border-radius:0;  /* was 50% */
  background:var(--accent);
}

/* two filled variants break the row up without reaching for a second palette */
.ind-pill--dark{
  border-color:var(--ink);
  background:var(--ink);
  color:var(--paper);
}
.ind-pill--dark i{ background:var(--accent); }

.ind-pill--accent{
  border-color:var(--accent-deep);
  background:var(--accent-deep);   /* white on brand red is 4.42:1 */
  color:var(--paper);
}
.ind-pill--accent i{ background:var(--paper); }

/* ---- gentle vertical float ------------------------------------------------
   Each pill rises and falls on its own timing, so the row undulates rather
   than heaving as one block. The stagger is keyed to a pill's position
   *within its set*, not to a global index: all three copies of a set then
   move identically, so the marquee's wrap point stays seamless. Negative
   delays start every pill part-way through its cycle, so the motion is
   already underway on load instead of arriving as a wave from the left.
   The float rides on .ind-pill while the drift rides on .ind-track, so the
   two transforms compose instead of overwriting one another. */
.ind-rows{
  --ind-amp:clamp(4px,.45vw,7px);
  /* the float's headroom, plus slack so a pill's rounded edge never lands
     exactly on a clip boundary and gets shaved by antialiasing */
  --ind-head:calc(var(--ind-amp) + 2px);

  /* The headroom has to live INSIDE this box. .ind-rows carries both the
     edge-fade mask (mask-clip is border-box) and the reveal system's
     clip-path: inset(0 0 -20% 0), so anything painted outside its border box
     is cut twice over — an earlier attempt gave each row padding and pulled
     it back with a negative margin, which put the top and bottom rows'
     headroom outside this box and sliced the pills by the full amplitude.
     So the container holds the padding and does the horizontal clipping,
     and the rows stop clipping their own overflow. */
  overflow:hidden;
  padding-block:var(--ind-head);
}
/* the container clips now; a row that clipped itself would cut the float off
   at its own edge, where there is no headroom to spare */
.ind-row{ overflow:visible; }

@keyframes ind-float{
  from{ transform:translate3d(0,calc(var(--ind-amp) * -1),0); }
  to  { transform:translate3d(0,var(--ind-amp),0); }
}

.ind-pill{ animation:ind-float 5.6s ease-in-out infinite alternate; }

/* irregular periods, so the six never fall back into step with each other */
.ind-set .ind-pill:nth-child(1){ animation-duration:5.6s; animation-delay:-0.2s; }
.ind-set .ind-pill:nth-child(2){ animation-duration:6.4s; animation-delay:-1.1s; }
.ind-set .ind-pill:nth-child(3){ animation-duration:5.0s; animation-delay:-2.3s; }
.ind-set .ind-pill:nth-child(4){ animation-duration:6.9s; animation-delay:-0.7s; }
.ind-set .ind-pill:nth-child(5){ animation-duration:5.9s; animation-delay:-1.8s; }
.ind-set .ind-pill:nth-child(6){ animation-duration:6.2s; animation-delay:-3.1s; }

/* hovering already parks the drift; park the bob with it, so a row the
   reader is trying to read holds still completely */
.ind-rows:hover .ind-pill{ animation-play-state:paused; }

@media (max-width:560px){
  /* tighter pills so the wrapped cloud does not become one name per line */
  .ind-pill{ gap:7px; padding:9px 14px; font-size:12.5px; }
  .ind-pill i{ width:6px; height:6px; }
}

@media (prefers-reduced-motion:reduce){
  /* No drift. display:contents dissolves the row/track/set wrappers so all
     eighteen pills become direct children of one wrapping flex container and
     settle into a centred cloud; the duplicate sets would only repeat
     themselves, so they come out. */
  .ind-rows{
    display:flex;
    flex-direction:row;   /* the base rule stacks the rows; here they merge */
    flex-wrap:wrap;
    justify-content:center;
    max-width:var(--work-cap);
    margin-inline:auto;
    padding:0 clamp(18px,3.4vw,55px);
    -webkit-mask-image:none;
            mask-image:none;
  }
  .ind-row,
  .ind-track,
  .ind-set{ display:contents; }
  .ind-set[aria-hidden]{ display:none; }
  .ind-track,
  .ind-pill{ animation:none; }
}

/* the web design page runs its FAQs on white, since the industries band sits
   directly above them; the hairline alone is too faint to separate white
   cards from a white ground, so the border is stepped up */
.faq--paper{ background:var(--paper); }
.faq--paper .faq-item{ border-color:var(--line-strong); }

/* ==========================================================================
   DARK SECTION MODIFIER
   A long page needs chapters. Adding .inv to a <section> flips it to the dark
   palette by re-pointing the token layer rather than restyling anything:
   every component already reads --ink / --paper / --grey / --line, so cards,
   hairlines, headings, borders and pills invert on their own. Moving the
   rhythm around is then one class, not a new block of CSS.

   The section ground is a literal so that --paper stays free to mean "a
   surface sitting on top of the ground" — which is what cards, chips and
   frames use it for.

   .wtab is not built this way on purpose: its rail and panel are a bespoke
   dark design rather than an inverted light one.
   ========================================================================== */
.inv{
  --ink:        #ffffff;
  /* neutral greys, not the warm ones this block started with — those were
     mixed to sit on #221F1F and read brown against a true black ground */
  --paper:      #141414;   /* card / chip surface, lifted off the ground */
  --paper-2:    #1c1c1c;
  --paper-3:    #242424;
  --band:       #1c1c1c;
  /* on black the copy is white, full stop - no grey tier here */
  --grey:       #ffffff;   /* was #a1a1a1 */
  --grey-light: #ffffff;   /* was #9a9a9a */
  --line:       rgba(255,255,255,.14);
  --line-strong:rgba(255,255,255,.30);
  /* the brand red on black measures 4.5:1 - large type and marks only,
     which is all it is used for here */
  --accent-deep:#F00030;   /* was the #ff5a70 tint */

  background:#000000;
  color:var(--ink);
}

/* shadows tuned for light grounds read as smudges on dark */
.inv .step,
.inv .svc-card,
.inv .wk-frame{ box-shadow:none; }
/* ==========================================================================
   LIST ARROW
   One marker for every bulleted list on the page. Sized in em so it tracks
   its own list's type scale, and painted with a mask so var(--accent) still
   drives the colour on light and dark grounds alike.
   ========================================================================== */
.duo-list li::before,
.wtab-list li::before{
  content:"";
  position:absolute;
  left:0;
  top:.34em;
  width:1em; height:1em;
  background:var(--accent);
  -webkit-mask:var(--arrow) no-repeat center / contain;
          mask:var(--arrow) no-repeat center / contain;
}

/* the gutter tracks the marker: 1em of arrow plus a fixed 12px of air, so
   both lists stay identical however their type scales */
.duo-list li,
.wtab-list li{ padding-left:calc(1em + 12px); }

/* ==========================================================================
   PAGE BANNER  (web-design.html)
   The homepage hero's split — ink copy panel left, artwork right — at about
   half the height. Static: no slider, so none of the hero's copy-swapping
   machinery comes with it, and the panel is styled here rather than shared
   because .hero-copy is wired to the slider's in/out classes.
   ========================================================================== */
/* first block in main now, so it carries the fixed header offset the
   breadcrumb used to hold */
.ibn{ padding-top:calc(var(--header-h) + var(--header-gap)); }
.ibn-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  /* a fixed band, not a viewport height, so the section below always
     starts in the same place */
  min-height:clamp(300px,34vw,470px);
}

.ibn-copy{
  background:var(--ink);
  color:var(--paper);
  padding:clamp(34px,4vw,66px) clamp(22px,4vw,72px);
  display:flex;
  flex-direction:column;
  justify-content:center;
}
/* smaller than the homepage h1 — this is an inner page, not the front door */
.ibn-copy h1{
  margin:0;
  font-size:clamp(32px,4.1vw,60px);   /* the largest type on the page */
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.035em;
}
.ibn-text{
  margin:clamp(14px,1.4vw,22px) 0 0;
  max-width:46ch;
  font-size:clamp(14px,1.02vw,17px);
  line-height:1.6;
  color:rgba(255,255,255,.74);   /* never var(--grey-light): it is #000 on this black panel */
}
.ibn-actions{ margin-top:clamp(20px,2.2vw,34px); }

.ibn-visual{
  position:relative;
  margin:0;
  overflow:hidden;
  background:var(--paper-3);
}
.ibn-visual img{
  position:absolute;
  inset:0;
  width:100%; height:100%;
  object-fit:cover;
  /* a website screenshot: hold its own header in frame */
  object-position:top center;
}

/* --- or, instead of the picture: a few points with drawn marks on blue.
   The same blue and the same fine outlines as the service cards further
   down, so the page opens in the language it carries on in. Two by two,
   with no lines between them; each mark stands on its own, no ring, and draws itself in
   as the page opens, one after another. */
.ibn-points{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  display:flex;
  align-items:center;
  padding:clamp(22px,2.6vw,48px) clamp(18px,3.2vw,60px);
  background:#1C2473;
  color:#fff;
}
/* a soft light from the top corner, so the blue has some depth to it */
.ibn-points::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  background:radial-gradient(120% 90% at 100% 0%, rgba(255,255,255,.11), transparent 58%);
}
.ibn-point-list{
  list-style:none;
  margin:0;
  padding:0;
  width:100%;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
}
.ibn-point{
  display:flex;
  align-items:center;
  gap:clamp(14px,1.3vw,26px);
  padding:clamp(20px,2vw,34px) clamp(12px,1.4vw,30px);
  animation:ibn-rise .9s var(--ease-soft) both;
  animation-delay:calc(.15s + var(--i,0) * .12s);
}

.ibn-point-mark{
  flex:none;
  display:block;
  width:clamp(34px,2.6vw,50px);
  aspect-ratio:1;
}
.ibn-point-mark svg{
  display:block;
  width:100%;
  height:auto;
  stroke-width:var(--sw, 1);   /* the script sets this so the line lands at 1.5px on screen */
}
/* drawn in, not faded in: the same 1-in-2 dash trick as the card marks,
   so an undrawn mark leaves no stray dots behind */
.ibn-point-mark svg *{
  stroke-dasharray:1.1 2;   /* a touch over the line, so circles close fully */
  animation:ibn-draw 1s var(--ease-soft) both;
  animation-delay:calc(.35s + var(--i,0) * .15s);
}

/* one big faint copy of the page's own mark behind the points, tilted and
   running off the corner — the same move as on the service cards below */
.ibn-ghost{
  position:absolute;
  z-index:-1;
  right:-8%;
  top:6%;
  height:118%;               /* by the panel's height, so it sits the same on any width */
  aspect-ratio:1;
  opacity:.18;
  color:#fff;
  transform:rotate(-9deg);
  transition:transform 1.1s var(--ease-soft), opacity 1.1s var(--ease-soft);
  pointer-events:none;
}
.ibn-ghost svg{
  display:block;
  width:100%;
  height:auto;
  stroke-width:var(--sw, .06);
}
.ibn-points:hover .ibn-ghost{ transform:rotate(-3deg) scale(1.04); opacity:.26; }

.ibn-point-copy{ min-width:0; }
.ibn-point-title{
  display:block;
  font-family:var(--font-display);
  font-size:clamp(15px,1.08vw,20px);
  font-weight:500;
  line-height:1.25;
  letter-spacing:-.01em;
}
.ibn-point-text{
  display:block;
  margin-top:6px;
  font-size:clamp(13px,1vw,17px);
  line-height:1.5;
  color:#fff;
}

@keyframes ibn-draw{ from{ stroke-dashoffset:1.12; } to{ stroke-dashoffset:0; } }
@keyframes ibn-rise{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }

@media (prefers-reduced-motion:reduce){
  .ibn-point,
  .ibn-point-mark svg *{ animation:none; }
  .ibn-ghost{ transition:none; }
  .ibn-points:hover .ibn-ghost{ transform:rotate(-9deg); opacity:.18; }
}

@media (max-width:820px){
  /* the picture leads on a phone, the same way the homepage hero reorders */
  .ibn-grid{ grid-template-columns:1fr; min-height:0; }
  .ibn-visual{ height:min(58vw,300px); order:-1; }
  .ibn-copy{ padding:clamp(30px,7vw,44px) clamp(20px,6vw,32px); }
  /* the points follow the words instead: they are reading, not a picture.
     Still two by two, but each one stacked, mark above words */
  .ibn-points{ padding:8px clamp(10px,3vw,24px); }
  .ibn-point{ flex-direction:column; align-items:flex-start; gap:12px; padding:22px clamp(10px,3vw,20px); }
  .ibn-point-mark{ width:34px; }
  .ibn-ghost{ height:112%; right:-24%; top:10%; }
}

/* ==========================================================================
   HOW WE DESIGN WEBSITES  (web-design.html)
   A black band carrying the statement, then a full-bleed split: artwork left,
   a white panel right. The panel is pulled up by exactly the band's bottom
   padding, so the white starts higher than the picture and the black steps
   down between them — the stagger the reference gets the same way.

   The reference toggles each item open and shut; these are set open, so there
   is no disclosure here at all — just headings and copy.
   ========================================================================== */
.cmc{
  --cmc-step: clamp(38px,5vw,92px);   /* how far the white panel rises */
  background:var(--accent);
  color:var(--paper);
}

.cmc-head{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(52px,6vw,104px) clamp(18px,3.4vw,55px) var(--cmc-step);
}
.cmc-heading{
  max-width:18ch;
  margin:0;
  font-size:clamp(28px,3.4vw,50px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.035em;
  color:var(--paper);
}

/* full-bleed on purpose: the artwork runs to the left edge and the panel to
   the right, the way the reference splits the band */
.cmc-body{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  align-items:stretch;
}

.cmc-shot{
  position:relative;
  margin:0;
  overflow:hidden;
  min-height:clamp(280px,32vw,520px);
  background:var(--paper-3);
}
.cmc-shot img{
  position:absolute;
  inset:0;
  width:100%; height:100%;
  object-fit:cover;
}

.cmc-copy{
  /* rises into the black band by the same amount the head padded below */
  margin-top:calc(var(--cmc-step) * -1);
  padding:clamp(30px,3.4vw,60px) clamp(22px,3.6vw,72px) clamp(38px,4.4vw,80px);
  background:var(--paper);
  color:var(--ink);
}
.cmc-lede{
  margin:0 0 clamp(24px,2.6vw,42px);
  max-width:26ch;
  font-family:var(--font-display);
  font-size:clamp(20px,1.9vw,31px);
  font-weight:500;
  line-height:1.2;
  letter-spacing:-.03em;
  color:var(--ink);
}

.cmc-list{
  display:grid;
  gap:clamp(20px,2.2vw,34px);
}
.cmc-item{ position:relative; padding-left:calc(1em + 14px); }
/* the same red arrow the lists use, so the marker vocabulary stays one thing */
.cmc-item-title::before{
  content:"";
  position:absolute;
  left:0; top:.34em;
  width:1em; height:1em;
  background:var(--accent);
  -webkit-mask:var(--arrow) no-repeat center / contain;
          mask:var(--arrow) no-repeat center / contain;
}
.cmc-item-title{
  margin:0 0 8px;
  font-size:clamp(15px,1.15vw,18px);
  font-weight:600;
  letter-spacing:-.01em;
  color:var(--ink);
}
.cmc-item p{
  margin:0;
  font-size:clamp(13.5px,.98vw,15.5px);
  line-height:1.65;
  color:var(--grey);
}

@media (max-width:900px){
  /* stacked: the picture leads, then the panel — and with nothing beside it
     the panel has no black left to rise into */
  .cmc-body{ grid-template-columns:1fr; }
  .cmc-copy{ margin-top:0; }
  .cmc-shot{ min-height:min(62vw,340px); }
  .cmc-head{ padding-bottom:clamp(26px,4vw,48px); }
  .cmc-heading{ max-width:none; }
}



/* ============================================================
   START A PROJECT — image left, form right (web-design page)
   Reuses the .quote-form / .qf-* / .chip components from the
   quote lightbox, which are all unscoped, so only the two-column
   shell is new here.
   ============================================================ */
.wdq{ background:var(--band); color:var(--ink); }
.wdq-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(56px,6.2vw,104px) clamp(18px,3.4vw,55px);
  display:grid;
  grid-template-columns:0.9fr 1fr;   /* the form needs the wider half */
  gap:clamp(28px,4vw,72px);
  align-items:center;
}
.wdq-shot{ margin:0; }
.wdq-shot img{
  display:block;
  width:100%;
  height:auto;               /* else the height attribute pins the box */
  aspect-ratio:4 / 5;
  object-fit:cover;
  border-radius:0;  /* was clamp(14px,1.3vw,22px) */
}

.wdq-title{
  margin:0 0 clamp(12px,1.4vw,18px);
  font-size:clamp(26px,3vw,42px);
  font-weight:500;
  line-height:1.12;
  letter-spacing:-.02em;
}
.wdq-lede{
  margin:0 0 clamp(24px,2.8vw,38px);
  max-width:52ch;
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.65;
  color:var(--grey);
}

/* the chips sit on the grey band here rather than the modal's white
   panel, so the unchecked chip needs a surface to read against */
.wdq .chip span{ background:var(--paper); }
.wdq .chip input:checked + span{ background:var(--ink); color:#ffffff; }

.qf-hint{
  margin-left:8px;
  letter-spacing:0;
  text-transform:none;
  font-weight:400;
  color:var(--grey);
}

@media (max-width:860px){
  .wdq-inner{ grid-template-columns:1fr; gap:clamp(24px,4vw,34px); }
  /* the picture lies down here, so only a band of it shows: hold that band
     high enough to keep the sign on the wall, not just the desk */
  .wdq-shot img{ aspect-ratio:16 / 10; object-position:center 35%; }
}

/* a required chip group that was left empty: the legend carries the error,
   since outlining fifteen chips at once would read as damage rather than
   as a prompt */
fieldset.qf-block.is-invalid > .qf-label{ color:var(--error); }

/* The shared .pill--solid hover empties the button to a transparent outline
   with navy text (.pill--solid:hover sets background:transparent, then a later
   rule swaps the colour to --hover and the arrow to --accent). On this form's
   grey band that reads as the button vanishing. Keep it filled instead, and
   use --accent-deep rather than --accent: white on #F00030 is 4.42:1, which
   misses AA for text this size, while #c40028 gives 6.17:1. */
.wdq .quote-form button.pill--solid:hover,
.wdq .quote-form button.pill--solid:focus-visible{
  background:var(--accent-deep);
  color:#ffffff;
  border-color:var(--accent-deep);
}
.wdq .quote-form button.pill--solid:hover .pill-arrow,
.wdq .quote-form button.pill--solid:focus-visible .pill-arrow{
  background:#ffffff;
  color:var(--accent-deep);
}

/* ============================================================
   HEADER — desktop nav vs mobile burger
   The inline nav needs roughly 950px once the logo, six links,
   the CTA and two icon buttons are laid out, so the swap happens
   at 1080px with headroom rather than at a round 1024.
   ============================================================ */
@media (min-width:1080px){
  .burger{ display:none; }
}
@media (max-width:1079px){
  .hdr-nav,
  .hdr-quote{ display:none; }
}
/* below this the two round buttons crowd the logo; the overlay menu still
   carries Call and WhatsApp, so nothing is lost */
@media (max-width:420px){
  .hdr-icon{ width:44px; height:44px; }
  .hdr-icon svg{ width:16px; height:16px; }
  .hdr-actions{ gap:7px; }
}

/* ============================================================
   ABOUT — opening image strip + statement
   ============================================================ */
.abt-strip{
  --abt-gap:clamp(10px,1.2vw,20px);
  --abt-lead:clamp(28px,4vw,64px);
  display:flex;
  overflow:hidden;
}
.abt-row{
  flex:none;
  display:flex;
  width:max-content;
  /* slow enough to read as drift rather than as scrolling — one set takes
     the whole 72s, so a card crosses the viewport in no particular hurry */
  animation:abt-drift 88s linear infinite;
}
/* three identical copies: shifting the track right by exactly one set lands
   the previous copy where the first one started, so the loop has no seam.
   Two copies would run the left edge dry on any viewport wider than a set. */
@keyframes abt-drift{
  from{ transform:translate3d(-33.3333%,0,0); }
  to  { transform:translate3d(0,0,0); }
}
.abt-strip:hover .abt-row{ animation-play-state:paused; }

.abt-set{
  display:flex;
  gap:var(--abt-gap);
  margin:0 var(--abt-gap) 0 0;     /* keeps the spacing even across the seam */
}
.abt-card{
  flex:none;
  width:clamp(230px,28vw,430px);
  aspect-ratio:4 / 3;              /* the 800x600 the portfolio shots ship at */
  margin:0;
  border-radius:0;  /* was clamp(18px,2.2vw,30px) */
  overflow:hidden;
  background:var(--band);
}
.abt-card img{
  display:block;
  width:100%; height:100%;
  object-fit:cover;
}

/* --- the statement --- */
.abt-say{
  background:var(--paper);
  color:var(--ink);
}
.abt-say-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(20px,3.4vw,55px);
}
.abt-say p{
  margin:0 auto;
  max-width:22ch;
  text-align:center;
  font-family:var(--font-display);
  font-size:clamp(26px,3.6vw,54px);
  font-weight:500;
  line-height:1.16;
  letter-spacing:-.028em;
}
.abt-say .hl{ font-style:normal; color:var(--accent); }

@media (max-width:640px){
  .abt-card{ width:clamp(150px,44vw,210px); }
  .abt-say p{ max-width:18ch; }
}

@media (prefers-reduced-motion:reduce){
  /* no drift; one set, centred, still bleeding off both edges */
  .abt-strip{ justify-content:center; }
  .abt-row{ animation:none; }
  .abt-set[aria-hidden]{ display:none; }
}

/* --- About: page title, and the room under the header --- */
.abt-head{
  background:var(--paper);
  color:var(--ink);
  /* the header offset lives here now, since this is the first thing on the
     page; the second value is the breathing room the design wants */
  padding:calc(var(--header-h) + clamp(54px,6.5vw,120px)) clamp(20px,3.4vw,55px) 0;
}
.abt-head-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  text-align:center;
}
.abt-head h1{
  margin:0;
  font-size:clamp(38px,5.6vw,88px);
  font-weight:500;
  line-height:1.04;
  letter-spacing:-.035em;
}

/* ============================================================
   FACTS & FIGURES — photo beside a 2x2 of solid stat cards.
   Flat fills only: no shadows and none of the reference's faint
   background shapes.
   ============================================================ */
.fig{ background:var(--paper); color:var(--ink); }
.fig-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
  display:grid;
  grid-template-columns:1.06fr 1fr;
  gap:clamp(12px,1.4vw,22px);
  align-items:stretch;
}
.fig-shot{
  margin:0;
  border-radius:0;  /* was clamp(14px,1.5vw,22px) */
  overflow:hidden;
  box-shadow:0 6px 20px rgba(0,0,0,.08);
  aspect-ratio:7 / 6;
}
.fig-shot img{ display:block; width:100%; height:100%; object-fit:cover; }

.fig-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:1fr 1fr;
  gap:clamp(12px,1.4vw,22px);
}
.fig-card{
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  gap:clamp(18px,2.6vw,44px);
  padding:clamp(16px,1.9vw,30px);
  border-radius:0;  /* was clamp(14px,1.5vw,22px) */
  border:1px solid var(--line);
  box-shadow:0 6px 20px rgba(0,0,0,.08);   /* small, per the brief */
}
.fig-label{
  margin:0;
  font-size:clamp(12.5px,1vw,16px);
  font-weight:500;
  line-height:1.35;
  letter-spacing:-.01em;
}
.fig-num{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(30px,4.2vw,66px);
  font-weight:700;
  line-height:.95;
  letter-spacing:-.035em;
}

/* Straight off browser-logo.svg: it holds exactly two colours, #db0032 and
   #1c2473. The logo red is darker than --accent, which is what makes it safe
   here — white on #db0032 is 5.17:1, while --accent #F00030 is only 4.42:1 and
   would miss AA for the 14px label. */
.fig-card--red{   background:var(--logo-red); color:#ffffff; border-color:transparent; }
.fig-card--navy{  background:var(--hover);    color:#ffffff; border-color:transparent; }
.fig-card--plain{ background:var(--paper);    color:var(--ink); }

@media (max-width:820px){
  .fig-inner{ grid-template-columns:1fr; }
  .fig-shot{ aspect-ratio:16 / 10; }
  .fig-card{ min-height:clamp(140px,30vw,190px); }
}

/* --- strip: a gentle rise and fall on top of the sideways drift ---------
   The drift lives on .abt-row and this on .abt-card, so the two transforms
   compose rather than one replacing the other. The stagger is keyed to a
   card's position WITHIN its set, so all three copies move identically and
   the loop stays seamless. */
.abt-strip{
  --abt-amp:clamp(5px,.62vw,9px);
  /* tighter above, because the strip belongs to the heading; the standard
     rhythm stays below it. Both still clear the 9px bob easily. */
  padding-top:var(--abt-lead);
  padding-bottom:var(--sec-pad);
}
@keyframes abt-bob{
  from{ transform:translate3d(0,calc(var(--abt-amp) * -1),0); }
  to  { transform:translate3d(0,var(--abt-amp),0); }
}
.abt-card{ animation:abt-bob 5.2s ease-in-out infinite alternate; }
.abt-set .abt-card:nth-child(1){ animation-duration:5.2s; animation-delay:-0.3s; }
.abt-set .abt-card:nth-child(2){ animation-duration:6.4s; animation-delay:-1.5s; }
.abt-set .abt-card:nth-child(3){ animation-duration:5.7s; animation-delay:-2.4s; }
.abt-set .abt-card:nth-child(4){ animation-duration:6.9s; animation-delay:-0.9s; }
.abt-set .abt-card:nth-child(5){ animation-duration:5.0s; animation-delay:-3.1s; }
.abt-set .abt-card:nth-child(6){ animation-duration:6.1s; animation-delay:-1.9s; }
.abt-set .abt-card:nth-child(7){ animation-duration:5.5s; animation-delay:-2.8s; }
.abt-set .abt-card:nth-child(8){ animation-duration:6.6s; animation-delay:-0.6s; }
.abt-set .abt-card:nth-child(9){ animation-duration:5.9s; animation-delay:-3.4s; }
.abt-set .abt-card:nth-child(10){ animation-duration:6.2s; animation-delay:-1.2s; }
.abt-set .abt-card:nth-child(11){ animation-duration:5.3s; animation-delay:-2.1s; }
.abt-set .abt-card:nth-child(12){ animation-duration:6.7s; animation-delay:-0.4s; }
.abt-set .abt-card:nth-child(13){ animation-duration:5.8s; animation-delay:-3.0s; }
.abt-set .abt-card:nth-child(14){ animation-duration:6.0s; animation-delay:-1.7s; }
.abt-strip:hover .abt-card{ animation-play-state:paused; }

@media (prefers-reduced-motion:reduce){
  .abt-card{ animation:none; }
}

/* --- About: studio film, centred rather than full bleed ----------------
   Held to a readable width in the middle of the page; the section keeps the
   standard vertical rhythm so the gaps either side stay equal. */
.abt-wide{
  background:var(--paper);
  padding-block:var(--sec-pad);
}
.abt-wide-inner{
  max-width:1340px;
  margin:0 auto;
  padding-inline:clamp(18px,3.4vw,55px);
}
.abt-media{ position:relative; }
.abt-video{
  display:block;
  width:100%;
  height:auto;
  aspect-ratio:16 / 9;      /* the file is 1400x788 */
  border-radius:0;  /* was clamp(14px,1.5vw,22px) */
  background:var(--band);   /* so the box is never a stark blank while loading */
  object-fit:cover;
}

/* Sound and stop, in the corner of the film. Always on show rather than
   appearing on hover: a finger has nothing to hover with, and a silent film
   whose sound is hidden behind a gesture may as well have none. */
.abt-controls{
  position:absolute;
  right:clamp(12px,1.4vw,22px);
  bottom:clamp(12px,1.4vw,22px);
  display:flex;
  gap:8px;
  z-index:2;
}
.abt-ctrl{
  width:44px; height:44px;
  padding:0; border:0;
  border-radius:0;
  cursor:pointer;
  background:var(--paper);
  color:var(--ink);
  box-shadow:0 2px 10px rgba(0,0,0,.20);   /* it sits on moving pictures */
  display:grid; place-items:center;
  transition:background-color .3s var(--ease), color .3s var(--ease);
}
.abt-ctrl:hover{ background:var(--hover); color:var(--paper); }
.abt-ctrl svg{ width:20px; height:20px; }

/* Each button carries both icons and shows the one that matches the state:
   a film that is running offers "pause", a silent one offers "sound on". */
.abt-ctrl .abt-icon-pause,
.abt-ctrl .abt-icon-on{ display:none; }
.abt-media.is-playing .abt-ctrl .abt-icon-play{ display:none; }
.abt-media.is-playing .abt-ctrl .abt-icon-pause{ display:block; }
.abt-media.is-loud .abt-ctrl .abt-icon-off{ display:none; }
.abt-media.is-loud .abt-ctrl .abt-icon-on{ display:block; }

/* ============================================================
   SPLIT INTRO — copy left, image right
   ============================================================ */
.spl{ background:var(--paper); color:var(--ink); }
.spl-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(28px,4.4vw,80px);
  align-items:center;
}
.spl-kicker{
  margin:0 0 clamp(10px,1.2vw,16px);
  font-size:clamp(13px,1vw,16px);
  font-weight:500;
  letter-spacing:-.01em;
}
.spl-title{
  margin:0 0 clamp(18px,2vw,30px);
  font-size:clamp(31px,4.1vw,60px);
  /* heavier than the page's usual 500 to match the reference, but stopping
     short of its 700 — the brief earlier was to pull the site's weight down */
  font-weight:600;
  line-height:1.06;
  letter-spacing:-.032em;
}
.spl-text{
  margin:0 0 clamp(24px,2.8vw,40px);
  max-width:54ch;
  font-size:clamp(14.5px,1.1vw,17.5px);
  line-height:1.7;
  color:var(--grey);
}
.spl-text strong{ color:var(--ink); font-weight:600; }
.spl-shot{ margin:0; }
.spl-shot img{
  display:block;
  width:100%;
  height:auto;
  border-radius:0;  /* was clamp(14px,1.5vw,22px) */
}

@media (max-width:860px){
  /* minmax(0,…) so a long button label cannot widen the column past the screen */
  .spl-inner{ grid-template-columns:minmax(0,1fr); gap:clamp(24px,4vw,34px); }
  /* image first on a phone, as the rest of the page stacks */
  .spl-shot{ order:-1; }
}
@media (max-width:560px){
  /* long call-to-action labels wrap inside the button instead of running off the page */
  .spl .pill{ max-width:100%; white-space:normal; text-align:left; line-height:1.25; }
  .spl .pill .pill-arrow{ flex:none; }
  /* project names under the work cards: a thumb-sized hit area, same look */
  .wk-name a{ display:inline-block; padding-block:10px; margin-block:-10px; }
}

/* ============================================================
   ANIMATED SCENES — drawings beside a page's introduction
   Built in the brand blue and red with a pale blue as the third
   colour. Every shape rests in its finished place, so a visitor
   who has asked for less motion simply sees the finished picture.
   The scene waits, paused, until it scrolls into view (the script
   adds and removes .is-paused), so the page builds itself in front
   of whoever arrives at it rather than off screen beforehand.
   ============================================================ */
.spl-shot--scene .scene{
  display:block;
  width:100%;
  height:auto;
  overflow:visible;
}
.scene.is-paused,
.scene.is-paused *{ animation-play-state:paused !important; }

/* everything that turns or grows does so about its own middle */
.scene .sc-orbit,
.scene .sc-grow,
.scene .sc-btn,
.scene .sc-ripple,
.scene .sc-sway,
.scene .sc-spin,
.scene .sc-twinkle,
.scene .sc-bob{ transform-box:fill-box; transform-origin:center; }
.scene .sc-grow{ transform-origin:left center; }

/* the page building in the browser: one eight-second loop, each piece
   arriving a moment after the last, holding, then clearing for the next */
.scene .sc-build{ animation:sc-build 8s var(--d,0s) cubic-bezier(.22,.61,.36,1) infinite both; }
.scene .sc-grow{ animation-name:sc-grow; }
.scene .sc-btn{ animation:sc-btn 8s cubic-bezier(.22,.61,.36,1) infinite both; }
@keyframes sc-build{
  0%{ opacity:0; transform:translateY(14px); }
  10%, 84%{ opacity:1; transform:none; }
  92%, 100%{ opacity:0; transform:none; }
}
@keyframes sc-grow{
  0%{ opacity:1; transform:scaleX(0); }
  12%, 84%{ opacity:1; transform:scaleX(1); }
  92%, 100%{ opacity:0; transform:scaleX(1); }
}
/* the button arrives, then gives as the cursor clicks it */
@keyframes sc-btn{
  0%, 11%{ opacity:0; transform:translateY(14px); }
  20%, 40%{ opacity:1; transform:none; }
  42%{ transform:scale(.86); }
  46%, 86%{ opacity:1; transform:none; }
  94%, 100%{ opacity:0; transform:none; }
}

/* the cursor: in from below, clicks the button, looks at the picture,
   moves on to the phone, and goes */
.scene .sc-cursor{ animation:sc-cursor 8s cubic-bezier(.45,0,.25,1) infinite both; }
@keyframes sc-cursor{
  0%{ opacity:0; transform:translate(330px,470px); }
  10%{ opacity:1; transform:translate(330px,440px); }
  38%{ transform:translate(172px,238px); }
  41%{ transform:translate(172px,238px) scale(.82); }
  44%{ transform:translate(172px,238px) scale(1); }
  62%{ transform:translate(402px,214px); }
  78%{ opacity:1; transform:translate(506px,332px); }
  88%{ opacity:1; transform:translate(506px,332px); }
  96%, 100%{ opacity:0; transform:translate(540px,384px); }
}
.scene .sc-ripple{ animation:sc-ripple 8s ease-out infinite both; }
@keyframes sc-ripple{
  0%, 40%{ opacity:0; transform:scale(.4); }
  41%{ opacity:1; transform:scale(.6); }
  54%, 100%{ opacity:0; transform:scale(3.2); }
}

/* the phone's page scrolls on its own, seamlessly */
.scene .sc-feed{ animation:sc-feed 6s linear infinite; }
@keyframes sc-feed{ to{ transform:translateY(-120px); } }
.scene .sc-phone{ animation:sc-float 6s ease-in-out infinite alternate; }

/* the tools floating round it */
.scene .sc-orbit{ animation:sc-spin 70s linear infinite; }
.scene .sc-spin{ animation:sc-spin 9s linear infinite; }
.scene .sc-float{ animation:sc-float 4s var(--d,0s) ease-in-out infinite alternate; }
.scene .sc-bob{ animation:sc-bob 3.2s ease-in-out infinite alternate; }
.scene .sc-sway{ animation:sc-sway 5s ease-in-out infinite alternate; }
.scene .sc-nib{ animation:sc-nib 1.6s ease-in-out infinite alternate; }
.scene .sc-twinkle{ animation:sc-twinkle 2.4s var(--d,0s) ease-in-out infinite alternate; }
@keyframes sc-spin{ to{ transform:rotate(360deg); } }
@keyframes sc-float{ from{ transform:translateY(0); } to{ transform:translateY(-9px); } }
@keyframes sc-bob{ from{ transform:translateY(4px) rotate(-6deg); } to{ transform:translateY(-10px) rotate(6deg); } }
@keyframes sc-sway{ from{ transform:rotate(-10deg); } to{ transform:rotate(10deg); } }
@keyframes sc-nib{ from{ transform:translate(0,0); } to{ transform:translate(-5px,6px); } }
@keyframes sc-twinkle{ from{ opacity:.25; transform:scale(.5); } to{ opacity:1; transform:scale(1.1); } }

/* lines that draw themselves: the chart climbing, the pen's curve */
.scene .sc-draw{
  stroke-dasharray:1.1 2;
  animation:sc-draw 8s cubic-bezier(.22,.61,.36,1) infinite both;
}
.scene .sc-draw--slow{ animation-duration:6s; }
@keyframes sc-draw{
  0%, 6%{ stroke-dashoffset:1.12; }
  40%, 84%{ stroke-dashoffset:0; }
  96%, 100%{ stroke-dashoffset:-1.12; }
}

/* --- the scene kit's colours. Scenes built from the kit paint with these
   classes rather than fixed colours, so one drawing works on a card's blue
   panel (the default) and on a page's white introduction (.scene--light).
   g = drawn straight on the ground, s = on a white surface, a = the red. */
.scene{
  --g:#fff;  --gs:#3A4396;
  --a:#F00030;
  --s:#fff;  --si:#1C2473; --ss:#E9EBF7; --sl:#D5D9EE;
}
.scene--light{ --g:#1C2473; --gs:#fff; }
.scene .fg{ fill:var(--g); }   .scene .fgs{ fill:var(--gs); }
.scene .fa{ fill:var(--a); }   .scene .fs{ fill:var(--s); }
.scene .fsi{ fill:var(--si); } .scene .fss{ fill:var(--ss); }
.scene .fsl{ fill:var(--sl); } .scene .fn{ fill:none; }
.scene .sg{ stroke:var(--g); } .scene .sa{ stroke:var(--a); }
.scene .ssi{ stroke:var(--si); } .scene .sgs{ stroke:var(--gs); }
/* on white, the white surfaces need an edge to stand off the pale ground */
.scene--light .surf{ stroke:var(--si); stroke-width:2.5; vector-effect:non-scaling-stroke; }
.scene--light .fgs.edge{ stroke:var(--si); stroke-width:2.5; vector-effect:non-scaling-stroke; }

/* the kit's further movements */
.scene .sc-rise,
.scene .sc-wave,
.scene .sc-flipx,
.scene .sc-tilt,
.scene .sc-snip,
.scene .sc-snip2,
.scene .sc-needle,
.scene .sc-hand{ transform-box:fill-box; }
.scene .sc-rise{ transform-origin:center; animation:sc-rise 2.6s var(--d,0s) ease-out infinite both; }
@keyframes sc-rise{ 0%{ opacity:0; transform:translateY(8px) scale(.7); } 25%{ opacity:1; } 100%{ opacity:0; transform:translateY(-34px) scale(1); } }
.scene .sc-wave{ transform-origin:left center; animation:sc-wave 2s var(--d,0s) ease-out infinite both; }
@keyframes sc-wave{ 0%{ opacity:0; transform:scale(.6); } 30%{ opacity:1; } 100%{ opacity:0; transform:scale(1.25); } }
.scene .sc-flipx{ transform-origin:left center; animation:sc-flipx 4s cubic-bezier(.65,0,.35,1) infinite; }
@keyframes sc-flipx{ 0%, 35%{ transform:scaleX(1); } 50%{ transform:scaleX(.04); } 65%, 100%{ transform:scaleX(1); } }
.scene .sc-tilt{ transform-origin:center top; animation:sc-tilt 3.4s ease-in-out infinite alternate; }
@keyframes sc-tilt{ from{ transform:rotate(-9deg); } to{ transform:rotate(9deg); } }
.scene .sc-snip{ transform-origin:right center; animation:sc-snip .9s ease-in-out infinite alternate; }
.scene .sc-snip2{ transform-origin:right center; animation:sc-snip2 .9s ease-in-out infinite alternate; }
@keyframes sc-snip{ from{ transform:rotate(0deg); } to{ transform:rotate(-14deg); } }
@keyframes sc-snip2{ from{ transform:rotate(0deg); } to{ transform:rotate(14deg); } }
/* a needle or a hand turning about its own end (drawn pointing up or right) */
.scene .sc-needle{ transform-origin:50% 100%; animation:sc-needle 3s cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes sc-needle{ from{ transform:rotate(-65deg); } to{ transform:rotate(60deg); } }
.scene .sc-hand{ transform-origin:0% 50%; animation:sc-spin 5s linear infinite; }
.scene .sc-lift{ animation:sc-lift 3.2s cubic-bezier(.45,0,.25,1) infinite; }
@keyframes sc-lift{ 0%, 25%{ transform:none; } 45%, 75%{ transform:translateY(-16px); } 95%, 100%{ transform:none; } }
.scene .sc-slide-s{ animation:sc-slide-s 4s cubic-bezier(.45,0,.25,1) infinite both; }
@keyframes sc-slide-s{ 0%{ opacity:0; transform:translateX(-28px); } 15%, 80%{ opacity:1; } 50%{ transform:none; } 100%{ opacity:0; transform:translateX(28px); } }
.scene .sc-down{ animation:sc-down 3s cubic-bezier(.22,.61,.36,1) infinite both; }
@keyframes sc-down{ 0%{ transform:translateY(-22px); opacity:0; } 20%{ opacity:1; } 60%, 85%{ transform:none; opacity:1; } 100%{ opacity:0; } }
.scene .sc-up{ animation:sc-up 2.4s var(--d,0s) linear infinite both; }
@keyframes sc-up{ 0%{ transform:translateY(16px); opacity:0; } 20%, 80%{ opacity:1; } 100%{ transform:translateY(-16px); opacity:0; } }
.scene .sc-scan{ animation:sc-scan 2.2s ease-in-out infinite alternate; }
@keyframes sc-scan{ from{ transform:translateY(0); } to{ transform:translateY(var(--scan,40px)); } }
.scene .sc-rank{ animation:sc-rank 6s cubic-bezier(.65,0,.35,1) infinite; }
@keyframes sc-rank{ 0%, 25%{ transform:translateY(var(--from,40px)); } 45%, 85%{ transform:none; } 100%{ transform:translateY(var(--from,40px)); } }
.scene .sc-hop2{ animation:sc-hop2 1.4s var(--d,0s) ease-in-out infinite; }
@keyframes sc-hop2{ 0%, 100%{ transform:none; } 40%{ transform:translateY(-10px); } 60%{ transform:translateY(-10px); } }
.scene .sc-roam{ animation:sc-roam 6s cubic-bezier(.45,0,.25,1) infinite; }
@keyframes sc-roam{ 0%, 12%{ transform:none; } 30%, 42%{ transform:translate(var(--rx1,40px), var(--ry1,0px)); } 60%, 72%{ transform:translate(var(--rx2,80px), var(--ry2,0px)); } 90%, 100%{ transform:none; } }
.scene .sc-dash{ animation:sc-dash 1.2s linear infinite; }
@keyframes sc-dash{ to{ stroke-dashoffset:-24; } }
.scene .sc-fly{ animation:sc-fly 5s cubic-bezier(.45,0,.25,1) infinite both; }
@keyframes sc-fly{ 0%{ opacity:0; transform:translate(-40px,26px) rotate(14deg); } 15%{ opacity:1; } 50%{ transform:translate(0,-6px) rotate(0deg); } 85%{ opacity:1; } 100%{ opacity:0; transform:translate(44px,18px) rotate(-12deg); } }
/* a progress bar filling from the left, over and over */
.scene .sc-progress{ transform-box:fill-box; transform-origin:left center; animation:sc-progress 6s linear infinite; }
@keyframes sc-progress{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

/* --- scenes on a service card's blue panel: the scene fills the panel,
   the card's number stays on top in its corner */
.svc-mark--scene .scene{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
}
.svc-mark--scene .svc-mark-num{ z-index:2; }

/* the further movements the card scenes use */
.scene .sc-pulse,
.scene .sc-turn,
.scene .sc-flip,
.scene .sc-meridian,
.scene .sc-hop{ transform-box:fill-box; transform-origin:center; }
.scene .sc-growy{ transform-box:fill-box; transform-origin:center bottom; }
/* these turn about a point written on the shape itself (style="transform-origin:…") */
.scene .sc-swing,
.scene .sc-spin-at{ transform-box:view-box; }

.scene .sc-pulse{ animation:sc-pulse 1.8s ease-in-out infinite; }
@keyframes sc-pulse{ 0%, 100%{ transform:scale(1); } 50%{ transform:scale(1.08); } }

/* a tablet turning to landscape and back */
.scene .sc-turn{ animation:sc-turn 6s cubic-bezier(.65,0,.35,1) infinite; }
@keyframes sc-turn{ 0%, 30%{ transform:rotate(0deg); } 45%, 80%{ transform:rotate(-90deg) scale(.78); } 95%, 100%{ transform:rotate(0deg); } }

.scene .sc-blink{ animation:sc-blink 1.6s var(--d,0s) ease-in-out infinite; }
@keyframes sc-blink{ 0%, 100%{ opacity:.25; } 40%, 60%{ opacity:1; } }

/* a needle swinging over a dial */
.scene .sc-swing{ animation:sc-swing 3s cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes sc-swing{ from{ transform:rotate(-70deg); } to{ transform:rotate(62deg); } }

.scene .sc-spin-at{ animation:sc-spin 6s linear infinite; }

/* bars growing up from the ground, in turn, then down again */
.scene .sc-growy{ animation:sc-growy 6s var(--d,0s) cubic-bezier(.22,.61,.36,1) infinite both; }
@keyframes sc-growy{ 0%{ transform:scaleY(.08); } 25%, 80%{ transform:scaleY(1); } 100%{ transform:scaleY(.08); } }

/* a block dragged into place by the cursor */
.scene .sc-drag{ animation:sc-drag 6s cubic-bezier(.45,0,.25,1) infinite both; }
@keyframes sc-drag{ 0%{ opacity:0; transform:translate(var(--dx,150px),var(--dy,120px)); } 12%{ opacity:1; transform:translate(var(--dx,150px),var(--dy,120px)); } 45%, 85%{ opacity:1; transform:none; } 100%{ opacity:0; transform:none; } }

/* an arrow flying in to the middle of the target */
.scene .sc-shoot{ animation:sc-shoot 4s cubic-bezier(.3,.7,.4,1) infinite both; }
@keyframes sc-shoot{ 0%{ opacity:0; transform:translate(70px,-70px); } 12%{ opacity:1; } 30%{ transform:none; } 32%{ transform:translate(-3px,3px); } 36%, 85%{ opacity:1; transform:none; } 100%{ opacity:0; transform:none; } }

/* leads falling through the funnel */
.scene .sc-drop{ animation:sc-drop 1.8s var(--d,0s) cubic-bezier(.55,0,.75,.4) infinite both; }
@keyframes sc-drop{ 0%{ opacity:0; transform:translateY(-6px); } 15%{ opacity:1; } 70%{ opacity:1; } 100%{ opacity:0; transform:translateY(86px); } }

/* rolling along, and back round */
.scene .sc-slide{ animation:sc-slide 7s linear infinite both; }
.scene .sc-slide--late{ animation-duration:5s; animation-delay:-2s; }
@keyframes sc-slide{ 0%{ opacity:0; transform:translateX(-60px); } 12%, 82%{ opacity:1; } 100%{ opacity:0; transform:translateX(150px); } }
.scene .sc-hop{ animation:sc-hop 7s ease-in-out infinite both; }
@keyframes sc-hop{ 0%, 20%{ opacity:0; transform:translateY(-40px); } 35%, 100%{ opacity:1; transform:none; } }

.scene .sc-flip{ animation:sc-flip 3s ease-in-out infinite; }
@keyframes sc-flip{ 0%, 40%{ transform:scaleX(1); } 50%{ transform:scaleX(.08); } 60%, 100%{ transform:scaleX(1); } }

/* reading right to left, and left to right */
.scene .sc-nudge-l{ animation:sc-nudge-l 2.4s ease-in-out infinite alternate; }
.scene .sc-nudge-r{ animation:sc-nudge-r 2.4s ease-in-out infinite alternate; }
@keyframes sc-nudge-l{ from{ transform:translateX(10px); } to{ transform:translateX(-10px); } }
@keyframes sc-nudge-r{ from{ transform:translateX(-10px); } to{ transform:translateX(10px); } }

/* a globe turning: its meridian sweeps across */
.scene .sc-meridian{ animation:sc-meridian 3s linear infinite; }
@keyframes sc-meridian{ 0%{ transform:scaleX(1); } 50%{ transform:scaleX(.05); } 100%{ transform:scaleX(1); } }

/* a switch flicking over and back */
.scene .sc-toggle{ animation:sc-toggle 3.2s cubic-bezier(.65,0,.35,1) infinite; }
@keyframes sc-toggle{ 0%, 35%{ transform:none; } 50%, 85%{ transform:translateX(28px); } 100%{ transform:none; } }

@media (prefers-reduced-motion:reduce){
  .scene *{ animation:none !important; }
}

/* ============================================================
   SERVICES DIRECTORY — six groups of deep service links
   ============================================================ */
.svcdir{ background:var(--band); color:var(--ink); }
.svcdir-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
}
.svcdir-head{ margin-bottom:clamp(30px,4vw,64px); }
.svcdir-heading{
  margin:0 0 clamp(12px,1.4vw,18px);
  font-size:clamp(26px,3vw,44px);
  font-weight:500;
  line-height:1.12;
  letter-spacing:-.02em;
}
.svcdir-lede{
  margin:0;
  max-width:60ch;
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.65;
  color:var(--grey);
}

.svcdir-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(26px,3.2vw,56px);
}
/* --- the group header card --- */
.svcdir-card{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:14px;
  min-height:clamp(74px,6.2vw,104px);
  margin-bottom:clamp(16px,1.8vw,26px);
  padding:clamp(15px,1.5vw,24px);
  border-radius:0;  /* was clamp(10px,1vw,14px) */
  color:#ffffff;
}
.svcdir-card span{
  font-family:var(--font-display);
  font-size:clamp(15.5px,1.35vw,22px);
  font-weight:500;
  line-height:1.15;
  letter-spacing:-.02em;
}
.svcdir-go{
  flex:none;
  display:grid;
  place-items:center;
  width:clamp(32px,2.7vw,42px);
  height:clamp(32px,2.7vw,42px);
  border:1px solid rgba(255,255,255,.5);
  border-radius:0;  /* was 9px */
  transition:background-color .3s var(--ease);
}
.svcdir-go svg{ width:15px; height:15px; }
.svcdir-card:hover .svcdir-go{ background:rgba(255,255,255,.18); }

/* solid fills, all drawn from the logo palette or its darker relatives;
   every one clears 4.5:1 against white text */
.svcdir-card--red{      background:var(--logo-red); }   /* #db0032  5.17:1 */
.svcdir-card--navy{     background:var(--hover);    }   /* #1c2473 13.55:1 */
.svcdir-card--ink{      background:var(--ink);      }   /* #000000 21:1    */
.svcdir-card--deep{     background:var(--accent);   }   /* was #a30026    */
.svcdir-card--indigo{   background:var(--hover);    }   /* was #2f3a8f    */
.svcdir-card--charcoal{ background:var(--ink);      }   /* was #2b2b2b    */

/* --- the link rows --- */
.svcdir-col ul{ margin:0; padding:0; list-style:none; }
.svcdir-col li{ border-bottom:1px solid var(--line); }
.svcdir-col li a{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  padding:clamp(9px,.95vw,13px) 0;
  font-size:clamp(13.5px,1vw,16px);
  line-height:1.4;
  color:var(--ink);
  transition:color .25s var(--ease);
}
.svcdir-col li a svg{
  flex:none;
  width:14px; height:14px;
  opacity:.42;
  transition:opacity .25s var(--ease), transform .25s var(--ease-io);
}
.svcdir-col li a:hover{ color:var(--accent); }
.svcdir-col li a:hover svg{ opacity:1; transform:translate(2px,-2px); }


@media (max-width:900px){
  .svcdir-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:560px){
  .svcdir-grid{ grid-template-columns:1fr; }
}

/* ============================================================
   PORTFOLIO PAGE — heading, filters, grid. Nothing else.
   ============================================================ */
/* the page opens straight into this section, so it carries the header offset */
.pf .work-inner{
  padding-top:calc(var(--header-h) + clamp(40px,5vw,86px));
}
.pf-title{
  margin:0 0 clamp(22px,2.6vw,40px);
  font-size:clamp(34px,5vw,74px);
  font-weight:500;
  line-height:1.04;
  letter-spacing:-.03em;
}
.pf-filters{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:clamp(8px,.9vw,12px);
  margin-bottom:clamp(28px,3.4vw,56px);
}
.pf-btn{
  padding:clamp(9px,.9vw,13px) clamp(16px,1.5vw,24px);
  border:1px solid var(--line-strong);
  border-radius:0;  /* was 999px */
  background:transparent;
  color:var(--ink);
  font-family:var(--font-sans);
  font-size:clamp(13px,1vw,15.5px);
  font-weight:500;
  line-height:1;
  white-space:nowrap;
  cursor:pointer;
  transition:background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.pf-btn:hover{ border-color:var(--ink); }
/* tokens flip inside .inv, so the active pill is white-on-dark here */
.pf-btn.is-on{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.pf-btn .pf-n{ opacity:.55; margin-left:6px; font-weight:400; }

.wk-card[hidden]{ display:none; }

/* page numbers under the grid, in the same square style as the filters */
.pf-pages{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:8px;
  margin-top:clamp(36px,4vw,64px);
}
.pf-pages[hidden]{ display:none; }
.pf-page{
  min-width:46px;
  min-height:46px;
  padding:0 14px;
  border:1px solid var(--line-strong);
  background:transparent;
  color:var(--ink);
  font-family:var(--font-sans);
  font-size:15px;
  font-weight:500;
  line-height:1;
  cursor:pointer;
  transition:background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.pf-page:hover{ border-color:var(--ink); }
.pf-page.is-on{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
.pf-page:disabled{ opacity:.35; cursor:default; }
.pf-page:disabled:hover{ border-color:var(--line-strong); }

/* on white, the buttons under each picture on a phone are outlined in ink */
.pf .wk-btn{ border:1px solid var(--ink); }

.pf-empty{
  margin:clamp(20px,3vw,48px) 0 0;
  font-size:clamp(14.5px,1.1vw,17.5px);
  line-height:1.7;
  color:var(--grey);
}

/* ============================================================
   HOVER FIX — white foregrounds on the fixed hover fills.

   --paper is white on a light ground but #141414 inside .inv,
   where it is the raised card surface. That is fine wherever it
   pairs with var(--ink), because both flip together. It breaks
   where the background is a FIXED colour: the hover blue and the
   accent arrow. Inside the dark work grid that put #141414 text
   on #1C2473 — measured 1.36:1, effectively invisible — and a
   near-black arrow on red. These three want white, always.
   ============================================================ */
.wk-btn:hover{ color:#ffffff; }                         /* 13.55:1 on #1C2473 */
.pill--outline:hover{ color:#ffffff; }
.pill:hover .pill-arrow,
.pill--solid:hover .pill-arrow,
.pill--outline:hover .pill-arrow,
.pill--light:hover .pill-arrow,
.pill--accent:hover .pill-arrow,
.wk-btn:hover .pill-arrow{ color:#ffffff; }             /* 4.42:1 on #F00030, icons need 3 */

/* ============================================================
   SOLID BUTTONS ON A DARK GROUND
   The shared hover empties a solid pill to a transparent outline
   with navy text. On white that reads; on the black of an
   inverted section it measures about 1.4:1 — the label all but
   disappears, which is what "View All Projects" was doing.
   Here the button fills with the hover blue and the label turns
   white, the same move the work cards own buttons make, so every
   button on a black background behaves alike.
   ============================================================ */
.inv .pill--solid:hover,
.inv .pill--solid:focus-visible{
  background:var(--hover);
  color:#ffffff;                 /* 13.6:1 on #1C2473 */
  border-color:var(--hover);
}

/* ============================================================
   WORK BUTTONS — solid white, content centred on one line.

   The label and arrow were stacking because .pill-arrow is a
   46px display:grid box and .wk-btn had no flex context, so the
   arrow wrapped below the text and sat left. And the resting
   fill was var(--paper), which inside .inv is the dark #141414
   rather than white.
   ============================================================ */
.wk-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:9px;
  text-align:center;
  background:#ffffff;
  color:#000000;                 /* 21:1 */
}
.wk-btn .pill-arrow{
  width:17px;
  height:17px;
  background:none;               /* an inline mark, not a circle at this size */
  color:inherit;
}
.wk-btn .pill-arrow svg{ width:16px; height:16px; }
/* hover keeps the navy fill, which now reads clearly against the white rest */
.wk-btn:hover .pill-arrow{ background:none; color:#ffffff; }

/* ============================================================
   GUIDE — copy left, three-image collage right with a stat card
   ============================================================ */
.gd{ background:var(--paper); color:var(--ink); }
.gd-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
  display:grid;
  grid-template-columns:0.86fr 1fr;
  gap:clamp(30px,4.6vw,86px);
  align-items:center;
}
.gd-title{
  margin:0 0 clamp(18px,2vw,30px);
  font-size:clamp(32px,4.4vw,64px);
  font-weight:500;
  line-height:1.04;
  letter-spacing:-.035em;
}
.gd-text{
  margin:0 0 clamp(26px,3vw,46px);
  max-width:44ch;
  font-size:clamp(14.5px,1.1vw,17.5px);
  line-height:1.7;
  color:var(--grey);
}

/* --- the collage --- */
.gd-art{
  display:grid;
  grid-template-columns:1.02fr 1fr;
  gap:clamp(10px,1.1vw,18px);
}
.gd-shot{
  margin:0;
  border-radius:0;  /* was clamp(12px,1.2vw,18px) */
  overflow:hidden;
  background:var(--band);
}
.gd-shot img{ display:block; width:100%; height:100%; object-fit:cover; }
/* the left frame runs the full height of the two stacked on the right */
.gd-shot--tall{ grid-row:1 / 3; }
.gd-shot--top,
.gd-shot--btm{ aspect-ratio:8 / 7; }
.gd-shot--btm{ position:relative; }

.gd-stat{
  position:absolute;
  left:clamp(10px,1vw,16px);
  right:clamp(10px,1vw,16px);
  bottom:clamp(10px,1vw,16px);
  padding:clamp(13px,1.3vw,20px);
  border-radius:0;  /* was clamp(10px,1vw,14px) */
  background:rgba(255,255,255,.96);
  color:var(--ink);
}
.gd-stat-num{
  margin:0 0 6px;
  font-family:var(--font-display);
  font-size:clamp(22px,2.2vw,34px);
  font-weight:500;
  line-height:1;
  letter-spacing:-.03em;
}
.gd-stat-text{
  margin:0;
  font-size:clamp(12px,.92vw,14px);
  line-height:1.45;
  color:var(--grey);
}

@media (max-width:900px){
  .gd-inner{ grid-template-columns:1fr; }
}
@media (max-width:520px){
  /* the tall frame stops spanning and the three simply stack */
  .gd-art{ grid-template-columns:1fr; }
  .gd-shot--tall{ grid-row:auto; aspect-ratio:8 / 7; }
}

/* ============================================================
   MISSION / VISION / VALUES — heading, then three flat items
   ============================================================ */
.blf{ background:var(--paper); color:var(--ink); }
.blf-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
}
.blf-title{
  margin:0 0 clamp(34px,4.4vw,76px);
  max-width:34ch;                   /* long enough to hold the authored line */
  font-size:clamp(28px,3.8vw,56px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.03em;
}
.blf-row{
  display:grid;
  grid-template-columns:repeat(3, minmax(0,1fr));
  gap:clamp(24px,3vw,56px);
  align-items:start;
}

/* the heading runs two lines: the second sits back in grey */
.blf-title span{ color:var(--grey); }

/* icon, hairline, then the text — no card, as in the reference */
.blf-item{
  display:flex;
  align-items:flex-start;
  gap:clamp(14px,1.5vw,24px);
}
.blf-ico{
  flex:none;
  width:clamp(26px,2.2vw,32px);
  height:clamp(26px,2.2vw,32px);
}
.blf-body{
  border-left:1px solid var(--line-strong);
  padding-left:clamp(14px,1.4vw,22px);
}
.blf-body h3{
  margin:0 0 clamp(6px,.6vw,9px);
  font-size:clamp(14.5px,1.05vw,17px);
  font-weight:600;
  letter-spacing:-.01em;
}
.blf-body p{
  margin:0;
  font-size:clamp(13px,.98vw,15.5px);
  line-height:1.6;
  color:var(--grey);
}
/* the three principle colours, all drawn from the logo palette or its
   darker relatives — 5.17:1, 13.55:1 and 9.89:1 on white, so each clears
   the 3:1 asked of a meaningful graphic */
.blf-ico--red{  color:var(--logo-red); }
.blf-ico--navy{ color:var(--hover); }
.blf-ico--deep{ color:var(--hover); }

@media (max-width:980px){ .blf-row{ grid-template-columns:repeat(2, minmax(0,1fr)); } }
@media (max-width:620px){ .blf-row{ grid-template-columns:1fr; } }

/* ============================================================
   CONTACT — the opening statement
   Set in the display face at statement size, the same treatment
   the about page uses for its one-line manifesto.
   ============================================================ */
.cnx{
  /* no ground of its own — it sits on the page background */
  color:var(--ink);
  /* more room than --header-gap gives: this opens on statement-size type,
     which needs air under the menu that a normal page banner does not */
  padding:calc(var(--header-h) + clamp(34px,3.6vw,64px)) clamp(20px,3.4vw,55px) 0;
}
.cnx-say{
  margin:0 auto;
  /* wider measure than .abt-say: this is a full sentence, not a line */
  max-width:28ch;
  text-align:center;
  font-family:var(--font-display);
  font-size:clamp(26px,3.6vw,54px);
  font-weight:500;
  line-height:1.16;
  letter-spacing:-.028em;
}
@media (max-width:640px){
  .cnx-say{ max-width:22ch; }
}

/* touch sizes: these are tapped, not clicked */
@media (max-width:760px){
  .pf-btn{ min-height:44px; }
  .cnt-card a{ display:flex; align-items:center; min-height:44px; }
}


/* --- contact details --- */
.cnt{ background:var(--paper); color:var(--ink); }
.cnt-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:var(--sec-pad) clamp(18px,3.4vw,55px);
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:clamp(22px,2.6vw,44px);
}
.cnt-card{
  display:flex;
  flex-direction:column;
  gap:clamp(8px,.8vw,12px);
  padding-top:clamp(8px,.8vw,12px);
  border-top:2px solid var(--ink);
}
.cnt-icon{
  display:block;
  width:clamp(46px,4vw,60px);
  height:clamp(46px,4vw,60px);
  margin-bottom:clamp(2px,.4vw,6px);
  color:var(--ink);
}
.cnt-icon svg{ display:block; width:100%; height:100%; }
/* The WhatsApp mark is the real solid logo, not a line drawing. Scale it
   down a touch so its filled shape does not out-weigh the three stroked
   icons beside it. Scale, not padding: a percentage padding resolves
   against the CARD width, which is ~5x the icon box. */
.cnt-icon--solid svg{ transform:scale(.88); }

/* each mark does one small thing every few seconds, then rests: the phone
   rings, a message arrives, a letter rises, the pin drops on the map */
.cnt-icon svg *{ transform-box:fill-box; }
.cnt-icon .ci-ring{ transform-origin:center; animation:ci-ring 3.6s ease-in-out infinite; }
@keyframes ci-ring{
  0%, 52%, 100%{ transform:none; }
  56%{ transform:rotate(-12deg); } 60%{ transform:rotate(10deg); } 64%{ transform:rotate(-9deg); }
  68%{ transform:rotate(7deg); }   72%{ transform:rotate(-4deg); } 76%{ transform:none; }
}
.cnt-icon .ci-wave{ transform-origin:left bottom; animation:ci-wave 3.6s ease-out infinite; }
.cnt-icon .ci-wave--2{ animation-delay:.12s; }
@keyframes ci-wave{ 0%, 50%{ opacity:0; transform:scale(.6); } 60%, 78%{ opacity:1; transform:none; } 92%, 100%{ opacity:0; transform:scale(1.1); } }

.cnt-icon .ci-pop{ transform-origin:center; animation:ci-pop 3.6s ease-in-out infinite; }
@keyframes ci-pop{ 0%, 55%, 100%{ transform:none; } 62%{ transform:scale(1.08); } 70%{ transform:none; } }
.cnt-icon .ci-badge{ transform-origin:center; animation:ci-badge 3.6s cubic-bezier(.34,1.56,.64,1) infinite; }
@keyframes ci-badge{ 0%, 55%{ opacity:0; transform:scale(0); } 64%, 90%{ opacity:1; transform:none; } 100%{ opacity:0; transform:scale(.6); } }

.cnt-icon .ci-letter{ animation:ci-letter 3.6s cubic-bezier(.45,0,.25,1) infinite; }
@keyframes ci-letter{ 0%, 45%{ transform:translateY(3px); opacity:0; } 55%{ opacity:1; } 65%, 85%{ transform:translateY(-6.5px); opacity:1; } 100%{ transform:translateY(3px); opacity:0; } }

.cnt-icon .ci-drop{ animation:ci-drop 3.6s cubic-bezier(.45,0,.25,1) infinite; }
@keyframes ci-drop{ 0%, 50%, 100%{ transform:none; } 60%{ transform:translateY(-4px); } 68%{ transform:none; } 74%{ transform:translateY(-1.5px); } 80%{ transform:none; } }
.cnt-icon .ci-ground{ transform-origin:center; animation:ci-ground 3.6s ease-out infinite; }
@keyframes ci-ground{ 0%, 66%{ opacity:0; transform:scale(.4); } 72%{ opacity:1; } 92%, 100%{ opacity:0; transform:scale(1.5); } }

/* a different moment for each card, so the four never move at once */
.cnt-card:nth-child(2) .cnt-icon *{ animation-delay:.9s; }
.cnt-card:nth-child(3) .cnt-icon *{ animation-delay:1.8s; }
.cnt-card:nth-child(4) .cnt-icon *{ animation-delay:2.7s; }
.cnt-card .cnt-icon .ci-wave--2{ animation-delay:.12s; }

@media (prefers-reduced-motion:reduce){
  .cnt-icon *{ animation:none !important; }
  .cnt-icon .ci-wave, .cnt-icon .ci-badge{ opacity:1; }
  .cnt-icon .ci-letter, .cnt-icon .ci-ground{ opacity:0; }
}

.cnt-label{
  margin:0;
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--accent);
}
.cnt-card a,
.cnt-card address{
  margin:0;
  font-style:normal;
  font-size:clamp(15px,1.25vw,20px);
  font-weight:500;
  line-height:1.5;
  letter-spacing:-.015em;
  color:var(--ink);
}

/* ============================================================
   PROJECT PAGE — /portolios/<project>/
   Laid out like the old site: main image beside the title and
   description, then the other images one under another.
   ============================================================ */
.wk-name a{ color:inherit; text-decoration:none; transition:color .3s var(--ease); }
.wk-name a:hover{ color:var(--accent); }

/* the breadcrumb opens this page, so it clears the fixed header */
.pj-top{ padding-top:calc(var(--header-h) + var(--header-gap)); background:var(--paper); }

.pj{ background:var(--paper); color:var(--ink); }
.pj-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:clamp(28px,3.4vw,56px) clamp(18px,3.4vw,55px) var(--sec-pad);
}
.pj-upper{
  max-width:var(--work-grid);
  margin-inline:auto;
  display:grid;
  grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  gap:clamp(24px,3.4vw,60px);
  align-items:start;
}
.pj-main{ margin:0; border:1px solid var(--line); background:var(--paper-2); }
.pj-main img{ display:block; width:100%; height:auto; }

/* the main image is often a full-page screenshot, so the text stays in view beside it */
.pj-sticky{ position:sticky; top:calc(var(--header-h) + var(--header-gap)); }
.pj-title{
  margin:0;
  font-size:clamp(30px,3.4vw,52px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.035em;
  text-wrap:balance;
}
.pj-actions{ margin-top:clamp(18px,2vw,28px); display:flex; flex-wrap:wrap; gap:10px; }
.pj-summary{
  margin:clamp(18px,2vw,28px) 0 0;
  max-width:46ch;
  font-size:clamp(15px,1.1vw,17.5px);
  line-height:1.7;
}

.pj-images{
  max-width:var(--work-grid);
  margin:clamp(34px,4vw,64px) auto 0;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:clamp(20px,2.4vw,40px);
}
.pj-shot{ margin:0; max-width:100%; border:1px solid var(--line); background:var(--paper-2); }
.pj-shot img{ display:block; max-width:100%; height:auto; }

/* "More portfolio" under a project: three across */
.work-grid--three{ grid-template-columns:repeat(3,minmax(0,1fr)); }

/* the portfolio page sets two projects to a row, large enough to read */
.pf .work-grid{ max-width:1320px; grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(30px,3vw,52px) clamp(20px,2.4vw,40px); }

@media (max-width:1100px){
  .work-grid--three,
  .pf .work-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:860px){
  .pj-upper{ grid-template-columns:1fr; }
  .pj-text{ order:-1; }            /* title and button first on a phone */
  .pj-sticky{ position:static; }
}
@media (max-width:640px){
  .work-grid--three,
  .pf .work-grid{ grid-template-columns:1fr; }
}

/* "Every Service": an odd last column sits in the middle of its row on desktop */
@media (min-width:901px){
  .svcdir-col:last-child:nth-child(3n+1){ grid-column:2; }
}

/* =====================================================================
   SERVICES MEGA MENU
   Full width under the header: a picture on the left that follows the
   group under the pointer, the service groups in columns on the right.
   Desktop only; below 1080px the burger menu carries the same links.
   ===================================================================== */
/* an invisible bridge from the button down to the panel, so the pointer
   does not cross dead space and close it */
.hdr-drop:hover::after{
  content:"";
  position:absolute;
  left:-30px; right:-30px; top:100%;
  height:40px;
}
.mega{
  position:fixed;
  left:0; right:0;
  top:var(--header-now);
  max-height:calc(100vh - var(--header-now));
  overflow-y:auto;
  overscroll-behavior:contain;
  background:var(--paper);
  border-top:1px solid var(--line);
  box-shadow:0 28px 50px -18px rgba(0,0,0,.22);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transform:translateY(-8px);
  transition:opacity .22s var(--ease), transform .35s var(--ease-io), visibility 0s linear .35s;
}
.hdr-drop:hover .mega,
.hdr-drop.is-open .mega{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:translateY(0);
  transition:opacity .28s var(--ease) .08s, transform .45s var(--ease-soft) .08s, visibility 0s linear 0s;
}
/* after a link is chosen, stay shut until the pointer leaves */
.hdr-drop.is-dismissed .mega{
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .15s var(--ease), visibility 0s linear .15s;
}
.mega-inner{
  max-width:1920px;
  margin:0 auto;
  padding:clamp(22px,2.2vw,36px) clamp(16px,3.4vw,54px) clamp(18px,1.8vw,26px);
  display:grid;
  grid-template-columns:minmax(260px,29%) minmax(0,1fr);
  grid-template-rows:1fr auto;
  column-gap:clamp(28px,3.2vw,64px);
}

/* --- the picture card --- */
.mega-feature{
  grid-row:1 / span 2;
  position:relative;
  min-height:clamp(300px,24vw,400px);
  overflow:hidden;
  background:var(--ink);
  isolation:isolate;
}
.mega-media img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  opacity:0;
  transform:scale(1.06);
  transition:opacity .5s var(--ease), transform 1.4s var(--ease-soft);
}
.mega-media img.is-active{ opacity:1; transform:scale(1); }
.mega-feature::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:1;
  background:linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(0,0,0,.82) 100%);
  pointer-events:none;
}
.mega-feature-copy{
  position:absolute;
  left:0; right:0; bottom:0;
  z-index:2;
  padding:clamp(18px,1.7vw,28px);
  color:var(--paper);
}
.mega-kicker{
  display:block;
  font-family:var(--font-display);
  font-size:11.5px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
}
.mega-captions{ display:grid; margin:10px 0 16px; }
.mega-caption{
  grid-area:1 / 1;
  margin:0;
  max-width:24ch;
  font-size:clamp(19px,1.5vw,26px);
  font-weight:500;
  line-height:1.18;
  letter-spacing:-.025em;
  opacity:0;
  transform:translateY(10px);
  transition:opacity .3s var(--ease), transform .5s var(--ease-soft);
}
.mega-caption.is-active{ opacity:1; transform:translateY(0); transition-delay:.08s; }
.mega-feature-link{
  display:inline-flex;
  align-items:center;
  gap:9px;
  padding-bottom:4px;
  border-bottom:1px solid rgba(255,255,255,.55);
  color:var(--paper);
  font-size:14.5px;
  font-weight:500;
  text-decoration:none;
  transition:border-color .3s var(--ease), gap .3s var(--ease);
}
.mega-feature-link svg{ width:15px; height:15px; }
.mega-feature-link:hover{ border-color:var(--paper); gap:13px; }

/* --- a service's own drawing, while the pointer is over it: on plain
   white, held still, without its pale disc, the words beneath in blue */
.mega-scene{
  position:absolute;
  left:0; right:0; top:2%; bottom:44%;
  z-index:0;
  opacity:0;
  transition:opacity .3s var(--ease);
  pointer-events:none;
}
.mega-scene .scene{ display:block; width:100%; height:100%; overflow:visible; }
.scene--menu .sc-ground{ display:none; }
.scene--still,
.scene--still *{ animation:none !important; }
.mega-feature{ transition:background-color .3s var(--ease); }
.mega-feature.is-scene{ background:var(--paper); }
.mega-feature.is-scene::after{ opacity:0; }
.mega-feature::after{ transition:opacity .3s var(--ease); }
.mega-feature.is-scene .mega-media img{ opacity:0; }
.mega-feature.is-scene .mega-scene{ opacity:1; }
.mega-feature.is-scene .mega-feature-copy{ color:var(--ink); }
.mega-feature.is-scene .mega-caption{ opacity:0; transform:translateY(10px); transition-delay:0s; }
.mega-feature.is-scene .mega-caption--scene{ opacity:1; transform:translateY(0); }
.mega-feature.is-scene .mega-feature-link{ color:var(--ink); border-color:rgba(28,36,115,.4); }
.mega-feature.is-scene .mega-feature-link:hover{ border-color:var(--ink); }

/* --- the groups --- */
.mega-groups{
  display:grid;
  grid-template-columns:repeat(4, minmax(0,1fr));
  gap:clamp(20px,2.4vw,44px);
  align-content:start;
}
.mega-group-title{
  position:relative;
  display:flex;
  align-items:baseline;
  gap:10px;
  margin-bottom:8px;
  padding-bottom:12px;
  border-bottom:1px solid var(--line);
  font-family:var(--font-display);
  font-size:12px;
  font-weight:600;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--ink);
}
/* the group under the pointer gets a red rule, in step with the picture */
.mega-group-title::after{
  content:"";
  position:absolute;
  left:0; bottom:-1px;
  width:100%;
  height:1.5px;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .45s var(--ease-io);
}
.mega-group.is-active .mega-group-title::after{ transform:scaleX(1); }
.mega-group-title i{ font-style:normal; color:var(--accent); }
.mega-group ul{ margin:0; padding:0; list-style:none; }
.mega-group a{
  display:block;
  padding:7px 0;
  font-size:clamp(14.5px,1.02vw,17px);
  font-weight:500;
  line-height:1.3;
  letter-spacing:-.01em;
  color:var(--ink);
  text-decoration:none;
  transition:color .2s var(--ease), transform .35s var(--ease-soft);
}
.mega-group a:hover,
.mega-group a:focus-visible{ color:var(--accent); transform:translateX(5px); }

/* --- bottom strip --- */
.mega-foot{
  grid-column:2;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:12px 28px;
  margin-top:clamp(18px,2vw,30px);
  padding-top:clamp(14px,1.4vw,20px);
  border-top:1px solid var(--line);
}
.mega-all,
.mega-quote{
  display:inline-flex;
  align-items:center;
  gap:9px;
  font-family:var(--font-display);
  font-size:13px;
  font-weight:600;
  letter-spacing:.07em;
  text-transform:uppercase;
  text-decoration:none;
  color:var(--ink);
  transition:color .25s var(--ease), background-color .25s var(--ease), gap .3s var(--ease);
}
.mega-all svg,
.mega-quote svg{ width:15px; height:15px; }
.mega-all:hover{ color:var(--accent); gap:13px; }
.mega-note{ margin:0 0 0 auto; font-size:14.5px; }
.mega-quote{
  padding:11px 16px 11px 18px;
  background:var(--ink);
  color:var(--paper);
}
.mega-quote:hover{ background:var(--accent); gap:13px; }

@media (max-width:1279px){
  .mega-inner{ grid-template-columns:230px minmax(0,1fr); }
  .mega-note,
  .mega-kicker{ display:none; }
  .mega-captions{ margin-top:0; }
  .mega-caption{ font-size:18px; }
  .mega-quote{ margin-left:auto; }
}
@media (prefers-reduced-motion:reduce){
  .mega,
  .mega-media img,
  .mega-caption,
  .mega-group a{ transition-duration:.01s !important; transition-delay:0s !important; }
}

/* =====================================================================
   FOOTER LEGAL ROW: copyright on the left, policy links on the right
   ===================================================================== */
.ft-legal{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:10px 24px;
}
.ft-legal p{ margin:0; }
.ft-legal-links{ display:flex; flex-wrap:wrap; gap:6px 22px; }
.ft-legal-links a{ color:var(--paper); text-decoration:none; transition:color .3s var(--ease); }
.ft-legal-links a:hover{ color:var(--accent); }
@media (max-width:820px){
  .ft-legal-links a{ display:inline-block; padding-block:7px; }
}

/* =====================================================================
   LEGAL PAGES (privacy policy, terms)
   ===================================================================== */
.legal{ background:var(--paper); color:var(--ink); }
.legal-inner{
  max-width:860px;
  margin:0 auto;
  padding:clamp(28px,3.4vw,56px) clamp(18px,3.4vw,55px) var(--sec-pad);
}
.legal-head{
  padding-bottom:clamp(24px,2.6vw,40px);
  margin-bottom:clamp(8px,1vw,16px);
  border-bottom:1px solid var(--line);
}
.legal-head h1{
  margin:0;
  font-size:clamp(36px,4.8vw,72px);
  font-weight:500;
  line-height:1.04;
  letter-spacing:-.035em;
}
.legal-intro{
  margin:clamp(14px,1.4vw,22px) 0 0;
  max-width:60ch;
  font-size:clamp(17px,1.35vw,21px);
  line-height:1.5;
}
.legal-date{ margin:14px 0 0; font-size:14px; }
.legal-body{ font-size:clamp(15.5px,1.1vw,17px); line-height:1.7; }
.legal-body h2{
  margin:clamp(34px,3.4vw,52px) 0 12px;
  font-size:clamp(22px,1.9vw,30px);
  font-weight:500;
  line-height:1.2;
  letter-spacing:-.025em;
}
.legal-body h3{ margin:26px 0 8px; font-size:clamp(17px,1.25vw,19px); font-weight:600; }
.legal-body p,
.legal-body ul{ margin:0 0 14px; }
.legal-body ul{ padding-left:1.2em; }
.legal-body li + li{ margin-top:6px; }
.legal-body a{ color:var(--accent); text-underline-offset:3px; overflow-wrap:anywhere; }
.legal-body a:hover{ color:var(--hover); }

/* =====================================================================
   PAGE NOT FOUND (404)
   ===================================================================== */
.nf{ background:var(--paper); color:var(--ink); }
.nf-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding:calc(var(--header-h) + clamp(54px,7vw,130px)) clamp(18px,3.4vw,55px) var(--sec-pad);
}
.nf-code{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(96px,16vw,240px);
  font-weight:600;
  line-height:.9;
  letter-spacing:-.06em;
  color:var(--accent);
}
.nf h1{
  margin:clamp(14px,1.6vw,26px) 0 0;
  max-width:20ch;
  font-size:clamp(30px,3.8vw,56px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-.035em;
}
.nf-text{ margin:16px 0 0; max-width:54ch; font-size:clamp(16px,1.25vw,20px); line-height:1.55; }
.nf-actions{ display:flex; flex-wrap:wrap; gap:12px; margin-top:clamp(24px,2.6vw,38px); }
.nf-links{
  margin-top:clamp(40px,4.6vw,72px);
  padding-top:clamp(22px,2.4vw,34px);
  border-top:1px solid var(--line);
}
.nf-label{ display:block; margin-bottom:14px; font-size:13px; letter-spacing:.08em; text-transform:uppercase; }
.nf-links ul{ margin:0; padding:0; list-style:none; display:flex; flex-wrap:wrap; gap:4px 28px; }
.nf-links a{
  display:inline-block;
  padding-block:6px;
  color:var(--ink);
  text-decoration:none;
  font-size:clamp(16px,1.3vw,21px);
  font-weight:500;
  transition:color .3s var(--ease);
}
.nf-links a:hover{ color:var(--accent); }

/* line breaks written into headings (hlbr filter) apply on wider screens only;
   on phones the heading wraps naturally instead of stranding single words */
@media (max-width:760px){
  .br-d{ display:none; }
}

/* industry buttons that open an industry page: on hover a colour wipe fills
   the button from the left, the text and square invert and an arrow slides in */
.ind-pill--link{
  position:relative;
  padding:0;
  overflow:hidden;
  isolation:isolate;
  transition:border-color .35s var(--ease);
}
.ind-pill--link::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .45s var(--ease-io);
}
.ind-pill--link a{
  display:flex;
  align-items:center;
  gap:inherit;
  padding:clamp(11px,1vw,15px) clamp(18px,1.6vw,26px);
  color:inherit;
  text-decoration:none;
  transition:color .3s var(--ease), padding .35s var(--ease-io);
}
.ind-pill--link i{ transition:background-color .3s var(--ease), transform .45s var(--ease-io); }
/* the arrow is the site arrow icon used as a mask, so it takes the text colour */
.ind-pill--link a::after{
  content:"";
  flex:none;
  width:0;
  height:13px;
  margin-left:-9px;
  background:currentColor;
  -webkit-mask:var(--arrow) center / 13px 13px no-repeat;
          mask:var(--arrow) center / 13px 13px no-repeat;
  opacity:0;
  transition:width .35s var(--ease-io), margin .35s var(--ease-io), opacity .3s var(--ease);
}
.ind-pill--link:hover,
.ind-pill--link:focus-within{ border-color:var(--accent); }
.ind-pill--link:hover::before,
.ind-pill--link:focus-within::before{ transform:scaleX(1); }
/* the arrow adds 22px (13px icon + 9px gap); the side padding gives the same
   back, so the button keeps its width and its neighbours do not shift */
.ind-pill--link:hover a,
.ind-pill--link:focus-within a{
  color:var(--paper);
  padding-left:calc(clamp(18px,1.6vw,26px) - 11px);
  padding-right:calc(clamp(18px,1.6vw,26px) - 11px);
}
.ind-pill--link:hover i,
.ind-pill--link:focus-within i{ background:var(--paper); transform:rotate(45deg); }
.ind-pill--link:hover a::after,
.ind-pill--link:focus-within a::after{ width:13px; margin-left:0; opacity:1; }

/* red buttons wipe to deep navy instead, so the change still shows */
.ind-pill--accent.ind-pill--link::before{ background:var(--hover); }
.ind-pill--accent.ind-pill--link:hover,
.ind-pill--accent.ind-pill--link:focus-within{ border-color:var(--hover); }
.ind-pill--accent.ind-pill--link:hover i,
.ind-pill--accent.ind-pill--link:focus-within i{ background:var(--accent); }

@media (prefers-reduced-motion:reduce){
  .ind-pill--link::before,
  .ind-pill--link a,
  .ind-pill--link a::after,
  .ind-pill--link i{ transition-duration:.01s; }
}

/* ============================================================
   SERVICE TABS — what we do, in words
   A blue band carrying one tab per service. The mark beside the
   words is drawn rather than photographed, so a page already
   heavy with pictures can still say a great deal about each
   service. Every panel is in the page for search engines; only
   the open one is shown.
   ============================================================ */
.svt{
  background:var(--hover);          /* the brand blue; white on it is 13.6:1 */
  color:var(--paper);
  padding-block:var(--sec-pad);
}
.svt-inner{
  max-width:var(--work-cap);
  margin:0 auto;
  padding-inline:clamp(18px,3.4vw,55px);
}

.svt-head{ margin-bottom:clamp(30px,3.4vw,52px); }
/* Both widths are set in `ch` — a width of each element's own type — so the
   line length holds as the clamped size grows, rather than the heading
   picking up an extra line every time the screen widens. */
.svt-heading{
  margin:0;
  max-width:33ch;
  font-size:clamp(30px,4.2vw,62px);
  line-height:1.04;
  letter-spacing:-.035em;
  font-weight:500;
}
/* The marked phrase stays white on the blue rather than turning red: red on
   this blue measures 3.07:1, which is thin even for type this size, and the
   heading reads better as one colour. The asterisks in the admin do no harm —
   they simply have nothing to change here. */
.svt-heading .hl{ color:inherit; }
.svt-intro{
  margin:clamp(14px,1.4vw,22px) 0 0;
  max-width:74ch;
  font-size:clamp(15px,1.15vw,19px);
  line-height:1.6;
  color:rgba(255,255,255,.78);
}

/* --- the tab strip --- */
/* One line on a wide screen; on a narrow one it wraps onto as many lines as it
   needs, so every service is in sight. A sideways-scrolling strip hides the
   last services behind an edge nobody thinks to drag. */
.svt-rail-wrap{
  border-bottom:1px solid rgba(255,255,255,.22);
  overflow-x:auto;
  overflow-y:hidden;
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
}
.svt-rail-wrap::-webkit-scrollbar{ display:none; }
.svt-rail{
  display:flex;
  gap:clamp(18px,2.4vw,38px);
  min-width:max-content;
}
.svt-btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:7px;
  padding:0 0 16px;
  border:0;
  background:none;
  cursor:pointer;
  font-family:var(--font-display);
  font-size:clamp(14px,1.05vw,17px);
  font-weight:500;
  letter-spacing:-.01em;
  white-space:nowrap;
  color:rgba(255,255,255,.62);
  transition:color .3s var(--ease);
}
.svt-btn:hover{ color:var(--paper); }
.svt-btn.is-active{ color:var(--paper); }
/* the rule under the open tab, drawn on the strip's own line */
.svt-btn::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:-1px;
  height:2px;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left;
  transition:transform .35s var(--ease);
}
.svt-btn.is-active::after{ transform:scaleX(1); }
/* the small red mark after each tab name, as on the reference */
.svt-mark{
  width:7px; height:7px;
  border-right:2px solid var(--accent);
  border-bottom:2px solid var(--accent);
  transform:rotate(45deg) translateY(-2px);
}

/* --- the open panel --- */
.svt-stage{ padding-top:clamp(30px,3.6vw,56px); }
.svt-panel{
  display:grid;
  grid-template-columns:minmax(0,1fr) clamp(160px,20vw,300px);
  gap:clamp(24px,4vw,70px);
  align-items:center;
}
.svt-panel[hidden]{ display:none; }   /* the attribute alone loses to display:grid */

/* the arriving panel rises the way everything else on the site does */
.svt-panel.is-entering .svt-copy > *,
.svt-panel.is-entering .svt-glyph{ animation:svt-arrive .55s var(--ease-soft) both; }
.svt-panel.is-entering .svt-text{ animation-delay:.06s; }
.svt-panel.is-entering .svt-points{ animation-delay:.12s; }
.svt-panel.is-entering .svt-link{ animation-delay:.18s; }
.svt-panel.is-entering .svt-glyph{ animation-delay:.1s; }
@keyframes svt-arrive{
  from{ opacity:0; transform:translateY(14px); }
  to{ opacity:1; transform:none; }
}

.svt-title{
  margin:0;
  font-size:clamp(23px,2.5vw,38px);
  line-height:1.12;
  letter-spacing:-.03em;
  font-weight:500;
}
.svt-title .hl{ color:var(--paper); text-decoration:underline; text-decoration-color:var(--accent); text-underline-offset:6px; text-decoration-thickness:3px; }
.svt-text{
  margin:clamp(12px,1.2vw,20px) 0 0;
  max-width:68ch;
  font-size:clamp(15px,1.1vw,18px);
  line-height:1.65;
  color:rgba(255,255,255,.82);
}

/* points: a red bar on the left, as on the reference */
.svt-points{
  margin:clamp(18px,2vw,30px) 0 0;
  padding:0;
  list-style:none;
  display:grid;
  gap:10px;
}
.svt-points li{
  padding-left:14px;
  border-left:3px solid var(--accent);
  font-size:clamp(14px,1vw,16px);
  font-weight:500;
  line-height:1.45;
}

.svt-link{
  display:inline-flex;
  align-items:center;
  gap:10px;
  margin-top:clamp(20px,2.2vw,32px);
  color:var(--paper);
  font-family:var(--font-display);
  font-size:clamp(14px,1vw,16px);
  font-weight:500;
  text-decoration:none;
  border-bottom:1px solid rgba(255,255,255,.35);
  padding-bottom:4px;
  transition:border-color .3s var(--ease), color .3s var(--ease);
}
.svt-link:hover{ color:var(--accent); border-bottom-color:var(--accent); }
.svt-arrow{ display:inline-flex; width:17px; height:17px; }
.svt-arrow svg{ width:100%; height:100%; }

/* --- the mark --- */
.svt-glyph{
  justify-self:end;
  width:100%;
  max-width:300px;
  color:var(--paper);
}
.svt-glyph svg{
  display:block;
  width:100%;
  height:auto;
  /* set here rather than in the drawing, so every mark on the site keeps the
     same weight whatever size it is used at */
  stroke-width:.7;
  opacity:.92;
}

@media (max-width:900px){
  .svt-panel{ grid-template-columns:1fr; gap:clamp(22px,4vw,34px); }
  /* the mark leads on a phone: it reads as the service's badge */
  .svt-glyph{ order:-1; justify-self:start; max-width:104px; }
  .svt-glyph svg{ stroke-width:1; }

  /* every service in sight: the strip wraps onto as many lines as it needs
     and the sideways scroll comes off, so nothing hides past the edge */
  .svt-rail-wrap{ overflow:visible; }
  .svt-rail{
    flex-wrap:wrap;
    min-width:0;
    column-gap:20px;
    row-gap:0;
  }
  /* a finger needs 44px; the strip is this whole section's control */
  .svt-btn{
    min-height:44px;
    padding:4px 0 8px;
    align-items:flex-end;
  }
  /* the rule under the open tab sits on the tab, not on the strip's one edge,
     now that there is more than one row of them */
  .svt-btn::after{ bottom:2px; }
}

@media (prefers-reduced-motion:reduce){
  .svt-panel.is-entering .svt-copy > *,
  .svt-panel.is-entering .svt-glyph{ animation:none; }
  .svt-btn::after{ transition:none; }
}

/* ============================================================
   A FEW WORDS AND LINKS ON THE LIGHTER PAGES
   The portfolio's line under its heading, and the contact page's
   line under its cards — each a way on into the rest of the site.
   ============================================================ */
.pf-intro{
  max-width:64ch;
  margin:calc(-1 * clamp(8px,1vw,18px)) 0 clamp(24px,2.8vw,44px);
  font-size:clamp(15px,1.1vw,18px);
  line-height:1.65;
  color:var(--grey);
}
.pf-intro a,
.cnt-more a{ color:var(--ink); text-decoration:underline; text-underline-offset:3px; }
.pf-intro a:hover,
.cnt-more a:hover{ color:var(--accent); }
.cnt-more{
  max-width:var(--work-cap);
  margin:calc(-1 * var(--sec-pad) + clamp(8px,1vw,16px)) auto 0;
  padding:0 clamp(18px,3.4vw,55px) var(--sec-pad);
  font-size:clamp(15px,1.1vw,17.5px);
  line-height:1.65;
  color:var(--grey);
}

/* a picture-and-text block with an animated scene in place of the picture:
   the drawing at its own proportions, a little inset from the column */
.duo-shot--scene .scene{
  display:block;
  width:100%;
  max-width:560px;
  height:auto;
  margin:0 auto;
  overflow:visible;
}

/* ============================================================
   THANK-YOU — the big green tick after an enquiry is sent
   The card springs up, the green disc pops in with a ripple and
   the white tick draws itself — the way a phone says "done".
   Square card as everywhere else; only the tick is round.
   ============================================================ */
.thanks{
  position:fixed;
  inset:0;
  z-index:10000;
  display:grid;
  place-items:center;
  padding:20px;
  visibility:hidden;
  pointer-events:none;
}
.thanks.is-open{ visibility:visible; pointer-events:auto; }
html.thanks-lock{ overflow:hidden; }

.thanks-backdrop{
  position:absolute;
  inset:0;
  background:rgba(12,14,34,.55);
  -webkit-backdrop-filter:blur(8px);
          backdrop-filter:blur(8px);
  opacity:0;
  transition:opacity .35s ease;
}
.thanks.is-open .thanks-backdrop{ opacity:1; }

.thanks-card{
  position:relative;
  width:min(440px,100%);
  padding:clamp(36px,5vw,48px) clamp(22px,4vw,40px) clamp(26px,4vw,34px);
  background:#fff;
  text-align:center;
  box-shadow:0 30px 80px rgba(12,14,34,.28);
  opacity:0;
  transform:translateY(28px) scale(.92);
  transition:transform .55s cubic-bezier(.2,1.35,.4,1), opacity .3s ease;
}
.thanks.is-open .thanks-card{ opacity:1; transform:none; }

/* the tick: a green disc, a ripple round it, and the stroke drawn in */
.thanks-tick{ width:112px; height:112px; margin:0 auto 22px; }
.thanks-tick svg{ display:block; width:100%; height:100%; overflow:visible; }
.thanks-disc{ fill:#34C759; transform-origin:60px 60px; transform:scale(0); }
.thanks-ring{ fill:none; stroke:#34C759; stroke-width:3; opacity:0; transform-origin:60px 60px; }
.thanks-check{
  fill:none;
  stroke:#fff;
  stroke-width:9;
  stroke-linecap:round;
  stroke-linejoin:round;
  stroke-dasharray:80;
  stroke-dashoffset:80;
}
.thanks.is-open .thanks-disc{ animation:thanks-pop .55s .12s cubic-bezier(.2,1.5,.4,1) forwards; }
.thanks.is-open .thanks-ring{ animation:thanks-ripple 1.1s .3s ease-out forwards; }
.thanks.is-open .thanks-check{ animation:thanks-draw .45s .5s cubic-bezier(.65,0,.35,1) forwards; }
@keyframes thanks-pop{ from{ transform:scale(0); } to{ transform:scale(1); } }
@keyframes thanks-ripple{ 0%{ opacity:.55; transform:scale(1); } 100%{ opacity:0; transform:scale(1.45); } }
@keyframes thanks-draw{ to{ stroke-dashoffset:0; } }

.thanks-title{
  margin:0 0 10px;
  font-family:var(--font-display, inherit);
  font-size:clamp(26px,3vw,32px);
  font-weight:600;
  line-height:1.15;
  color:var(--ink, #111);
}
.thanks-lead{ margin:0 0 6px; font-size:17px; font-weight:500; color:var(--ink, #111); }
.thanks-text{ margin:0; font-size:15px; line-height:1.6; color:var(--grey, #5a5a66); }
.thanks-actions{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:10px;
  margin-top:28px;
}
.thanks-actions .pill{ min-width:150px; justify-content:center; }

@media (prefers-reduced-motion:reduce){
  .thanks-backdrop,
  .thanks-card{ transition:none; }
  .thanks.is-open .thanks-disc,
  .thanks.is-open .thanks-ring,
  .thanks.is-open .thanks-check{ animation:none; }
  .thanks.is-open .thanks-disc{ transform:none; }
  .thanks.is-open .thanks-check{ stroke-dashoffset:0; }
}
.thanks-actions .pill{ padding-left:24px; padding-right:24px; }
