

@font-face{font-family:'Figtree';src:url('../fonts/figtree-latin-var.woff2') format('woff2');font-weight:300 900;font-display:swap}
@font-face{font-family:'Poppins';src:url('../fonts/poppins-latin-700.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'Poppins';src:url('../fonts/poppins-latin-600.woff2') format('woff2');font-weight:600;font-display:swap}

:root{

  --bg:#201a28; --panel:#2e2738; --panel-2:#342c3f; --wash:#2d2539;
  /* note 1 - styles.NOTES.txt */
  --panel-3:#2a2336;
  --ink:#eef1f5; --muted:#aba1b8; --line:rgba(255,255,255,.10);

  /* --card is the fill for any panel, tile or accordion sitting INSIDE a
     section, and it exists because --panel (#2e2738) and --wash (#2d2539)
     are one point apart. A card painted --panel on a --wash band is
     invisible: measured across the site on 9 Sept 2026, twenty-six panels
     were within 8 of their own background, including every FAQ accordion
     on a washed section, the project cards, the photo tiles and the review
     cards.

     So a card never names a colour directly. It uses var(--card), and each
     BAND declares what a card on it should be - dark cards on a light band,
     light cards on a dark one. Because custom properties inherit, a card
     dropped into any section gets the right fill with no rule of its own,
     and a section that changes band takes its cards with it.

     ⚠ WHEN YOU ADD A SECTION THAT SETS --slant-bg, SET --card TOO. The
     pairing is the whole mechanism. _dev/blendcheck.js measures every
     panel against its band and fails on anything within 8. */
  --card:var(--panel);

  --dim:#9a93aa;

  /* note 2 - styles.NOTES.txt */
  --blue:#2678b3; --blue-deep:#1a5c8c; --blue-hi:#7cc4f5; --blue-soft:#e7f2fb;
  --sun:#ffb03a;

  --svc-web:#1f6ca2;
  /* note 3 - styles.NOTES.txt */
  --svc-care:#ec0540;
  --svc-brand:#4a2340;
  --svc-video:#1a7466;

  /* ⚠ BANG! HOSTING BRAND PINK AND THE CARE GREENS - added 13 Sept 2026 for the
     /hosting/ tables. Both were SAMPLED, not invented: the pink off
     assets/img/bang-hosting.webp (it is also the pink already documented in
     assets/img/services/README.txt), the green off the demo banner Andy built
     for the abandoned Bang! Hosting site.

     ⚠ EACH -hd VALUE IS THE BRAND COLOUR DARKENED UNTIL WHITE TEXT CLEARS
     4.5:1. Do not put white type on the raw brand values - #fb2f62 measures
     3.69:1 and #5d995e measures 3.40:1. Both fail.

     The three care greens deepen as the price rises, which is deliberate: the
     cheapest column is the lightest, so it reads as the entry point rather
     than the default. */
  --bh-pink:#fb2f62;        /* the logo's own pink - large type and fills only */
  --bh-pink-hd:#d82955;     /* white text safe, 4.80:1 */
  --care-1:#4b7c4c;         /* 4.90:1 */
  --care-2:#3e663f;         /* 6.61:1 */
  --care-3:#325232;         /* 8.81:1 */
  /* ⚠ --care-hi IS A TEXT COLOUR, THE OTHER THREE ARE BACKGROUNDS. Their ratios
     above are white type ON them; used AS type on --wash #2d2539 the lightest of
     them is 2.99:1 and unreadable. This is --care-1's hue at 121 degrees, lifted
     in lightness until it measures 7.71:1 on --wash - the same contrast as
     --blue-hi, so a green link and a blue link carry the same weight. */
  --care-hi:#91ca92;        /* 7.71:1 on --wash, 8.93:1 on --bg */

  --l-ink:#221d33; --l-muted:#635d76; --l-line:#e9e6f1; --l-wash:#f5f3fa;
  --btn-radius:5px;

  --r-lg:20px; --r-md:12px; --r-sm:7px;

  --sec-pad:clamp(96px,14.5vh,190px);

  --sec-62:calc(var(--sec-pad) * .62);
  --sec-3rd:calc(var(--sec-pad) / 3);
  --sec-80:calc(var(--sec-pad) * .8);
  --band-pad:clamp(84px,11vh,140px);

  --head-gap:clamp(30px,4.5vh,52px);
  --head-gap-l:clamp(48px,7vh,84px);
  --head-gap-s:clamp(24px,3.2vh,38px);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
html,body{overflow-x:clip}
body{font-family:'Figtree',sans-serif;color:var(--ink);background:var(--bg);line-height:1.6}
/* note 4 - styles.NOTES.txt */
h1,h2,h3,h4,h5,h6{font-family:'Poppins',sans-serif;line-height:1.15}
h3,h4,h5,h6{line-height:1.3}
a{text-decoration:none;color:inherit}
img{max-width:100%}
.wrap{max-width:1200px;margin:0 auto;padding:0 clamp(22px,4vw,32px)}

.reveal{opacity:0;transform:translateY(26px);transition:opacity .7s ease,transform .7s ease}
.reveal.in{opacity:1;transform:none}
.hero .reveal{opacity:1;transform:none;transition:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

.skip{position:fixed;left:50%;top:-100px;transform:translateX(-50%);z-index:200;background:var(--blue-deep);color:#fff;padding:10px 18px;border-radius:0 0 8px 8px;font-weight:600}
.skip:focus{top:0;outline:2px solid #fff;outline-offset:-5px}

/* note 5 - styles.NOTES.txt */

/* note 6 - styles.NOTES.txt */
.navbar .links>li>a, .navbar .links>li>.drop-toggle,
.gmark, .tst-more, .ck-reopen, .ck-link, .ck-links a,
.strip .legal a, .fcol a{position:relative}

.navbar .links>li>a::after, .navbar .links>li>.drop-toggle::after,
.gmark::after, .tst-more::after, .ck-reopen::after, .ck-link::after,
.ck-links a::after, .strip .legal a::after, .fcol a::after{
  content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;
  width:max(100%,24px);height:max(100%,24px)}

/* note 7 - styles.NOTES.txt */
:focus-visible{outline:2px solid var(--blue-hi);outline-offset:3px}
a:focus-visible{border-radius:2px}

/* Light surfaces. Measured, not guessed - see the table above. */
.navbar :focus-visible,
.svc-subnav :focus-visible,
.subnav-links a:focus-visible,
.skip:focus-visible{outline-color:var(--blue-deep)}

/* The footer brand card sits on the blue band and is a rounded card, so the
   ring follows its corners. It used to declare a 0px outline and paint
   nothing at all. */
.fbrand:focus-visible{outline-offset:4px;border-radius:16px}

/* ---------------- navbar ---------------- */
.navbar{position:fixed;top:10px;left:50%;transform:translateX(-50%);z-index:90;width:calc(100% - 20px);max-width:1200px;
  display:flex;align-items:center;gap:24px;background:#fff;border-radius:5px;padding:10px 22px;
  box-shadow:0 2px 8px -4px rgba(0,0,0,.5);transition:padding .25s ease,top .25s ease,box-shadow .25s ease}
.navbar.scrolled{top:6px;padding-top:6px;padding-bottom:6px}
.navbar .logo img{height:42px;width:auto;display:block;transition:height .25s ease}
.navbar.scrolled .logo img{height:36px}
.navbar .links{list-style:none;display:flex;align-items:center;gap:30px;margin-left:auto}
.navbar .links>li>a,.navbar .links>li>.drop-toggle{font-weight:600;font-size:15px;color:#2f2a45;
  display:flex;align-items:center;gap:6px;cursor:pointer}
.navbar .links>li>a:hover,.navbar .links>li>.drop-toggle:hover{color:var(--blue-deep)}

.drop-toggle{background:none;border:0;padding:0;margin:0;font-family:inherit;line-height:inherit}
.drop-toggle:focus-visible{outline-offset:4px;border-radius:3px}
.caret{display:inline-flex;align-items:center;color:var(--l-muted);transition:transform .2s ease;vertical-align:middle;margin-top:-1px}
.has-drop{position:static}
.has-drop.mini{position:relative}
.navcta{flex:none;margin-left:16px;background:var(--blue);color:#fff;font-weight:600;font-size:14.5px;padding:9px 20px;border-radius:var(--btn-radius);transition:background-color .25s ease}
.navcta:hover{background:var(--blue-deep)}

/* ---- Client login ---- */
/* note 8 - styles.NOTES.txt */
.acct{flex:none;margin-left:16px;display:flex;align-items:center}
/* note 9 - styles.NOTES.txt */
.acct .drop-toggle{display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;padding:0;border-radius:var(--btn-radius);color:#2f2a45;
  cursor:pointer;transition:color .25s ease}
.acct .drop-toggle:hover,.acct.open .drop-toggle{color:var(--blue-deep)}
/* note 10 - styles.NOTES.txt */
.drop.drop-acct{width:min(330px,92vw);padding:12px}
.acct-h{display:block;font-size:11px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--l-muted);font-weight:600;margin:2px 4px 8px}
.acct-row{display:flex;align-items:flex-start;gap:12px;padding:10px 12px;
  border-radius:var(--btn-radius);color:var(--l-ink);transition:background-color .2s ease}
.acct-row:hover{background:var(--l-wash)}
.acct-row .ic{flex:none;width:36px;height:36px;border-radius:8px;display:grid;place-items:center;
  background:var(--l-wash);color:var(--blue-deep)}
.acct-row .tx{display:block}
.acct-row .tx b{display:block;font-weight:700;font-size:14.5px;line-height:1.3}
.acct-row .tx span{display:block;font-size:12.5px;color:var(--l-muted);line-height:1.45;margin-top:2px}
.acct-row .ex{margin-left:auto;color:var(--l-muted);flex:none;margin-top:9px}
.acct-sep{height:1px;background:var(--l-line);margin:5px 4px}
/* note 11 - styles.NOTES.txt */

.drop{position:absolute;top:calc(100% + 12px);right:0;width:min(880px,94vw);background:#fff;

  border-radius:var(--btn-radius);
  padding:14px;opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity .2s ease,transform .2s ease,visibility .2s ease;
  box-shadow:0 30px 60px -20px rgba(0,0,0,.45);color:var(--l-ink)}

.drop::before{content:"";position:absolute;left:0;right:0;top:-18px;height:18px}

.has-drop.open .drop{opacity:1;visibility:visible;transform:none}
.drop.drop-about{width:min(720px,94vw)}
.drop-about .ab-wrap{grid-template-columns:minmax(0,1fr) 262px}
.ab-links{display:flex;flex-direction:column;gap:8px}
/* note 12 - styles.NOTES.txt */
.ab-links a{display:flex;align-items:center;gap:14px;flex:1;padding:14px 16px;border-radius:var(--btn-radius);
  text-decoration:none;transition:background-color .2s ease}
.ab-links a:hover{background:var(--l-wash)}
.ab-ic{flex:none;display:grid;place-items:center;width:42px;height:42px;border-radius:50%;
  background:rgba(72,156,216,.14);color:var(--blue-deep)}
.ab-ic svg{width:20px;height:20px}
.ab-links a:nth-child(1) .ab-ic{background:rgba(140,100,220,.16);color:#6a48b0}
.ab-links a:nth-child(2) .ab-ic{background:rgba(240,178,60,.18);color:#b07c1a}
.ab-links a:nth-child(3) .ab-ic{background:rgba(64,170,140,.16);color:#1e7a5e}
.ab-tx{min-width:0}
.ab-tx b{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:15px;color:#221d33}
.ab-tx span{display:block;font-size:12.5px;line-height:1.5;color:var(--l-muted);margin-top:2px}
.ab-go{margin-left:auto;flex:none;font-size:22px;line-height:1;color:var(--blue);opacity:0;transform:translateX(-6px);
  transition:opacity .2s,transform .2s}
.ab-links a:hover .ab-go{opacity:1;transform:none}
.np-side.ab-side{background:linear-gradient(150deg,#2c2540,#221c31)}
.ab-side .np-side-h{color:#fff}
/* ⚠ .ab-stars WAS HERE AND IS DELETED. The five-star row it styled was removed
   from the navbar's client panel on 13 Sept 2026 and was the last one on the
   site. A self-drawn star rating is unverifiable and every review is 5-star
   anyway, so it said nothing - see claude/review-card-design.md, where the same
   decision was made for the case-study card. ⚠ Do not re-add the rule; if stars
   ever come back the reasoning has to be revisited first. */
.ab-quote{margin:0 0 12px;font-size:12.5px;line-height:1.55;color:var(--muted);font-style:italic}
.ab-who{display:flex;align-items:center;gap:9px;margin-bottom:16px}
/* Rounded square, not a circle, and on the same radius as every other
   review photo on the site - Andy, 9 Sept 2026: "follow the same curved
   edge rather than being circular". 42px rather than 34 so the face is
   actually readable at menu size. The initials fallback below has to
   match it exactly or the row jumps when a photo is missing. */
.ab-ph img{width:42px;height:42px;border-radius:var(--r-sm);object-fit:cover;
  object-position:center top;display:block}
.ab-ini{display:grid;place-items:center;width:42px;height:42px;border-radius:var(--r-sm);background:var(--blue);color:#fff;font-weight:700;font-size:13px}
.ab-nm{font-weight:600;font-size:13px;color:#fff}
.ab-side .np-cta{margin-top:auto}
.has-drop.open .caret{transform:rotate(180deg)}

@media (hover:hover) and (pointer:fine){
  .has-drop:hover .drop{opacity:1;visibility:visible;transform:none}
  .has-drop:hover .caret{transform:rotate(180deg)}
}

.navscrim{position:fixed;inset:0;z-index:88;background:rgba(16,12,22,.55);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .25s ease,visibility .25s ease}
header:has(.has-drop.open) + .navscrim{opacity:1;visibility:visible}
@media (hover:hover) and (pointer:fine){
  header:has(.has-drop:hover) + .navscrim{opacity:1;visibility:visible}
}
@media (prefers-reduced-motion:reduce){.navscrim{transition:none}}

.np-wrap{display:grid;grid-template-columns:minmax(0,1fr) 262px;gap:12px;align-items:stretch}
.np-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}

.np{position:relative;overflow:hidden;border-radius:var(--btn-radius);isolation:isolate;
  background:var(--svc);color:#fff;display:flex;flex-direction:column;justify-content:flex-end;
  min-height:148px;padding:16px 15px 15px;
  transition:transform .35s cubic-bezier(.2,.7,.3,1)}
.np-web{--svc:var(--svc-web)} .np-care{--svc:var(--svc-care)}
.np-brand{--svc:var(--svc-brand)} .np-video{--svc:var(--svc-video)}

.np:hover{transform:translateY(-3px)}
.np:focus-visible{outline-offset:2px}

/* ⚠ object-position 50% 10% - MEASURED, NOT CHOSEN. Added 13 Sept 2026.
   Andy: "in the navigation ... The services pictures show weird parts of the
   image for web design and branding."

   THE CAUSE: all four source images are **760x1400 PORTRAIT** (ratio 0.54),
   because they were made for the homepage plates, which are portrait on desktop
   (ratio 0.57) and show about 95% of the file. Every other use is landscape:

       homepage plate, desktop   0.57   ~95% of the image visible
       nav dropdown plate        1.92   ~28%
       mobile menu plate         1.96   ~28%
       homepage plate at 400px   1.93   ~28%

   With no object-position, cover defaults to 50% and takes a thin band from the
   VERTICAL MIDDLE - which on these four files is the worst part of every one.

   Swept 0/10/20/30/40/50/65/80% at 1.92 and compared all four:
     websites  10% shows the Copeland site on the monitor; 20%+ is the stand
               and bare desk
     hosting   10% shows racks with depth; 40%+ is an orange blur
     branding  10% shows the Mojo Divers and rizzovoice logos whole; 20%+ chops
               "Mojo" and 40%+ gives the chopped "ESSEX DIDGERIDOO" Andy spotted
     video     10% shows the camera and its monitor; 20%+ gives the chopped
               "AL ARTS" text

   ⚠ 10% IS RIGHT FOR ALL FOUR, so there are no per-image magic numbers to
   maintain. If an image is replaced, re-run the sweep before assuming 10% still
   holds - the value belongs to these four photographs, not to the component. */
.np-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 10%;z-index:-3;
  opacity:var(--plate-img);
  transition:opacity .4s ease,transform .7s cubic-bezier(.2,.7,.3,1);
  -webkit-mask-image:var(--plate-mask);mask-image:var(--plate-mask)}
.np:hover .np-bg{opacity:1;transform:scale(1.05)}

.np::before{content:"";position:absolute;inset:0;z-index:-2;pointer-events:none;
  background:var(--svc);
  -webkit-mask-image:var(--plate-anchor);mask-image:var(--plate-anchor)}
.np::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,var(--plate-scrim)) 0%,
    rgba(0,0,0,calc(var(--plate-scrim) * .46)) 34%,rgba(0,0,0,0) 64%)}
.np-nm{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:14.5px;
  line-height:1.2;letter-spacing:-.01em;color:#fff}
.np-ds{display:block;margin-top:5px;font-size:12px;line-height:1.4;color:rgba(255,255,255,.92)}

.np-side{position:relative;background:var(--l-wash);border-radius:var(--btn-radius);
  padding:18px;display:flex;flex-direction:column;justify-content:center}
.np-side-h{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:15px;
  color:var(--l-ink);margin-bottom:8px}
.np-side p{font-size:12.5px;line-height:1.5;color:var(--l-muted);margin:0 0 14px}
.np-cta{align-self:flex-start;background:var(--blue);color:#fff;font-weight:600;font-size:13.5px;
  padding:9px 18px;border-radius:var(--btn-radius);transition:background-color .25s ease}
.np-cta:hover{background:var(--blue-deep)}


.th-web{background:var(--blue-soft);color:var(--blue-deep)}
.th-care{background:#fff3dd;color:#c07d13}
.th-video{background:#efeef4;color:var(--l-ink)}
.th-brand{background:#f3e9f7;color:#7a4a8c}

/* note 13 - styles.NOTES.txt */
.burger{display:none;width:38px;height:38px;position:relative;background:none;border:none;cursor:pointer;padding:0;flex:none}
/* note 14 - styles.NOTES.txt */
.burger span{position:absolute;left:8px;right:8px;height:2px;border-radius:2px;background:#221d33;transition:transform .25s ease,opacity .18s ease,top .25s ease}
.burger span:nth-child(1){top:10.5px}.burger span:nth-child(2){top:18px}.burger span:nth-child(3){top:25.5px}
.navbar.open .burger span:nth-child(1){top:18px;transform:rotate(45deg)}
.navbar.open .burger span:nth-child(2){opacity:0}
.navbar.open .burger span:nth-child(3){top:18px;transform:rotate(-45deg)}

/* ---------------- mobile menu ---------------- */

/* note 15 - styles.NOTES.txt */
.mobilemenu{position:fixed;inset:0;z-index:80;background:var(--bg);
  padding:clamp(78px,14vh,86px) 16px calc(12px + env(safe-area-inset-bottom));
  padding-top:clamp(78px,14dvh,86px);
  display:flex;flex-direction:column;overflow:hidden;opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .28s ease,visibility .28s ease;color:var(--ink)}
.mobilemenu.open{opacity:1;visibility:visible;pointer-events:auto}

.mobilemenu::before{content:"";position:absolute;border-radius:50%;pointer-events:none;
  width:340px;height:340px;top:-90px;right:-130px;
  background:radial-gradient(circle,rgba(72,156,216,.22),transparent 68%)}
.mm-nav{display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto;position:relative;
  padding-top:clamp(4px,1.6vh,15px);padding-top:clamp(4px,1.6dvh,15px)}
.mm-eyebrow{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--blue-hi);margin:0 2px clamp(4px,.9vh,8px);margin-bottom:clamp(4px,.9dvh,8px)}
.mm-eyebrow-gap{margin-top:clamp(6px,2.4vh,24px);margin-top:clamp(6px,2.4dvh,24px)}

.mm-plates{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(6px,.9vh,8px);gap:clamp(6px,.9dvh,8px)}
.mm-plates .np{min-height:clamp(58px,11.5vh,124px);min-height:clamp(58px,11.5dvh,124px);
  padding:clamp(7px,1.1vh,10px) 11px;padding:clamp(7px,1.1dvh,10px) 11px}
.mm-plates .np-nm{font-size:clamp(12.5px,1.6vh,13.5px);font-size:clamp(12.5px,1.6dvh,13.5px)}
.mm-plates .np-ds{font-size:clamp(10.5px,1.35vh,11.5px);font-size:clamp(10.5px,1.35dvh,11.5px);
  margin-top:3px}

.mm-link{display:flex;align-items:center;gap:10px;width:100%;font-family:'Poppins',sans-serif;
  font-weight:700;color:var(--ink);border-bottom:1px solid var(--line);
  line-height:1.35;
  font-size:clamp(14.5px,2vh,16.5px);padding:clamp(5px,1.5vh,15px) 4px;
  font-size:clamp(14.5px,2dvh,16.5px);padding:clamp(5px,1.5dvh,15px) 4px}
/* The chevron is the tallest thing on the row, so its line box - not the
   label - was setting the row height. Scaled with the row and given a line
   box of its own so it stops doing that. */
.mm-link::after{content:'\203A';color:var(--blue-hi);font-weight:700;line-height:1;margin-left:auto;
  font-size:clamp(15px,2.3vh,18px);font-size:clamp(15px,2.3dvh,18px)}
.mm-link:active{color:var(--blue-hi)}

.mm-tail{flex:none;padding-top:clamp(8px,2vh,20px);padding-top:clamp(8px,2dvh,20px)}
.mm-cta{width:100%;justify-content:center;font-size:15px;
  padding:clamp(9px,1.5vh,13px) 20px;padding:clamp(9px,1.5dvh,13px) 20px}

/* note 16 - styles.NOTES.txt */
@media (max-height:600px){
  .mm-plates .np-ds{display:none}
  .mm-plates .np{min-height:clamp(46px,9vh,58px);min-height:clamp(46px,9dvh,58px)}
}

.mobilemenu .mm-nav>*{opacity:0;transform:translateY(14px);transition:opacity .32s ease,transform .32s ease}
.mobilemenu.open .mm-nav>*{opacity:1;transform:none}
.mobilemenu.open .mm-nav>*:nth-child(1){transition-delay:.04s}
.mobilemenu.open .mm-nav>*:nth-child(2){transition-delay:.09s}
.mobilemenu.open .mm-nav>*:nth-child(3){transition-delay:.14s}
.mobilemenu.open .mm-nav>*:nth-child(4){transition-delay:.19s}
.mobilemenu.open .mm-nav>*:nth-child(5){transition-delay:.24s}
.mobilemenu.open .mm-nav>*:nth-child(6){transition-delay:.29s}
.mobilemenu.open .mm-nav>*:nth-child(7){transition-delay:.34s}
.mobilemenu.open .mm-nav>*:nth-child(8){transition-delay:.39s}
.mobilemenu.open .mm-nav>*:nth-child(9){transition-delay:.44s}
@media (prefers-reduced-motion:reduce){.mobilemenu .mm-nav>*{opacity:1;transform:none;transition:none}}

/* ---------------- hero: diagonal portfolio wall behind a scrim ---------------- */

.hero{--hero-drop:clamp(30px,calc(14vh - 60px),140px);
  position:relative;overflow:hidden;min-height:100vh;display:flex;align-items:center;
  padding:calc(96px + 6vh + var(--hero-drop)) 0 calc(clamp(150px,24vh,270px) - var(--hero-drop))}

.wall{position:absolute;left:-13%;width:126%;top:50%;display:flex;flex-direction:column;gap:16px;
  transform:translateY(-50%) rotate(-7deg);z-index:0}
.row{display:flex;width:max-content;animation:wallSlide 160s linear infinite;will-change:transform;backface-visibility:hidden}
.row.rev{animation:wallSlideRev 195s linear infinite}

.row:nth-of-type(3){animation-duration:180s}
@keyframes wallSlide{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@keyframes wallSlideRev{from{transform:translateX(-50%)}to{transform:translateX(0)}}

.row .shot{height:clamp(150px,18vw,285px);width:auto;max-width:clamp(280px,40vw,580px);margin-right:24px;flex:none;display:block;border-radius:14px;overflow:hidden;background:var(--panel);box-shadow:0 18px 40px -22px rgba(0,0,0,.7)}

.row .shot img{height:100%;width:auto;max-width:100%;object-fit:contain;object-position:center;display:block}
@media (prefers-reduced-motion:reduce){.row,.row.rev{animation:none}}

.scrim{position:absolute;inset:0;z-index:1;
  background:

    radial-gradient(1100px 640px at 6% 74%,rgba(32,26,40,.88) 0%,rgba(32,26,40,.7) 38%,rgba(32,26,40,.26) 66%,rgba(32,26,40,0) 82%),

    linear-gradient(52deg,rgba(32,26,40,.78) 0%,rgba(32,26,40,.56) 22%,rgba(32,26,40,.22) 40%,rgba(32,26,40,.04) 54%,rgba(32,26,40,0) 64%)}

.hero-copy{position:relative;z-index:2;width:100%}
.hero-copy h1{max-width:18ch}

@media (max-width:1024px){
  .wall{gap:12px;left:-18%;width:136%}
  .row .shot{margin-right:16px}
  .scrim{background:
    radial-gradient(900px 620px at 4% 76%,rgba(32,26,40,.88) 0%,rgba(32,26,40,.72) 42%,rgba(32,26,40,.3) 70%,rgba(32,26,40,0) 86%),
    linear-gradient(56deg,rgba(32,26,40,.8) 0%,rgba(32,26,40,.6) 26%,rgba(32,26,40,.3) 46%,rgba(32,26,40,.06) 62%,rgba(32,26,40,0) 76%)}
}

@media (max-width:640px){
  .hero{min-height:86vh;padding:calc(90px + 5vh) 0 9vh}
  .wall{gap:10px;left:-24%;width:148%;transform:translateY(-50%) rotate(-9deg)}
  .row .shot{margin-right:12px;height:132px}
  .scrim{background:linear-gradient(to top,rgba(32,26,40,.94) 0%,rgba(32,26,40,.85) 38%,rgba(32,26,40,.58) 62%,rgba(32,26,40,.32) 82%,rgba(32,26,40,.18) 100%)}
  .hero-copy h1{font-size:clamp(1.75rem,7.4vw,2.4rem);max-width:none}
  .hero-copy .sub{font-size:.98rem}

  .hero-copy{text-align:center}
  .hero-copy h1,.hero-copy .sub{margin-inline:auto}
  .kicker{font-size:.74rem;letter-spacing:.08em;padding:8px 12px;margin-bottom:20px;
    text-align:center}

  .kicker .k-sep{display:none}
  .kicker .k-a,.kicker .k-b{display:block}
  .ctas{justify-content:center}
  .ctas .btn{flex:1 1 auto;justify-content:center}
}

.kicker{display:inline-block;font-weight:700;font-size:.92rem;letter-spacing:.11em;
  text-transform:uppercase;color:#fff;background:rgba(32,26,40,.9);
  padding:9px 16px;border-radius:var(--btn-radius);margin-bottom:24px}
h1{font-size:clamp(2.4rem,5.4vw,4.4rem);font-weight:700;line-height:1.08;letter-spacing:-.025em;max-width:21ch}
h1 .after{color:var(--sun)}
.hero-copy h1{font-size:clamp(2rem,4.2vw,3.4rem);text-shadow:0 2px 18px rgba(18,16,25,.5)}

/* note 17 - styles.NOTES.txt */
.hero:not(.svchero) .hero-copy h1{max-width:24ch}
.hero:not(.svchero) .hero-copy h1 .after{display:block;font-size:.55em;line-height:1.16;margin-top:.3em}
@media (max-width:640px){
  /* .55em against a 28px phone heading lands on top of the sub-line's size and
     stops reading as part of the heading, so the phone gets .7em. */
  .hero:not(.svchero) .hero-copy h1 .after{font-size:.7em;margin-top:.24em}
}
.sub{font-size:1.02rem;color:var(--muted);max-width:540px;margin-top:24px}

.hero-copy .sub{color:#d9e0e8;text-shadow:0 1px 12px rgba(18,16,25,.65)}

.ctas{margin-top:32px;display:flex;gap:12px;flex-wrap:wrap}

/* note 18 - styles.NOTES.txt */
.btn{display:inline-flex;align-items:center;gap:8px;font-weight:600;border-radius:var(--btn-radius);cursor:pointer;font-family:inherit;font-size:14.5px;line-height:1.6;padding:9px 20px;border:1.5px solid transparent;transition:background-color .25s ease,color .25s ease,border-color .25s ease,box-shadow .25s ease,transform .12s ease;white-space:nowrap}
.btn-blue{background:var(--blue);color:#fff}
.btn-blue:hover{background:var(--blue-deep)}
.btn-reel{background:#be5151;color:#fff;border-color:#be5151}
.btn-reel:hover{background:#a44343;border-color:#a44343}
.btn-outline{background:rgba(255,255,255,.08);color:#fff;border-color:rgba(255,255,255,.5)}
.btn-outline:hover{background:rgba(255,255,255,.16)}
.textlink{display:inline-block;margin-top:16px;color:var(--blue-hi);font-weight:600}
.textlink:hover{color:#fff}

/* ---------------- cards ---------------- */
.work,.services{padding:var(--sec-pad) 0}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:18px}
.card{background:var(--panel);border-radius:14px;padding:28px;display:block;
  transition:transform .25s ease,border-color .25s ease}
a.card:hover{transform:translateY(-5px);border-color:rgba(72,156,216,.45)}
.card .tag{display:block;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--sun)}
.card .tag-blue{color:var(--blue-hi)}
.card h3{font-size:1.2rem;font-weight:700;margin:12px 0 10px;line-height:1.25}
.card p{font-size:.94rem;color:var(--muted)}
.card .go{display:inline-block;margin-top:16px;color:var(--blue-hi);font-weight:600;font-size:.88rem}
a.card:hover .go{color:#fff}
blockquote.card p{color:var(--ink);font-size:1rem;line-height:1.55}
blockquote.card footer{margin-top:16px;font-size:.85rem;color:var(--muted)}

:root{--slant:3.84vw}
/* A .slanted section with no --slant-bg of its own falls back to --wash
   (see ::before below), so the DEFAULT card fill has to be the dark one.
   Sections that declare --slant-bg:var(--bg) override this to --panel, and
   they all appear later in this file, so they win. Without this line the
   project cards and the case-study tiles sat --panel on a --wash band and
   could not be seen. */
.slanted{position:relative;isolation:isolate;--card:var(--bg)}
.slanted::before{content:"";position:absolute;left:0;right:0;
  top:calc(var(--slant) * -1);bottom:calc(var(--slant) * -1);
  background:var(--slant-bg,var(--wash));z-index:-1;

  clip-path:polygon(0 var(--slant),100% 0,100% calc(100% - var(--slant)),0 100%)}

.slanted.flat-bottom::before{bottom:0;
  clip-path:polygon(0 var(--slant),100% 0,100% 100%,0 100%)}

section.slanted{
  padding-top:calc(var(--pad-t,var(--pad,var(--sec-pad))) - var(--slant) / 2);
  padding-bottom:calc(var(--pad-b,var(--pad,var(--sec-pad))) + var(--slant) / 2)}

section.slanted.flat-bottom{padding-bottom:var(--pad-b,var(--pad,var(--sec-pad)))}
@media (max-width:560px){:root{--slant:5vw}}

section.studioband{--slant-bg:var(--svc-web);--card:var(--bg);color:#fff;

  --pad:var(--band-pad);

  padding-top:var(--pad)}
.studioband .inner{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(24px,4vw,64px);align-items:center}
.studioband h2{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.03em;
  line-height:1.1;font-size:clamp(1.45rem,2.9vw,2.25rem);max-width:22ch;text-wrap:balance}
.studioband p{color:rgba(255,255,255,.92);font-size:1rem;line-height:1.6;max-width:52ch}
/* The selectivity line, lifted out of the paragraph onto its own line. Inherits
   size, leading and measure from .studioband p above; only the weight, the full
   white and the gap are its own. */
.studioband .sb-pick{margin-top:24px;font-weight:700;color:#fff}
.studioband .meta{display:flex;gap:clamp(18px,3vw,40px);flex-wrap:wrap;margin-top:20px;
  font-size:.86rem;color:rgba(255,255,255,.8)}
.studioband .meta b{display:block;color:#fff;font-weight:700;font-size:.98rem;margin-top:2px}
/* note 19 - styles.NOTES.txt */
.studioband .btn{margin-top:22px}
@media (max-width:840px){.studioband .inner{grid-template-columns:1fr;gap:18px}}

/* ---------------- shared section furniture ---------------- */
.sec-head{margin-bottom:var(--head-gap)}
.sec-head h2{font-size:clamp(1.5rem,2.8vw,2.2rem);font-weight:700;letter-spacing:-.02em;margin:0}
.sec-head .sec-sub{color:var(--muted);margin-top:10px;max-width:56ch}
.sec-head .textlink{margin-top:0}
/* note 20 - styles.NOTES.txt */
.sec-head .btn{margin-top:14px;align-self:flex-start}
@media (min-width:760px){
  .sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:30px}
  .sec-head .btn{margin-top:0;align-self:center}
  /* note 21 - styles.NOTES.txt */
  .faq .sec-head .btn{margin-top:18px}
}

.eyebrow{color:var(--muted);font-size:1rem;margin-bottom:6px}

section.work{--slant-bg:var(--bg);--card:var(--panel)}

@media (min-width:760px){
  /* note 22 - styles.NOTES.txt */
  section.services .sec-head{display:block}
  section.services .sec-sub{margin-top:12px;max-width:none}
}
section.services .sec-head{margin-bottom:calc(var(--head-gap) - clamp(8px,1.6vw,18px))}
section.services .sec-head.centred{margin-bottom:var(--head-gap-l)}

.pitch-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(28px,4.5vw,72px);align-items:start}
.pitch-grid h2{font-size:clamp(1.6rem,3.2vw,2.5rem);font-weight:700;letter-spacing:-.025em;
  line-height:1.15;max-width:15ch}
.pitch-bd .nar-lead{margin-top:0}
.pitch-bd .textlink{display:inline-block;margin-top:18px}

.pitch-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(20px,3vw,44px);
  margin-top:clamp(30px,4vh,48px);padding-top:clamp(24px,3vh,34px);
  border-top:1px solid var(--line)}
.pstat strong{display:block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.9rem,3.4vw,2.8rem);line-height:1;letter-spacing:-.03em;color:var(--blue-hi)}
.pstat p{color:var(--muted);font-size:.88rem;line-height:1.5;margin-top:8px;max-width:26ch}
@media (max-width:900px){
  .pitch-grid{grid-template-columns:1fr;gap:18px}
  .pitch-grid h2{max-width:none}
  .pitch-stats{grid-template-columns:1fr;gap:18px}
  .pstat{display:flex;align-items:baseline;gap:14px}
  .pstat strong{font-size:1.7rem;min-width:4.2ch}
  .pstat p{margin-top:0}
}

.spec{--slant-bg:var(--bg);--card:var(--panel)}

.spec-head{display:flex;align-items:baseline;justify-content:space-between;gap:28px;flex-wrap:wrap;
  margin-bottom:clamp(24px,3.2vh,38px)}
.spec-head h2{font-size:clamp(1.5rem,2.8vw,2.2rem);font-weight:700;
  letter-spacing:-.025em;line-height:1.15;max-width:22ch}
.spec-sub{color:var(--muted);font-size:.98rem;max-width:36ch}
.spec-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(20px,3vw,44px)}
.spec-item b{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:.98rem;
  color:var(--ink);margin-bottom:8px;padding-left:14px;position:relative}

.spec-item b::before{content:"";position:absolute;left:0;top:.3em;width:4px;height:.84em;
  border-radius:2px;background:var(--svc-care)}
.spec-item p{font-size:.88rem;line-height:1.6;color:var(--muted);padding-left:14px}
@media (max-width:900px){.spec-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:26px 32px}}
@media (max-width:560px){.spec-grid{grid-template-columns:1fr;gap:22px}}

.e404{--slant-bg:var(--bg);--card:var(--panel)}

section.e404.slanted.flat-bottom{display:flex;align-items:center;

  --nav-clear:calc(82px + 2.2vh);
  min-height:min(78vh,820px);
  --pad-t:calc(var(--nav-clear) + var(--sec-80));--pad-b:var(--sec-80)}

@media (max-width:840px){section.e404.slanted.flat-bottom{--nav-clear:77px}}
section.e404 > .wrap{width:100%}
.e404-in{max-width:52ch;margin-inline:auto;text-align:center}
.e404-num{display:block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(3.4rem,9vw,7rem);line-height:.85;letter-spacing:-.05em;
  color:var(--blue-hi);opacity:.22;margin-bottom:clamp(10px,1.6vh,18px)}
.e404 h1{font-size:clamp(1.7rem,3.4vw,2.6rem);font-weight:700;letter-spacing:-.025em;line-height:1.15}
.e404 p{color:var(--muted);font-size:1.04rem;margin-top:16px}

.e404-links{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(12px,1.6vh,16px);margin-top:clamp(30px,4vh,44px);
  max-width:46rem;margin-inline:auto;text-align:center}
.e404-link{display:block;background:var(--panel);border-radius:var(--r-md);
  padding:clamp(14px,1.8vh,18px) clamp(16px,1.8vw,20px);
  transition:background .2s ease,transform .2s ease}
.e404-link b{display:block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:.98rem;color:var(--ink);margin-bottom:3px}
.e404-link span{display:block;font-size:.85rem;color:var(--muted)}
@media (hover:hover) and (pointer:fine){
  .e404-link:hover{background:var(--panel-2);transform:translateY(-2px)}
}

@media (max-width:560px){.e404-links{grid-template-columns:1fr}}

/* ---------------- narrative: "launch day is the easy part" ---------------- */
.narrative{--slant-bg:var(--bg);--card:var(--panel)}

.nar-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(28px,5vw,64px);align-items:stretch}
.nar-arg{display:flex;flex-direction:column}

.nar-face{--nar-tilt:0deg;
  margin:0;height:100%;display:flex;flex-direction:column;
  transform:rotate(var(--nar-tilt));
  border-radius:var(--r-lg);overflow:hidden;background:var(--panel-2);

  min-height:380px}

@media (min-width:901px){.nar-face{--nar-tilt:5deg}}
.nar-face.reveal{transform:translateY(26px) rotate(var(--nar-tilt))}
.nar-face.reveal.in{transform:rotate(var(--nar-tilt))}
@media (prefers-reduced-motion:reduce){
  .nar-face.reveal,.nar-face.reveal.in{transform:rotate(var(--nar-tilt))}
}
.nar-face-ph{position:relative;flex:1;min-height:150px}
.nar-face-ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;

  object-position:center 30%;display:block}

.nar-face-cap{position:absolute;left:0;right:0;bottom:0;margin:0;
  padding:clamp(40px,6vh,64px) clamp(20px,2.2vw,26px) 16px;
  background:linear-gradient(to top,
    rgba(12,10,17,.94) 0%,rgba(12,10,17,.84) 34%,
    rgba(12,10,17,.44) 66%,rgba(12,10,17,0) 100%)}
.nar-face-said{margin:0;font-style:italic;color:#fff;font-size:.95rem;line-height:1.55}

.nar-face-who{display:block;margin-top:9px;font-size:.78rem;color:var(--muted);font-style:normal}
.nar-face-who b{font-family:'Poppins',sans-serif;color:#fff;font-weight:700;font-size:.82rem}
.nar-face-who b::after{content:", "}

.nar-facts{flex:none;display:grid;grid-template-columns:1fr 1fr;
  background:#171320}
.nar-fact{padding:clamp(14px,1.8vh,19px) clamp(16px,1.8vw,22px)}
.nar-fact b{display:block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.4rem,2vw,1.7rem);line-height:1;letter-spacing:-.03em;
  color:var(--blue-hi);margin-bottom:5px}
.nar-fact span{display:block;font-size:.78rem;line-height:1.4;color:var(--muted)}

@media (max-width:900px){
  .nar-grid{align-items:start}
  .nar-arg{display:block}
  .nar-face{height:auto;min-height:0}
  .nar-face-ph{aspect-ratio:4/5;flex:none}
}
@media (max-width:560px){.nar-face-ph{aspect-ratio:1/1}}

.narrative h2{font-size:clamp(1.6rem,3.2vw,2.5rem);font-weight:700;letter-spacing:-.025em;line-height:1.15;max-width:16ch}
.nar-lead{color:var(--muted);font-size:1.04rem;margin-top:18px;max-width:54ch}


.nar-kicker{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.02em;line-height:1.3;
  font-size:clamp(1.15rem,1.9vw,1.5rem);color:var(--dim);

  margin-top:auto;padding-top:clamp(30px,4vh,48px)}
.nar-kicker b,.nar-kicker strong{color:var(--ink);font-weight:700}
@media (max-width:900px){.nar-grid{grid-template-columns:1fr}.narrative h2{max-width:none}}

.nar-foot{display:grid;grid-template-columns:1fr auto;gap:clamp(20px,4vw,56px);align-items:end;
  margin-top:clamp(34px,5vh,64px);padding-top:clamp(26px,3.5vh,44px);border-top:1px solid var(--line)}
.nar-foot h3{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.02em;line-height:1.25;
  font-size:clamp(1.15rem,1.9vw,1.5rem);max-width:30ch}
.nar-foot p{color:var(--muted);margin-top:10px;max-width:72ch;font-size:.95rem}
.nar-foot .textlink{margin-top:0;white-space:nowrap}
@media (max-width:760px){.nar-foot{grid-template-columns:1fr;align-items:start}}

.work{padding:var(--sec-pad) 0}
.wl{display:grid;grid-template-columns:.95fr 1.05fr;gap:clamp(30px,5vw,72px);align-items:center}

.wl-list{display:flex;flex-direction:column}
.wl-row{display:block;border-bottom:1px solid var(--line);
  transition:padding-left .35s cubic-bezier(.2,.7,.3,1)}
.wl-row:first-child{border-top:1px solid var(--line)}

.wl-head{display:block;text-decoration:none;color:inherit}
.wl-line{display:flex;align-items:baseline;gap:16px;padding:clamp(22px,3.4vh,38px) 4px}

.wl-no{flex:none;font-family:'Poppins',sans-serif;font-weight:700;font-size:.78rem;letter-spacing:.1em;
  color:var(--muted);transition:color .25s ease}
.wl-name{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.025em;line-height:1.15;
  font-size:clamp(1.3rem,2.4vw,1.9rem);color:var(--dim);transition:color .3s ease}
.wl-meta{margin-left:auto;flex:none;text-align:right;font-size:.82rem;color:var(--muted);transition:color .25s ease}

.wl-row.on,.wl-row:hover,.wl-row:focus-within{padding-left:16px}
.wl-row.on .wl-name,.wl-row:hover .wl-name,.wl-row:focus-within .wl-name{color:var(--ink)}
.wl-row.on .wl-no,.wl-row:hover .wl-no,.wl-row:focus-within .wl-no{color:var(--sun)}
.wl-head:focus-visible{border-radius:var(--r-sm)}

.wl-drop{display:grid;grid-template-rows:0fr;transition:grid-template-rows .45s cubic-bezier(.2,.7,.3,1)}
.wl-drop-in{overflow:hidden;min-height:0}
.wl-row.on .wl-drop{grid-template-rows:1fr}
.wl-did{display:block;color:var(--muted);font-size:.95rem;max-width:52ch;padding-bottom:4px}
.wl-foot{display:flex;align-items:baseline;gap:18px;flex-wrap:wrap;margin-top:16px;padding-bottom:26px}
.wl-scope{font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;color:var(--dim)}

.wl-go{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;
  background:var(--blue);color:#fff;font-weight:600;font-size:14.5px;line-height:1;
  padding:11px 20px;border-radius:var(--btn-radius);text-decoration:none;white-space:nowrap;
  transition:background-color .25s ease}
.wl-go:hover,.wl-go:focus-visible{background:var(--blue-deep);color:#fff}

.wl-row:hover .wl-drop,.wl-row:focus-within .wl-drop{grid-template-rows:1fr}

.wl-stage{position:relative;overflow:hidden;aspect-ratio:16/11;border-radius:var(--r-lg);
  background:#15131d;box-shadow:0 34px 66px -36px rgba(0,0,0,.85)}
.wl-stage img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top center;
  opacity:0;transform:scale(1.05);transition:opacity .5s ease,transform 1.1s cubic-bezier(.2,.7,.3,1)}
.wl-stage img.on{opacity:1;transform:none}

.wl-todo{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:8px;background:var(--panel-2);color:var(--dim);
  font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.8rem;letter-spacing:.06em;
  text-transform:uppercase;opacity:0;transition:opacity .5s ease}
.wl-todo.on{opacity:1}
.wl-todo em{font-style:normal;text-transform:none;letter-spacing:0;color:var(--muted);font-size:.86rem}

.no-js .wl-stage img:first-child{opacity:1;transform:none}

.wl-thumb{display:none}
.wl-chip{display:none}
.wl-chev{display:none}

@media (max-width:900px){

  .wl{grid-template-columns:1fr;gap:0}
  .wl-stage{display:none}
  .wl-list{gap:12px}
  .wl-row{border:0;border-radius:var(--r-lg);overflow:hidden;background:var(--panel);
    padding-left:0;transition:background .25s ease}
  .wl-row:first-child{border-top:0}
  .wl-row.on,.wl-row:hover,.wl-row:focus-within{padding-left:0}
  .wl-row.on{background:var(--panel-2)}
  .wl-row:active{background:var(--panel-2)}
  .wl-head:focus-visible{outline-offset:-3px}

  .wl-chip{display:block;width:64px;aspect-ratio:16/9;overflow:hidden;
    border-radius:var(--r-sm);background:#15131d}
  .wl-chip img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}

  .wl-line{display:grid;grid-template-columns:78px minmax(0,1fr) 24px;
    column-gap:0;row-gap:2px;align-items:center;padding:13px 14px 13px 13px}
  .wl-no{display:none}
  .wl-name{grid-column:2;grid-row:1;min-width:0;color:var(--ink);font-size:1.08rem}
  .wl-meta{grid-column:2;grid-row:2;margin:0;padding:0;text-align:left;font-size:.78rem}
  .wl-chip{grid-column:1;grid-row:1 / span 2}

  .wl-row.on .wl-chip{display:none}
  .wl-row.on .wl-line{grid-template-columns:0 minmax(0,1fr) 24px}
  .wl-chev{display:block;grid-column:3;grid-row:1 / span 2;justify-self:end;
    width:10px;height:10px;
    border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
    transform:rotate(45deg);transform-origin:65% 65%;
    transition:transform .4s cubic-bezier(.2,.7,.3,1),border-color .25s ease}
  .wl-row.on .wl-chev{transform:rotate(-135deg);border-color:var(--sun)}

  .wl-thumb{display:block;overflow:hidden;background:#15131d;aspect-ratio:16/9;
    position:relative;margin-bottom:18px}
  .wl-thumb .wl-todo{opacity:1}
  .wl-thumb img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}

  .wl-drop,.wl-row:hover .wl-drop,.wl-row:focus-within .wl-drop{grid-template-rows:0fr}
  .wl-row.on .wl-drop,.wl-row.on:hover .wl-drop{grid-template-rows:1fr}
  .wl-drop-in{overflow:hidden}

  .no-js .wl-drop{grid-template-rows:1fr}
  .wl-did,.wl-foot{padding-left:20px;padding-right:20px}
  .wl-foot{padding-bottom:20px;margin-top:16px;gap:14px}

  .wl-go{margin-left:0;width:100%;min-height:44px}
  .wl-go:active{background:var(--blue-deep)}
  .wl-scope{flex-basis:100%}
}
@media (prefers-reduced-motion:reduce){
  .wl-row,.wl-name,.wl-no,.wl-chev,.wl-stage img,.wl-drop{transition:none}
  .wl-stage img{transform:none}
}

/* ---------------- page head ---------------- */
/* note 23 - styles.NOTES.txt */

.contact{padding:clamp(40px,6vh,70px) 0 clamp(60px,9vh,110px)}
.c-col{max-width:860px;margin-inline:auto}

.c-tabs{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:22px}
.c-tab{display:flex;align-items:center;gap:14px;text-align:left;cursor:pointer;
  background:var(--panel-2);border:1px solid transparent;border-radius:var(--r-lg);
  padding:clamp(16px,2vw,22px) clamp(16px,2.2vw,24px);color:var(--ink);font:inherit;
  transition:border-color .2s ease,background-color .2s ease}
.c-tab:hover{background:rgba(255,255,255,.05)}
.c-tab:focus-visible{outline-offset:2px}
.c-tab.on{border-color:var(--blue);background:rgba(72,156,216,.08)}
.c-tab-ic{flex:0 0 auto;width:44px;height:44px;border-radius:var(--r-md);display:flex;
  align-items:center;justify-content:center;background:var(--panel);color:var(--muted)}
.c-tab.on .c-tab-ic{color:var(--blue-hi)}
.c-tab-ic svg{width:24px;height:24px}
.c-tab-t{min-width:0}
.c-tab-t b{display:block;font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.02em;
  font-size:clamp(1rem,1.6vw,1.2rem)}
.c-tab-t small{display:block;color:var(--muted);font-size:.88rem;margin-top:2px}

.c-panel{background:var(--panel-2);border-radius:var(--r-lg);
  padding:clamp(20px,2.8vw,34px)}
.c-panel.off{display:none}
/* note 24 - styles.NOTES.txt */
.c-panel-lead{color:var(--muted);line-height:1.65;margin-bottom:18px}
/* note 25 - styles.NOTES.txt */
.c-cal{min-height:480px}

.cform-two{display:grid;grid-template-columns:1fr 1fr;gap:0 18px}
.cform label{display:block;margin-top:14px;font-size:.92rem;color:var(--muted)}
.cform input,.cform textarea,.cform select{display:block;width:100%;margin-top:7px;
  background:var(--panel);border:1px solid rgba(255,255,255,.1);border-radius:10px;
  padding:12px 14px;color:var(--ink);font:inherit;font-size:.98rem}
.cform select{appearance:none;-webkit-appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 20px) 50%,calc(100% - 14px) 50%;background-size:6px 6px;background-repeat:no-repeat}
.cform input:focus,.cform textarea:focus,.cform select:focus{outline:2px solid var(--blue);outline-offset:1px;border-color:transparent}
.cform textarea{resize:vertical;min-height:130px}
.cform ::placeholder{color:var(--dim)}
/* note 26 - styles.NOTES.txt */
.cform .btn{margin-top:22px;width:100%;justify-content:center}
.cform .c-consent{display:flex;gap:10px;align-items:flex-start;margin-top:18px}
.c-consent span{font-size:.88rem;color:var(--muted);line-height:1.55}
.c-consent a{color:var(--blue-hi)}
/* note 27 - styles.NOTES.txt */
.c-needs{border:0;margin-top:16px;min-width:0}
.c-needs legend{font-size:.92rem;color:var(--muted);padding:0}
.c-needs legend span{color:var(--dim);font-size:.85rem;margin-left:9px}
/* note 28 - styles.NOTES.txt */
.c-needs-grid{display:grid;gap:0;margin-top:11px}
.c-needs-grid label{display:flex;align-items:center;gap:12px;margin-top:0;
  color:var(--ink);font-size:.95rem;cursor:pointer;padding:11px 14px;
  border-radius:10px;transition:background-color .18s ease}
.c-needs-grid label:hover{background:rgba(255,255,255,.04)}
.c-needs-grid label:has(input:checked){background:rgba(72,156,216,.10)}
/* The native box is small and sits badly against the rest of the form, so it is
   drawn here: 21px, the form's own panel colour, filling blue with a CSS tick. */
.c-needs-grid input,
.c-consent input{appearance:none;-webkit-appearance:none;width:21px;height:21px;
  flex:0 0 auto;margin-top:0;border-radius:6px;border:1.5px solid rgba(255,255,255,.22);
  background:var(--panel);position:relative;cursor:pointer;padding:0;
  transition:background-color .15s ease,border-color .15s ease}
/* note 29 - styles.NOTES.txt */
.c-needs-grid input:checked,
.c-consent input:checked{border-color:var(--blue);
  background:var(--blue) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / 15px 15px no-repeat}
.c-needs-grid input:focus-visible,
.c-consent input:focus-visible{outline-offset:2px}
/* note 30 - styles.NOTES.txt */
.c-consent input{margin-top:1px}
/* note 31 - styles.NOTES.txt */
.c-need-t{flex:0 0 auto}
.c-need-p{margin-left:auto;font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:12.5px;color:var(--dim);font-variant-numeric:tabular-nums;
  text-align:right;line-height:1.5}
/* Each figure inside the ballpark stays whole; the fold happens at the comma. */
.c-need-p span{white-space:nowrap}
.c-needs-grid label:has(input:checked) .c-need-p{color:var(--blue-hi)}
.c-needs-note{color:var(--dim);font-size:.85rem;margin-top:12px;padding-left:14px}
@media (max-width:520px){
  /* note 32 - styles.NOTES.txt */
  .c-needs-grid label{flex-wrap:wrap;row-gap:0}
  .c-need-t{flex:1 1 0;min-width:0}
  .c-need-p{margin-left:33px;flex-basis:100%;margin-top:2px;text-align:left}
}

.c-check{margin-top:16px}
/* Centred under a full-width button - left-aligned it hangs off one end of a
   symmetrical block. Only used once, directly under the submit. */
.c-note{color:var(--muted);font-size:.85rem;margin-top:12px;text-align:center;text-wrap:balance}

/* note 33 - styles.NOTES.txt */
@keyframes c-done-in{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@keyframes c-done-pop{0%{opacity:0;transform:scale(.7)}60%{transform:scale(1.06)}100%{opacity:1;transform:scale(1)}}
@keyframes c-done-draw{to{stroke-dashoffset:0}}
.c-done{text-align:center;padding:clamp(18px,3vw,40px) 12px;
  animation:c-done-in .6s cubic-bezier(.2,.7,.3,1) both}
/* note 34 - styles.NOTES.txt */
.c-done:focus,.c-done:focus-visible{outline:none}
.c-done .c-done-ic{animation:c-done-pop .55s cubic-bezier(.2,.8,.3,1) .1s both}
/* 57 is a whisker over the ring's circumference (2 x pi x 9) and 12 over the
   tick's length, so both start fully hidden and finish exactly drawn. */
.c-done .c-done-ic svg circle{stroke-dasharray:57;stroke-dashoffset:57;
  animation:c-done-draw .8s ease .3s forwards}
.c-done .c-done-ic svg path{stroke-dasharray:12;stroke-dashoffset:12;
  animation:c-done-draw .45s ease 1.05s forwards}
.c-done h2{animation:c-done-in .55s cubic-bezier(.2,.7,.3,1) .45s both}
.c-done p{animation:c-done-in .55s cubic-bezier(.2,.7,.3,1) .6s both}
.c-done .btn{animation:c-done-in .55s cubic-bezier(.2,.7,.3,1) .8s both}
/* Held at the first frame until .go. Every animated child inherits the pause. */
.c-done,.c-done *{animation-play-state:paused}
.c-done.go,.c-done.go *{animation-play-state:running}
@media (prefers-reduced-motion:reduce){
  .c-done,.c-done .c-done-ic,.c-done h2,.c-done p,.c-done .btn{animation:none}
  .c-done .c-done-ic svg circle,.c-done .c-done-ic svg path{stroke-dashoffset:0;animation:none}
}
.c-done-ic{display:inline-flex;width:64px;height:64px;border-radius:50%;align-items:center;
  justify-content:center;background:rgba(72,156,216,.12);color:var(--blue-hi);margin-bottom:18px}
.c-done-ic svg{width:34px;height:34px}
.c-done h2{font-size:clamp(1.4rem,2.4vw,1.8rem);font-weight:700;letter-spacing:-.02em}
.c-done p{color:var(--muted);line-height:1.65;max-width:44ch;margin:14px auto 0}
.c-done-sub{font-size:.95rem}
.c-done .btn{margin-top:22px}
.c-err{color:#f2b8c6;margin-bottom:4px;font-size:.95rem}

.cf-hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
@media (max-width:640px){
  .cform-two{grid-template-columns:1fr}
  .c-tabs{grid-template-columns:1fr}
  /* note 35 - styles.NOTES.txt */
  .c-cal{min-height:0;margin-inline:calc(clamp(20px,2.8vw,34px) * -1)}
}

/* ---------------- logo gallery ---------------- */
.marks{padding:var(--sec-pad) 0}
.markgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:16px}
.mark{margin:0}
.mark-img{display:flex;align-items:center;justify-content:center;aspect-ratio:1/1;overflow:hidden;
  background:var(--panel);border-radius:14px;transition:background-color .3s ease,transform .3s ease}
.mark:hover .mark-img{border-color:rgba(72,156,216,.45);transform:translateY(-4px)}
.mark-img img{width:100%;height:100%;object-fit:contain;display:block}
.mark figcaption{margin-top:12px;font-size:.9rem}
.mark figcaption b{font-family:'Poppins',sans-serif;font-weight:700;display:block}
.mark figcaption span{color:var(--muted);font-size:.82rem}

/* ---------------- checklist ---------------- */
.checklist{list-style:none;display:flex;flex-direction:column;gap:12px}
.checklist li{position:relative;padding-left:30px;color:var(--muted);font-size:.98rem}
.checklist li::before{content:"";position:absolute;left:2px;top:.55em;width:11px;height:6px;
  border-left:2px solid var(--blue-hi);border-bottom:2px solid var(--blue-hi);transform:rotate(-45deg)}

/* ---------------- numbered steps ---------------- */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px}
.step{background:var(--panel);border-radius:14px;padding:26px}
.stepno{font-family:'Poppins',sans-serif;font-weight:700;font-size:.86rem;letter-spacing:.1em;color:var(--sun)}
.step h3{font-size:1.12rem;font-weight:700;margin:12px 0 8px}
.step p{color:var(--muted);font-size:.93rem}

/* ---------------- bento: services ---------------- */
.services{padding:var(--sec-pad) 0}

/* ⚠ THE PLATE TINT - measured, 13 Sept 2026. Read before changing a number.

   Andy: the colour was "too much ... particularly on the hosting one. They need
   to be readable yet see the image beneath."

   THE COLOUR WAS NEVER A TINT OVER THE PHOTO. The photo is MASKED OUT on the
   diagonal, so a large bottom-left wedge of every plate was flat --svc with no
   photograph in it at all. That wedge was the problem, and Hosting read worst
   because #ec0540 is the most saturated of the four. The mask is the lever, not
   the opacity.

   ⚠ PULLING THE MASK BACK BREAKS CONTRAST UNLESS THE SCRIM GOES UP. White copy
   then sits on bare photography - the Websites plate has a pale wooden desk
   exactly where its text lands and fell to 3.73:1. Three drafts failed 4.5:1
   before this one. The scrim value below is the LOWEST that clears 4.8:1 on all
   four plates, solved for rather than guessed.

   MEASURED (white body copy, 95th-percentile worst case of the ground behind it,
   text hidden so the glyphs are not sampled):

       before   web 5.97   care 6.67   brand 9.97   video 8.25
       after    web 5.11   care 8.70   brand 5.90   video 11.00

   ⚠ Websites and Branding now have the least headroom. A LIGHTER PHOTOGRAPH IN
   EITHER SLOT MUST BE RE-MEASURED - do not swap one in and assume.

   ⚠ The same three tokens drive the navbar dropdown and the mobile menu, which
   used to carry these numbers hardcoded and could drift. They are declared on
   .splate,.np below so every plate on the site shares one set. */
.splates{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;
  min-height:clamp(380px,44vw,520px);padding:clamp(8px,1.6vw,18px) 0}
.splate{position:relative;overflow:hidden;border-radius:var(--r-md);isolation:isolate;
  background:var(--svc);color:#fff;display:flex;flex-direction:column;justify-content:flex-end;
  padding:26px 22px 28px;box-shadow:0 24px 46px -28px rgba(0,0,0,.9);
  transition:transform .45s cubic-bezier(.2,.7,.3,1),box-shadow .45s ease}
.splate,.np{--plate-img:1; --plate-scrim:.10;
  --plate-mask:linear-gradient(to top right,rgba(0,0,0,.18) 0%,rgba(0,0,0,.55) 45%,rgba(0,0,0,1) 100%);
  --plate-anchor:linear-gradient(to top,rgba(0,0,0,1) 0%,rgba(0,0,0,.62) 30%,rgba(0,0,0,0) 62%)}
/* ⚠ ONE PHOTOGRAPH DICTATES THIS. The Websites shot has a pale wooden desk
   exactly where its copy sits and needs FOUR TIMES the black of the other
   three; every version where all four shared one value was really that photo
   setting terms for the rest, which is what made them all too dark.
   Reframe or replace that image and this override can go. */
.splate-web,.np-web{--plate-scrim:.52}
.splate-web{--svc:var(--svc-web)} .splate-care{--svc:var(--svc-care)}
.splate-brand{--svc:var(--svc-brand)} .splate-video{--svc:var(--svc-video)}
.splate:hover,.splate:focus-visible{transform:translateY(-8px);
  box-shadow:0 40px 66px -28px rgba(0,0,0,1);z-index:2}
/* The one component that keeps its own colour: the ring sits partly over the
   photograph on the plate, where blue disappears. Measured, kept. */
.splate:focus-visible{outline-color:#fff}

/* ⚠ SAME 50% 10% AS .np-bg, AND IT IS NEEDED HERE TOO. Andy only reported the
   navbar, but these plates are 1.93 at phone widths - the identical 28% crop -
   so the homepage had the same fault on mobile. On DESKTOP this plate is 0.57
   and shows ~95% of the file, so the shift is about 20px and changes nothing.
   Read the full note beside .np-bg before touching either value. */
.splate-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 10%;
  z-index:-3;opacity:var(--plate-img);transition:opacity .5s ease,transform .8s cubic-bezier(.2,.7,.3,1);
  -webkit-mask-image:var(--plate-mask);mask-image:var(--plate-mask)}
.splate:hover .splate-bg{opacity:1;transform:scale(1.05)}

/* the colour anchor: a solid service-colour layer, masked so it is full strength
   at the foot and gone by 62% up. This is what carries the white copy - the
   black scrim below it only tops up what the photograph takes away. */
.splate::before{content:"";position:absolute;inset:0;z-index:-2;pointer-events:none;
  background:var(--svc);
  -webkit-mask-image:var(--plate-anchor);mask-image:var(--plate-anchor)}
.splate::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,var(--plate-scrim)) 0%,
    rgba(0,0,0,calc(var(--plate-scrim) * .46)) 34%,rgba(0,0,0,0) 64%)}

.splate .nm{position:absolute;left:20px;top:24px;bottom:26px;
  writing-mode:vertical-rl;transform:rotate(180deg);
  font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.02em;color:#fff;
  font-size:clamp(1rem,1.5vw,1.35rem);line-height:1;
  display:flex;align-items:flex-end;text-wrap:balance}
.splate .ds{display:block;color:rgba(255,255,255,.94);font-size:.9rem;line-height:1.5;margin-left:44px}
.splate .go{display:block;margin-top:14px;margin-left:44px;color:#fff;font-weight:700;font-size:.9rem}

@media (max-width:900px){
  .splates{grid-template-columns:repeat(2,minmax(0,1fr));min-height:0}
  .splate{min-height:280px}
}
@media (max-width:560px){
  .splates{grid-template-columns:1fr}
  .splate{min-height:0;padding:24px}
  .splate .nm{position:static;writing-mode:horizontal-tb;transform:none;display:block;
    font-size:1.4rem;margin-bottom:12px}
  .splate .ds,.splate .go{margin-left:0}
}
@media (prefers-reduced-motion:reduce){.splate,.splate-bg{transition:none}}

section.ask{--slant-bg:var(--bg);--card:var(--panel);--pad:80px;text-align:center}
section.ask .inner{max-width:640px;display:flex;flex-direction:column;
  align-items:center;gap:18px}

section.ask h2{font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.5rem,2.8vw,2.2rem);letter-spacing:-.02em;line-height:1.15;
  text-wrap:balance;margin:0}

.tst{--slant-bg:var(--bg);--card:var(--panel)}

.tst .sec-head{margin-bottom:var(--head-gap)}
.tst-rows{display:flex;flex-direction:column;gap:14px;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%)}

.tst-row{overflow-x:auto;overflow-y:hidden;
  touch-action:pan-x pan-y;overscroll-behavior-x:contain;
  scrollbar-width:none;-ms-overflow-style:none;cursor:grab;-webkit-overflow-scrolling:touch}
.tst-row::-webkit-scrollbar{display:none}
.tst-row.dragging{cursor:grabbing}
.tst-track{display:flex;gap:14px;width:max-content}







.is-long blockquote{display:-webkit-box;-webkit-line-clamp:5;
  -webkit-box-orient:vertical;overflow:hidden}

.tst-more{font-size:.78rem;font-weight:700;color:var(--blue-hi);flex:none;display:block}
a.tst-more:hover{color:var(--sun)}

.tst-ph{width:44px;height:44px;flex:none;border-radius:var(--r-sm);overflow:hidden;
  position:relative;background:var(--panel-2)}
.tst-ph img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}

.tst-ini{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:'Poppins',sans-serif;font-weight:700;font-size:.82rem;letter-spacing:.02em;
  color:#fff;background:#7d6b98}
.tst-who{display:flex;flex-direction:column;gap:1px;min-width:0}

.gmark{margin-left:auto;flex:none;width:15px;height:15px;display:block;opacity:.85;
  transition:opacity .2s ease,transform .2s ease}
a.gmark:hover{opacity:1;transform:scale(1.12)}
.gmark svg{width:100%;height:100%;display:block}

.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

.tst-nm{font-family:'Poppins',sans-serif;font-weight:700;font-size:.84rem;line-height:1.3}
.tst-co{font-size:.76rem;color:var(--muted);line-height:1.3}

@media (max-width:560px){
}

@media (prefers-reduced-motion:reduce){
  .tst-rows{-webkit-mask-image:none;mask-image:none}
  .tst-row{overflow:visible;cursor:auto}
  .tst-track{width:auto;flex-wrap:wrap;justify-content:center}
  .is-long blockquote{-webkit-line-clamp:none;display:block;overflow:visible}
  .tst-more{display:none}
}

.tpage{padding:var(--sec-80) 0 var(--sec-pad)}
.tpage-head{max-width:62ch;margin-bottom:clamp(34px,5vh,60px)}
.tpage-head h1{font-size:clamp(1.9rem,4vw,2.9rem);font-weight:700;letter-spacing:-.03em;line-height:1.1}
.tpage-head p{color:var(--muted);margin-top:14px}
.tpage-head .textlink{margin-top:16px;display:inline-block}
.tpage-empty{color:var(--muted)}
.tpage-list{display:flex;flex-direction:column;gap:14px;max-width:900px}



















/* note 36 - styles.NOTES.txt */

.tpage-grid{display:grid;gap:clamp(24px,3vw,34px)}
.tpage-main{min-width:0}
.tside-card{background:var(--panel);border-radius:var(--r-md);padding:20px}
.tside-card + .tside-card{margin-top:12px}
.tside-h{display:block;font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.02em;
  font-size:1.05rem;color:var(--ink);margin-bottom:8px}
.tside-card p{font-size:.86rem;line-height:1.5;color:var(--muted);margin:0 0 16px}
.tside-card .btn{width:100%;justify-content:center;text-align:center;white-space:normal}
.tside-g svg{width:15px;height:15px;flex:none}

@media (min-width:1025px){

  .tpage-grid{grid-template-columns:minmax(0,1fr) clamp(210px,19vw,260px)}

  .tpage-side{grid-column:2;grid-row:1;height:100%}
  .tpage-main{grid-column:1;grid-row:1}

  .tside-stick{position:sticky;top:110px}
}
@media (max-width:1024px){
  .tpage-side{margin-bottom:clamp(24px,4vh,38px)}

  .tside-stick{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
  .tside-card + .tside-card{margin-top:0}
}
@media (max-width:560px){
}

/* ---------------- client band: thin tilted strip under the hero ---------------- */

.cband{position:relative;z-index:3;width:112%;margin-left:-6%;margin-top:-7vh;overflow:hidden;
  transform:rotate(-2.2deg);background:var(--panel-2);
    box-shadow:0 -30px 60px -30px rgba(0,0,0,.7)}

.cband-inner{padding:clamp(18px,1.9vw,30px) 0;position:relative;overflow-x:auto;overflow-y:hidden;

  touch-action:pan-x pan-y;overscroll-behavior-x:contain;scrollbar-width:none;-ms-overflow-style:none;
  cursor:grab;-webkit-overflow-scrolling:touch}
.cband-inner::-webkit-scrollbar{display:none}
.cband-inner.dragging{cursor:grabbing}
.cband-inner.dragging .cb-item{pointer-events:none}

.cband-inner{
  -webkit-mask-image:linear-gradient(90deg,transparent 5.4%,#000 12%,#000 88%,transparent 94.6%);
  mask-image:linear-gradient(90deg,transparent 5.4%,#000 12%,#000 88%,transparent 94.6%)}
.cbandrow{display:flex;align-items:center;width:max-content}
@media (prefers-reduced-motion:reduce){.cbandrow{flex-wrap:wrap;width:auto;justify-content:center;row-gap:18px}}

.cb-item{display:flex;flex-direction:column;align-items:center;justify-content:center;margin-right:52px;white-space:nowrap;min-height:62px}

.cb-logo{height:calc(36px * var(--s,1));width:auto;max-width:calc(150px * var(--s,1));
  object-fit:contain;display:block;filter:brightness(0) invert(1);opacity:.92}
.cb-name{font-family:'Poppins',sans-serif;font-weight:700;font-size:1.2rem;letter-spacing:-.015em;line-height:1.2}
.cb-item em{font-style:normal;font-size:.76rem;color:var(--muted);margin-top:5px}
@media (max-width:840px){
  .cband{transform:rotate(-3deg);width:118%;margin-left:-9%;margin-top:-5vh}

  .cband-inner{padding:clamp(16px,2.4vw,24px) 0;
    -webkit-mask-image:linear-gradient(90deg,transparent 7.6%,#000 15%,#000 85%,transparent 92.4%);
    mask-image:linear-gradient(90deg,transparent 7.6%,#000 15%,#000 85%,transparent 92.4%)}
  .cb-item{margin-right:36px;min-height:56px}
  .cb-logo{height:calc(30px * var(--s,1));max-width:calc(124px * var(--s,1))}
}


/* note 37 - styles.NOTES.txt */
/* note 38 - styles.NOTES.txt */
.did-band{--slant-bg:var(--svc-web);--card:var(--bg);position:relative;z-index:3}
/* Same box as .wrap, so the label and the first pill line up with
   every heading and paragraph on the page rather than sitting in
   their own gutter. */
.did-inner{max-width:1200px;margin:0 auto;padding:0 clamp(22px,4vw,32px);
  padding-top:calc(var(--slant) + 6px);padding-bottom:clamp(26px,2.6vw,36px)}
.did-lab{display:block;margin-bottom:16px;font-family:'Poppins',sans-serif;
  font-weight:700;font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;
  color:#fff;opacity:.78}
.did-row{display:flex;flex-wrap:wrap;justify-content:flex-start;gap:10px}
/* note 39 - styles.NOTES.txt */
.cb-pill{display:inline-flex;align-items:center;white-space:nowrap;
  font-family:'Poppins',sans-serif;font-weight:600;font-size:.86rem;
  color:#fff;background:rgba(15,42,64,.42);border:1px solid rgba(255,255,255,.26);
  border-radius:999px;padding:9px 16px}
@media (max-width:840px){
  .did-inner{padding:calc(var(--slant) + 10px) clamp(22px,4vw,32px) clamp(24px,4vw,32px)}
  .did-row{gap:9px}
  .cb-pill{font-size:.82rem;padding:8px 14px}
}

.faq{--slant-bg:var(--bg);--card:var(--panel)}

.faq .sec-head{margin-bottom:var(--head-gap);text-align:center}
/* note 40 - styles.NOTES.txt */
.faq .sec-head .sec-sub{margin-inline:auto}
@media (min-width:760px){
  .faq .sec-head{display:block}

  .faq-item{text-align:center}
}

.faq-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(24px,3vh,38px) clamp(30px,5vw,72px)}
.faq-item h3{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.015em;
  font-size:1.02rem;line-height:1.3;color:var(--ink);margin-bottom:8px}
.faq-item p{font-size:.93rem;line-height:1.62;color:var(--muted)}
@media (max-width:760px){
  .faq-grid{grid-template-columns:1fr;gap:26px}
}

/* note 41 - styles.NOTES.txt */
/* note 42 - styles.NOTES.txt */
.faq .faq-list{max-width:74ch;margin-inline:auto}
/* note 43 - styles.NOTES.txt */
/* ============================================================
   .sec-cta - AN ASK AT THE FOOT OF AN EXISTING SECTION
   ============================================================
   ONE RULE, DELIBERATELY. Added 13 Sept 2026 after measuring every page and
   finding the only conversion ask sat at 86-92% of pages 8,500-14,300px tall,
   while every mid-page button led AWAY. Andy: "I have concerns about the call
   to action being all the way down the page on most pages ... I would usually
   put it in numerous places down the page."

   ⚠ IT IS NOT A SECTION, AND THAT IS THE WHOLE POINT. A new full-width band
   would reverse band parity on everything below it, on five pages, each needing
   its own arithmetic. A <p> at the end of an existing section's .wrap changes
   nothing structurally. See claude/bands-and-card-surfaces.md for why that
   matters.

   ⚠ A PROOF-PLUS-ASK CARD WAS BUILT, SHOWN AND REJECTED. Andy, 13 Sept: "I am
   leaning towards not adding this new section at all. But finding places to add
   a cta in each page." Do not reintroduce it. The research behind it is in
   claude/cta-depth-and-review-placement.md and the per-page review audit in
   claude/review-service-relevance.md - both still useful, neither a licence to
   build the card.

   ⚠ ON THE REVIEWS WALL the rows live OUTSIDE .wrap (full bleed), so an ask
   there needs its own <div class="wrap"> after them, not an append to the
   existing one. */
.sec-cta{margin:clamp(28px,3.6vh,44px) auto 0;text-align:center}

/* ⚠ USED BY THE HOMEPAGE ONLY. The "More questions ›" button was removed from
   all four SERVICE pages on 13 Sept 2026 and stays on the homepage, because a
   service page carries every question for its product while the homepage carries
   a curated 8 of 38. See partials/sec-faq.php and
   claude/cta-depth-and-review-placement.md. ⚠ Do not take this rule's presence
   as licence to put the button back on a service page. */
.faq .faq-more{max-width:74ch;margin:clamp(24px,3.2vh,38px) auto 0;text-align:center}

.faq-ac{background:var(--card);border-radius:var(--r-sm);overflow:hidden;
  border:1px solid transparent;transition:border-color .2s ease,background-color .2s ease}
.faq-ac + .faq-ac{margin-top:10px}
/* note 44 - styles.NOTES.txt */
.faq-ac.reveal{transform:none;
  transition:opacity .45s ease,border-color .2s ease,background-color .2s ease}
.faq-ac:hover{background:var(--panel-2)}
.faq-ac[open]{border-color:var(--line)}
.faq-ac > summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  gap:16px;padding:15px 20px;text-align:left}
.faq-ac > summary::-webkit-details-marker{display:none}
.faq-ac > summary::marker{content:""}
.faq-ac > summary:focus-visible{outline-offset:-2px}
.faq-ac summary h3{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.015em;
  font-size:1rem;line-height:1.35;color:var(--ink);margin:0}
.faq-ac-x{margin-left:auto;flex:none;width:20px;height:20px;color:var(--blue-hi);
  display:grid;place-items:center}
.faq-ac-x svg{width:100%;height:100%;display:block}
.faq-ac-x .v{transform-origin:12px 12px;transition:transform .22s ease}
.faq-ac[open] .faq-ac-x .v{transform:scaleY(0)}
/* note 45 - styles.NOTES.txt */
/* note 46 - styles.NOTES.txt */
.faq-ac::details-content{display:grid;grid-template-rows:0fr;overflow:hidden;
  transition:grid-template-rows .3s ease,content-visibility .3s allow-discrete}
.faq-ac[open]::details-content{grid-template-rows:1fr}

/* note 47 - styles.NOTES.txt */
.js-acc .faq-ac::details-content{display:block;grid-template-rows:none;
  overflow:visible;transition:none;content-visibility:visible}
.js-acc .faq-ac:not([open]) .faq-ac-a{height:0}
/* note 48 - styles.NOTES.txt */
/* note 49 - styles.NOTES.txt */
.faq-ac-a{min-height:0;overflow:hidden}
.faq-ac-a p{font-size:.96rem;line-height:1.7;color:var(--muted);
  margin:0;padding:0 20px 18px 20px}
@media (prefers-reduced-motion:reduce){
  .faq-ac,.faq-ac.reveal,.faq-ac-x .v{transition:none}
  .faq-ac::details-content{transition:none}
}

/* The expand-all control. Sits between the jump nav and the first group, on
   the right, where it is out of the way until wanted. */
/* note 50 - styles.NOTES.txt */
/* note 51 - styles.NOTES.txt */
.faq-tools{--slant-bg:transparent;position:relative;z-index:1}
.faq-tools .wrap{display:flex;justify-content:flex-end;
  padding-top:clamp(26px,3.4vh,40px);padding-bottom:calc(var(--slant) + 10px)}

.close{--slant-bg:var(--bg);--card:var(--panel)}
.close-panel{background:var(--panel-2);border-radius:var(--r-lg);
  padding:clamp(30px,4vw,54px)}

.close-panel{display:flex;justify-content:center;text-align:center}
.close-cta{max-width:34rem}

.close-cta h2{font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.025em;line-height:1.15;
  font-size:clamp(1.4rem,2.6vw,2.05rem);max-width:22ch;margin-inline:auto}
.close-cta p{color:var(--muted);margin:12px auto 0;max-width:52ch}

.close-who{display:inline-flex;align-items:center;gap:12px;text-align:left;
  margin:22px auto 24px;padding:9px 20px 9px 10px;border-radius:999px;
  background:rgba(255,255,255,.05);border:1px solid var(--line)}
.close-ph{flex:none;width:44px;height:44px;border-radius:50%;overflow:hidden;
  background:var(--card);display:flex;align-items:center;justify-content:center}
.close-ph img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
.close-ini{font-family:'Poppins',sans-serif;font-weight:700;font-size:.8rem;color:var(--dim)}
.close-who-txt{font-size:.86rem;line-height:1.45;color:var(--muted);max-width:30ch}
.close-who-txt b{color:var(--ink);font-weight:700}
.close-cta .btn{display:inline-flex}

/* ---------------- family band ---------------- */

.family{position:relative;overflow:hidden;color:#fff;padding:clamp(64px,9vh,110px) 0;
  background:radial-gradient(circle at 12% 16%,rgba(124,196,245,.16),transparent 54%),
    linear-gradient(135deg,var(--bg) 0%,var(--svc-web) 100%)}
.family::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;transform-origin:50% 50%;will-change:transform;
  background:repeating-radial-gradient(circle at 50% 50%,transparent 0 56px,rgba(255,255,255,.06) 56px 57.5px,transparent 57.5px 58px);
  animation:famPulse 9s ease-in-out infinite}
@keyframes famPulse{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.16);opacity:1}}
@media (prefers-reduced-motion:reduce){.family::before{animation:none}}
.family .wrap{position:relative;z-index:1}
.family .fh{text-align:center;margin-bottom:28px}
.family .fh h2{font-size:clamp(26px,3.4vw,36px);font-weight:700;letter-spacing:-.02em}
.family .fh p{color:#cfe4f5;margin-top:10px;font-size:16px;max-width:52ch;margin-left:auto;margin-right:auto}
.fbrands{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-width:920px;margin:0 auto}
@media (max-width:760px){.fbrands{grid-template-columns:1fr}}
/* note 52 - styles.NOTES.txt */
.fbrand{background:#fff;border-radius:16px;padding:30px 26px;text-align:center;
  transition:box-shadow .15s ease;display:flex;flex-direction:column;align-items:center;color:var(--l-ink)}
.fbrand:hover{box-shadow:0 26px 52px -22px rgba(72,156,216,.55)}

.fbrand img{height:44px;width:auto;max-width:190px;object-fit:contain;object-position:center;margin-bottom:16px}

.fbrand b{font-family:'Poppins',sans-serif;font-weight:700;font-size:1.32rem;
  height:44px;display:flex;align-items:center;margin-bottom:16px}
.fbrand.this{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.2);color:#fff}
.fbrand span{display:block;color:var(--l-muted);font-size:14.5px}
.fbrand.this span{color:#bcd3ea}
.fbrand .go{display:inline-block;margin-top:12px;color:var(--blue-deep);font-weight:600;font-size:13.5px}
.fbrand.this .go{color:#8fc3ec}

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

footer{padding:0 0 clamp(34px,5vh,60px)}
.foot{border-top:1px solid var(--line);padding:clamp(42px,5.5vw,68px) 0 0;color:var(--ink)}

/* ⚠ FOUR CHILDREN SINCE 15 SEPT 2026: brand / Studio / Services / Hosting &
   Maintenance. The brand keeps 1.5fr and the three link cells share the rest. The
   gap had to come down from 72px - at four cells the old clamp pushed the last
   column off the 1440 grid. */
.foot .top{display:grid;grid-template-columns:minmax(0,1.5fr) repeat(3,minmax(0,1fr));
  gap:clamp(26px,3.2vw,48px);align-items:start}
/* ⚠ .fcol-stack IS GONE. It existed for one render, to stack an About heading under
   Studio. Andy took the heading out the same day - "those options can all sit under
   studio" - so the four cells are the grid's own children and nothing needs stacking.
   Do not reintroduce it without a second heading to put in it. */

.foot .flogo img{height:42px;width:auto;display:block}
.foot .flogo.chip img{background:#fff;border-radius:6px;padding:7px 11px}
.foot .blurb{font-size:14.5px;color:var(--muted);margin-top:22px;max-width:38ch;line-height:1.6}
.foot .nap{font-size:13.5px;color:var(--dim);margin-top:18px;line-height:1.6;font-style:normal}
/* Social links under the address (1 Oct 2026). Overrides the column-list ul rules. */
.foot ul.fsocial{flex-direction:row;gap:10px;margin-top:21px}
.foot ul.fsocial a{display:flex;align-items:center;justify-content:center;width:38px;height:38px;
  background:var(--panel-2);border-radius:var(--r-sm);color:var(--dim);transition:color .2s ease,background .2s ease}
.foot ul.fsocial a:hover,.foot ul.fsocial a:focus-visible{color:#fff;background:var(--blue)}
/* Each network's own brand colour on hover. White icon passes 4.5:1 on both. */
.foot ul.fsocial a.s-li:hover,.foot ul.fsocial a.s-li:focus-visible{background:#0a66c2}
.foot ul.fsocial a.s-fb:hover,.foot ul.fsocial a.s-fb:focus-visible{background:#0866ff}

.foot h3{color:var(--blue-hi);font-family:'Poppins',sans-serif;font-weight:700;font-size:13px;
  letter-spacing:.09em;text-transform:uppercase;margin-bottom:16px}
.foot ul{list-style:none;display:flex;flex-direction:column;gap:9px}
.foot ul a{font-size:14.5px;color:var(--ink);transition:color .2s ease}
.foot ul a:hover{color:var(--blue-hi)}
.foot .strip{display:flex;align-items:center;gap:26px;flex-wrap:wrap;font-size:13.5px;color:var(--dim);
  margin-top:clamp(34px,4.5vh,52px);padding-top:24px;border-top:1px solid var(--line)}
.foot .strip a{color:var(--dim);transition:color .2s ease}
.foot .strip a:hover{color:#fff}
.foot .strip .legal{display:flex;gap:24px;margin-left:auto}
@media (max-width:840px){
  /* Brand across the top, then the three link columns two-up: [Studio][Services]
     then [Hosting & Maintenance] on its own row. */
  .foot .top{grid-template-columns:1fr 1fr;gap:30px}
  .foot-brand{grid-column:1 / -1}
  .foot .strip .legal{margin-left:0;width:100%}
}


/* ================= TAP TARGETS - WCAG 2.2 SC 2.5.8 (24x24) =================
   Added 15 Sept 2026 at Andy's request. Four groups measured under 24px in the
   rendered page, on desktop and at 390px:
     .gmark              16x16   the Google logo in 20 review attributions
     .rq-more.textlink   ...x22  "Read in full" on 14 review cards
     .foot ul a          ...x18  the footer column links
     .strip .legal a     ...x22  Accessibility / Privacy / Terms / Cookie settings
   ⚠ EVERY ONE IS FIXED WITHOUT MOVING ANYTHING. The padding that grows the hit
   box is paid for by a matching reduction in the gap or by a negative margin, so
   the rendered layout is identical - verified by screenshot either side, not
   assumed. If you change any of these paddings, change its companion too.
   ⚠ A BARE min-height DOES NOTHING on an inline element - that is why the legal
   row uses inline-flex and the others use padding on an inline-block. And on the
   footer column links a min-height would have added 6px of pitch to every row,
   which is what the gap reduction below is paying for. */

/* 16x16 Google logo -> 24x24. The negative margin cancels the padding, so the
   icon sits exactly where it did. */
.gmark{padding:4px;margin:-4px;box-sizing:content-box}

/* 22px -> 24px. One pixel top and bottom, nothing else to compensate for
   because these sit on their own line. */
.rq-more.textlink{display:inline-block;padding-block:1px}

/* 18px -> 25.2px. ⚠ MEASURED, NOT ASSUMED, AND TWO EARLIER ATTEMPTS WERE WRONG.
   As an inline element the link's hit area was only the 18px text box even though
   its line box was taller; display:block makes the whole 23.2px line the target,
   and 1px of padding clears 24. inline-block was tried first and put the link
   back inside a line box, which added the descender space on top of the padding
   and made every row 32.2px instead of 34.6. Dropping the list gap to 3px was
   also tried and over-corrected the other way, shortening each column by 6px.
   ⚠ THE GAP STAYS AT 9px. Row pitch goes 34.59 -> 34.19, which is 0.4px a row and
   invisible; anything else moves the columns. width:fit-content keeps the hit
   area the width of the words rather than the whole column. */
.foot ul a{display:block;width:fit-content;padding-block:1px}

/* The legal row and the consent button. ⚠ PADDING ALONE WAS WRONG HERE and two
   attempts proved it: 1px gave 23.59px, which rounds to 24 and still fails, and
   2px fixed the desktop while leaving the button at 20px on a phone, because the
   strip's font-size drops and the line box shrinks with it. inline-flex with a
   min-height is size-independent and holds at every width. */
.foot .strip .legal a,.foot .strip .legal .ck-reopen{
  display:inline-flex;align-items:center;min-height:24px}
/* ⚠ FIVE LINKS ARE STILL UNDER 24px AND THAT IS CORRECT, NOT AN OVERSIGHT.
   They are links inside sentences - "website maintenance terms" under the care
   table, and four in the legal pages' prose. SC 2.5.8 exempts them by name:
   "Inline: the target is in a sentence, or its size is otherwise constrained by
   the line-height of non-target text." Padding them would push the lines of the
   paragraph apart and make the underline overlap the line above. Leave them. */
/* ======================= END TAP TARGETS ======================= */

/* ---------------- responsive ---------------- */
@media (max-width:840px){
  .navbar{gap:14px;padding:10px 14px 10px 20px}
  /* .navcta used to be hidden here alongside the links, which left the phone
     with no call to action in the bar at all. It stays, shortened. */
  .navbar .links{display:none}
  .navcta{margin-left:0;padding:8px 14px;font-size:14px}
  /* note 53 - styles.NOTES.txt */
  .acct{margin-left:auto}
  .navbar .burger{display:block}
  /* note 54 - styles.NOTES.txt */
  .navbar .logo img{height:clamp(34px,10vw,50px)}
  .navbar.scrolled{top:10px;padding-top:10px;padding-bottom:10px}
  .navbar.scrolled .logo img{height:clamp(34px,10vw,50px)}
  .foot{padding:34px 24px 26px}
  .foot .top{grid-template-columns:1fr;text-align:center}
  .foot-brand{max-width:none}
  /* note 55 - styles.NOTES.txt */
  .foot .flogo{display:block;width:fit-content;margin-left:auto;margin-right:auto}
  .foot .cols{grid-template-columns:1fr;gap:30px;width:100%}
  .foot .blurb{margin-left:auto;margin-right:auto}
  .foot ul.fsocial{justify-content:center}
  /* Column links are display:block + width:fit-content (tap targets, above),
     which parks them left even under text-align:center. Auto margins centre them. */
  .foot .fcol a{margin-left:auto;margin-right:auto}
  .foot .strip{justify-content:center;text-align:center}
  .foot .legal{justify-content:center;flex-wrap:wrap;gap:16px}
  .subfoot{flex-direction:column;text-align:center;gap:14px}
  .subfoot .r{text-align:center}
  .subfoot-right{flex-direction:column;gap:14px}
}

/* Must stay AFTER the 840px block above or its values win over these. */
@media (max-width:430px){
  /* note 56 - styles.NOTES.txt */
  .navbar{gap:12px;padding:10px 12px 10px 16px}
}

.ck-reopen{background:none;border:0;padding:0;font-family:inherit;font-size:inherit;
  color:inherit;cursor:pointer;transition:color .2s ease}
.cookie{position:fixed;left:16px;bottom:16px;z-index:200;
  width:min(390px,calc(100% - 32px))}
.cookie[hidden]{display:none}

.cookie::before{content:"";position:fixed;inset:0;z-index:-1;
  background:rgba(16,12,22,.55);pointer-events:none}

@media (prefers-reduced-motion:no-preference){
  .cookie{transition:opacity .25s ease,display .25s ease allow-discrete}
  .cookie[hidden]{opacity:0}
  @starting-style{
    .cookie{opacity:0}
  }
}
.cookie-card{background:var(--panel-2);color:var(--ink);border-radius:var(--r-lg);
  padding:clamp(20px,2.4vw,26px);
  box-shadow:0 30px 70px -20px rgba(0,0,0,.8)}
.ck-top{display:flex;gap:14px;align-items:flex-start}
.ck-ic{width:46px;height:46px;border-radius:50%;background:var(--sun);color:#5d4210;
  display:flex;align-items:center;justify-content:center;flex:none}
.ck-ic svg{width:26px;height:26px}
.cookie h3{font-family:'Poppins',sans-serif;font-size:1.15rem;font-weight:700;
  letter-spacing:-.015em;color:var(--ink)}
.cookie p{font-size:.86rem;color:var(--muted);line-height:1.55;margin-top:6px}
.ck-btns{display:flex;gap:10px;margin-top:18px}
.ck-btns .btn{flex:1;justify-content:center;text-align:center}
.ck-links{display:flex;gap:12px;align-items:center;justify-content:center;margin-top:16px}
.ck-links a,.ck-link{color:var(--muted);font-size:.8rem;text-decoration:underline;
  background:none;border:0;cursor:pointer;font-family:inherit;padding:0;
  transition:color .15s ease}
.ck-links span{color:var(--dim)}
.ck-opt{display:flex;justify-content:space-between;align-items:center;gap:16px;
  padding:15px 0;border-bottom:1px solid var(--line)}
.ck-opt:first-of-type{border-top:1px solid var(--line);margin-top:14px}
.ck-opt b{font-size:.92rem;font-weight:700;color:var(--ink);display:block}
.ck-opt>div span{font-size:.8rem;color:var(--muted);display:block;margin-top:2px;line-height:1.4}
.ck-always{font-size:.8rem;color:var(--muted);flex:none;white-space:nowrap}
#ckSave{width:100%;justify-content:center;margin-top:18px}

.ck-toggle{position:relative;width:46px;height:26px;flex:none;cursor:pointer;display:inline-block}
.ck-toggle input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.ck-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.ck-slider{position:absolute;inset:0;background:#4a465e;border-radius:999px;
  transition:background-color .2s ease;pointer-events:none}
.ck-slider::before{content:"";position:absolute;width:20px;height:20px;left:3px;top:3px;
  background:#fff;border-radius:50%;transition:transform .2s ease}
.ck-toggle input:checked + .ck-slider{background:var(--blue)}
.ck-toggle input:checked + .ck-slider::before{transform:translateX(20px)}
.ck-toggle input:focus-visible + .ck-slider{outline:2px solid var(--blue-hi);outline-offset:3px}

@media (hover:hover) and (pointer:fine){
  .ck-reopen:hover{color:var(--ink)}
  .ck-links a:hover,.ck-link:hover{color:var(--ink)}
}
.ck-reopen:focus-visible,.ck-link:focus-visible,.ck-links a:focus-visible{border-radius:3px}
@media (prefers-reduced-motion:reduce){
  .ck-slider,.ck-slider::before,.ck-reopen,.ck-links a,.ck-link{transition:none}
}
@media (max-width:560px){
  .cookie{left:10px;right:10px;bottom:10px;width:auto}
  .ck-btns{flex-direction:column}
}

/* ---------------- service pages ---------------- */
.subnav{position:sticky;top:70px;z-index:70;margin:22px 10px 0}
/* note 57 - styles.NOTES.txt */
.subnav-in{max-width:1200px;margin:0 auto;display:flex;align-items:center;gap:14px;position:relative;
  background:#e9f1f8;border-radius:5px;padding:7px 22px;box-shadow:0 2px 8px -4px rgba(0,0,0,.35);
  transition:border-radius .2s ease,box-shadow .25s ease}
/* note 58 - styles.NOTES.txt */
.subnav.joined .subnav-in{border-top-left-radius:0;border-top-right-radius:0;
  box-shadow:0 4px 13px -6px rgba(0,0,0,.4);animation:sndock .2s ease}
@keyframes sndock{from{top:-5px}to{top:0}}
@media (prefers-reduced-motion:reduce){.subnav.joined .subnav-in{animation:none}}
.navbar.has-sub-joined{border-bottom-left-radius:0;border-bottom-right-radius:0;box-shadow:0 -3px 13px -6px rgba(0,0,0,.35)}
.subnav-links{display:flex;align-items:center;justify-content:flex-end;gap:4px;flex:1;min-width:0}
.subnav-links a{flex:none;padding:9px 14px;border-radius:5px;font-weight:600;font-size:14.5px;
  color:#2f2a45;text-decoration:none;transition:background .2s,color .2s}
.subnav-links a:hover{color:var(--blue-deep)}
.subnav-links a.on{background:#fff;color:var(--blue-deep);box-shadow:0 1px 4px -2px rgba(0,0,0,.3)}
/* note 59 - styles.NOTES.txt */
.subnav-cta{flex:none;margin-left:14px;font-weight:600;font-size:14.5px;padding:9px 20px;
  border-radius:var(--btn-radius);text-decoration:none;color:#fff;white-space:nowrap;
  transition:background-color .25s ease,opacity .28s ease,transform .28s ease,margin-left .28s ease,visibility .28s}
.subnav-cta.hid{opacity:0;visibility:hidden;transform:translateX(14px);pointer-events:none;
  margin-left:calc(-14px - var(--cta-w))}
.subnav-cta.nofx{transition:none}
.subnav-reel{background:#be5151}
.subnav-reel:hover{background:#a44343}
@media (prefers-reduced-motion:reduce){.subnav-cta{transition:background-color .25s ease,opacity .28s ease}
  .subnav-cta.hid{transform:none}}
.sn-jump{display:none}
main section[id]{scroll-margin-top:140px}
@media (max-width:840px){
  .subnav-in{padding:7px 14px 7px 20px}
  .sn-jump{display:flex;align-items:center;gap:10px;width:100%;background:none;border:0;
    font-family:inherit;font-weight:700;font-size:14.5px;color:#2f2a45;cursor:pointer;padding:9px 0}
  .sn-jump .sn-current{color:var(--blue-deep)}
  /* note 60 - styles.NOTES.txt */
  .sn-jump .sn-x{margin-left:auto;display:flex;align-items:center;justify-content:center;
    width:30px;height:30px;flex:none;border-radius:50%;
    background:rgba(31,108,162,.1);color:var(--blue-deep);transition:transform .2s}
  .subnav.open .sn-jump .sn-x{transform:rotate(180deg)}
  .subnav-links{position:absolute;left:0;right:0;top:calc(100% + 6px);flex-direction:column;align-items:stretch;
    background:#fff;border-radius:var(--r-md);box-shadow:0 24px 50px -20px rgba(0,0,0,.55);padding:8px;gap:2px;
    opacity:0;visibility:hidden;transform:translateY(-8px);
    transition:opacity .2s ease,visibility .2s ease,transform .2s ease;z-index:5}
  .subnav.open .subnav-links{opacity:1;visibility:visible;transform:none}
  .subnav-links a{font-size:15px;padding:11px 14px}
  .subnav-cta{position:fixed;z-index:75;right:14px;bottom:calc(14px + env(safe-area-inset-bottom));
    display:inline-flex;align-items:center;gap:10px;margin-left:0;font-size:15px;padding:13px 18px;
    box-shadow:0 14px 30px -10px rgba(0,0,0,.75)}
  .subnav-cta.hid{margin-left:0;transform:translateY(12px) scale(.95)}
  .subnav-reel::before{content:"";flex:none;width:0;height:0;border-left:10px solid currentColor;
    border-top:6.5px solid transparent;border-bottom:6.5px solid transparent}
}
@media (max-width:840px) and (prefers-reduced-motion:reduce){.subnav-cta.hid{transform:none}}

/* ---------------- voiceover demos ---------------- */
/* note 61 - styles.NOTES.txt */
.vodemos{margin-top:20px}
.vodemos h3{font-family:'Poppins',sans-serif;font-size:.82rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dim);margin-bottom:12px}
.vod-row{padding:12px 14px;border-radius:10px;background:rgba(255,255,255,.045);transition:background .2s ease}
.vod-row + .vod-row{margin-top:8px}
.vod-row.on{background:rgba(72,156,216,.15)}
.vod-head{display:flex;align-items:center;gap:14px}
.vod-btn{flex:none;width:42px;height:42px;border:0;border-radius:50%;background:var(--blue);cursor:pointer;
  display:grid;place-items:center;transition:background .2s ease,transform .15s ease}
.vod-btn svg{width:16px;height:16px;fill:#14202b;display:block}
.vod-btn:active{transform:scale(.94)}

@media (hover:hover) and (pointer:fine){
  .vod-row:hover{background:rgba(255,255,255,.08)}
  .vod-row.on:hover{background:rgba(72,156,216,.19)}
  .vod-btn:hover{background:var(--blue-hi)}
}
.vod-meta{flex:1;min-width:0}
.vod-t{font-weight:600;font-size:.96rem;color:var(--ink);line-height:1.3}
.vod-s{font-size:.8rem;color:var(--muted);margin-top:2px}
.vod-time{flex:none;font-size:.8rem;color:var(--muted);font-variant-numeric:tabular-nums}
.vod-bar{display:none;margin-top:10px}
.vod-row.on .vod-bar{display:block}
.vod-seek{display:flex;align-items:center;gap:11px}
.vod-el{flex:none;min-width:34px;font-size:.78rem;color:var(--muted);font-variant-numeric:tabular-nums}
.vod-seek input[type=range]{-webkit-appearance:none;appearance:none;flex:1;height:16px;margin:0;
  background:none;cursor:pointer}
.vod-seek input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:999px;
  background:linear-gradient(var(--blue),var(--blue)) 0/var(--p,0%) 100% no-repeat,rgba(255,255,255,.16)}
.vod-seek input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:13px;height:13px;
  margin-top:-4.5px;border-radius:50%;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.6)}
.vod-seek input[type=range]::-moz-range-track{height:4px;border-radius:999px;background:rgba(255,255,255,.16)}
.vod-seek input[type=range]::-moz-range-progress{height:4px;border-radius:999px;background:var(--blue)}
.vod-seek input[type=range]::-moz-range-thumb{width:13px;height:13px;border:0;border-radius:50%;background:#fff}
.vod-seek input[type=range]:focus-visible{outline-offset:2px;border-radius:999px}
.vod-row noscript audio{width:100%;margin-top:10px}
@media (prefers-reduced-motion:reduce){.vod-row,.vod-btn{transition:none}}

.hero.svchero{min-height:min(74vh,780px);
  padding:calc(96px + 4vh) 0 clamp(100px,14vh,170px)}
.svchero .hero-copy h1{max-width:20ch}

/* note 62 - styles.NOTES.txt */
.hero:not(:has(+ .slanted))::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:var(--slant);
  background:var(--hero-cut,var(--bg));z-index:1;pointer-events:none;
  clip-path:polygon(0 100%,100% 0,100% 100%)}
.svchero-photo{position:absolute;inset:0;z-index:0}
.svchero-photo img{width:100%;height:100%;object-fit:cover}
.svchero-photo::after{content:"";position:absolute;inset:0;background:
  radial-gradient(1100px 640px at 8% 70%,rgba(32,26,40,.78) 0%,rgba(32,26,40,.52) 40%,rgba(32,26,40,.18) 70%,rgba(32,26,40,.03) 100%),
  linear-gradient(52deg,rgba(32,26,40,.62) 0%,rgba(32,26,40,.28) 30%,rgba(32,26,40,.07) 62%,rgba(32,26,40,0) 100%)}
/* ⚠ AN EXTRA HORIZONTAL SCRIM, FOR A HERO PHOTOGRAPH THAT IS TOO BRIGHT
   BEHIND THE HEADLINE. Added 11 Sept 2026 for Chaseway Lane Botanicals,
   whose hero is a jar in sunlit foliage. Opt in with class="svchero-dim" on
   the hero section; no other page is touched.

   ⚠ WHY A 90deg BAND AND NOT JUST MORE OF THE HOUSE GRADIENT. The house
   radial is anchored at 8% of the VIEWPORT while the copy sits in a centred
   1136px wrap - so the wider the screen, the further the headline drifts out
   of the dark part. Raising the house alphas fixed 1400px and made 1920px
   WORSE: white went 3.44 -> 5.08 at 1400 and 3.44 -> 2.58 at 1920. That is
   the whole reason this is a different shape rather than a bigger number.

   Measured against the painted pixels at four widths, worst case under any
   glyph, after this band goes on:

              white   amber          (bars: 4.5:1 normal, 3:1 large)
     1920px   5.04    3.58
     1600px   5.66    4.29
     1400px   7.63    4.68
     1100px   8.56    5.43

   ⚠ RE-MEASURE IF THE PHOTOGRAPH CHANGES. Do not assume it carries over -
   that is the whole reason the numbers are written down here. Method: shoot
   the hero twice, once with .hero-copy hidden, difference the two to find
   the glyphs, then read the background under them. */
.svchero-dim .svchero-photo::after{background:
  linear-gradient(90deg,rgba(32,26,40,.62) 0%,rgba(32,26,40,.50) 46%,rgba(32,26,40,0) 74%),
  radial-gradient(1100px 640px at 8% 70%,rgba(32,26,40,.78) 0%,rgba(32,26,40,.52) 40%,rgba(32,26,40,.18) 70%,rgba(32,26,40,.03) 100%),
  linear-gradient(52deg,rgba(32,26,40,.62) 0%,rgba(32,26,40,.28) 30%,rgba(32,26,40,.07) 62%,rgba(32,26,40,0) 100%)}
.svchero-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.92fr);gap:clamp(28px,4vw,72px);align-items:center;position:relative;z-index:2}
.svchero-shot img{width:100%;height:auto;display:block;border-radius:var(--r-lg);transform:rotate(2.2deg);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.75)}
@media (max-width:900px){
  .svchero-grid{grid-template-columns:1fr}
  .svchero-shot{display:none}
}
.svcproof-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
.svcp{display:block;background:var(--card);border-radius:var(--r-md);overflow:hidden;
  transition:transform .2s ease,background .2s ease}
@media (hover:hover) and (pointer:fine){.svcp:hover{transform:translateY(-3px);background:var(--panel-2)}}
.svcp img{width:100%;height:auto;display:block;aspect-ratio:16/10;object-fit:cover;object-position:top}
.svcp figcaption{padding:16px 18px 18px}
.svcp b{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:1.02rem;color:var(--ink)}
.svcp span{display:block;font-size:.88rem;color:var(--muted);margin-top:4px}
@media (max-width:900px){.svcproof-grid{grid-template-columns:1fr}}
.svc-prose{--slant-bg:var(--bg);--card:var(--panel)}
.svc-wash{--slant-bg:var(--wash);--card:var(--bg)}
.svc-split{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);gap:clamp(28px,4.5vw,72px);align-items:center}
/* note 63 - styles.NOTES.txt */
.svc-split.flip{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr)}
.svc-split.flip>.svc-media{order:-1}
.svc-media img{width:100%;height:auto;display:block;border-radius:var(--r-lg);
  box-shadow:0 30px 70px -28px rgba(0,0,0,.7)}
.ph-tile{aspect-ratio:4/3;background:var(--card);border-radius:var(--r-lg);
  display:grid;place-items:center;text-align:center;padding:20px}
.ph-tile b{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:.92rem;color:var(--dim)}
.ph-tile span{display:block;font-size:.8rem;color:var(--dim);margin-top:6px;max-width:30ch}
@media (max-width:900px){
  /* ⚠ .flip MUST BE RESET HERE TOO. .svc-split.flip is specificity (0,2,0)
     and this rule is (0,1,0); a media query adds no specificity of its own,
     so without the second selector the flipped sections stayed TWO COLUMNS
     on a phone - the text column collapsed to 143px on a 390px screen,
     about four words a line. Andy reported it on three pages, 9 Sept 2026.
     Same trap as .gal-4 .gal-wall. If a modifier ever changes columns, it
     has to be unwound at every breakpoint. */
  .svc-split,.svc-split.flip{grid-template-columns:1fr}
  .svc-split.flip>.svc-media{order:0}
}
.svc-prose .sec-head{margin-bottom:clamp(18px,2.6vh,30px)}
.svc-prose .nar-lead{max-width:70ch}
.mini-gal .mg-main{position:relative;aspect-ratio:4/3;border-radius:var(--r-lg);overflow:hidden;
  box-shadow:0 30px 70px -28px rgba(0,0,0,.7)}
.mini-gal .mg-slide{position:absolute;inset:0;margin:0;opacity:0;transition:opacity .7s ease}
.mini-gal .mg-slide.on{opacity:1}
.mini-gal .mg-slide img{width:100%;height:100%;object-fit:cover;border-radius:0;box-shadow:none}
.mini-gal .mg-slide figcaption{position:absolute;left:14px;bottom:12px;padding:6px 12px;border-radius:999px;
  background:rgba(22,18,30,.72);color:#fff;font-size:.78rem;font-weight:600;letter-spacing:.02em;
  backdrop-filter:blur(4px)}
.mg-thumbs{display:flex;gap:10px;margin-top:12px}
.mg-thumbs button{flex:1;padding:0;border:2px solid transparent;border-radius:10px;overflow:hidden;
  background:var(--panel);cursor:pointer;opacity:.55;transition:opacity .25s,border-color .25s}
.mg-thumbs button img{width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;display:block;border-radius:0;box-shadow:none}
.mg-thumbs button.on,.mg-thumbs button:hover{opacity:1;border-color:var(--blue-hi)}
.mg-thumbs button:focus-visible{outline-offset:2px}
.svc-prose .nar-lead + .nar-lead{margin-top:18px}
/* note 64 - styles.NOTES.txt */
.svc-prose .nar-lead + .btn{margin-top:28px}
.svc-prose .textlink{margin-top:22px}
.svc-xsell p{max-width:64ch}
.svc-xsell .textlink{margin-right:26px}

.spec-head.centred{display:block;text-align:center;margin-bottom:var(--head-gap-l)}
.spec-head.centred h2{margin-inline:auto;max-width:none}
.spec-head.centred .spec-sub{margin:12px auto 0;max-width:56ch}
.sec-head.centred{display:block;text-align:center;margin-bottom:var(--head-gap-l)}
.sec-head.centred .sec-sub{margin:10px auto 0;max-width:56ch}
.spec-ic{display:grid;place-items:center;width:64px;height:64px;border-radius:50%;
  background:rgba(124,196,245,.12);color:var(--blue-hi);margin:0 auto 16px}
.spec-ic svg{width:26px;height:26px}
.spec-centre .spec-grid{gap:clamp(30px,4vh,48px) clamp(24px,2.6vw,40px)}
.spec-centre .spec-item{text-align:center}
.spec-centre .spec-item b{padding-left:0}
.spec-centre .spec-item b::before{display:none}
.spec-centre .spec-item p{padding-left:0}
/* note 65 - styles.NOTES.txt */
.spec-cta{margin-top:clamp(30px,4.4vh,52px);text-align:center}
.steps-centre .step{background:none;border-radius:0;padding:0;text-align:center}
.steps-centre .steps{gap:clamp(30px,4vh,48px) clamp(24px,2.6vw,40px)}
.steps-centre .step h3{margin:0 0 8px}

/* ================ THE HOSTING AND CARE TABLES - hosting.php #plans ==========
   Rebuilt 13 Sept 2026 as real hosting-comparison tables, after Andy said the
   previous section "seems off" and, of the spec-list version, "They do not look
   like this. The price also appears nowhere here."

   ⚠ THE SHAPE CAME FROM READING HOSTINGER, KRYSTAL AND 20i's OWN COMPARISON
   TABLE. Four things hold on all three and every earlier draft here broke at
   least two of them:

     1. THE PRICE LIVES INSIDE THE TABLE, at the top of its column - not in a
        separate block further down the page.
     2. A CTA SITS IN THAT HEADER, directly under the price.
     3. VALUES ARE WORDS AND NUMBERS, NEVER A COLUMN OF TICKS. Krystal's table
        reads "1", "5", "Unlimited", "Daily", "Weekdays 9:00-20:00".
     4. ROWS ARE GROUPED under small section labels, and the table is LONG -
        Krystal runs about 49 rows across seven groups.

   ⚠ THE TABLE SURFACE IS LIGHTER THAN THE BAND IT SITS ON. The first attempt
   painted the headers --bg, the darkest colour in the palette, so the tables
   sat darker than the page. Andy: "The tables themselves also look very dark."
   --panel-2 on a --bg band is the right way round. Do not flip it.

   ⚠ NO OUTLINES. Hairline row separators and a faint zebra only. */

.ptop{text-align:center;margin:0 auto clamp(34px,4.6vh,48px)}
.ptop h2{font-size:clamp(1.9rem,3.4vw,2.6rem);font-weight:700;letter-spacing:-.03em;margin:0 0 12px}
.ptop p{color:var(--muted);font-size:1.04rem;line-height:1.65;max-width:64ch;margin:0 auto}
/* ⚠ THE SECOND PARAGRAPH IS WHY THIS RULE EXISTS. .ptop p carries margin:0 auto,
   which was right while every .ptop had one paragraph. The maintenance section
   gained a second one on 15 Sept (the auto-core-updates reason) and the two ran
   together into one block with no break. Scoped to p + p so the single-paragraph
   .ptop above #plans does not move. */
.ptop p + p{margin-top:14px}

/* the care table is four columns wide, so it scrolls rather than crushes */
.ptbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.ptbl{width:100%;border-collapse:separate;border-spacing:0;background:var(--panel-2);
  border-radius:var(--r-lg);overflow:hidden}
.ptbl th,.ptbl td{text-align:left;vertical-align:top;padding:15px clamp(14px,1.7vw,20px)}

/* ---- the priced header ---- */
.p-hd{color:#fff;background:var(--bh-pink-hd)}
/* ⚠ CENTRED IN THE HOSTING HEADER ONLY. Andy, 13 Sept 2026: "Make logo and text
   central in the headers" - then, on being asked: "The hosting header i mean".
   The logo and the pink block are one wide banner across the top of that table,
   so centring reads as deliberate there. The three CARE headers are narrow
   columns sitting over columns of ranged-left copy, and centring them broke the
   alignment down the table - they stay left. Body rows are always left. */
.p-host .p-hd{text-align:center}
.p-hd .lab{display:block;font-family:'Poppins',sans-serif;font-weight:700;font-size:.72rem;
  letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.92);margin-bottom:9px}
.p-hd .fig{display:block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.7rem,3vw,2.05rem);line-height:1;letter-spacing:-.03em}
.p-hd .per{font-family:'Figtree',sans-serif;font-weight:400;letter-spacing:0;
  font-size:.88rem;color:rgba(255,255,255,.88);margin-left:7px}
.p-hd .sub{display:block;font-size:.84rem;color:rgba(255,255,255,.92);margin-top:8px}
.p-host .p-hd .sub{max-width:34ch;margin-left:auto;margin-right:auto}
.p-hd .btn{margin-top:15px;background:#fff;color:var(--bh-pink-hd)}
@media (hover:hover) and (pointer:fine){.p-hd .btn:hover{background:#fff;color:#a81f40}}
.p-c1{background:var(--care-1)} .p-c2{background:var(--care-2)} .p-c3{background:var(--care-3)}

/* ---- the corner stub. Hosting carries the logo, care carries the word. ---- */
/* ⚠ THE TABLE CENTRES THE LOGO, NOT FLEXBOX. The first version wrapped it in a
   flex box with height:100% and a min-height. A span's height:100% inside a <th>
   resolves against nothing useful, so it stayed 150px tall inside a cell the
   pink header had stretched to ~300px, and the logo sat near the top. Andy:
   "On desktop, that logo is not central."
   vertical-align:middle plus text-align:center on the CELL is the native table
   behaviour and it is exact at any cell height. Do not reintroduce the wrapper's
   height rules. */
.p-corner{background:#f7f5f7;vertical-align:middle!important;text-align:center;
  padding:26px clamp(14px,1.7vw,20px)}
.p-corner span{display:block}
.p-corner img{display:inline-block;width:clamp(120px,13vw,170px);height:auto}
/* ⚠ the care stub is NOT white - Andy, 13 Sept: "no need for that area to be
   white". A soft wash of the lightest green, so the corner still reads as
   deliberate rather than as a gap. */
.p-stub{background:rgba(75,124,76,.22);vertical-align:middle}
.p-stub span{display:flex;align-items:center;justify-content:center;height:100%;min-height:96px;
  font-family:'Poppins',sans-serif;font-weight:700;font-size:.82rem;letter-spacing:.18em;
  text-transform:uppercase;color:#b7dab8}

/* ---- rows ---- */
.p-grp td{font-family:'Poppins',sans-serif;font-size:.72rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:#cbbcd6;padding:26px clamp(14px,1.7vw,20px) 8px;
  background:rgba(255,255,255,.03)}
.p-r th,.p-r td{border-top:1px solid rgba(255,255,255,.07)}
.p-r:nth-of-type(even) th,.p-r:nth-of-type(even) td{background:rgba(255,255,255,.028)}
.p-r th{font-weight:600;font-size:.95rem;color:var(--ink);width:30%}
.p-r td{font-size:.95rem;color:#bdb4c8;line-height:1.45}

/* the scroll hint and the fade - both phone-only, see the note in hosting.php */
.pscroll-hint{display:none}
.pscroll{position:relative}

.pcare{margin-top:clamp(50px,6.6vh,80px)}
.pcare-h{text-align:center;margin-bottom:clamp(22px,3vh,30px)}
.pcare-h h3{font-family:'Poppins',sans-serif;font-size:clamp(1.15rem,2vw,1.35rem);font-weight:700;
  letter-spacing:-.02em;margin:0 0 8px}
.pcare-h p{color:var(--muted);font-size:.98rem;line-height:1.6;max-width:64ch;margin:0 auto}
.pfoot{text-align:center;color:var(--muted);font-size:.93rem;line-height:1.6;
  max-width:70ch;margin:clamp(20px,2.8vh,28px) auto 0}
/* ⚠ THE RETENTION NOTE under the hosting table - the one sentence kept from
   the deleted #leaving section. Sized between the table and the VAT line so it
   reads as a closing remark on the price, not as another table row. */
.ptbl-note{max-width:62ch;margin:22px auto 0;text-align:center;color:var(--muted);
  font-size:.95rem;line-height:1.62}
/* ⚠ THE HOSTING TERMS LINK IN THE NOTE UNDER THE PRICE TABLE. Andy, 15 Sept 2026:
   "it feels hidden right now - make it a different colour too. Maybe the pink?"
   ⚠ --bh-pink MEASURES 4.59:1 ON --bg #201a28, so it clears AA for this text at
   .95rem. It is the Bang! Hosting logo pink and it is already a token.
   ⚠ --svc-care #ec0540 WAS THE OTHER CANDIDATE AND IT FAILS: 3.76:1 on the same
   background. Do not swap the pinks over.
   ⚠ AND THIS ONLY HOLDS BECAUSE #plans SITS ON --bg. On --wash #2d2539 the same
   pink is 3.96:1 and fails. If that band ever flips, this colour has to change
   with it - see the band alternation rule at the top of hosting.php.
   The underline, offset and half-strength decoration colour are lifted from
   .lg-prose a so an inline link reads the same way across the site. */
.ptbl-note a{color:var(--bh-pink);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:rgba(251,47,98,.5)}
.ptbl-note a:hover,.ptbl-note a:focus-visible{text-decoration-color:var(--bh-pink)}
/* ⚠ THE CARE TERMS LINK UNDER THE CARE TABLE IS GREEN, NOT THE PINK USED UNDER THE
   PRICE TABLE, AND NOT THE SITE'S USUAL BLUE EITHER. Andy, 15 Sept 2026: "maybe the
   care link should be green as that is the colour of the care section?"
   ⚠ IT USES --care-hi AND MUST NOT BE SWAPPED FOR --care-1/2/3. Those are the
   column backgrounds and measure 2.99:1 or worse as text on this band.
   ⚠ AND IT CANNOT BE THE PINK. This section is svc-wash #2d2539, where --bh-pink
   is 3.96:1 and fails AA at this size. The pink under the price table only clears
   AA because #plans sits on --bg. Do not "make them match".
   Same underline idiom as .lg-prose a, so every inline link on the site behaves
   the same way whatever colour it is. */
.pfoot-terms{margin-top:10px}
.pfoot-terms a{color:var(--care-hi);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:rgba(145,202,146,.5)}
.pfoot-terms a:hover,.pfoot-terms a:focus-visible{text-decoration-color:var(--care-hi)}
.pvat{text-align:center;color:var(--muted);font-size:.88rem;margin:clamp(26px,3.4vh,36px) auto 0}

/* ⚠ ONLY THE CARE TABLE SCROLLS. It has four columns and cannot fit a phone.
   The hosting table has two and fits, so a blanket min-width made it scroll for
   no reason - the price header was cut off at 420px. */
@media (max-width:820px){
  .pcare .ptbl{min-width:660px}
  .p-corner{padding:20px 14px}
  .p-corner img{width:clamp(104px,30vw,150px)}
  .p-r th{width:36%}
  .ptbl th,.ptbl td{padding:13px 14px}

  /* ⚠ THE HOSTING TABLE STACKS COMPLETELY ON A PHONE. Andy: "On mobile it looks
     terrible. It should dropdown underneath each other." Logo above the price,
     and every row's label above its value.

     ⚠ thead, tr AND the cells all need display:block. Setting it on the row
     alone leaves the row a block child of a table-header-group, and the cells
     then take their width from the tbody's first column - the header came out
     about two thirds wide. All four, or none.

     ⚠ THE ROW RULE MOVES TO THE tr. With the cells as blocks, a border-top on
     both th and td draws the hairline twice per row. */
  .p-host thead,.p-host thead tr,.p-host thead th,
  .p-host tbody,.p-host tbody tr,.p-host tbody th,.p-host tbody td{display:block;width:auto}
  .p-host .p-corner{border-radius:0}
  .p-host .p-r th,.p-host .p-r td{border-top:0}
  .p-host .p-r{border-top:1px solid rgba(255,255,255,.07)}
  .p-host .p-r:nth-of-type(even){background:rgba(255,255,255,.028)}
  .p-host .p-r:nth-of-type(even) th,.p-host .p-r:nth-of-type(even) td{background:none}
  .p-host .p-r th{padding-bottom:2px;font-size:.9rem;color:var(--muted)}
  .p-host .p-r td{padding-top:0;font-size:1rem;color:var(--ink)}
  .p-host .p-grp td{padding-top:24px}

  /* the scroll is signposted rather than left to be discovered */
  .pscroll-hint{display:block;text-align:right;margin:0 0 8px;
    font-family:'Poppins',sans-serif;font-weight:700;font-size:.72rem;
    letter-spacing:.14em;text-transform:uppercase;color:#b7dab8}
  .pscroll::after{content:"";position:absolute;top:0;right:0;bottom:0;width:46px;
    pointer-events:none;border-radius:0 var(--r-lg) var(--r-lg) 0;
    background:linear-gradient(to left,var(--bg),rgba(32,26,40,.72) 42%,rgba(32,26,40,0))}
}

/* ---------------- the hosting demo band - hosting.php #demo ----------------
   Andy missed the first demo button entirely, so it is a full-width strip now,
   on the same device as the studio banner: a .slanted section with its own
   --slant-bg and --pad:var(--band-pad), symmetric top and bottom.

   TWO IDEAS TAKEN FROM ANDY'S OWN BANNER on the abandoned Bang! Hosting site,
   which he sent as the reference:
     1. THE HEADING SITS IN A SOLID KNOCKOUT BOX - white block, band-coloured
        type. That is the signature move of his design and it is what makes the
        strip impossible to scroll past. ⚠ Do not flatten it back to plain
        white type on blue.
     2. A GRADIENT ACROSS THE BAND rather than a flat fill, light to deep along
        the reading direction.
   His was green because that site had a different palette; here it takes the
   site's own blues.

   ⚠ --slant-bg stays a SOLID token so _dev/bandcheck.js still reads a real
   colour; the gradient is painted over it on ::before. */
.demoband{--slant-bg:var(--svc-web);--card:var(--bg);color:#fff;--pad:var(--band-pad)}
/* ⚠ THE LIGHT END OF THIS GRADIENT WAS #2f8ecb AND IT FAILED WCAG AA.
   All the band's text sits on the pale left end, and measured on the rendered
   page the body paragraph and the eyebrow were both 3.80:1 against a 4.5:1
   floor. Not a judgement call - a failure, on live copy, found 13 Sept 2026.
   The light end was swept and #2878ad is the LIGHTEST value that clears every
   floor: body and eyebrow 4.67, heading 5.06. #2572a6 gives more headroom
   (4.93) at the cost of a flatter sweep, if the band is ever redrawn.
   ⚠ DO NOT LIGHTEN THE 0% STOP. Anything above #2878ad reintroduces the
   failure, and the check that catches it is a rendered measurement with the
   text made TRANSPARENT - not visibility:hidden, which hides the backdrop too. */
.demoband::before{background:linear-gradient(100deg,#2878ad 0%,var(--svc-web) 44%,#17527d 100%)}
.demoband-in{display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(24px,4vw,56px);align-items:center}
/* ⚠ THIS IS THE HERO KICKER, DELIBERATELY AND EXACTLY. Same background, same
   padding, same var(--btn-radius). Andy, 13 Sept 2026: "make the pill less of a
   pill and more of a rectangle, use the same border radius as the hero boxes."
   ⚠ IT IS DARK, NOT TRANSLUCENT WHITE, AND THAT IS THE POINT TWICE OVER:
   1. A 18%-white box measured 3.61:1 for its own text - it FAILS AA, because
      tinting the backdrop toward white attacks white type. The dark box is
      15.65:1.
   2. The whole reason this band was reworked is that it had two white shapes
      competing. Putting a white-ish one back, smaller, recreates it.
   ⚠ If this ever needs to be lighter, rgba(0,0,0,.26) reads softer and still
   measures 7.84:1. Do not go translucent white. */
.demoband-k{display:inline-block;font-family:'Poppins',sans-serif;font-weight:700;
  font-size:.92rem;letter-spacing:.11em;text-transform:uppercase;color:#fff;
  background:rgba(32,26,40,.9);padding:9px 16px;border-radius:var(--btn-radius);
  margin-bottom:18px}
/* ⚠ NO WHITE KNOCKOUT BOX ON THIS HEADING. It used to be background:#fff with
   color:var(--svc-web) and a 12px radius - the only treatment of its kind
   anywhere on the site, and it was the same fill and the same text colour as
   .btn-onband sitting a few hundred pixels to its right. Andy, 13 Sept 2026:
   "This white background is interfering with the button. They look the same.
   This is the only place on the entire site it is used."
   ⚠ THE BUTTON IS NOW THE ONLY SOLID WHITE SHAPE ON THE BAND, which is how it
   reads as the one thing to press without being made bigger. Do not put a
   white panel of any kind back on this band.
   ⚠ display:block MATTERS. The heading was inline-block for the old box; left
   inline-block next to an inline-block eyebrow it flows onto the same line. */
.demoband h2{display:block;color:#fff;
  font-family:'Poppins',sans-serif;font-weight:700;letter-spacing:-.03em;line-height:1.15;
  font-size:clamp(1.35rem,2.7vw,2.05rem);margin:0;max-width:24ch;text-wrap:balance}
/* ⚠ :not(.demoband-k) IS LOAD-BEARING. The eyebrow is a <p>, so this rule
   used to win over .demoband-k on specificity and quietly gave it 94% white,
   line-height 1.65 and an 18px TOP margin it was never meant to have - which is
   why it measured 2px taller than the identical hero kicker. Found by comparing
   the two computed styles side by side, 13 Sept 2026. Keep them comparable:
   the eyebrow and .kicker should report the same background, colour, radius and
   padding. */
.demoband p:not(.demoband-k){color:rgba(255,255,255,.94);font-size:1rem;line-height:1.65;
  max-width:54ch;margin-top:18px}
.demoband-cta{display:flex;flex-direction:column;align-items:flex-start;gap:12px}
/* ⚠ NO SIZE OVERRIDES HERE. This rule used to set font-size:1.02rem and
   padding:15px 26px, which made every "Book a hosting demo" button noticeably
   bigger than every other button on the site. Andy, 13 Sept 2026: "Book hosting
   demo buttons are too big. They are out of place compared to the rest of the
   site." He was right - .btn is 14.5px / 9px 20px everywhere else, and these
   two were the only exceptions in the stylesheet.
   ⚠ .btn-onband NOW ONLY CHANGES COLOUR: white on a coloured band. Do not add
   a font-size or a padding back to it. If a CTA needs more weight, give it more
   space around it, not a bigger box. */
.btn-onband{background:#fff;color:var(--svc-web);white-space:nowrap;
  box-shadow:0 8px 20px -8px rgba(0,0,0,.5)}
@media (hover:hover) and (pointer:fine){.btn-onband:hover{background:#eaf4fd;color:#17527d}}
.demoband-note{font-size:.84rem;color:rgba(255,255,255,.78)}
@media (max-width:860px){
  .demoband-in{grid-template-columns:1fr;gap:26px}
  .demoband-cta{align-items:stretch}
  .btn-onband{text-align:center}
}

/* note 66 - styles.NOTES.txt */
.gal-wall{columns:3;column-gap:10px}
/* note 67 - styles.NOTES.txt */
.gal-4 .gal-wall{columns:4}
/* note 68 - styles.NOTES.txt */
.gal-wall:has(.gw-item:only-child){columns:1;max-width:340px;margin-inline:auto}
/* note 103 - styles.NOTES.txt */
.gal-wall:has(.gw-item:nth-child(2):last-child){columns:2}
.gw-item{display:block;break-inside:avoid;margin:0 0 10px;
  border-radius:var(--r-md);overflow:hidden;background:var(--card);
  transition:transform .2s ease,box-shadow .2s ease}
.gw-item:hover{transform:translateY(-3px);box-shadow:0 18px 36px -18px rgba(0,0,0,.7)}
.gw-item img{width:100%;height:auto;display:block}
.gw-empty{color:var(--muted);font-size:.95rem}

/* note 109 - styles.NOTES.txt */
.screens{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(16px,1.9vw,24px);margin-top:clamp(24px,3.4vh,40px)}
.screens .scr{margin:0}
 /* ⚠ NO BORDER ON IMAGE TILES. Andy, 10 Sept 2026: "We seem to have white
    outlines to the branding images. I do not want this ... I do not want a
    border on images." Removed here, on .cartdemo-stage and on .cs-shot img -
    everywhere an image had one.

    ⚠ AND IT WAS WORSE THAN A 1px LINE, WHICH IS WHY IT LOOKED WHITE. The rule
    was border:1px solid var(--line), i.e. rgba(255,255,255,.10) - on its own
    almost invisible. But a background paints UNDER its border by default
    (background-clip:border-box) and .screens.fit sets that background to
    var(--plate), #f7f5f7. The image is clipped to the PADDING box, so it never
    reached the border strip, and what showed all the way round every tile was
    1px of near-white plate at 90% opacity. Measured off the rendered page:
    (52,44,63) section, then (247,246,247), then the artwork.
    ⚠ SO DO NOT "RESTORE THE SUBTLE BORDER". On a fit tile it is not subtle.
    Checked with _dev/ringcheck.js, which measures pixels, not CSS. */
.scr-shot{display:block;border-radius:var(--r-md);overflow:hidden;background:var(--card);
  line-height:0;
  transition:transform .2s ease,box-shadow .2s ease}
.scr-shot:hover{transform:translateY(-3px);box-shadow:0 18px 36px -18px rgba(0,0,0,.7)}
.scr-shot img{width:100%;height:auto;display:block}
.screens figcaption{margin-top:11px;font-size:.86rem;line-height:1.6;color:var(--muted)}
/* A short last row is centred, never parked on the left - the same fault as
   the two-image wall in note 103. One left over centres in column 2; two
   left over shift right by half a column. */
.screens > .scr:nth-last-child(1):nth-child(3n+1){grid-column:2/3}
.screens > .scr:nth-last-child(2):nth-child(3n+1){
  margin-left:calc(50% + (clamp(16px,1.9vw,24px) / 2))}
/* note 114 - styles.NOTES.txt */
.cartdemo{margin:clamp(28px,4vh,44px) 0 0}
.cartdemo-stage{position:relative;overflow:hidden;border-radius:var(--r-md);
  background:var(--card);line-height:0}
.cartdemo-shop{display:block;width:100%;height:auto}
/* MEASURED, NOT CHOSEN. Both numbers come off Andy's two grabs of the real
   shop - the scrim by least-squares over 3.3M page pixels (alpha .702/.704/
   .703 across R/G/B, so it really is one flat overlay), the drawer width from
   where its own shadow starts. Do not round them to something tidier. */
.cartdemo-scrim{position:absolute;inset:0;background:rgba(53,57,46,.70)}
.cartdemo-drawer{position:absolute;top:0;right:0;height:100%;width:23.96%;
  object-fit:cover;object-position:left top}
.cartdemo-bar{display:flex;flex-direction:column;align-items:center;gap:14px;
  margin-top:16px}
/* ⚠ CENTRED, LIKE EVERYTHING ELSE IN THIS SECTION. The first version put the
   button and the caption in a left-aligned row under a full-width figure,
   inside a section whose heading and prose are both centred. That is the
   mixed-alignment fault the case study build notes have been pulled up on
   four times. The caption also takes the same 64ch measure as .cs-text above
   it, so the two columns of type line up rather than one running 1136px. */
.cartdemo figcaption{margin:0;max-width:64ch;text-align:center;
  font-size:.86rem;line-height:1.6;color:var(--muted)}
/* ⚠ THE OPEN STATE IS THE DEFAULT AND THAT IS THE POINT. With no JavaScript
   this is simply a photograph of the shop with the basket open, which is a
   perfectly good picture. The script adds .js-cartdemo, which closes it and
   reveals the button. Nothing here depends on JS to look finished. */
.cartdemo-btn{display:none}
.js-cartdemo .cartdemo-btn{display:inline-flex}
.js-cartdemo .cartdemo-scrim{opacity:0;transition:opacity .42s ease}
.js-cartdemo .cartdemo-drawer{transform:translateX(101%);
  transition:transform .42s cubic-bezier(.22,.61,.36,1)}
.js-cartdemo.is-open .cartdemo-scrim{opacity:1}
.js-cartdemo.is-open .cartdemo-drawer{transform:translateX(0)}
@media (prefers-reduced-motion:reduce){
  .js-cartdemo .cartdemo-scrim,.js-cartdemo .cartdemo-drawer{transition-duration:.01ms}
}
/* ⚠ ON A PHONE THE DEMO BECOMES THE BASKET ALONE, AND THE INTERACTION GOES.
   The shop grab is a DESKTOP layout. At 390px it draws about 346px wide - a
   3.3x reduction, so none of its type is readable and the drawer inside it is
   83px. That is not a demonstration of anything.

   This is the same call the monitor makes further up the page, which switches
   its inner scroller off on touch: show the half that survives the size. The
   basket is the half worth seeing and it is portrait, so it reads perfectly at
   this width. The caption carries the rest.

   ⚠ NOT just a smaller version of the desktop treatment. Do not "restore" the
   button here - with the page grab hidden there is nothing for the drawer to
   slide over, so the control would toggle a picture against nothing. */
@media (max-width:700px){
  .cartdemo-stage{max-width:340px;margin-inline:auto;border-radius:var(--r-md)}
  .cartdemo-shop,.cartdemo-scrim{display:none}
  .cartdemo-drawer{position:static;width:100%;height:auto;
    transform:none !important;transition:none !important}
  .js-cartdemo .cartdemo-btn{display:none}
}

/* A single still inside a prose section - see note 114. */
.cs-shot{margin:clamp(28px,4vh,44px) 0 0}
/* ⚠ THE FRAME IS ON THE IMAGE, NOT ON A WRAPPING LINK, so a .cs-shot looks
   identical whether or not it opens a lightbox. It was the other way round
   at first and taking the anchor off the Bang! Cart shot stripped its border
   and corners with it. */
.cs-shot img{display:block;width:100%;height:auto;border-radius:var(--r-md);
  background:var(--card)}
/* ⚠ SCOPED TO .gw-item, NOT TO EVERY ANCHOR IN THE FIGURE. Written first as
   .cs-shot a, which also caught the button underneath the caption and turned
   it into a 1136px full-width bar - .btn is inline-flex and this said block. */
.cs-shot a.gw-item{display:block;border-radius:var(--r-md);line-height:0;
  transition:transform .2s ease,box-shadow .2s ease}
.cs-shot a.gw-item:hover{transform:translateY(-3px);box-shadow:0 18px 36px -18px rgba(0,0,0,.7)}
.cs-shot figcaption{margin-top:11px;font-size:.86rem;line-height:1.6;
  color:var(--muted);text-align:center}
/* The one off-site link on the case study, under the picture it belongs to
   rather than beside the caption - a button in a caption row reads as part of
   the caption. Centred with everything else in the section. */
.cs-shot-cta{margin:16px 0 0;text-align:center}
.cartdemo + .cs-text,.cs-shot + .cs-text{margin-top:clamp(28px,4vh,44px)}

/* The leaf-through document, centred in a prose section rather than sitting
   in the /branding/ page's two-column .svc-split. Constrained because the
   pages are landscape A4 - at the full 1136px content width the cover reads
   as a hero rather than as one exhibit in a case study.
   ⚠ THE RIGHT AND BOTTOM PADDING IS THE SHEET STACK. .bc-stack draws two
   offset sheet edges behind the cover at +14/+16px and again at +18/+21 on
   hover; without room they clip against the next thing. See note 114 area
   and the branding document notes. */
/* NO PLAYLIST - the case studies show the film or films tagged for that
   client, /video/ shows the whole list. Same markup either way so main.js
   needs nothing new; the list and the now-playing line are simply hidden.
   ⚠ THE .vp-item IS STILL IN THE HTML and must stay: the script reads the
   film's name from it for the iframe title, and without it a screen reader
   announces "Video". */
.vplayer-solo + .vp-list,.vplayer-solo .vp-now{display:none}
/* ⚠ HIDING THE PLAYLIST DOES NOT REMOVE ITS COLUMN. .vplayer-wrap is a
   two-column grid with a FIXED 320px track for the list. display:none takes
   .vp-list out of the grid but leaves the track behind, so above 900px a solo
   player was being laid out into (width - 320 - 18) and sitting with a third
   of the row empty beside it - 185px of film inside a 531px column once the
   two Everest films went side by side.

   ⚠ IT LOOKS LIKE NOTHING. A slightly small player reads as a design choice,
   which is why this survived the single-film version of the page. Found
   10 Sept 2026 by measuring .vp-stage across twelve viewport widths.

   margin-top:0 because the wrap's own 44-80px is for /video/, where it sits
   straight under prose. In a case study .cs-film already supplies the gap.
   :has() is used elsewhere in this file already. */
.vplayer-wrap:has(.vplayer-solo){grid-template-columns:1fr;margin-top:0}
.cs-film{margin:clamp(28px,4vh,44px) auto 0;max-width:900px}
.cs-film figcaption{margin-top:12px;font-size:.86rem;line-height:1.6;
  color:var(--muted);text-align:center}

/* TWO OR MORE FILMS SIDE BY SIDE - Everest has a series, one film per family
   situation, and the point of it only lands if they are seen together.

   ⚠ THE WRAPPER GETS WIDER, NOT THE PLAYERS. .cs-film caps at 900px for a
   single film because a lone 16:9 player any wider dominates the section.
   Two of them at 900px each would be a wall, so the grid caps at 1080px and
   each player takes about half of it - roughly a 520px film, which is still
   comfortably above the point where Vimeo's own controls start crowding.

   ⚠ EACH FILM KEEPS ITS OWN <figcaption>. They are not decoration: without
   them the two frames look like the same film twice, which is the exact
   misreading the series is meant to avoid.

   Below 760px they stack. Two 16:9 players side by side on a phone are 160px
   wide and the play button is most of the frame. */
.cs-films{margin:clamp(28px,4vh,44px) auto 0;max-width:1080px;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(20px,3vw,34px)}
.cs-films .cs-film{margin:0;max-width:none}
.cs-films-note{margin:clamp(18px,2.4vh,26px) auto 0;max-width:760px;
  font-size:.86rem;line-height:1.6;color:var(--muted);text-align:center}
@media (max-width:760px){
  .cs-films{grid-template-columns:1fr;max-width:900px}
}

.cs-doc{max-width:640px;margin:clamp(28px,4vh,44px) auto 0}
/* ⚠ SYMMETRIC PADDING, SO THE VISIBLE COVER IS WHAT ENDS UP CENTRED.
   .bookcover carries padding:0 14px 16px 0 to make room for the sheet edges
   it draws behind itself. On /branding/ that sits in a column and nobody can
   tell. Centred in a case study section it pushed the cover 7px left of the
   heading. Matching the left padding to the right costs 14px of empty space
   and puts it back on the axis. */
.cs-doc .bookcover{padding-left:14px}

/* note 113 - styles.NOTES.txt */
.screens.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}
/* !important because the short-last-row rules above carry four selectors and
   would otherwise out-specify this and park item four in column two. The
   mobile block below already does the same thing for the same reason. */
.screens.cols-2 > .scr{grid-column:auto !important;margin-left:0 !important}
.screens.fit .scr-shot{background:var(--plate,var(--card))}
.screens.fit .scr-shot img{aspect-ratio:3/2;object-fit:contain}
@media (max-width:980px){
  .screens{grid-template-columns:repeat(2,minmax(0,1fr))}
  .screens > .scr{grid-column:auto !important;margin-left:0 !important}
  .screens > .scr:last-child:nth-child(odd){grid-column:1/-1 !important;
    width:calc(50% - clamp(8px,1vw,12px));margin-inline:auto !important}
}
@media (max-width:700px){
  .screens{grid-template-columns:1fr}
  /* ⚠ cols-2 HAS TO BE COLLAPSED BY NAME. It is a two-class selector, so it
     beats the plain .screens rule above even inside this media query, and a
     grid left at two columns on a 320px screen draws each tile 128px wide -
     a business card at 128px is a smudge. Measured 10 Sept 2026; note 113. */
  .screens.cols-2{grid-template-columns:1fr}
  .screens > .scr:last-child:nth-child(odd){width:auto !important}
}

.svchero-video .svchero-photo{overflow:hidden}
.svchero-video .svchero-photo video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.svchero-video .svchero-photo iframe{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:max(100vw,177.78vh);height:max(56.25vw,100vh);border:0;pointer-events:none}
.video-wall{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin-top:clamp(28px,4vh,48px)}
.vw-item{margin:0}
.svc-media-stack{display:grid;gap:14px}
.vw-frame{position:relative;aspect-ratio:16/9;border-radius:var(--r-md);overflow:hidden;background:var(--panel);
  box-shadow:0 18px 40px -22px rgba(0,0,0,.7)}
.vw-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vw-item figcaption{margin-top:9px;font-size:.86rem;color:var(--muted)}
@media (max-width:900px){.video-wall{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.video-wall{grid-template-columns:1fr}}

@media (max-width:900px){.gal-wall{columns:3}.gal-4 .gal-wall{columns:3}}
/* note 69 - styles.NOTES.txt */
@media (max-width:560px){.gal-wall{columns:2}.gal-4 .gal-wall{columns:2}}
.lightbox{position:fixed;inset:0;z-index:210;background:rgba(16,12,22,.93);display:flex;
  flex-direction:column;align-items:center;justify-content:center;padding:28px;
  opacity:0;visibility:hidden;transition:opacity .25s ease,visibility .25s ease}
.lightbox.on{opacity:1;visibility:visible}
.lightbox img{max-width:min(1100px,92vw);max-height:78vh;border-radius:var(--r-md);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.9)}
.lb-frame{position:relative;width:min(1100px,92vw);aspect-ratio:16/9;border-radius:var(--r-md);overflow:hidden;
  background:#000;box-shadow:0 40px 90px -30px rgba(0,0,0,.9)}
.lb-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.lb-cap{color:var(--muted);font-size:.9rem;margin-top:14px;text-align:center;max-width:70ch}
.lb-btn{position:absolute;display:grid;place-items:center;width:46px;height:46px;border-radius:50%;
  background:rgba(255,255,255,.1);color:#fff;border:0;cursor:pointer;font-size:26px;line-height:1;
  transition:background .2s}
.lb-btn:hover{background:rgba(255,255,255,.22)}
.lb-close{top:20px;right:20px}
.lb-prev{left:16px;top:50%;transform:translateY(-50%)}
.lb-next{right:16px;top:50%;transform:translateY(-50%)}
@media (max-width:560px){.lb-prev{left:6px}.lb-next{right:6px}.lb-btn{width:40px;height:40px}}
.vg-top{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(28px,4vw,60px);
  align-items:start;margin-bottom:clamp(30px,4.5vh,56px)}
.vg-shots{position:relative;padding:6px 0 clamp(30px,5vw,64px)}
.vg-shots figure{margin:0;transition:transform .3s ease,box-shadow .3s ease}
.vg-shots img{width:100%;height:auto;display:block;border-radius:10px}
.vg-shots .vg-s1{width:76%;transform:rotate(-3deg);filter:drop-shadow(0 26px 44px rgba(0,0,0,.55))}
.vg-shots .vg-s2{width:76%;margin:calc(-26% + 40px) 0 0 24%;transform:rotate(3deg);position:relative;
  filter:drop-shadow(0 26px 44px rgba(0,0,0,.55))}
.vg-shots figure:hover{transform:rotate(0) scale(1.015);z-index:2}
/* note 70 - styles.NOTES.txt */
.vg-top.flip{grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr)}
.vg-top.flip>.vg-shots{order:-1}
/* ---------------- branding guidelines document ---------------- */
/* note 71 - styles.NOTES.txt */
.bookcover{position:relative;display:block;padding:0 14px 16px 0}
.bc-stack{position:relative;display:block}
.bc-stack::before,.bc-stack::after{content:"";position:absolute;inset:0;border-radius:10px;z-index:0;
  background:#efe9dc;box-shadow:0 10px 26px -14px rgba(0,0,0,.7);transition:transform .3s ease}
.bc-stack::before{transform:translate(14px,16px)}
.bc-stack::after{transform:translate(7px,8px);background:#f6f2ea}
.bc-shot{position:relative;z-index:1;display:block;border-radius:10px;overflow:hidden;
  box-shadow:0 22px 44px -20px rgba(0,0,0,.85);transition:transform .3s ease}
.bc-shot img{width:100%;height:auto;display:block}
.bc-hint{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:10px;
  padding:15px 16px;color:#fff;font-weight:600;font-size:.95rem;text-shadow:0 1px 3px rgba(0,0,0,.5);
  background:linear-gradient(to top,rgba(16,12,22,.94) 0%,rgba(16,12,22,.82) 55%,rgba(16,12,22,0) 100%)}
.bc-hint svg{width:19px;height:19px;fill:currentColor;flex:none}
.bc-count{margin-left:auto;font-weight:600;font-size:.85rem;color:var(--muted)}
.bookcover:focus-visible{outline-offset:6px;border-radius:var(--r-md)}
@media (hover:hover) and (pointer:fine){
  .bookcover:hover .bc-shot{transform:translateY(-4px)}
  .bookcover:hover .bc-stack::after{transform:translate(9px,11px)}
  .bookcover:hover .bc-stack::before{transform:translate(18px,21px)}
}
.doc-pages{display:none}

.docview{position:fixed;inset:0;z-index:210;background:rgba(16,12,22,.95);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;
  overscroll-behavior:contain;opacity:0;visibility:hidden;transition:opacity .25s ease,visibility .25s}
.docview.on{opacity:1;visibility:visible}
/* dvh, not vh - on a phone vh ignores the address bar and the page gets cut off */
.dv-stage{position:relative;flex:none;background:#f6f2ea;border-radius:6px;overflow:hidden;
  width:min(1400px,92vw,106vh);width:min(1400px,92vw,106dvh);
  box-shadow:0 30px 70px -28px rgba(0,0,0,.9)}
.dv-stage img{width:100%;height:auto;display:block}
.dv-stage img.dv-next{position:absolute;inset:0;height:100%;opacity:0;
  transition:opacity .26s ease;pointer-events:none}
.dv-stage img.dv-next.on{opacity:1}
/* note 72 - styles.NOTES.txt */
.dv-bar{display:flex;align-items:center;justify-content:space-between;gap:18px;color:var(--muted);
  font-size:.92rem;flex:none;padding:0 2px;text-align:left;
  width:min(1400px,92vw,106vh);width:min(1400px,92vw,106dvh);
  padding-bottom:env(safe-area-inset-bottom)}
.dv-bar b{color:#fff;font-weight:600}
.dv-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dv-tools{display:flex;align-items:center;gap:10px;flex:none}
.dv-btn{width:46px;height:46px;border:0;border-radius:50%;background:rgba(255,255,255,.1);
  color:#fff;font-size:22px;line-height:1;cursor:pointer;display:grid;place-items:center;
  transition:background .2s ease}
.dv-btn[disabled]{opacity:.3;cursor:default}
.dv-btn svg{width:20px;height:20px;fill:currentColor;display:block}
@media (hover:hover) and (pointer:fine){.dv-btn:not([disabled]):hover{background:rgba(255,255,255,.2)}}
.dv-close{position:fixed;top:16px;right:16px;top:calc(16px + env(safe-area-inset-top));
  width:46px;height:46px;border:0;border-radius:50%;background:rgba(255,255,255,.1);
  color:#fff;font-size:24px;cursor:pointer;z-index:4}
/* the invisible half-page targets are for a mouse. On a touch screen they would
   swallow the page and block pinch to zoom, so touch gets the swipe instead. */
.dv-nav{display:none}
@media (hover:hover) and (pointer:fine){
  .dv-nav{display:block;position:absolute;top:0;bottom:0;width:38%;border:0;background:none;
    cursor:pointer;z-index:3}
  .dv-nav.p{left:0}.dv-nav.n{right:0}
}
@media (max-width:600px){
  /* no room for both on a phone - the page number carries it, the title is in
     the alt text where it still does its job */
  .dv-label b:first-of-type{margin-left:0}
  .dv-title{display:none}
}
@media (max-height:520px){
  .docview{gap:0}
  .dv-stage{width:min(1400px,92vw,132vh);width:min(1400px,92vw,132dvh)}
  .dv-bar{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);z-index:5;width:auto;
    background:rgba(16,12,22,.72);border-radius:999px;padding:6px 14px;justify-content:center;
    font-size:.8rem;gap:10px;white-space:nowrap}
  .dv-title{display:none}
  .dv-btn{width:34px;height:34px;font-size:18px}
}
@media (prefers-reduced-motion:reduce){
  .dv-stage img.dv-next,.bc-shot,.bc-stack::before,.bc-stack::after{transition:none}
}

.vplayer-wrap{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:18px;align-items:stretch;
  margin-top:clamp(44px,6vh,80px)}
.vp-stage{position:relative;aspect-ratio:16/9;border-radius:var(--r-md);overflow:hidden;background:#000;
  box-shadow:0 34px 74px -30px rgba(0,0,0,.85)}
/* ⚠ var(--card), NOT var(--panel) - CSS note 111, the mechanism the whole
   site uses. --panel is a fixed #2e2738; inside a svc-wash section that is
   #2d2539 behind it, Δ4, so the play button vanished into its own section.
   --card is redefined per band, so it is right on every one of them.
   Showed on /video/ #animation and, from 10 Sept, on the Everest case study
   too - and it matters more there, because two Vimeo posters are being
   fetched and the buttons are bare until they land. */
.vp-play{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;background:var(--card);
  cursor:pointer;display:none}
.vp-play.on{display:block}
.vp-play img{width:100%;height:100%;object-fit:cover;display:block}
.vp-blank{position:absolute;inset:0;display:grid;place-items:center;color:var(--dim);font-weight:600;font-size:1rem}
.vp-btn{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:76px;height:76px;border-radius:50%;
  background:rgba(20,16,28,.62);color:#fff;display:grid;place-items:center;backdrop-filter:blur(3px);
  transition:background .2s ease,transform .2s ease}
.vp-btn svg{width:34px;height:34px;margin-left:3px}
.vp-play:hover .vp-btn{background:var(--blue);transform:translate(-50%,-50%) scale(1.06)}
.vp-stage iframe,.vp-stage video{position:absolute;inset:0;width:100%;height:100%;border:0;background:#000}
.vp-now{margin:12px 2px 0;font-size:.9rem;color:var(--muted)}
.vp-list{display:flex;flex-direction:column;justify-content:flex-start;gap:8px}
.vp-item{display:flex;align-items:center;gap:12px;width:100%;padding:8px;border:0;border-radius:10px;
  background:transparent;color:var(--ink);text-align:left;cursor:pointer;font:inherit;
  transition:background .2s ease}
.vp-item:hover{background:var(--panel)}
.vp-item.on{background:var(--panel-2)}
.vp-th{flex:none;width:104px;aspect-ratio:16/9;border-radius:var(--r-sm);overflow:hidden;background:var(--panel-2);display:block}
.vp-th img{width:100%;height:100%;object-fit:cover;display:block}
.vp-thtxt{display:grid;place-items:center;width:100%;height:100%;padding:4px;text-align:center;
  font-size:.62rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--dim);line-height:1.25}
.vp-tt{font-size:.9rem;font-weight:600;line-height:1.35}
.vp-item.on .vp-tt{color:var(--blue-hi)}
@media (max-width:900px){
  .vg-top{grid-template-columns:1fr}
  .vg-shots{padding-bottom:clamp(24px,9vw,54px)}
  .vg-shots .vg-s1,.vg-shots .vg-s2{width:78%}
  .vg-shots .vg-s2{margin:calc(-24% + 24px) 0 0 22%}
  .vg-top.flip{grid-template-columns:1fr}
  .vg-top.flip>.vg-shots{order:0}
  .vplayer-wrap{grid-template-columns:1fr}
  .vp-list{flex-direction:row;overflow-x:auto;scrollbar-width:none;padding-bottom:4px}
  .vp-list::-webkit-scrollbar{display:none}
  .vp-item{flex:none;width:150px;flex-direction:column;align-items:stretch;gap:7px}
  .vp-th{width:100%}
  .vp-tt{font-size:.82rem}
}

/* note 73 - styles.NOTES.txt */
.lg-sec{
  /* note 74 - styles.NOTES.txt */
  --nav-clear:calc(82px + 2.2vh);
  padding:calc(var(--nav-clear) + var(--sec-62)) 0 var(--sec-pad)}
.lg-head{max-width:70ch;margin-bottom:clamp(34px,5vh,54px)}
.lg-eye{display:block;color:var(--blue-hi);font-size:.82rem;letter-spacing:.14em;
  text-transform:uppercase;margin-bottom:14px}
.lg-head h1{font-size:clamp(2.1rem,4.6vw,3.4rem);line-height:1.08;margin:0 0 14px;
  letter-spacing:-.02em;text-wrap:balance}
.lg-updated{color:var(--dim);font-size:.95rem;margin:0}

.lg-prose{max-width:70ch}
.lg-prose > p{color:var(--muted);margin:0 0 18px;line-height:1.72}
.lg-prose > p:last-child{margin-bottom:0}
.lg-prose h2{font-size:clamp(1.25rem,2.1vw,1.6rem);line-height:1.25;color:var(--ink);
  margin:clamp(38px,5.2vh,58px) 0 14px;letter-spacing:-.01em}
.lg-prose h2:first-child{margin-top:0}
.lg-prose h3{font-size:1.05rem;color:var(--ink);margin:26px 0 10px}
.lg-prose b,.lg-prose strong{color:var(--ink);font-weight:600}
.lg-prose a{color:var(--blue-hi);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:rgba(124,196,245,.45)}
.lg-prose a:hover,.lg-prose a:focus-visible{text-decoration-color:var(--blue-hi)}
.lg-prose ul{margin:0 0 18px;padding-left:0;list-style:none;display:grid;gap:11px}
.lg-prose ul li{color:var(--muted);line-height:1.66;padding-left:22px;position:relative}
.lg-prose ul li::before{content:"";position:absolute;left:4px;top:.62em;
  width:5px;height:5px;border-radius:50%;background:var(--blue-deep)}
.lg-prose .lg-note{background:var(--panel);border-radius:var(--r-sm);
  padding:18px 22px;margin:0 0 18px;color:var(--muted);line-height:1.66}
.lg-prose .lg-note b{display:block;color:var(--ink);margin-bottom:5px}
@media (max-width:640px){
  .lg-prose > p,.lg-prose ul li{font-size:.98rem}
}
/* note 75 - styles.NOTES.txt */


/* note 76 - styles.NOTES.txt */
.lg-grid{display:grid;gap:clamp(34px,4.4vw,72px);align-items:start}
@media (min-width:900px){
  .lg-grid{grid-template-columns:minmax(0,1fr) 244px}
  .lg-grid .lg-prose{grid-column:1;grid-row:1}
  .lg-grid .lg-toc{grid-column:2;grid-row:1;
    /* navbar bottom measures 72px at rest and 62px scrolled, so 96px
       clears it in both states without any script. */
    position:sticky;top:96px;max-height:calc(100vh - 120px);overflow-y:auto;
    scrollbar-width:thin;scrollbar-color:var(--panel-2) transparent}
}
.lg-toc-t{font-size:.82rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);margin:0 0 14px;font-family:'Figtree',sans-serif;font-weight:600}
.lg-toc-list{list-style:none;margin:0;padding:0;display:grid;gap:2px;counter-reset:none}
.lg-toc-list a{display:block;color:var(--muted);text-decoration:none;
  font-size:.93rem;line-height:1.4;padding:7px 12px;border-radius:var(--r-sm);
  transition:color .18s ease,background .18s ease}
@media (hover:hover) and (pointer:fine){
  .lg-toc-list a:hover{color:var(--ink);background:var(--panel)}
}
.lg-toc-list a:focus-visible{outline-offset:2px}
/* note 77 - styles.NOTES.txt */
.lg-toc-list a.on{color:var(--ink);background:rgba(124,196,245,.14)}
/* Jumped-to headings must clear the fixed navbar. */
.lg-prose h2{scroll-margin-top:104px}
@media (max-width:899px){
  .lg-toc{background:var(--panel);border-radius:var(--r-md);padding:20px 18px}
  .lg-toc-list{gap:0}
  .lg-toc-list a{padding:9px 10px}
  /* The block itself is --panel here, so the current item needs the next
     step up or the highlight is invisible against its own container. */
  .lg-toc-list a:hover{background:var(--panel-2)}
  .lg-prose h2{scroll-margin-top:96px}
}

/* note 78 - styles.NOTES.txt */
.spec-grid.cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:760px){.spec-grid.cols-3{grid-template-columns:1fr}}

/* note 79 - styles.NOTES.txt */
.svcproof-grid .svcp{scroll-margin-top:104px}
.svcp-flat{margin:0;cursor:default}
@media (hover:hover) and (pointer:fine){
  .svcp-flat:hover{transform:none;background:var(--panel)}
}
.svcp .svcp-go{display:block;margin-top:11px;color:var(--blue-hi);
  font-size:.86rem;font-weight:600}

/* note 80 - styles.NOTES.txt */
.cs-text{max-width:64ch;margin-inline:auto}
.cs-text p{color:var(--muted);font-size:1.04rem;line-height:1.72;margin:0}
.cs-text p + p{margin-top:18px}
/* note 108 - styles.NOTES.txt */
.cs-text p a,.nar-lead a,.sec-sub a,.spec-sub a{color:var(--blue-hi);
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;
  text-decoration-color:color-mix(in srgb,var(--blue-hi) 45%,transparent)}
.cs-text p a:hover,.nar-lead a:hover,.sec-sub a:hover,.spec-sub a:hover{
  color:#fff;text-decoration-color:currentColor}
/* note 104 - styles.NOTES.txt */
.cs-stack{font-size:.92rem;color:var(--muted);opacity:.82;margin-top:22px}
.cs-sec .sec-head.centred{margin-bottom:var(--head-gap)}

/* note 81 - styles.NOTES.txt */

/* --- BAND --- */
.cs-band{--slant-bg:transparent;position:relative;isolation:isolate}
/* note 82 - styles.NOTES.txt */
.cs-band-photo{position:absolute;left:0;right:0;z-index:-1;overflow:hidden;
  isolation:isolate;will-change:transform;
  top:calc(var(--slant) * -1);bottom:calc(var(--slant) * -1);
  clip-path:polygon(0 var(--slant),100% 0,100% calc(100% - var(--slant)),0 100%)}
.cs-band-photo img{width:100%;height:100%;object-fit:cover;object-position:center 40%;
  filter:saturate(1) brightness(1.25);display:block}
/* note 83 - styles.NOTES.txt */
.cs-band-scrim{position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(18,15,24,.68) 0%,rgba(18,15,24,.64) 50%,
    rgba(18,15,24,.40) 68%,rgba(18,15,24,.12) 84%,rgba(18,15,24,.03) 100%)}
.cs-band .cs-text{margin-inline:0}
.cs-band .cs-text p{color:#fff}   /* not #ded9e8 - see the scrim note above */
.cs-band h2{color:#fff}
.cs-band .cs-hold{max-width:62ch}
/* ⚠ A PHOTO BAND DIRECTLY UNDER THE SUBNAV NEEDS PUSHING DOWN, 13 Sept
   2026. Andy: "The sub menu is lost hovering over two sections."

   .cs-band-photo starts at top:calc(var(--slant) * -1) - it deliberately
   reaches UP out of its own section so the parallelogram clip lines the
   photo up with the diagonal. On every case study but Choppers the first
   section is a plain panel, so the bar rests on 111px of flat dark and
   reads as a bar. On Choppers the first section carries the Koh Tao photo,
   and that upward overhang put the sky behind the bottom two thirds of the
   bar - 39px of overhang at 1000px wide, and MORE on a big screen, because
   --slant is 3.84vw. So the wider the monitor, the worse it looked.

   The margin is the slant back plus a 44px dark gap, which keeps the gap
   the same at every width. Do not swap it for padding: the photo is
   positioned against the section box, so padding moves the words and
   leaves the picture exactly where it was. */
.subnav + .cs-band{margin-top:calc(var(--slant) + 44px)}
@media (max-width:900px){
  /* note 84 - styles.NOTES.txt */
  .cs-band-photo img{object-position:78% 40%}
  .cs-band-scrim{background:rgba(18,15,24,.64)}
  .cs-band .cs-hold{max-width:none;margin-bottom:150px}
}

/* --- SPLIT --- prose left, a SHORT client line right.
   Kept because it is the right treatment for one or two sentences. It is not
   in use on Choppers any more; see TESTIMONY below for why. */
.cs-split{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);
  gap:clamp(36px,4.6vw,78px);align-items:center}
.cs-split .cs-text{margin-inline:0;max-width:none}
.cs-quote{background:var(--panel);border-radius:var(--r-md);padding:clamp(30px,3vw,44px)}
.cs-quote p{font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.12rem,1.55vw,1.45rem);line-height:1.35;letter-spacing:-.015em;
  color:#fff;margin:0}
.cs-quote cite{display:block;margin-top:20px;font-style:normal;font-size:.85rem;color:var(--muted)}

/* note 85 - styles.NOTES.txt */
.cs-said{position:relative;background:var(--card);border-radius:var(--r-md);
  padding:clamp(30px,3vw,44px);margin:0;overflow:hidden}
.cs-said-mark{position:absolute;top:-14px;left:10px;width:86px;height:86px;
  color:var(--blue-hi);opacity:.10;pointer-events:none}
.cs-said-mark svg{width:100%;height:100%;display:block}
.cs-said blockquote{margin:0;position:relative}
.cs-said blockquote p{font-family:'Poppins',sans-serif;font-weight:700;
  font-size:clamp(1.12rem,1.55vw,1.45rem);line-height:1.35;letter-spacing:-.015em;
  color:#fff;margin:0}
.cs-said-by{display:flex;align-items:center;gap:14px;margin-top:26px;
  padding-top:22px;border-top:1px solid var(--line)}
.cs-said-ph{flex:none;width:52px;height:52px;border-radius:50%;overflow:hidden;
  background:var(--panel-2);display:grid;place-items:center}
.cs-said-ph img{width:100%;height:100%;object-fit:cover;display:block}
.cs-said-ini{font-family:'Poppins',sans-serif;font-weight:700;font-size:1rem;
  color:var(--blue-hi);letter-spacing:.02em}
.cs-said-nm{display:flex;flex-direction:column;line-height:1.3}
.cs-said-nm b{font-family:'Poppins',sans-serif;font-weight:700;font-size:.98rem;color:var(--ink)}
.cs-said-nm span{font-size:.85rem;color:var(--muted)}
@media (max-width:900px){
  .cs-split{grid-template-columns:1fr;gap:clamp(28px,4vh,40px)}
}

/* note 86 - styles.NOTES.txt */
/* note 87 - styles.NOTES.txt */


/* The header row. Tinted a touch above the card so it reads as a header and
   not as the first paragraph. */







/* Source and date, hard right. .gmark is margin-left:auto in the testimonial
   cards; here the wrapper takes that job so the mark sits with its label. */




/* note 88 - styles.NOTES.txt */


/* note 89 - styles.NOTES.txt */

/* Opens on the first paragraph and closes on the last, so a review in three
   parts still reads as one quotation. */





/* note 90 - styles.NOTES.txt */
@media (max-width:560px){
}

/* note 91 - styles.NOTES.txt */
/* note 92 - styles.NOTES.txt */
.ab-thumb{flex:none;width:112px;height:76px;border-radius:9px;
  overflow:hidden;background:var(--l-line);line-height:0}
/* note 93 - styles.NOTES.txt */
.ab-thumb img{width:100%;height:100%;object-fit:cover;object-position:72% center;
  display:block;transition:transform .35s ease}
@media (hover:hover) and (pointer:fine){
  .ab-links a:hover .ab-thumb img{transform:scale(1.06)}
}

/* note 94 - styles.NOTES.txt */
.cs-mon{--cs-mon-w:800px;max-width:var(--cs-mon-w);margin:0 auto;position:relative}

.cs-mon-body{position:relative;
  background:linear-gradient(180deg,#232326,#0e0e10);
  padding:10px 10px 30px;border-radius:10px;
  box-shadow:0 1px 0 rgba(255,255,255,.16) inset,
             0 -1px 0 rgba(255,255,255,.05) inset,
             0 18px 38px -26px rgba(0,0,0,.6);
}
.cs-screen{position:relative;aspect-ratio:16/10;overflow:hidden;border-radius:3px;background:#000}
.cs-scroll{
  position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.28) transparent;
}
.cs-scroll::-webkit-scrollbar{width:9px}
.cs-scroll::-webkit-scrollbar-track{background:transparent}
.cs-scroll::-webkit-scrollbar-thumb{
  background:rgba(255,255,255,.24);border-radius:9px;
  border:2px solid transparent;background-clip:content-box;
}
.cs-scroll::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.45);background-clip:content-box}
.cs-scroll img{display:block;width:100%;height:auto;-webkit-user-drag:none;user-select:none}
.cs-scroll:focus-visible{outline-offset:-2px}
.cs-scroll{cursor:grab}
.cs-scroll.cs-dragging{cursor:grabbing}

/* note 105 - styles.NOTES.txt  -  the bottom fade was REMOVED, do not
   reinstate it. */

.cs-mon-led{
  position:absolute;left:50%;bottom:11px;transform:translateX(-50%);
  width:5px;height:5px;border-radius:50%;
  background:var(--blue-hi);box-shadow:0 0 7px 1px rgba(124,196,245,.55);
}
.cs-mon-neck{width:112px;height:38px;margin:0 auto;background:linear-gradient(180deg,#1e1e20,#111112)}
.cs-mon-foot{
  width:290px;max-width:58%;height:14px;margin:0 auto;
  background:linear-gradient(180deg,#1e1e20,#0a0a0b);
  clip-path:polygon(3% 0,97% 0,100% 100%,0 100%);
  box-shadow:0 8px 16px -12px rgba(0,0,0,.55);
}
.cs-mon.no-stand .cs-mon-neck,.cs-mon.no-stand .cs-mon-foot{display:none}

.cs-mon-foot-links{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:0 14px;
  margin:26px 0 0;font-size:15px;
}
/* .textlink carries margin-top:16px from the house rules, which in a flex row
   shunts the links down. The site already zeroes it in .sec-head and .nar-foot. */
.cs-mon-foot-links .textlink{margin-top:0}
.cs-mon-sep{color:var(--dim);opacity:.6}
/* note 110 - styles.NOTES.txt */
.cs-mon-hold + .cs-text{margin-top:clamp(34px,4.8vh,58px)}

/* note 95 - styles.NOTES.txt */
/* ===================================================================
   .rq  -  THE CLIENT REVIEW CARD, one layout at three sizes
   ===================================================================
   Attribution on a tinted strip at the top, quote below, source mark
   hard right. Replaced .tst-card, .tfull and .cs-testimony, which were
   three different layouts for the same content - the long note above
   review_card() in partials/lib-testimonials.php says why that mattered
   on this site in particular.

   ONLY THESE THINGS CHANGE BETWEEN SIZES: the type steps down, the
   compact card clamps its text, the medium card carries the Work line,
   the feature card sets its first paragraph large and white as an entry
   point to a long read. Everything else is shared - which is what makes
   three sizes read as one component instead of three designs.

   PHOTOS ARE ROUNDED SQUARES, never circles: --r-sm, the radius the
   buttons and tiles use. Andy, 9 Sept 2026: "I dont think photos should
   be circular. It doesn't match other button elements then."

   NO DATE IS PRINTED. There is no CSS for one because there is no
   markup for one. See lib-testimonials.php.

   THE STUDIO PULL QUOTE (.cs-said) IS NOT THIS and must not be folded
   into it - different speaker, deliberately different treatment, and
   the graphic quote mark belongs to it alone.
   =================================================================== */
.rq{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  overflow:hidden;display:flex;flex-direction:column;margin:0}
.rq:target{outline:2px solid var(--tint,var(--blue));outline-offset:0}
.rq-who{display:flex;align-items:center;gap:14px;padding:16px 22px;
  background:rgba(255,255,255,.035);border-bottom:1px solid var(--line)}
/* note 111 - styles.NOTES.txt */
.rq-ph{width:44px;height:44px;flex:none;border-radius:var(--r-sm);overflow:hidden;
  background:rgba(255,255,255,.09);display:grid;place-items:center}
.rq-ph img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
.rq-ini{font-family:'Poppins',sans-serif;font-weight:700;color:var(--muted);font-size:.9rem}
.rq-nm{display:flex;flex-direction:column;gap:1px;min-width:0}
.rq-nm b{font-family:'Poppins',sans-serif;font-weight:700;font-size:.98rem;color:#fff;line-height:1.25}
.rq-nm span{font-size:.84rem;color:var(--muted)}
.rq-src{margin-left:auto;display:flex;align-items:center;gap:8px;
  font-size:.78rem;color:var(--muted);flex:none}
.rq-bd{padding:22px;display:flex;flex-direction:column;gap:14px;flex:1;margin:0}
.rq-bd p{margin:0;color:var(--muted);font-size:.95rem;line-height:1.7}
.rq-bd p:first-of-type::before{content:"\201C"}
.rq-bd p:last-of-type::after{content:"\201D"}
.rq-work{margin-top:auto;padding-top:14px;border-top:1px solid var(--line);
  font-size:.76rem;color:var(--dim);line-height:1.45}
.rq-work b{font-family:'Poppins',sans-serif;font-weight:700;font-size:.66rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--blue-hi);margin-right:9px}
/* COMPACT - the moving strip. Fixed size: the row loops seamlessly and a
   card that grows with its quote breaks the loop's arithmetic. */
.rq-compact{width:400px;height:250px;flex:none}
.rq-compact .rq-who{padding:13px 18px;gap:11px}
.rq-compact .rq-ph{width:38px;height:38px}
.rq-compact .rq-nm b{font-size:.9rem}
.rq-compact .rq-nm span{font-size:.78rem}
.rq-compact .rq-bd{padding:16px 18px;overflow:hidden}
.rq-compact .rq-bd p{font-size:.9rem;line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden}
.rq-compact .rq-bd p + p{display:none}
.rq-more{margin-top:auto;font-size:.86rem}
/* MEDIUM - the reviews page list. */
.rq-medium .rq-ph{width:56px;height:56px}
.rq-medium .rq-bd{padding:24px}
.rq-medium .rq-bd p{font-size:1rem;line-height:1.72}
/* THE BOLD LEAD, on the /reviews/ cards as well as the feature ones.
   Andy, 11 Sept 2026: "the first 2-3 sentences as bold and the rest as not."
   The feature card has had this since it was built; a medium card never did,
   because until testimonial_paragraphs() learned to split a single-paragraph
   review there was no second paragraph for it to contrast with.
   ⚠ var(--ink), NOT #fff like the feature card. A medium card sits on a panel
   surface in a grid of twenty-one; pure white on every one of them turns the
   page into a chessboard. The feature card is alone on its page and can
   carry it. */
.rq-medium .rq-bd p:first-of-type{font-family:'Poppins',sans-serif;font-weight:600;
  font-size:1.06rem;line-height:1.55;letter-spacing:-.01em;color:var(--ink)}
/* FEATURE - one review on a case study. */
.rq-feature{max-width:900px;margin-inline:auto}
.rq-feature .rq-who{padding:clamp(18px,2vw,24px) clamp(24px,2.9vw,34px)}
.rq-feature .rq-ph{width:60px;height:60px}
.rq-feature .rq-nm b{font-size:1.06rem}
.rq-feature .rq-bd{padding:clamp(24px,2.9vw,34px);gap:17px}
.rq-feature .rq-bd p{font-size:1rem;line-height:1.75}
.rq-feature .rq-bd p:first-of-type{font-family:'Poppins',sans-serif;font-weight:600;
  font-size:clamp(1.1rem,1.42vw,1.24rem);line-height:1.48;letter-spacing:-.012em;color:#fff}
/* The gap between the card and the prose that follows it. This rule
   existed on the old .cs-testimony and was lost when that component was
   deleted, which left the paragraphs sitting hard against the card -
   Andy spotted it, 9 Sept 2026. Restored at the same value. */
.rq-feature + .cs-text{margin-top:clamp(32px,4.6vh,56px)}
/* The base .gmark carries margin-left:auto, written for a layout where it
   was the last thing in a row. Here it sits BEFORE its own label inside
   .rq-src, so the auto margin is cancelled and the size set deliberately
   rather than inherited from a component that no longer exists. */
.rq-src .gmark{margin-left:0;width:16px;height:16px}
@media (max-width:560px){
  /* The source label drops to the bare G so the header never wraps. */
  .rq-src span:last-child{display:none}
  /* ⚠ NOT width:100%. A compact card lives in .tst-track, which is
     width:max-content - a percentage there resolves against the whole
     track (35,000px on the homepage), so the card became wider than the
     document and the reveal observer's area threshold could never be
     met. Every review on every page was invisible below 560px.
     Andy reported it, 11 Sept 2026. Size it against the VIEWPORT. */
  .rq-compact{width:min(400px,calc(100vw - 44px));height:auto}
  .rq-compact .rq-bd p{-webkit-line-clamp:6}
}

.cs-phone{position:absolute;right:-38px;bottom:-16px;width:155px;z-index:5;
  padding:6px;border-radius:22px;background:linear-gradient(180deg,#2c2c31,#171718);
  box-shadow:0 20px 40px -20px rgba(0,0,0,.9),0 1px 0 rgba(255,255,255,.14) inset}
.cs-phone::before{content:"";position:absolute;top:11px;left:50%;transform:translateX(-50%);
  width:40px;height:4px;border-radius:3px;background:#0b0b0c;z-index:2}
.cs-phone-screen{display:block;border-radius:17px;overflow:hidden;background:#000}
.cs-phone-screen img{display:block;width:100%;height:auto}
@media (max-width:700px){
  /* On a phone the reader IS the mobile view, so the handset stops
     earning its place and only costs height on an already long page. */
  .cs-phone{display:none}
}

/* ---- POINTER: the curved arrows in the gutters ----
   ONE IN EACH GUTTER, the left a mirror of the right. Andy, 11 Sept 2026.
   Both arrows point AT the screen; the flip is what makes that true on the
   left, and the flex order is what keeps the arrow on the inside of the
   text on both sides.

   ⚠ THE GUTTER IS NOT ALWAYS 150px WIDE. The wrap is 1136px, so at a 1400px
   viewport each gutter is 132px and a 150px cue overhangs. It does not cause
   a scrollbar because the section clips nothing and the overhang lands in
   the viewport's own margin - but it is the reason the static fallback below
   exists rather than simply narrowing the cue. Measured across twelve widths
   on 11 Sept; no horizontal scroll at any of them. */
.cs-cue{
  position:absolute;top:54px;width:150px;z-index:2;
  display:flex;align-items:center;gap:9px;pointer-events:none;
  color:var(--muted);font:500 14px/1.35 'Figtree',sans-serif;
  opacity:1;transition:opacity .4s ease;
}
.cs-cue-r{left:calc(100% + 16px)}
.cs-cue-l{right:calc(100% + 16px)}
.cs-cue b{display:block;font-weight:600;color:var(--ink)}
/* Amber is settled. Both cue arrows use --sun and it is the only accent in
   the component - do not offer to tone it down again. */
.cs-cue svg{flex:0 0 auto;color:var(--sun)}
/* RIGHT gutter: arrow nearest the screen, so arrow first, text second. */
.cs-cue-r svg{order:1}
.cs-cue-r .cs-cue-t{order:2}
/* LEFT gutter: the mirror. Text first, arrow second and flipped, so it still
   points inward at the screen rather than off the edge of the page. */
.cs-cue-l svg{order:2;transform:scaleX(-1)}
.cs-cue-l .cs-cue-t{order:1;text-align:right}
.cs-mon.scrolled .cs-cue{opacity:.25}

/* note 96 - styles.NOTES.txt */
/* ⚠ 1140, NOT 1080. Raised 11 Sept 2026 when the second cue went in.

   The monitor is a fixed ~800px and centred, so each gutter is
   (viewport - 800) / 2, and a cue needs 150px plus its 16px offset = 166.
   That makes 1132px the width below which a cue cannot fit beside the
   frame. At the old 1080 breakpoint the gutter was 140px and the cue was
   being clipped by 26px - ON THE RIGHT, ALREADY, BEFORE THERE WAS A LEFT
   ONE. Nobody had measured it; it only showed up because the left one
   failed the same way and was visible about it. Measured, not guessed. */
@media (max-width:1140px){
  /* No gutters left to sit in, so the cue goes above the frame as one line
     of text. ⚠ THE LEFT ONE IS DROPPED ENTIRELY HERE - two stacked copies of
     the same sentence reads as a bug, not as emphasis. */
  .cs-cue-l{display:none}
  .cs-cue{position:static;width:auto;justify-content:flex-end;margin:0 0 12px}
  .cs-cue svg{display:none}
  .cs-cue .cs-cue-t{text-align:right}
}

/* ---- TOUCH: tap the design to wake it ---- */
.cs-gate{
  position:absolute;inset:0;z-index:3;display:none;
  appearance:none;border:0;margin:0;padding:0 0 16px;background:transparent;
  align-items:flex-end;justify-content:center;cursor:pointer;
  transition:opacity .3s ease;font-family:inherit;
}
/* note 97 - styles.NOTES.txt */
.cs-gate span{
  display:inline-flex;align-items:center;gap:8px;
  padding:10px 18px;border-radius:var(--btn-radius);
  background:var(--blue);color:#fff;font:600 14px/1 'Figtree',sans-serif;
  box-shadow:0 6px 22px rgba(0,0,0,.55),0 1px 0 rgba(255,255,255,.16) inset;
}
.cs-gate svg{color:#fff}
.cs-gate:active span{background:var(--blue-deep)}
.cs-gate:focus-visible{outline-offset:-3px}
/* Done stays recessive on purpose - the blue means "start here", and two
   blue controls would compete. House outline style, so it still reads as
   one of ours rather than one of theirs. */
.cs-done{
  position:absolute;top:9px;right:9px;z-index:4;display:none;
  appearance:none;border:1.5px solid rgba(255,255,255,.5);
  padding:6px 13px;border-radius:var(--btn-radius);
  background:rgba(0,0,0,.55);color:#fff;cursor:pointer;
  font:600 12px/1 'Figtree',sans-serif;
}
.cs-done:focus-visible{outline-offset:2px}

@media (hover:none){
  .cs-cue{display:none}
  .cs-scroll{cursor:auto}
  .cs-gate{display:flex}
  .cs-mon.live .cs-gate{opacity:0;pointer-events:none}
  .cs-mon.live .cs-done{display:block}
  /* Inert until tapped: the swipe passes through to the page. */
  .cs-mon:not(.live) .cs-scroll{overflow:hidden;pointer-events:none}
}

@media (max-width:760px){
  .cs-mon-body{padding:7px 7px 20px;border-radius:8px}
  .cs-mon-neck{height:26px;width:84px}
  .cs-mon-foot{height:11px}
  .cs-mon-led{bottom:8px;width:4px;height:4px}
  .cs-screen::after{height:48px}
  /* note 98 - styles.NOTES.txt */
  .cs-gate{padding-bottom:9px}
  .cs-gate span{font-size:13px;padding:9px 15px;gap:7px}
  .cs-gate svg{width:13px;height:13px}
  .cs-done{font-size:11px;padding:5px 11px;top:7px;right:7px}
}
/* Stacked links: the middle dot orphans onto its own line when the row wraps. */
@media (max-width:560px){
  .cs-mon-foot-links{flex-direction:column;gap:11px}
  .cs-mon-sep{display:none}
}

/* note 99 - styles.NOTES.txt */
.cs-close .close-cta .btn{margin-top:clamp(22px,2.8vh,30px)}

/* note 100 - styles.NOTES.txt */
/* ⚠ touch-action:pan-y IS LOAD-BEARING ON A PHONE, 13 Sept 2026. It gives
   the browser vertical swipes (the page still scrolls over the image) and
   hands SIDEWAYS drags to us, which is what main.js needs to move the
   divider. Without it the browser keeps the horizontal gesture too and the
   slider cannot be dragged at all on iOS. Do not change it to none - that
   traps the page scroll under the image. */
.cmp{position:relative;display:block;max-width:760px;margin-inline:auto;
  border-radius:var(--r-md);overflow:hidden;background:#fff;line-height:0;
  touch-action:pan-y;
  -webkit-touch-callout:none;-webkit-user-select:none;user-select:none;
  box-shadow:0 22px 48px -24px rgba(0,0,0,.8)}
/* ⚠ THE THREE LINES BELOW ARE WHY A REAL IPHONE BEHAVED UNLIKE THE ONLINE
   TESTERS, 13 Sept 2026. Andy: "on a safari tester and iphone tester online
   it works. But in person it did not." Those testers drive a simulator with a
   MOUSE. A real finger pressed and held on an image in iOS Safari starts the
   system's own image drag, or raises the save/share callout, and the browser
   takes the gesture away mid-drag - neither of which a mouse ever triggers.
   pointer-events:none takes the images out of hit-testing entirely, so every
   press lands on .cmp and reaches the handler in main.js. */
.cmp img{width:100%;height:auto;display:block;
  pointer-events:none;-webkit-user-drag:none;user-select:none;-webkit-user-select:none}
.cmp-b{position:absolute;inset:0;display:block;overflow:hidden;
  clip-path:inset(0 calc(100% - var(--cmp)) 0 0)}
.cmp-line{position:absolute;top:0;bottom:0;left:var(--cmp);width:2px;
  background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.35);pointer-events:none}
/* note 101 - styles.NOTES.txt */
.cmp-line::before{content:"";position:absolute;top:50%;left:50%;width:44px;height:44px;
  transform:translate(-50%,-50%);border-radius:50%;background:#fff;
  box-shadow:0 2px 12px rgba(0,0,0,.5)}
.cmp-line::after{content:"\276E\00A0\276F";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);font-family:'Poppins',sans-serif;font-weight:700;
  font-size:15px;line-height:1;color:#201a28;letter-spacing:-1px}
.cmp-tag{position:absolute;bottom:12px;font-family:'Poppins',sans-serif;font-weight:600;
  font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;line-height:1;
  padding:6px 10px;border-radius:999px;background:rgba(18,15,24,.72);color:#fff}
.cmp-tag-a{left:12px}
.cmp-tag-b{right:12px}
/* The control is a real range input: keyboard works, and the browser gives
   it a proper role. It is made invisible but NOT display:none, because a
   hidden input is not focusable. */
.cmp-range{position:absolute;inset:0;width:100%;height:100%;margin:0;
  appearance:none;-webkit-appearance:none;background:transparent;cursor:ew-resize}
.cmp-range::-webkit-slider-thumb{-webkit-appearance:none;width:44px;height:100%;
  background:transparent;cursor:ew-resize}
.cmp-range::-moz-range-thumb{width:44px;height:100%;border:0;background:transparent;cursor:ew-resize}
.cmp-range:focus-visible{outline:2px solid var(--blue-hi);outline-offset:3px}


/* note 102 - styles.NOTES.txt */
.brandpair{display:grid;grid-template-columns:minmax(0,1.32fr) minmax(0,.68fr);
  gap:clamp(22px,3vw,40px);align-items:start;max-width:1000px;margin-inline:auto}
.brandpair figure{margin:0}
.brandpair .cmp{max-width:none}
.brandpair-mark{background:#fff;border-radius:var(--r-md);overflow:hidden;
  box-shadow:0 22px 48px -24px rgba(0,0,0,.8);display:block;line-height:0}
.brandpair-mark img{width:100%;height:auto;display:block}
/* note 107 - styles.NOTES.txt */
.brandpair-mark.is-slot{aspect-ratio:16/10}
.brandpair-mark.is-slot img{width:100%;height:100%;object-fit:cover;display:block}
.brandpair figcaption{margin-top:14px;font-size:.88rem;line-height:1.6;color:var(--muted)}
.brandpair figcaption b{display:block;color:var(--ink);font-family:'Poppins',sans-serif;
  font-weight:700;font-size:.94rem;margin-bottom:4px}
/* note 112 - styles.NOTES.txt */
.brandpair.even{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
/* ⚠ .even HAS TO BE NAMED HERE. A bare .brandpair rule is specificity
   (0,1,0) and .brandpair.even above is (0,2,0), so .even keeps its two
   columns through this media query however late the query is written -
   order does not save it. Found 11 Sept 2026 on ClearFirst and it was
   already live on Copeland: the brand tiles were rendering 162px + 162px
   on a 390px phone, which is two thumbnails where two pieces of artwork
   should be. Fixed for both at once. Note 112 covers what .even is for. */
@media (max-width:800px){.brandpair,.brandpair.even{grid-template-columns:1fr}}

/* note 106 - styles.NOTES.txt */
.pal{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.pal-chip{display:grid;grid-template-columns:52px 1fr;align-items:center;
  column-gap:14px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-md);padding:12px 16px 12px 12px;
  font-size:.82rem;color:var(--muted);font-variant-numeric:tabular-nums}
.pal-chip span{width:52px;height:52px;border-radius:var(--r-sm);display:block;
  grid-row:1/3;box-shadow:0 0 0 1px rgba(255,255,255,.14) inset}
.pal-chip b{font-family:'Poppins',sans-serif;font-weight:700;font-size:.9rem;
  color:var(--ink);align-self:end;line-height:1.2}
.pal-chip{grid-template-rows:auto auto}
.pal-chip b{grid-column:2}


/* ---- MOCKUP: stacked control-panel shots ---- */
.shot-cap{margin:12px 0 0;font-size:.86rem;line-height:1.5;color:var(--muted)}
.shot-cap b{color:var(--ink);font-weight:600}
.svc-media-stack figure{margin:0}
