/* v05 — dark theme and restructured section rhythm.
   Colour tokens are v03's. The section layout differs: the page is now
   hero → statement → work → service panels → about → FAQ → footer, so the
   statement carries the weight the removed sections used to. */

/* The neutrals come from tokens.css, shared with the pricing page; only the colours this
   page uses alone are defined here. */
:root{
  --bg:var(--sp-bg);          /* page base */
  --panel:var(--sp-panel);    /* raised sections: work, FAQ, footer */
  --surface:var(--sp-surface);     /* cards resting on the page base */
  --surface-2:var(--sp-surface-2); /* cards resting on a panel */
  --service-rest:#26272f; /* service row at rest — lifted off --surface so the drop to
                            black has more range to read across, the dark-theme stand-in
                            for the reference's #eee to #000 flip */
  --void:#000;           /* deepest step, used by the expanded service row */
  --ink:var(--sp-ink);
  --ink-muted:var(--sp-ink-muted);
  --ink-dim:var(--sp-ink-dim);
  --line:var(--sp-line);
  --line-strong:var(--sp-line-strong);
  --accent:#7ee0d3;
  --accent-surface:#122927;
  --focus:#8f8fff;
}

/* ---------- base ---------- */
html{color-scheme:dark}
body{background:var(--bg);color:var(--ink)}
button:focus-visible,a:focus-visible{outline-color:var(--focus)}
::selection{background:var(--accent);color:#06100f}

/* ---------- navigation ---------- */
.pill{border-color:var(--line-strong)}
.pill:hover{background:var(--ink);color:var(--bg);border-color:var(--ink)}

/* ---------- "What we do": its own moment on the page ---------- */
/* This replaces v02's two-column eyebrow-and-paragraph row. It is given close to a
   full screen so nothing else competes with it, which is why the sections that used
   to pad this part of the page are gone. */
/* Both gaps are derived, not picked by eye.

   Above: the statement should crest the fold exactly as the hero copy begins to
   dissolve, so the two hand over to each other. hero-v05.js starts that fade at 34% of
   a scrub travel of 0.95x the hero, i.e. at a scroll of 0.323x the hero height. The
   viewport foot sits at that scroll plus one screen, so the copy should start there:
   padding-top = 100svh - 0.677 x hero height.

   Below: enough room that when the copy is centred the work panel has only just crept
   into frame. The 200px offset is half the copy block plus the sliver allowed to show. */
.statement{--hero-h:clamp(720px,90svh,1100px);
 display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
 padding-top:max(96px,calc(100svh - 0.79 * var(--hero-h)));
 padding-bottom:clamp(210px,calc(50svh - 200px),480px)}
.statement .eyebrow{color:var(--ink-dim);letter-spacing:.18em;font-size:13px;
 margin-bottom:clamp(30px,4.5vh,54px)}
.statement-text{font-size:clamp(25px,3.15vw,54px);line-height:1.2;letter-spacing:-.035em;
 font-weight:500;color:var(--ink);max-width:min(18em,92%);margin-inline:auto;text-wrap:balance}
/* Supporting line: clearly subordinate so the section still reads as one statement. */
.statement-sub{margin:clamp(26px,3.4vh,42px) auto 0;max-width:min(30em,92%);
 font-size:clamp(16px,1.25vw,20px);line-height:1.55;letter-spacing:-.012em;
 font-weight:450;color:var(--ink-muted);text-wrap:balance}
@media(max-width:767px){
 .statement{--hero-h:clamp(640px,82svh,900px);
  padding-top:max(80px,calc(100svh - 0.79 * var(--hero-h)));
  padding-bottom:clamp(150px,calc(50svh - 170px),320px)}
 .statement-text{font-size:clamp(23px,6.4vw,34px);line-height:1.24;max-width:100%}
 .statement-sub{font-size:16px;line-height:1.55;max-width:100%;margin-top:22px}
 .statement .eyebrow{margin-bottom:26px}
}

/* ---------- raised panels ---------- */
.dark{background:var(--panel);color:var(--ink)}
/* At this tonal step the rounded shoulder needs a hairline to stay legible. */
.rounded:after{content:'';position:absolute;top:0;left:0;right:0;height:1px;
 background:linear-gradient(90deg,transparent,rgba(255,255,255,.14) 18%,rgba(255,255,255,.14) 82%,transparent);
 border-radius:inherit;pointer-events:none;z-index:2}
.dark .pill{border-color:var(--line-strong);color:var(--ink)}
.dark .pill:hover{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.project-caption{color:var(--ink)}
/* The work panel is a slab now that no section rises over its foot. */
.projects.rounded{border-radius:calc(64 * var(--unit)) calc(64 * var(--unit)) calc(64 * var(--unit)) calc(64 * var(--unit))}
@media(max-width:767px){.projects.rounded{border-radius:32px}}

/* ---------- work tiles ---------- */
/* Tiles are 3:3.5. The key art is exported at 2560x1300, so cover crops it to a
   central vertical slice — object-position holds the upper-middle, where the
   character and logo sit in these compositions. */
.project-media.tile{aspect-ratio:3/3.5}
.project-media.tile img{object-position:var(--tile-focus,50% 42%)}
.project-columns{gap:clamp(28px,3.4vw,56px)}
.project-columns>div:nth-child(2){padding-top:calc(96 * var(--unit))}
.project{margin-bottom:calc(64 * var(--unit))}
.project-caption{font-size:calc(24 * var(--unit));font-weight:650;letter-spacing:-.03em;margin-top:20px}
.project-note{display:block;margin-top:8px;max-width:42ch;color:var(--ink-muted);
 font-size:calc(15.5 * var(--unit));line-height:1.5;letter-spacing:-.01em}
.project-media{background:var(--surface)}
@media(max-width:767px){
 .project-columns>div:nth-child(2){padding-top:0}
 .project{margin-bottom:44px}
 .project-caption{font-size:21px;margin-top:16px}
 .project-note{font-size:15px;max-width:100%}
}

/* ---------- light band ---------- */
/* Services and About run on a light ground; the work panel above and the FAQ below stay
   dark. Everything inside is already written against tokens, so the band only has to
   redefine them — no rule below needs a light-mode twin. It also restores the reference's
   full #eee-to-black flip on the service rows, which the dark page could only hint at. */
.light-band{display:flow-root;position:relative;background:var(--light-bg);color:var(--ink);
 border-radius:calc(64 * var(--unit)) calc(64 * var(--unit)) 0 0;
 --light-bg:#f5f5f3;
 --service-rest:#e7e7e4;
 --ink:#0d0d10;
 --ink-muted:#56565c;
 --ink-dim:#8a8a90;
 --line:rgba(0,0,0,.14);
 --line-strong:rgba(0,0,0,.24);
 --surface:#eceae5;
 --accent-surface:#e2f2ef;
 --accent:#1f7d72}
/* The FAQ rises back over the band, mirroring how the band rises over the work panel. */
.faq{border-radius:calc(64 * var(--unit)) calc(64 * var(--unit)) 0 0;position:relative}
@media(max-width:767px){
 .light-band,.faq{border-radius:32px 32px 0 0}
}

/* ---------- service panels ---------- */
.services{margin-top:calc(128 * var(--unit))}
/* Scroll-scrubbed, matching the reference rather than a one-shot toggle. app.js writes
   --p (linear progress) and --e (the same progress eased quadratically out) every frame,
   so nothing here may carry a transition — it would fight the per-frame updates. */
.service{transition:none;
 background:color-mix(in srgb,var(--void) calc(var(--e,0) * 100%),var(--service-rest));
 color:color-mix(in srgb,#fff calc(var(--e,0) * 100%),var(--ink-muted))}
.service h3{transition:none;color:color-mix(in srgb,#fff calc(var(--e,0) * 100%),var(--ink))}
/* Only the last panel carries one. It sits on the expanded row's black fill, so it is
   keyed to white rather than to the band's ink, and fades in with the row like the copy. */
.service-cta{display:inline-flex;align-items:center;gap:9px;margin-top:clamp(18px,2.2vh,28px);
 padding:12px 22px;border-radius:100px;border:1px solid rgba(255,255,255,.28);
 color:#fff;font-size:15px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;
 transition:background .35s cubic-bezier(.16,1,.3,1),border-color .35s cubic-bezier(.16,1,.3,1),color .35s cubic-bezier(.16,1,.3,1)}
.service-cta span{transition:transform .35s cubic-bezier(.16,1,.3,1)}
.service-cta:hover{background:#fff;color:#000;border-color:#fff}
.service-cta:hover span{transform:translate(3px,-3px)}
@media(prefers-reduced-motion:reduce){.service-cta,.service-cta span{transition:none}}

.service-accordion{transition:none}
.service-body{transition:none;opacity:1}
/* The artwork used to sit in the right 68%, leaving the row's own fill showing as a
   hard-edged panel behind the copy. It now spans the whole row and a left-to-right
   scrim carries the text instead, so there is no edge to read as a card. */
.service-bg{transition:none;width:100%;opacity:calc(var(--e,0) * var(--bg-max,1))}
.service-bg img{object-position:var(--panel-focus,50% 50%)}
.service-bg:after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,
 rgba(0,0,0,.94) 0%,rgba(0,0,0,.82) 26%,rgba(0,0,0,.42) 52%,rgba(0,0,0,.06) 78%,rgba(0,0,0,0) 100%)}

/* ---------- about ---------- */
.about{border-top-color:var(--line);padding-top:calc(96 * var(--unit))}
.eyebrow{color:var(--ink-muted)}
.intro{color:var(--ink)}
.aqua,.stat:nth-child(n+4).aqua{background:var(--accent-surface)}
.gray,.stat:nth-child(n+4){background:var(--surface)}
.stat-icon{color:var(--accent)}
.stat small{color:var(--ink-muted)}

/* ---------- FAQ ---------- */
.faq{padding-top:calc(128 * var(--unit))}
.faq-item{border-top-color:var(--line)}
.plus:before,.plus:after{background:var(--ink-dim)}
.open .plus:before,.open .plus:after{background:var(--accent)}
.faq-answer p{color:var(--ink-muted)}
/* An answer can end on a button (the first one links to pricing). It reuses the service
   panel's pill, which is already keyed to a dark ground. The answer clips its content
   for the open/close, so it gets 8px of side room to keep the focus ring whole; the
   negative margin leaves the text where it was. */
.faq-answer>div{padding-inline:8px;margin-inline:-8px}
.faq-answer .faq-cta{margin:2px 0 30px}
/* Held to a readable measure; at 90% of the column the answers ran near 100 characters. */
@media(min-width:768px){.faq-answer p{max-width:min(90%,64ch)}}

/* ---------- footer ---------- */
/* Email and page links only. The template's phone number, offices, social icons and
   privacy link are gone until real ones exist, so the grid is two columns, not three. */
.footer-top{grid-template-columns:1fr 1.9fr}
.contact-pill{border-color:var(--line-strong);min-height:44px;align-items:center}
.contact-pill:hover{border-color:var(--ink)}
.copyright{color:var(--ink-dim);margin-left:0}
/* On touch screens every footer link is a full 44px target; the row gap shrinks to keep
   the block the same height. */
@media(pointer:coarse),(max-width:767px){
 .footer nav{row-gap:4px}
 .footer nav a{display:inline-flex;align-items:center;min-height:44px}
}

/* ---------- reveal motion ---------- */
/* Measured off the reference: opacity runs 0→1 in 1s on a quadratic ease-out while the
   68px rise takes 1.5s on a much longer tail, so the card settles after it has finished
   fading in. No scale — the reference does not scale cards on reveal. */
.reveal{opacity:0;transform:translateY(68px);will-change:opacity,transform;
 transition:opacity 1s cubic-bezier(.25,.46,.45,.94),transform 1.5s cubic-bezier(.16,1,.3,1)}
.reveal.visible{opacity:1;transform:none}

/* Headings rise per word from behind a clipped mask, rather than the whole line
   un-wiping. The overflow clip is on the outer span; the negative margin and matching
   padding stop descenders being shaved. */
.section-title.reveal{clip-path:none;transform:none;opacity:1;transition:none}
.section-title.visible{animation:none}
.section-title .word{display:inline-block;overflow:clip;vertical-align:top;margin:-.2em}
.section-title .word>span{display:inline-block;padding:.2em;transform:translateY(120%);
 transition:transform 1.2s cubic-bezier(.16,1,.3,1) var(--wd,0s)}
.section-title.visible .word>span{transform:translateY(0)}

/* Hover easing copied from the reference's media transition. */
.project-media img,.project-media video{transition:transform 1.2s cubic-bezier(.16,1,.3,1),opacity .4s}

@media(max-width:767px){
 .reveal{transform:translateY(48px)}
 .service{--bg-max:.72}
 .service-bg:after{background:linear-gradient(90deg,
  rgba(0,0,0,.92) 0%,rgba(0,0,0,.78) 42%,rgba(0,0,0,.4) 74%,rgba(0,0,0,0) 100%)}
}
@media(prefers-reduced-motion:reduce){
 .reveal{transform:none}
 .section-title .word>span{transform:none}
}

/* ---------- overlays ---------- */
.mobile-menu{background:var(--panel);color:var(--ink);border-left:1px solid var(--line)}
.muted{color:var(--ink-dim)}
/* The menu email is a 44px touch target like every other link in the menu. */
.menu-contact a{display:inline-flex;align-items:center;min-height:44px}
.menu-backdrop{background:rgba(0,0,0,.62)}
.cursor span{color:var(--bg)}
/* The cursor follows the pointer on translate (app.js) and grows on scale, so neither
   touches layout. 100px at .08 is the original 8px dot. */
.cursor{width:100px;height:100px;transform:translate(-50%,-50%) scale(.08);
 transition:transform .4s var(--ease),opacity .2s}
.cursor.large{transform:translate(-50%,-50%) scale(1)}

/* ---------- logo ---------- */
/* The SpinPulse wordmark (white on transparent) replaces the text mark. */
/* The padding makes the logo a 44px-plus target; the negative margin keeps the bar's layout. */
.wordmark{display:block;line-height:0;padding-block:6px;margin-block:-6px}
/* Sized so the lettering (about 60% of the artwork height) matches the old 27px mark. */
.wordmark img{display:block;height:36px;width:auto}
@media(max-width:767px){.wordmark img{height:32px}}

/* ---------- team photo ---------- */
/* The wide About block carries the team photo instead of a line of copy. The block
   changes shape with the viewport (1.55:1 on phones to 2.6:1 at 2560), so the photo
   covers it, anchored a little below centre where the faces are. The copy it
   replaces stays for screen readers. */
.stats .stat-photo{position:relative;overflow:hidden;padding:0;background:var(--surface)}
.stat-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 55%}
.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- skip link ---------- */
/* First in the tab order; it stays off screen until focused. */
.skip-link{position:fixed;z-index:100;left:16px;top:16px;padding:12px 20px;border-radius:100px;
 background:var(--sp-action);color:var(--sp-on-action);font-size:15px;font-weight:600;
 transform:translateY(-160%);transition:transform .2s}
.skip-link:focus{transform:none}
/* main takes focus from the skip link only; it is not a control, so it draws no ring. */
main:focus{outline:none}
.noscript-note{padding:64px 0;color:var(--ink-muted);font-size:17px;line-height:1.5}
.noscript-note a{color:var(--ink);text-decoration:underline;text-underline-offset:4px}
