/* ==========================================================================
   K1 Nova components
   ========================================================================== */

/* --------------------------------------------------------------
   Header
   -------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  padding-block: 0.9rem;
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease), padding 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-stuck {
  background: rgba(7, 11, 20, 0.9);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border-bottom-color: var(--line);
  padding-block: 0.6rem;
}
.site-header__inner {
  display: flex; align-items: center; gap: 1.25rem;
}

.brand { display: inline-flex; align-items: center; gap: 0.7rem; flex: none; }
.brand__icon { width: 38px; height: 38px; border-radius: 11px; }
.brand__wordmark { width: 118px; height: auto; }
.brand:hover .brand__icon { filter: brightness(1.12); }
.brand__icon, .brand__wordmark { transition: filter 0.3s var(--ease); }

.nav { margin-inline: auto; }
.nav__list {
  display: flex; align-items: center; gap: 0.15rem;
  list-style: none; padding: 0.3rem; margin: 0;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  backdrop-filter: blur(10px);
}
.nav__item { position: relative; }
.nav__link {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.5rem 0.95rem;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm); font-weight: 500; color: var(--muted);
  background: none; border: 0; cursor: pointer;
  transition: color 0.25s var(--ease), background-color 0.25s var(--ease);
  white-space: nowrap;
}
.nav__link:hover { color: var(--white); background: rgba(255, 255, 255, 0.06); }
.nav__link.is-current { color: var(--white); background: rgba(59, 130, 246, 0.16); }
.nav__chev { width: 9px; height: 6px; transition: transform 0.3s var(--ease); opacity: 0.75; }
[aria-expanded='true'] .nav__chev { transform: rotate(180deg); }

.nav__menu {
  position: absolute; top: calc(100% + 0.7rem); left: 50%;
  transform: translateX(-50%);
  width: min(30rem, 84vw);
  z-index: 40;
}
.nav__menu[hidden] { display: none; }
.nav__menu-inner {
  display: grid; gap: 0.35rem; padding: 0.55rem;
  background: rgba(13, 20, 36, 0.96);
  backdrop-filter: blur(22px);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lift);
  animation: menu-in 0.28s var(--ease-out);
}
@keyframes menu-in { from { opacity: 0; transform: translateY(-6px); } }
.nav__menu-link {
  display: grid; gap: 0.15rem; padding: 0.85rem 1rem;
  border-radius: var(--r-md);
  transition: background-color 0.25s var(--ease);
}
.nav__menu-link:hover, .nav__menu-link:focus-visible { background: rgba(59, 130, 246, 0.14); }
.nav__menu-link.is-current { background: rgba(59, 130, 246, 0.1); }
.nav__menu-title { font-weight: 600; font-size: var(--fs-sm); }
.nav__menu-blurb { font-size: var(--fs-xs); color: var(--muted); line-height: 1.5; }

.site-header__actions { display: flex; align-items: center; gap: 0.8rem; flex: none; }
.site-header__phone {
  display: inline-flex; align-items: center; min-height: 2.5rem; padding-inline: 0.35rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--muted);
  transition: color 0.25s var(--ease);
}
.site-header__phone:hover { color: var(--white); }

.burger {
  display: none; width: 44px; height: 44px;
  align-items: center; justify-content: center;
  flex-direction: column; gap: 5px;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--line);
  border-radius: 13px; cursor: pointer;
}
.burger span {
  display: block; width: 17px; height: 1.6px; background: var(--white);
  border-radius: 2px; transition: transform 0.35s var(--ease), opacity 0.25s var(--ease);
}
.burger[aria-expanded='true'] span:first-child { transform: translateY(3.3px) rotate(45deg); }
.burger[aria-expanded='true'] span:last-child { transform: translateY(-3.3px) rotate(-45deg); }

.mobile-menu {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(7, 11, 20, 0.97);
  backdrop-filter: blur(24px);
  padding: 6.5rem var(--gutter) 2.5rem;
  overflow-y: auto;
  animation: fade-in 0.3s var(--ease-out);
}
.mobile-menu[hidden] { display: none; }
@keyframes fade-in { from { opacity: 0; } }
.mobile-menu__inner { display: flex; flex-direction: column; min-height: 100%; gap: 1.5rem; }
.mobile-menu__list { list-style: none; padding: 0; margin: 0; display: grid; }
.mobile-menu__list a {
  display: block; padding: 1.05rem 0;
  font-family: var(--font-display); font-size: 1.6rem; font-weight: 500;
  letter-spacing: -0.02em;
  border-bottom: 1px solid var(--line);
}
.mobile-menu__list a:hover { color: var(--blue-light); }
.mobile-menu__foot { margin-top: auto; display: grid; gap: 1rem; padding-top: 1.5rem; }
.mobile-menu__phone { text-align: center; color: var(--muted); font-weight: 500; }
body.menu-open { overflow: hidden; }

/* --------------------------------------------------------------
   Hero
   -------------------------------------------------------------- */
.hero {
  position: relative;
  padding-top: clamp(2.5rem, 5vw, 4.5rem);
  padding-bottom: clamp(5rem, 9vw, 8.5rem);
  overflow: hidden;
  isolation: isolate;
}
.hero__glow-a {
  width: 60vw; height: 60vw; max-width: 900px; max-height: 900px;
  top: -22%; right: -14%;
}
.hero__glow-b {
  width: 40vw; height: 40vw; max-width: 620px; max-height: 620px;
  bottom: -18%; left: -12%;
}
.hero__inner {
  position: relative; z-index: 2;
  display: grid; gap: clamp(2.5rem, 5vw, 4rem);
  align-items: center;
}
.hero__eyebrow { margin-bottom: 1.4rem; }
.hero__heading {
  /* A shade smaller than .display, because this heading carries the full
     promise rather than three short lines, and at the display size it ran to
     five lines and pushed the buttons off the first screen. */
  font-size: clamp(2.2rem, 1.2rem + 3.5vw, 3.7rem);
  font-weight: 500; letter-spacing: -0.035em; line-height: 1.02;
  margin-bottom: 1.6rem;
  max-width: 16ch;
}
.hero__lead { max-width: 46ch; margin-bottom: 2.2rem; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-bottom: 2.6rem; }

.hero__recent {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.55rem 0.9rem;
  font-size: var(--fs-xs); color: var(--muted-dim);
}
.hero__recent-label {
  text-transform: uppercase; letter-spacing: 0.13em; font-weight: 600;
  color: var(--muted-dim);
}
.hero__recent-item {
  position: relative; padding-left: 0.95rem;
  color: var(--muted); font-weight: 500; letter-spacing: 0.01em;
}
.hero__recent-item::before {
  content: ''; position: absolute; left: 0; top: 50%;
  width: 4px; height: 4px; margin-top: -2px; border-radius: 50%;
  background: var(--blue); opacity: 0.8;
}

.hero__media { position: relative; }
.hero__video { width: 100%; height: auto; background: var(--ink-900); }
.hero__video--desktop {
  /* The clip has its own near black background, so a soft radial mask lets it
     dissolve into the page instead of sitting inside an obvious card. */
  -webkit-mask-image: radial-gradient(ellipse 62% 50% at 54% 50%, #000 24%, rgba(0, 0, 0, 0.55) 56%, transparent 100%);
  mask-image: radial-gradient(ellipse 62% 50% at 54% 50%, #000 24%, rgba(0, 0, 0, 0.55) 56%, transparent 100%);
}
.hero__video--mobile { display: none; }
.hero__scrim { display: none; }

@media (max-width: 899px) {
  .hero {
    min-height: 88svh;
    display: flex; align-items: flex-end;
    padding-top: clamp(3rem, 14vw, 6rem);
    padding-bottom: clamp(5.5rem, 14vw, 8rem);
  }
  .hero__media { display: none; }
  .hero__video--mobile {
    display: block; position: absolute; inset: 0; z-index: 0;
    width: 100%; height: 100%; object-fit: cover;
    opacity: 0.85;
  }
  .hero__scrim {
    display: block; position: absolute; inset: 0; z-index: 1;
    background:
      linear-gradient(180deg, rgba(7, 11, 20, 0.94) 0%, rgba(7, 11, 20, 0.55) 34%,
      rgba(7, 11, 20, 0.72) 62%, var(--ink-900) 97%);
  }
  .hero__glow-a { width: 100vw; height: 70vw; top: -10%; right: -30%; opacity: 0.7; }
  .hero__heading { letter-spacing: -0.032em; }
  .hero__lead { font-size: 1.02rem; max-width: 34ch; }
  .hero__actions { margin-bottom: 1.9rem; }
  .hero__actions .btn { flex: 1 1 auto; justify-content: center; min-width: 13rem; }
}

@media (min-width: 900px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .hero__media { position: relative; }
  .hero__video--desktop { width: 132%; max-width: none; margin-left: -12%; margin-block: -8%; }
}
@media (min-width: 1400px) {
  .hero__video--desktop { width: 142%; margin-left: -14%; }
}

/* --------------------------------------------------------------
   Trust strip
   -------------------------------------------------------------- */
.trust { padding-bottom: 0; }
.trust__panel { padding: clamp(1.75rem, 3.4vw, 2.75rem); }
.trust__panel::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.75) 30%, rgba(124, 58, 237, 0.55) 68%, transparent);
}
.trust__head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem;
  padding-bottom: 1.6rem;
}
.trust__sub { font-size: var(--fs-sm); }
.trust__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1.5rem;
  border-top: 1px solid var(--line);
  padding-top: 1.75rem;
}
.trust__item { position: relative; }
.trust__index {
  display: block; font-family: var(--font-display); font-size: var(--fs-xs);
  font-weight: 500; letter-spacing: 0.14em; color: var(--blue);
  margin-bottom: 0.7rem;
}
.trust__title { font-family: var(--font-display); font-size: 1.06rem; font-weight: 500; letter-spacing: -0.015em; margin-bottom: 0.35rem; }
.trust__body { font-size: var(--fs-sm); color: var(--muted); line-height: 1.55; }

@media (min-width: 560px) {
  .trust__list { grid-template-columns: 1fr 1fr; gap: 1.5rem clamp(1.5rem, 4vw, 2.5rem); }
}
@media (min-width: 940px) {
  .trust__list { grid-template-columns: repeat(4, 1fr); gap: 0; }
  .trust__item { padding-inline: clamp(1rem, 2vw, 1.9rem); }
  .trust__item:first-child { padding-left: 0; }
  .trust__item:last-child { padding-right: 0; }
  .trust__item + .trust__item { border-left: 1px solid var(--line); }
}

/* --------------------------------------------------------------
   Section heads
   -------------------------------------------------------------- */
.section-head { max-width: 44rem; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.section-head .eyebrow { margin-bottom: 1.1rem; }
.section-head .lead { margin-top: 1.2rem; }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .lead { margin-inline: auto; }
.section-head--center .eyebrow { justify-content: center; }

/* --------------------------------------------------------------
   Problems
   -------------------------------------------------------------- */
.problems { background: var(--ink-800); }
.problems__grid { display: grid; gap: clamp(2.5rem, 5vw, 5rem); }
.problems__aside .eyebrow { margin-bottom: 1.1rem; }
.problems__heading { margin-bottom: 1.3rem; }
.problems__link { margin-top: 1.6rem; }
.problems__list { list-style: none; margin: 0; padding: 0; }
.problems__item {
  display: grid; grid-template-columns: auto 1fr; gap: 1.1rem;
  padding: 1.35rem 0.25rem 1.35rem 0;
  border-bottom: 1px solid var(--line);
  transition: padding-left 0.4s var(--ease);
}
.problems__item:first-child { border-top: 1px solid var(--line); }
.problems__item:hover { padding-left: 0.65rem; }
.problems__num {
  font-family: var(--font-display); font-size: var(--fs-xs); font-weight: 500;
  color: var(--blue); letter-spacing: 0.1em; padding-top: 0.42rem;
  transition: color 0.3s var(--ease);
}
.problems__item:hover .problems__num { color: var(--blue-light); }
.problems__title { margin-bottom: 0.3rem; }
.problems__body { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; max-width: 52ch; }

@media (min-width: 960px) {
  .problems__grid { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr); align-items: start; }
  .problems__aside { position: sticky; top: 8rem; }
}

/* --------------------------------------------------------------
   Feature (alternating service blocks)
   -------------------------------------------------------------- */
.feature { overflow: hidden; isolation: isolate; padding-block: clamp(4rem, 7.5vw, 7.5rem); }
.feature__glow {
  width: 46vw; height: 46vw; max-width: 720px; max-height: 720px;
  top: 8%; right: -16%; opacity: 0.75;
}
.feature--flip .feature__glow { right: auto; left: -16%; }
.feature__grid { position: relative; z-index: 2; display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); align-items: center; }
.feature__heading { margin: 1.2rem 0 1.4rem; }
.feature__body + .feature__body { margin-top: 1rem; }
.feature__cta { margin-top: 2rem; }
.feature__media { min-width: 0; }

@media (min-width: 980px) {
  .feature__grid { grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); }
  .feature--flip .feature__grid { grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr); }
  .feature--flip .feature__copy { order: 2; }
  .feature--flip .feature__media { order: 1; }
  .feature__copy { max-width: 34rem; }
  .feature:not(.feature--flip) .feature__copy { margin-left: auto; margin-right: 0; }
}

.checklist { list-style: none; margin: 2rem 0 0; padding: 0; display: grid; gap: 0.75rem 1.6rem; }
.checklist li {
  position: relative; padding-left: 1.7rem;
  font-size: var(--fs-sm); color: var(--muted); line-height: 1.5;
}
.checklist li::before {
  content: ''; position: absolute; left: 0; top: 0.34em;
  width: 1.05rem; height: 1.05rem; border-radius: 50%;
  background: rgba(59, 130, 246, 0.16);
  border: 1px solid rgba(59, 130, 246, 0.4);
}
.checklist li::after {
  content: ''; position: absolute; left: 0.32rem; top: 0.66em;
  width: 0.4rem; height: 0.22rem;
  border-left: 1.6px solid var(--blue-light);
  border-bottom: 1.6px solid var(--blue-light);
  transform: rotate(-45deg);
}
.checklist--tight { margin-top: 0; gap: 0.6rem; }
@media (min-width: 640px) { .checklist { grid-template-columns: 1fr 1fr; } }
.checklist--single { grid-template-columns: 1fr !important; }

/* --------------------------------------------------------------
   Device frames
   -------------------------------------------------------------- */
.frame { position: relative; border-radius: var(--r-lg); overflow: hidden; background: var(--ink-700); }
.frame--browser {
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-lift);
  border-radius: clamp(12px, 1.6vw, 20px);
}
.frame__bar {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.62rem 0.9rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.02));
  border-bottom: 1px solid var(--line);
}
.frame__dots { display: inline-flex; gap: 0.36rem; }
.frame__dots i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, 0.18); }
.frame__url {
  flex: 1; text-align: center; font-size: 0.68rem; color: var(--muted-dim);
  letter-spacing: 0.02em;
}
.frame__screen { position: relative; background: #fff; }
.frame__screen img { width: 100%; }

.frame--phone {
  border-radius: 22px; padding: 5px;
  background: linear-gradient(160deg, #2b3550, #10182a);
  border: 1px solid var(--line-2);
  box-shadow: 0 30px 60px -22px rgba(0, 0, 0, 0.95);
}
.frame--phone .frame__screen { border-radius: 17px; overflow: hidden; }

.showcase, .project__media { position: relative; }
.showcase__phone, .project__phone {
  position: absolute; z-index: 3;
  bottom: -12%;
  /* Overhang is tied to the page gutter so the phone never leaves the viewport. */
  left: max(-7%, calc(var(--gutter) * -0.55));
  width: clamp(96px, 21%, 190px);
}
.seo-visual img {
  width: 100%; border-radius: var(--r-xl);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lift);
}

/* --------------------------------------------------------------
   Services: the three things we do
   -------------------------------------------------------------- */
.services { overflow: hidden; isolation: isolate; }
.services__glow {
  width: 70vw; height: 40vw; max-width: 900px;
  top: -8%; left: 50%; transform: translateX(-50%); opacity: 0.55;
}
/* Three large horizontal cards stacked vertically, each revealing on its own
   as it scrolls into view. */
.services__stack {
  position: relative; z-index: 2;
  display: grid; gap: clamp(1.25rem, 2.5vw, 2rem);
}

.svc {
  position: relative; overflow: hidden;
  display: grid; gap: clamp(1.75rem, 3.5vw, 3.5rem);
  align-items: center;
  padding: clamp(1.6rem, 3.2vw, 3rem);
  background: var(--ink-800);
  border: 1px solid var(--line);
  border-radius: var(--r-2xl);
  transition: border-color 0.4s var(--ease), background-color 0.4s var(--ease),
    transform 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.svc::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.65) 35%, rgba(124, 58, 237, 0.45) 72%, transparent);
}
.svc:hover {
  border-color: rgba(59, 130, 246, 0.34);
  background: var(--ink-700);
  transform: translateY(-3px);
  box-shadow: 0 40px 90px -50px rgba(59, 130, 246, 0.5);
}

.svc__copy { min-width: 0; }
.svc__num {
  display: block; font-family: var(--font-display);
  font-size: var(--fs-xs); font-weight: 500; letter-spacing: 0.16em;
  color: var(--blue); margin-bottom: 0.9rem;
}
.svc__title { font-size: clamp(1.75rem, 1.2rem + 1.9vw, 2.6rem); margin-bottom: 0.7rem; }
.svc__lede {
  font-size: var(--fs-lead); color: var(--white); line-height: 1.45;
  letter-spacing: -0.012em; margin-bottom: 1.5rem; max-width: 34ch;
}
.svc__points { list-style: none; margin: 0 0 1.6rem; padding: 0; display: grid; gap: 0.65rem; }
.svc__points li {
  position: relative; padding-left: 1.35rem;
  font-size: var(--fs-sm); color: var(--muted); line-height: 1.5;
}
.svc__points li::before {
  content: ''; position: absolute; left: 0; top: 0.6em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--blue);
}

/* Media column. Nothing in here is allowed to size the card. */
.svc__media { min-width: 0; }
.svc__media > * { max-width: 100%; }
.svc__media img { width: 100%; height: auto; max-width: 100%; display: block; }
.svc__media .frame--browser { box-shadow: 0 30px 70px -34px rgba(0, 0, 0, 0.9); }
.seo-visual--card img { border-radius: var(--r-lg); }

.svc__store { position: relative; }

/* Scroll spacer used only by the deck layout below. */
.svc-gap { display: none; }

/* Platform badges. Small, fixed, and explicitly constrained so a large source
   file can never blow up the layout. */
.platforms {
  list-style: none; margin: 0.9rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.5rem;
}
.platform {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 0.8rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--line-2);
  backdrop-filter: blur(8px);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.01em;
  color: var(--muted); white-space: nowrap;
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease);
}
.platform__mark {
  width: 20px; height: 20px;
  max-width: 24px; max-height: 24px;
  min-width: 20px;
  flex: none; object-fit: contain;
  color: var(--muted-dim);
  transition: color 0.35s var(--ease);
}
.svc:hover .platform { color: var(--white); border-color: var(--line-3); }
.svc:hover .platform__mark { color: var(--blue-light); }

@media (min-width: 900px) {
  .svc { grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); }
  /* Alternate the media side so the stack does not read as three identical rows.
     Column widths swap along with the order, so the media always keeps the
     wider column and every card's visual is the same size. */
  .svc:nth-child(even) { grid-template-columns: minmax(0, 1.22fr) minmax(0, 0.78fr); }
  .svc:nth-child(even) .svc__copy { order: 2; }
  .svc:nth-child(even) .svc__media { order: 1; }
}

/* --------------------------------------------------------------
   Service cards as a scrolled deck.
   Each card pins to the middle of the screen and the next one rides up
   over it, so one card is in view at a time. The card underneath scales
   back a little so it reads as a stack rather than a jump cut.

   Sticky positioning does the work; the classes only add the depth. If
   the script never runs, or the viewport is short, or the visitor asked
   for reduced motion, this degrades to three cards stacked down the page.
   -------------------------------------------------------------- */
/* Whether the deck runs is decided in the script, not here, because it depends
   on the tallest card actually fitting the viewport under the header. A media
   query cannot measure that, and it varies with phone size and font settings.
   Everything below only applies once the script adds .is-deck. */
@media (prefers-reduced-motion: no-preference) {
  /* Sticky does not work inside a clipping ancestor, so the section drops its
     overflow while the deck is on. The ambient glow is still contained by the
     overflow-x on body. */
  .services:has(.is-deck) { overflow: visible; }

  .services__stack.is-deck {
    display: block;
    /* Cards pin against this box, so they stay pinned once stuck and the next
       card rides up over the one before it. */
    position: relative;
  }

  /* The scroll distance between cards has to be a sibling rather than a margin
     on the card. A sticky element stops sticking when its MARGIN box reaches the
     bottom of the containing block, so a margin here would cut each card's pin
     short. Padding on the stack does not help either: Chrome constrains sticky
     to the content box, not the padding box. A real empty sibling is content, so
     it extends the travel without shortening it. */
  .is-deck .svc-gap { display: block; height: 58vh; }

  .is-deck .svc {
    position: sticky;
    /* Clears the sticky header, then centres the tallest card. */
    top: max(5.5rem, calc((100svh - var(--deck-card-h, 30rem)) / 2));
    /* scale and opacity rather than transform, so the entrance animation on
       [data-reveal] keeps its own transform and the two do not fight. */
    transition:
      scale 0.5s var(--ease-out),
      opacity 0.5s var(--ease-out),
      filter 0.5s var(--ease-out),
      border-color 0.4s var(--ease),
      background-color 0.4s var(--ease);
    will-change: scale, opacity;
  }

  /* The card that has been scrolled past, now sitting under the incoming one. */
  .is-deck .svc.is-behind {
    scale: 0.945;
    opacity: 0.4;
    filter: saturate(0.7);
  }
  .is-deck .svc.is-behind:hover { transform: none; }
}

/* --------------------------------------------------------------
   Why K1 Nova
   -------------------------------------------------------------- */
.why { background: var(--ink-800); }
.why__grid { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); }
.why__aside .eyebrow { margin-bottom: 1.1rem; }
.why__heading { margin-bottom: 1.2rem; }
.why__cta { margin-top: 1.8rem; }
.why__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.why__item {
  padding: 1.3rem 0;
  border-top: 1px solid var(--line);
}
.why__item:last-child { border-bottom: 1px solid var(--line); }
.why__title {
  font-family: var(--font-display); font-size: 1.06rem; font-weight: 500;
  letter-spacing: -0.015em; margin-bottom: 0.3rem;
}
.why__body { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; max-width: 54ch; }

@media (min-width: 900px) {
  .why__grid { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start; }
  .why__aside { position: sticky; top: 8rem; }
  .why__list { grid-template-columns: 1fr 1fr; gap: 0 clamp(1.5rem, 4vw, 3rem); }
  .why__item:nth-child(2) { border-top: 1px solid var(--line); }
  .why__item:nth-last-child(2) { border-bottom: 1px solid var(--line); }
}

.feature__note {
  margin-top: 1.4rem; font-size: var(--fs-xs); color: var(--muted-dim);
  line-height: 1.6; max-width: 48ch;
}

/* --------------------------------------------------------------
   Before / after comparison
   -------------------------------------------------------------- */
.compare { overflow: hidden; isolation: isolate; background: var(--ink-800); }
.compare__glow { width: 60vw; height: 40vw; max-width: 900px; top: 6%; left: 50%; transform: translateX(-50%); opacity: 0.6; }
.compare__head { position: relative; z-index: 2; max-width: 44rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.compare__head .eyebrow { margin-bottom: 1.1rem; }
.compare__head .lead { margin-top: 1.2rem; }

.compare__stage { position: relative; z-index: 2; max-width: 1100px; margin-inline: auto; }
.compare__viewer {
  position: relative;
  aspect-ratio: var(--compare-ratio, 1440 / 1010);
  border-radius: clamp(14px, 1.8vw, 22px);
  overflow: hidden;
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-lift);
  background: #fff;
  touch-action: pan-y;
  cursor: ew-resize;
  --pos: 50%;
}
/* Nested inside a browser frame: the frame already supplies the chrome, the
   rounding and the clipping, so the viewer drops its own and fills the screen. */
.frame__screen .compare__viewer {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  width: 100%;
}
.frame--compare .frame__screen { overflow: hidden; }

.compare__img { position: absolute; inset: 0; }
.compare__img img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.compare__img--before { clip-path: inset(0 calc(100% - var(--pos)) 0 0); }

.compare__tag {
  position: absolute; top: 0.9rem; z-index: 4;
  padding: 0.3rem 0.75rem; border-radius: var(--r-pill);
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  background: rgba(7, 11, 20, 0.9); color: #fff;
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  pointer-events: none;
}
.compare__tag--before { left: 0.9rem; }
.compare__tag--after { right: 0.9rem; background: rgba(29, 78, 216, 0.94); border-color: rgba(255, 255, 255, 0.35); }

.compare__handle {
  position: absolute; top: 0; bottom: 0; left: var(--pos);
  width: 2px; margin-left: -1px; z-index: 5;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), #fff 22%, #fff 78%, rgba(255, 255, 255, 0.5));
  pointer-events: none;
}
.compare__grip {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(7, 11, 20, 0.9); color: #fff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(6px);
}
.compare__grip svg { width: 20px; height: 12px; }

.compare__range {
  position: absolute; inset: 0; z-index: 6;
  width: 100%; height: 100%; margin: 0; opacity: 0;
  cursor: ew-resize; -webkit-appearance: none; appearance: none; background: none;
}
.compare__range:focus-visible { opacity: 1; outline: 3px solid var(--blue-light); outline-offset: 4px; }
.compare__range::-webkit-slider-thumb { -webkit-appearance: none; width: 44px; height: 100%; }
.compare__range::-moz-range-thumb { width: 44px; height: 100%; border: 0; background: transparent; }

.compare__notes {
  position: relative; z-index: 2;
  max-width: 1100px; margin: clamp(2rem, 4vw, 3rem) auto 0;
}
.compare__notes-title { margin-bottom: 1.1rem; }
.compare__changes {
  list-style: none; margin: 0 0 1.4rem; padding: 0;
  display: grid; gap: 0.7rem 2rem;
  font-size: var(--fs-sm); color: var(--muted);
}
.compare__changes li { position: relative; padding-left: 1.35rem; line-height: 1.55; }
.compare__changes li::before {
  content: ''; position: absolute; left: 0; top: 0.62em;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--blue);
}
.compare__disclaimer { font-size: var(--fs-xs); color: var(--muted-dim); margin-bottom: 1.2rem; max-width: 60ch; }
@media (min-width: 760px) { .compare__changes { grid-template-columns: 1fr 1fr; } }

/* --------------------------------------------------------------
   Work / project blocks
   -------------------------------------------------------------- */
.work__list { display: grid; gap: clamp(4rem, 9vw, 8rem); }
.project { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }
.project__index {
  display: block; font-family: var(--font-display); font-size: var(--fs-xs);
  font-weight: 500; letter-spacing: 0.16em; color: var(--blue); margin-bottom: 0.9rem;
}
.project__name { margin-bottom: 0.5rem; font-size: clamp(1.85rem, 1.25rem + 2vw, 2.8rem); }
.project__meta {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--muted-dim); margin-bottom: 1.2rem;
}
.project__summary { margin-bottom: 1.5rem; }

.tags { list-style: none; display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 0 0 1.6rem; padding: 0; }
.tags li {
  padding: 0.32rem 0.75rem; border-radius: var(--r-pill);
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--muted); background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--line);
}

@media (min-width: 980px) {
  .project { grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr); gap: clamp(3rem, 5vw, 5rem); }
  .project__copy { max-width: 30rem; }
  .project--flip .project__media { order: 2; }
  .project--flip .project__copy { order: 1; }
  .project--flip .project__phone { left: auto; right: max(-7%, calc(var(--gutter) * -0.55)); }
}

/* --------------------------------------------------------------
   Process
   -------------------------------------------------------------- */
.process { background: var(--ink-800); }
.process__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2.25rem; counter-reset: step; }
.process__step { position: relative; padding-top: 1.75rem; border-top: 1px solid var(--line); }
.process__step::after {
  content: ''; position: absolute; top: -1px; left: 0; width: 2.5rem; height: 2px;
  background: linear-gradient(90deg, var(--blue), var(--violet));
}
.process__num {
  display: block; font-family: var(--font-display); font-size: 2.2rem; font-weight: 500;
  letter-spacing: -0.03em;
  color: transparent; -webkit-text-stroke: 1px rgba(255, 255, 255, 0.22);
  margin-bottom: 0.8rem; line-height: 1;
}
.process__title { margin-bottom: 0.5rem; }
.process__body { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; }
@media (min-width: 860px) { .process__list { grid-template-columns: repeat(4, 1fr); gap: 2rem; } }

/* --------------------------------------------------------------
   Pricing
   -------------------------------------------------------------- */
.pricing { position: relative; overflow: hidden; isolation: isolate; }
.pricing__glow { width: 56vw; height: 40vw; max-width: 820px; top: 4%; left: 50%; transform: translateX(-50%); opacity: 0.7; }
.pricing__grid { position: relative; z-index: 2; display: grid; gap: 1.25rem; align-items: stretch; }

.price {
  display: flex; flex-direction: column;
  padding: clamp(1.6rem, 2.6vw, 2.25rem);
  background: var(--ink-800);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  position: relative;
}
.price--featured {
  background: linear-gradient(178deg, rgba(59, 130, 246, 0.13), rgba(124, 58, 237, 0.07) 55%, transparent 88%), var(--ink-700);
  border-color: rgba(59, 130, 246, 0.42);
  box-shadow: 0 40px 90px -40px rgba(59, 130, 246, 0.55);
}
.price__flag {
  position: absolute; top: -0.75rem; left: clamp(1.6rem, 2.6vw, 2.25rem);
  padding: 0.28rem 0.8rem; border-radius: var(--r-pill);
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.11em; text-transform: uppercase;
  background: linear-gradient(100deg, var(--blue-solid), #6D28D9); color: #fff;
}
.price__name { margin-bottom: 0.5rem; }
.price__tagline { font-size: var(--fs-sm); color: var(--muted); margin-bottom: 1.4rem; min-height: 2.9em; line-height: 1.5; }
.price__amount { display: flex; flex-direction: column; gap: 0.15rem; }
.price__from { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.13em; color: var(--muted-dim); }
.price__amount strong {
  font-family: var(--font-display); font-size: clamp(2.1rem, 4vw, 2.7rem);
  font-weight: 500; letter-spacing: -0.035em; line-height: 1.05;
}
/* Offer price with the regular price struck through beside it. */
.price__figures { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.price__was {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2vw, 1.45rem);
  font-weight: 500; letter-spacing: -0.02em;
  color: var(--muted-dim);
  text-decoration-thickness: 1.5px;
  text-decoration-color: rgba(170, 180, 200, 0.75);
}
.price__offer-note { font-size: var(--fs-xs); color: var(--muted); margin-top: 0.3rem; }
.price__flag--offer { background: linear-gradient(100deg, #C2410C, #DC2626); }
.price__rule { margin: 1.4rem 0; }
.price .checklist { grid-template-columns: 1fr; }
.price__best {
  font-size: var(--fs-xs); color: var(--muted-dim); line-height: 1.55;
  margin: 1.4rem 0 1.6rem; padding-top: 1.2rem; border-top: 1px solid var(--line);
}
.price__cta { margin-top: auto; }
@media (min-width: 900px) { .pricing__grid { grid-template-columns: repeat(3, 1fr); gap: 1.5rem; } }

.pricing__note {
  position: relative; z-index: 2;
  margin-top: clamp(2rem, 4vw, 3rem);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1rem 2rem;
  padding: 1.4rem clamp(1.4rem, 2.5vw, 2rem);
  background: rgba(255, 255, 255, 0.028);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.pricing__note p { color: var(--muted); font-size: var(--fs-sm); }
.pricing__note strong { color: var(--white); }

/* --------------------------------------------------------------
   Management
   -------------------------------------------------------------- */
.management__panel { display: grid; gap: 2rem; padding: clamp(1.75rem, 3.4vw, 2.75rem); }
.management__copy .eyebrow { margin-bottom: 1rem; }
.management__copy h2 { margin-bottom: 0.9rem; }
.management__body { font-size: var(--fs-sm); line-height: 1.65; max-width: 52ch; }
.management__points { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem; align-content: center; }
.management__points li {
  position: relative; padding-left: 1.4rem; font-size: var(--fs-sm); color: var(--muted);
}
.management__points li::before {
  content: ''; position: absolute; left: 0; top: 0.62em; width: 6px; height: 6px;
  border-radius: 50%; background: linear-gradient(120deg, var(--blue), var(--violet));
}
@media (min-width: 860px) { .management__panel { grid-template-columns: 1.1fr 0.9fr; gap: 3rem; } }

/* --------------------------------------------------------------
   FAQ
   -------------------------------------------------------------- */
.faq__grid { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); }
.faq__aside .eyebrow { margin-bottom: 1.1rem; }
.faq__aside h2 { margin-bottom: 1.2rem; }
.faq__aside .link-arrow { margin-top: 1.5rem; }
.faq__list { display: grid; }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__item:first-child { border-top: 1px solid var(--line); }
.faq__q {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem;
  padding: 1.3rem 0; cursor: pointer; list-style: none;
  font-family: var(--font-display); font-size: 1.02rem; font-weight: 500;
  letter-spacing: -0.012em; line-height: 1.4;
  transition: color 0.25s var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: var(--blue-light); }
.faq__icon {
  position: relative; flex: none; width: 1.1rem; height: 1.1rem; margin-top: 0.2rem;
}
.faq__icon::before, .faq__icon::after {
  content: ''; position: absolute; left: 50%; top: 50%; background: var(--blue-light);
  transform: translate(-50%, -50%); transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}
.faq__icon::before { width: 1.1rem; height: 1.5px; }
.faq__icon::after { width: 1.5px; height: 1.1rem; }
.faq__item[open] .faq__icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.faq__a { padding-bottom: 1.4rem; }
.faq__a p { font-size: var(--fs-sm); color: var(--muted); line-height: 1.68; max-width: 66ch; }
.faq__item[open] .faq__a { animation: faq-in 0.35s var(--ease-out); }
@keyframes faq-in { from { opacity: 0; transform: translateY(-6px); } }
@media (min-width: 960px) {
  .faq__grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); align-items: start; }
  .faq__aside { position: sticky; top: 8rem; }
}

/* --------------------------------------------------------------
   Final CTA
   -------------------------------------------------------------- */
.cta-panel {
  position: relative; overflow: hidden; isolation: isolate;
  border-radius: var(--r-3xl);
  border: 1px solid var(--line-2);
  background:
    radial-gradient(120% 130% at 12% 0%, rgba(59, 130, 246, 0.22), transparent 58%),
    radial-gradient(90% 120% at 96% 100%, rgba(124, 58, 237, 0.2), transparent 62%),
    var(--ink-800);
  padding: clamp(2.5rem, 6vw, 5rem);
  text-align: center;
}
.cta-panel__glow { width: 70%; height: 120%; top: -40%; left: 15%; opacity: 0.5; }
.cta-panel__content { position: relative; z-index: 2; max-width: 46rem; margin-inline: auto; }
.cta-panel__heading { margin-bottom: 1.2rem; }
.cta-panel__body { margin-inline: auto; margin-bottom: 2.2rem; }
.cta-panel__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; }

/* --------------------------------------------------------------
   Page hero (interior pages)
   -------------------------------------------------------------- */
.page-hero {
  position: relative; overflow: hidden; isolation: isolate;
  padding-top: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
}
.page-hero__glow { width: 62vw; height: 46vw; max-width: 900px; top: -28%; right: -12%; }
.page-hero__grid { position: relative; z-index: 2; display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: center; }
.page-hero__heading { margin: 1.2rem 0 1.4rem; }
.page-hero__lead { max-width: 52ch; }
.page-hero__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-top: 2.2rem; }
@media (min-width: 980px) {
  .page-hero__grid--split { grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr); }
}

.crumbs { position: relative; z-index: 2; margin-bottom: 1.75rem; }
.crumbs ol {
  display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0; padding: 0;
  font-size: var(--fs-xs); color: var(--muted-dim);
}
.crumbs li + li::before { content: '/'; margin-right: 0.5rem; opacity: 0.5; }
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--blue-light); }

/* --------------------------------------------------------------
   Footer
   -------------------------------------------------------------- */
.site-footer {
  position: relative;
  padding-top: clamp(3.5rem, 7vw, 6rem);
  padding-bottom: 2.5rem;
  border-top: 1px solid var(--line);
  background: var(--ink-850);
}
.site-footer::before {
  content: ''; position: absolute; inset: -1px 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.5) 25%, rgba(124, 58, 237, 0.4) 70%, transparent);
}
.site-footer__top { display: grid; gap: 3rem; padding-bottom: 3rem; }
.site-footer__brand img { width: 230px; height: auto; }
.site-footer__blurb { margin: 1.5rem 0; font-size: var(--fs-sm); color: var(--muted); max-width: 40ch; line-height: 1.65; }
.site-footer__contact { display: grid; gap: 0.35rem; font-size: var(--fs-sm); }
.site-footer__contact a { color: var(--muted); transition: color 0.25s var(--ease); }
.site-footer__contact a:hover { color: var(--blue-light); }

.site-footer__nav { display: grid; gap: 2.25rem; }
.site-footer__heading {
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.13em; color: var(--white);
  margin-bottom: 1rem;
}
.site-footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.15rem; }
/* Footer links carry a comfortable tap area rather than sitting at text height. */
.site-footer__col a {
  display: inline-flex; align-items: center; min-height: 2.5rem;
  font-size: var(--fs-sm); color: var(--muted); transition: color 0.25s var(--ease);
}
.site-footer__col a:hover { color: var(--white); }
.site-footer__contact a { display: inline-flex; align-items: center; min-height: 2.5rem; }
.site-footer__legal a { display: inline-flex; align-items: center; min-height: 2.5rem; }
.site-footer__area { margin-top: 1rem; font-size: var(--fs-xs); color: var(--muted-dim); line-height: 1.6; max-width: 30ch; }

.site-footer__bottom {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; justify-content: space-between;
  padding-top: 2rem; border-top: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--muted-dim);
}
.site-footer__legal { display: flex; gap: 1.5rem; list-style: none; margin: 0; padding: 0; }
.site-footer__legal a { transition: color 0.25s var(--ease); }
.site-footer__legal a:hover { color: var(--white); }

@media (min-width: 760px) { .site-footer__nav { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1020px) { .site-footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); gap: 4rem; } }

/* --------------------------------------------------------------
   Responsive header
   -------------------------------------------------------------- */
@media (max-width: 1079px) {
  .nav, .site-header__phone { display: none; }
  .burger { display: flex; }
  .site-header__inner { justify-content: space-between; }
}
@media (max-width: 479px) {
  .site-header__cta { display: none; }
  .brand__wordmark { width: 100px; }
}

/* --------------------------------------------------------------
   Forms
   -------------------------------------------------------------- */
.quote-form { display: grid; gap: 1.5rem; }
.honeypot { position: absolute; left: 0; top: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; clip-path: inset(50%); }
.quote-form__grid { display: grid; gap: 1.25rem; }
@media (min-width: 620px) { .quote-form__grid { grid-template-columns: 1fr 1fr; } }

/* align-content keeps a field's rows packed at the top. Without it a field
   sitting beside one that carries a hint line gets stretched to match the row,
   which made the email input taller than the website input next to it. */
.field { display: grid; gap: 0.45rem; min-width: 0; align-content: start; }
.field--full { grid-column: 1 / -1; }
.field__label {
  display: flex; align-items: baseline; gap: 0.5rem;
  font-size: var(--fs-sm); font-weight: 600; color: var(--white);
}
.field__req { color: var(--blue-light); }
.field__opt { font-size: 0.7rem; font-weight: 500; color: var(--muted-dim); letter-spacing: 0.03em; }
.field__input {
  width: 100%; padding: 0.85rem 1rem;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  color: var(--white); font-size: var(--fs-sm);
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.field__input::placeholder { color: rgba(170, 180, 200, 0.5); }
.field__input:hover { border-color: var(--line-3); }
.field__input:focus {
  outline: none; border-color: var(--blue);
  background: rgba(59, 130, 246, 0.07);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.22);
}
.field__input[aria-invalid='true'] { border-color: #F87171; }
.field__textarea { resize: vertical; min-height: 9rem; line-height: 1.6; font-family: inherit; }
.field__select { position: relative; }
.field__select select { appearance: none; -webkit-appearance: none; padding-right: 2.5rem; cursor: pointer; }
.field__select option { background: var(--ink-700); color: var(--white); }
.field__select svg {
  position: absolute; right: 1rem; top: 50%; transform: translateY(-50%);
  width: 10px; height: 6px; color: var(--muted); pointer-events: none;
}
.field__hint { font-size: var(--fs-xs); color: var(--muted-dim); }
.field__error { font-size: var(--fs-xs); color: #F87171; min-height: 0; }
.field__error:empty { display: none; }

.quote-form__foot { display: grid; gap: 0.9rem; justify-items: start; }
.quote-form__note { font-size: var(--fs-xs); color: var(--muted-dim); max-width: 42ch; }

.form__status { font-size: var(--fs-sm); padding: 0.85rem 1.1rem; border-radius: var(--r-md); }
.form__status:empty { display: none; }
.form__status.is-success { background: rgba(52, 211, 153, 0.12); border: 1px solid rgba(52, 211, 153, 0.35); color: #A7F3D0; }
.form__status.is-error { background: rgba(248, 113, 113, 0.1); border: 1px solid rgba(248, 113, 113, 0.32); color: #FCA5A5; }
.form__status.is-pending { background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.32); color: var(--blue-light); }

/* --------------------------------------------------------------
   Prose (privacy, terms, case study body copy)
   -------------------------------------------------------------- */
.prose { max-width: 46rem; }
.prose > * + * { margin-top: 1.15rem; }
.prose h2 {
  font-size: var(--fs-h3); margin-top: 2.75rem; margin-bottom: 0.4rem;
  padding-top: 2rem; border-top: 1px solid var(--line);
}
.prose h3 { font-size: var(--fs-h4); margin-top: 1.9rem; margin-bottom: 0.2rem; }
.prose p, .prose li { color: var(--muted); line-height: 1.75; }
.prose strong { color: var(--white); font-weight: 600; }
.prose a { color: var(--blue-light); text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover { color: #8DBBFF; }
.prose ul, .prose ol { padding-left: 1.2rem; display: grid; gap: 0.5rem; }
.prose li::marker { color: var(--blue); }
.prose .note {
  padding: 1.1rem 1.3rem; border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------
   Split layout (heading left, body right)
   -------------------------------------------------------------- */
.split { display: grid; gap: clamp(1.5rem, 4vw, 3.5rem); }
.split__side .eyebrow { margin-bottom: 1rem; }
.split__note { font-size: var(--fs-sm); margin-top: 1rem; max-width: 34ch; }
.split__body > * + * { margin-top: 1.1rem; }
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); align-items: start; }
}

/* --------------------------------------------------------------
   Numbered grid list
   -------------------------------------------------------------- */
.grid-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-xl); overflow: hidden; }
.grid-list__item { padding: clamp(1.4rem, 2.6vw, 2rem); background: var(--ink-850); }
.grid-list__num {
  display: block; font-family: var(--font-display); font-size: var(--fs-xs);
  font-weight: 500; letter-spacing: 0.14em; color: var(--blue); margin-bottom: 0.9rem;
}
.grid-list__item h3 { margin-bottom: 0.45rem; }
.grid-list__item p { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; }
@media (min-width: 700px) { .grid-list { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1060px) { .grid-list { grid-template-columns: repeat(4, 1fr); } }

.page-hero__visual { width: 100%; border-radius: var(--r-xl); border: 1px solid var(--line); }

/* --------------------------------------------------------------
   Background clips

   Artwork that sits under copy: the arc below the closing call to action, the
   lattice across the top of the interior pages. Markup comes from
   movingBackdrop() in lib/html.js, the clip is attached by site.js.

   The still and the clip are the same picture, laid exactly over each other at
   the same opacity, so only one of them is ever visible and the band can never
   double up and brighten. `is-bg-video` goes on the parent, and only once the
   clip is really playing: until then, and for anyone whose clip never arrives,
   the still is what is on screen and nothing looks unfinished.

   Both sit under a scrim rather than being dimmed on their own, because the
   text over them has to stay at its contrast whatever the clip is doing at that
   moment. `npm run check` measures that.
   -------------------------------------------------------------- */
.cta-band__art,
.cta-band__video,
.page-hero__art,
.page-hero__video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.cta-band__art img,
.page-hero__art img { width: 100%; height: 100%; object-fit: cover; }
.cta-band__video,
.page-hero__video { object-fit: cover; opacity: 0; }

/* The still fades out as the clip fades in, both over the same moment. */
.cta-band__art img,
.page-hero__art img,
.cta-band__video,
.page-hero__video { transition: opacity 0.8s var(--ease-out); }

/* The arc is a curve across the bottom of its frame with the glow above it, so
   it is anchored to the bottom of the band: the light rises into the copy
   rather than being cropped away above it. */
.cta-band__art img,
.cta-band__video { object-position: 50% 100%; opacity: 0.55; }
.cta-band.is-bg-video .cta-band__art img { opacity: 0; }
.cta-band.is-bg-video .cta-band__video { opacity: 0.55; }
.cta-band__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, var(--ink-850) 0%, rgba(11, 16, 23, 0.72) 42%, rgba(11, 16, 23, 0.55) 100%);
}

/* The lattice is weighted to the right of its frame and falls away to black on
   the left, which is where the heading and the lead sit. Anchored right, it
   fills the empty half of the band and leaves the copy on plain dark. */
.page-hero__art img,
.page-hero__video { object-position: 100% 50%; opacity: 0.5; }
.page-hero.is-bg-video .page-hero__art img { opacity: 0; }
.page-hero.is-bg-video .page-hero__video { opacity: 0.5; }
.page-hero__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(90deg, var(--ink-900) 0%, rgba(7, 11, 20, 0.86) 38%, rgba(7, 11, 20, 0.45) 100%),
    linear-gradient(180deg, rgba(7, 11, 20, 0.5) 0%, transparent 30%, var(--ink-900) 100%);
}

/* On a narrow window the copy runs the full width of the band, so the lattice
   sits under the heading rather than beside it. That is why it is dimmer here,
   and it stays dimmer: this only makes it move at that weight.

   It used to be taken out altogether, which left the interior pages still on a
   phone while the arc under the closing call to action moved, and the two bands
   on one page disagreeing about whether the artwork was alive read as the top
   one being broken. The clip is 57KB, the scrim over it is what holds the
   text's contrast rather than the artwork being dark, and `npm run check`
   measures that at this width too. Reduced motion and a saved-data connection
   still get the still, which is the same picture. */
@media (max-width: 780px) {
  .page-hero__art img { opacity: 0.28; }
  .page-hero.is-bg-video .page-hero__video { opacity: 0.28; }
}

/* Anyone who asked for less motion keeps the still, which is the same picture.
   site.js never attaches a clip for them either; this is the belt to that
   brace, and it also covers a clip that was already playing when the setting
   was changed with the page open. */
@media (prefers-reduced-motion: reduce) {
  .cta-band__video,
  .page-hero__video { display: none; }
  .cta-band.is-bg-video .cta-band__art img { opacity: 0.55; }
  .page-hero.is-bg-video .page-hero__art img { opacity: 0.5; }
}

/* --------------------------------------------------------------
   Pricing teaser
   -------------------------------------------------------------- */
.pricing-teaser__panel {
  display: grid; gap: 1.75rem; align-items: center;
  padding: clamp(1.75rem, 3.4vw, 2.75rem);
  background:
    radial-gradient(110% 140% at 8% 0%, rgba(59, 130, 246, 0.14), transparent 62%),
    var(--ink-800);
}
.pricing-teaser__panel h2 { margin: 0.9rem 0 0.7rem; }
.pricing-teaser__body { font-size: var(--fs-sm); max-width: 52ch; line-height: 1.65; }
.pricing-teaser__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
@media (min-width: 900px) {
  .pricing-teaser__panel { grid-template-columns: 1.4fr auto; gap: 3rem; }
}

/* --------------------------------------------------------------
   Three column explainer
   -------------------------------------------------------------- */
.cols-3 { display: grid; gap: 1.25rem; }
.col-card {
  padding: clamp(1.5rem, 2.8vw, 2.1rem);
  background: var(--ink-800);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  position: relative;
}
.col-card::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.6), transparent);
}
.col-card__title { margin-bottom: 0.8rem; }
.col-card p { font-size: var(--fs-sm); color: var(--muted); line-height: 1.65; }
@media (min-width: 860px) { .cols-3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 700px) { .cols-3--four { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1060px) { .cols-3--four { grid-template-columns: repeat(4, 1fr); } }

.source-note { margin-top: 1.5rem; font-size: var(--fs-xs); color: var(--muted-dim); }
/* On a light band --muted-dim is too pale to clear AA at this size. */
.section--light .source-note { color: var(--muted-on-light); font-size: var(--fs-sm); }

/* --------------------------------------------------------------
   Expectations panel
   -------------------------------------------------------------- */
.expectations__panel {
  display: grid; gap: 2rem;
  padding: clamp(1.75rem, 3.4vw, 2.75rem);
  background:
    radial-gradient(120% 150% at 100% 0%, rgba(124, 58, 237, 0.13), transparent 60%),
    var(--ink-800);
}
.expectations__copy h2 { margin: 0.9rem 0 0.8rem; }
.expectations__body { font-size: var(--fs-sm); line-height: 1.65; max-width: 44ch; }
.expectations__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.85rem; }
.expectations__list li {
  position: relative; padding-left: 1.6rem;
  font-size: var(--fs-sm); color: var(--muted); line-height: 1.6;
}
.expectations__list li::before {
  content: ''; position: absolute; left: 0; top: 0.52em;
  width: 0.6rem; height: 0.6rem; border-radius: 2px;
  border: 1.5px solid rgba(124, 58, 237, 0.7);
  transform: rotate(45deg);
}
@media (min-width: 900px) { .expectations__panel { grid-template-columns: 0.9fr 1.1fr; gap: 3rem; } }

@media (min-width: 700px) { .cols-3--six { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .cols-3--six { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------
   About panel
   -------------------------------------------------------------- */
.about-panel {
  padding: clamp(2rem, 4.5vw, 3.5rem);
  background:
    radial-gradient(110% 150% at 100% 0%, rgba(59, 130, 246, 0.16), transparent 62%),
    var(--ink-800);
  isolation: isolate;
}
.about-panel__glow { width: 60%; height: 140%; top: -30%; right: -10%; opacity: 0.5; }
.about-panel__content { position: relative; z-index: 2; max-width: 50rem; }
.about-panel__content h2 { margin: 0.9rem 0 1rem; }
.about-panel__body { margin-bottom: 2rem; }
.about-panel__contact { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem 2rem; }
.about-panel__details { display: grid; gap: 0.2rem; font-size: var(--fs-sm); }
.about-panel__details a { display: inline-flex; align-items: center; min-height: 2.25rem; color: var(--muted); }
.about-panel__details a:hover { color: var(--blue-light); }

/* --------------------------------------------------------------
   Contact
   -------------------------------------------------------------- */
.page-hero--contact { padding-bottom: clamp(3rem, 6vw, 5rem); }
.contact__glow-b { width: 40vw; height: 40vw; max-width: 620px; bottom: -10%; left: -14%; }
.contact__grid { position: relative; z-index: 2; display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: start; }
.contact__heading { margin: 1.2rem 0 1.3rem; }
.contact__intro .lead { max-width: 44ch; }

.contact__direct { display: grid; gap: 0.75rem; margin: 2.25rem 0; }
.contact__card {
  display: grid; gap: 0.15rem;
  padding: 0.95rem 1.2rem;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease), transform 0.3s var(--ease);
}
a.contact__card:hover { border-color: rgba(59, 130, 246, 0.45); background: rgba(59, 130, 246, 0.08); transform: translateY(-2px); }
.contact__card-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.13em; color: var(--muted-dim); font-weight: 600; }
.contact__card-value { font-weight: 600; font-size: var(--fs-sm); }
@media (min-width: 520px) { .contact__direct { grid-template-columns: 1fr 1fr; } }

.contact__steps { padding-top: 1.75rem; border-top: 1px solid var(--line); }
.contact__steps-title { margin-bottom: 1.1rem; }
.contact__steps-list { list-style: none; margin: 0 0 1.1rem; padding: 0; display: grid; gap: 0.8rem; }
.contact__steps-list li {
  display: flex; gap: 0.8rem; align-items: flex-start;
  font-size: var(--fs-sm); color: var(--muted); line-height: 1.55;
}
.contact__steps-list span {
  flex: none; display: grid; place-items: center;
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  background: rgba(59, 130, 246, 0.16); border: 1px solid rgba(59, 130, 246, 0.4);
  color: var(--blue-light); font-size: 0.72rem; font-weight: 700;
}
.contact__reassure { font-size: var(--fs-xs); color: var(--muted-dim); max-width: 46ch; }

.contact__form-panel { padding: clamp(1.5rem, 3vw, 2.5rem); border-radius: var(--r-xl); }
.contact__form-title { margin-bottom: 0.4rem; }
.contact__form-sub { font-size: var(--fs-xs); color: var(--muted-dim); margin-bottom: 1.75rem; }

@media (min-width: 1000px) {
  .contact__grid { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  .contact__form-wrap { position: sticky; top: 7rem; }
}

/* --------------------------------------------------------------
   Case study
   -------------------------------------------------------------- */
.case-hero__grid { position: relative; z-index: 2; display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: end; }
.case-hero__heading { margin: 1.1rem 0 1.3rem; }
.case-hero__lead { max-width: 52ch; }
.case-hero__tags { margin-top: 1.6rem; margin-bottom: 0; }

.case-facts { display: grid; gap: 0; margin: 0; border-top: 1px solid var(--line); }
.case-facts__row { display: grid; gap: 0.2rem; padding: 0.95rem 0; border-bottom: 1px solid var(--line); }
.case-facts dt { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.13em; color: var(--muted-dim); font-weight: 600; }
.case-facts dd { margin: 0; font-size: var(--fs-sm); color: var(--white); line-height: 1.5; }
@media (min-width: 980px) { .case-hero__grid { grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr); } }

.case-shot { max-width: 1200px; margin-inline: auto; }

.case-approach { display: grid; gap: 2rem; }
.case-approach__item { display: grid; grid-template-columns: auto 1fr; gap: 1.1rem; }
.case-approach__num {
  font-family: var(--font-display); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: 0.14em; color: var(--blue); padding-top: 0.35rem;
}
.case-approach__item h3 { margin-bottom: 0.4rem; }
.case-approach__item p { font-size: var(--fs-sm); color: var(--muted); line-height: 1.68; max-width: 60ch; }

.case-screens { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); align-items: center; }
.case-screens__phone { max-width: 260px; margin-inline: auto; }
@media (min-width: 900px) {
  .case-screens { grid-template-columns: minmax(0, 1fr) auto; }
  .case-screens--solo { grid-template-columns: minmax(0, 1fr); }
  .case-screens__phone { margin-inline: 0; }
}

.case-full__scroller {
  max-width: 900px; margin-inline: auto;
  max-height: min(80vh, 760px); overflow-y: auto;
  border-radius: var(--r-lg); border: 1px solid var(--line-2);
  box-shadow: var(--shadow-lift);
  background: #fff;
  scrollbar-width: thin;
}
.case-full__scroller img { width: 100%; }

.case-more { display: grid; gap: 1.5rem; }
.case-more__card {
  display: grid; gap: 0.9rem;
  padding: 1rem; border-radius: var(--r-xl);
  border: 1px solid var(--line); background: var(--ink-800);
  transition: border-color 0.3s var(--ease), transform 0.35s var(--ease), background-color 0.3s var(--ease);
}
.case-more__card:hover { border-color: rgba(59, 130, 246, 0.4); transform: translateY(-3px); background: var(--ink-700); }
.case-more__card picture img { border-radius: var(--r-md); width: 100%; }
.case-more__meta { display: grid; gap: 0.15rem; padding-inline: 0.4rem; }
.case-more__name { font-family: var(--font-display); font-size: 1.1rem; font-weight: 500; letter-spacing: -0.015em; }
.case-more__industry { font-size: var(--fs-xs); color: var(--muted-dim); }
.case-more__card .link-arrow { padding-inline: 0.4rem; padding-bottom: 0.4rem; }
@media (min-width: 760px) { .case-more { grid-template-columns: 1fr 1fr; } }

.showcase--phones { display: flex; gap: clamp(0.75rem, 2vw, 1.5rem); align-items: flex-start; justify-content: center; }
.showcase--phones .frame--phone { flex: 1 1 0; max-width: 250px; }
.showcase__phone-b { margin-top: clamp(1.5rem, 4vw, 3.5rem); }

.local-proof-links { display: flex; flex-wrap: wrap; gap: 1.5rem 2.5rem; margin-top: 1.75rem; justify-content: center; }

/* --------------------------------------------------------------
   Legal pages
   -------------------------------------------------------------- */
.page-hero--legal { padding-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.legal__heading { margin: 1.1rem 0 0.6rem; }
.legal__updated { font-size: var(--fs-sm); }

/* --------------------------------------------------------------
   404
   -------------------------------------------------------------- */
.notfound {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: 76svh; display: flex; align-items: center;
  padding-block: clamp(4rem, 10vw, 8rem);
}
.notfound__glow { width: 70vw; height: 60vw; max-width: 900px; top: -25%; left: 50%; transform: translateX(-50%); }
.notfound__inner { position: relative; z-index: 2; max-width: 46rem; }
.notfound__heading { margin: 1.2rem 0 1.4rem; }
.notfound__lead { margin-bottom: 2.2rem; }
.notfound__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-bottom: 2.75rem; }
.notfound__links {
  display: flex; flex-wrap: wrap; gap: 0.6rem;
  padding-top: 1.75rem; border-top: 1px solid var(--line);
}
.notfound__links a {
  display: inline-flex; align-items: center; min-height: 2.5rem;
  padding: 0.42rem 0.95rem; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: rgba(255, 255, 255, 0.035);
  font-size: var(--fs-xs); font-weight: 500; color: var(--muted);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.notfound__links a:hover { color: var(--white); border-color: var(--line-3); background: rgba(255, 255, 255, 0.07); }
.notfound__contact { margin-top: 1.75rem; font-size: var(--fs-sm); color: var(--muted); }
.notfound__contact a { color: var(--blue-light); }

/* --------------------------------------------------------------
   Section rhythm: lighter bands read as large rounded panels
   stacked on the page, and the closing CTA overlaps the footer.
   -------------------------------------------------------------- */
.surface-alt, .problems, .process, .compare {
  border-radius: clamp(26px, 3vw, 54px);
  position: relative;
  z-index: 1;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
/* Two lighter bands in a row should read as one, not two stacked cards. */
.surface-alt + .surface-alt,
.problems + .surface-alt { margin-top: calc(clamp(26px, 3vw, 54px) * -1); }

.cta-section { padding-bottom: 0; position: relative; z-index: 3; }
.cta-panel { margin-bottom: clamp(-4.5rem, -4vw, -2.5rem); }
.site-footer { padding-top: clamp(6.5rem, 11vw, 9.5rem); }

/* ==========================================================================
   The entry
   --------------------------------------------------------------------------
   A filmed desk, a monitor mid build, and a scroll that walks you into it.

   Measured off the footage, as a fraction of the 1280x720 frame, the monitor's
   screen sits at:

       first frame   left 27.188%  top 20.139%  width 46.484%  height 46.944%
       last frame    left 21.953%  top 15.972%  width 56.719%  height 57.361%

   The camera pushes straight in, so the centre barely moves: 50.43%, 43.61% at
   the start and 50.31%, 44.65% at the end. The overlay is pinned to that centre
   at the larger of the two sizes, and the zoom is computed from it. The clip
   plays and loops on its own, so the monitor is never at a known point in its
   dolly; that is fine, because the handover to the real screen is a dissolve,
   and by the time the panel is readable the filmed one is blurred behind it.

   The plain hero is the DEFAULT here, and `is-intro-active` on the root element
   is what turns the film on. It is set by the inline boot script in lib/seo.js
   before first paint, so a visitor with no JavaScript, one who asked for less
   motion, and one on a metered connection all get the hero at full size and
   never download the video at all -- and nobody sees the hero appear and then
   get covered by a film landing on top of it. --z is the zoom and --p is scroll
   progress; both only ever drive transforms and opacities, so nothing
   re-lays out.
   ========================================================================== */
.enter { position: relative; background: var(--ink-900); }
.enter__stage { position: relative; }
.enter__video,
.enter__vignette,
.ecode,
.enter__cue { display: none; }
.enter__screen { position: relative; min-height: 88svh; }
.enter__site { position: relative; min-height: 88svh; }

.enter__hero {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: clamp(1.25rem, 4vw, 3rem);
  text-align: center;
}
.enter__hero-glow {
  width: 60%; height: 60%;
  top: 8%; left: 50%; transform: translateX(-50%);
  opacity: 0.5;
  z-index: 1;
}
/* Wide enough that the heading's first line stays one line at its largest size.
   Sized in rem, not vw: for most of the entry this sits inside the screen box
   rather than the window. */
.enter__hero-inner { position: relative; z-index: 2; max-width: 52rem; width: 100%; }
.enter__wordmark { width: 132px; height: auto; margin: 0 auto 2.2rem; opacity: 0.9; display: block; }
.enter__eyebrow {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--blue-light);
  margin-bottom: 1.1rem;
}
.enter__heading {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5.4vw, 4rem);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin-bottom: 1.3rem;
}
.enter__line { display: block; }
.enter__sub {
  font-size: clamp(0.98rem, 1.25vw, 1.15rem);
  color: var(--muted);
  line-height: 1.6;
  max-width: 34rem;
  margin: 0 auto 2.2rem;
}
.enter__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; }

/* ==========================================================================
   Live: the film, the zoom and the build
   ========================================================================== */
.is-intro-active .enter {
  /* The sticky child pins for one viewport; the rest is the scroll the zoom is
     spread over. Kept short on purpose. */
  height: calc(100vh + var(--enter-scroll, 170vh));
}
.is-intro-active .enter .enter__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  /* Both cuts cover the window, so this is only ever seen in the frame or two
     before the film has anything to draw, and on a window shaped like neither. */
  background:
    radial-gradient(90% 55% at 50% 40%, rgba(19, 33, 58, 0.55), transparent 70%),
    #05070A;
}

/* The film. A 16:9 box sized to cover the viewport, then scaled about the point
   the monitor's screen is centred on, so the push lands the screen dead centre
   whatever shape the window is. */
.is-intro-active .enter .enter__stage {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Sized to cover and nothing more. It used to be 14% larger than that, so it
     could be hung off the monitor's centre rather than its own, and every one of
     those percent was the 720p source being magnified further. The frame is
     simply centred now, and the push still reads as going into the monitor
     because the ZOOM is anchored there: transform-origin is the glass, so the
     glass is the one thing that holds still while everything grows around it. */
  --stage-w: max(100vw, calc(100svh * 1280 / 720));
  background: #05070A;
  width: var(--stage-w);
  height: calc(var(--stage-w) * 720 / 1280);
  transform: translate(-50%, -50%) scale(var(--z, 1));
  transform-origin: 50.17% 44.00%;
  will-change: transform;
  /* First beat of the entrance. See "The entrance" below. */
  opacity: var(--in, 1);
  transition: --in 1.1s var(--ease-out);
}

.is-intro-active .enter .enter__video {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Softened and dimmed as the panel takes over, which is also what stops the
     filmed screen's set dressing from ever being legible. */
  filter: blur(calc(var(--film-soft, 0) * 14px)) brightness(calc(1 - var(--film-soft, 0) * 0.55));
}

.is-intro-active .enter .enter__vignette {
  display: block;
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 44%, transparent 38%, rgba(5, 7, 10, 0.55) 100%);
  opacity: calc(1 - var(--film-soft, 0));
}

/* The monitor's screen, and after the handover, the site. */
/* The screen sits in viewport pixels rather than inside the scaled stage, so it
   can start life as the monitor's glass and grow from there into the whole
   window. The script writes these four values every frame; they interpolate from
   wherever the monitor currently is to the full viewport as the panel takes
   over. That is what makes this work in portrait, where a 16:9 frame can never
   cover the window and the monitor would otherwise be a letterbox sliver. */
.is-intro-active .enter .enter__screen {
  position: absolute;
  left: var(--screen-x, 0px);
  top: var(--screen-y, 0px);
  width: var(--screen-w, 100%);
  height: var(--screen-h, 100%);
  min-height: 0;
  z-index: 2;
  overflow: hidden;
  /* The panel sizes its type off this box. Declared on the parent because cqw
     inside the container element resolves against the container outside it. */
  container-type: inline-size;
  border-radius: var(--screen-radius, 0px);
}

/* ---------- The build panel ---------- */
.is-intro-active .enter .ecode {
  display: flex;
  position: absolute;
  inset: 0;
  flex-direction: column;
  background: linear-gradient(180deg, #0B1017 0%, #080B10 100%);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* Sized against the screen box, so the code grows with the push.

     It used to be clamped between 12px and 13px, which meant the ratio never
     applied: the type was the same size on a 390px phone as on a 1440px
     window, and the code sat in the corner of the box at both. What sets the
     ratio is the longest line, which measures 21.5em including the number
     gutter. At 3.7cqw that line asks for 80% of the box, so it has room at
     every point of the push -- from a sliver of monitor glass to the whole
     window -- and the code is a page of code rather than a stamp in a corner.
     The 7px is a guard, not a size anyone reads at; the cap is what stops a
     1440px window from setting the code at 53px. */
  font-size: clamp(7px, 3.7cqw, 18px);
  opacity: var(--code-in, 0);
  z-index: 2;
  /* The block half of this is what the panel used to have none of: the progress
     bar sat flush on the bottom edge of the window, and for most of the push it
     hung below it. A percentage rather than an em so the inset shrinks with the
     box on its way out of the monitor. */
  padding: 2% 7%;
}

/* The background has to reach the edges, because covering the film behind it is
   its job, but what the panel draws does not. That sits in a column the width of
   an editor window and centred in the box: the full width of a phone, and on a
   desktop a window, rather than a title bar ruled across 1440px with the code
   in the left third of it. */
.ecode__bar,
.ecode__body,
.ecode__status { width: min(100%, 32em); margin-inline: auto; }
.ecode__bar {
  display: flex;
  align-items: center;
  gap: 0.9em;
  padding: 0.75em 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
}
.ecode__lights { display: flex; gap: 0.45em; }
.ecode__lights i { width: 0.62em; height: 0.62em; border-radius: 50%; background: rgba(255, 255, 255, 0.16); }
.ecode__lights i:first-child { background: rgba(255, 96, 92, 0.75); }
.ecode__lights i:nth-child(2) { background: rgba(255, 189, 68, 0.75); }
.ecode__lights i:nth-child(3) { background: rgba(0, 202, 78, 0.7); }
.ecode__title { font-size: 1em; letter-spacing: 0.06em; color: var(--muted-dim); }

.ecode__body {
  flex: 1;
  padding-block: 1.1em;
  display: grid;
  /* Centred rather than stacked at the top, because at full zoom this box is
     the whole window and a column pinned to one corner reads as a mistake. */
  align-content: center;
  gap: 0.85em;
  overflow: hidden;
}
.ecode__block { display: grid; gap: 0.05em; }
.ecode__file {
  display: flex; align-items: center; gap: 0.5em;
  margin: 0 0 0.3em;
  font-size: 1em; letter-spacing: 0.05em; color: var(--muted-dim);
  /* Arrives with its own first line. The block keeps its height either way, so
     nothing below it moves as the code is written. */
  opacity: clamp(0, calc((var(--typed, 0) - var(--from, 0) + 1) * 1.6), 1);
}
.ecode__dot { width: 0.5em; height: 0.5em; border-radius: 50%; background: var(--blue); box-shadow: 0 0 0.8em var(--blue); }
.ecode__line {
  margin: 0;
  line-height: 1.6;
  white-space: nowrap;
  /* Revealed one after another by the scroll. --line is this line's index and
     --typed is how many lines have been written so far. */
  opacity: clamp(0, calc((var(--typed, 0) - var(--line)) * 2.2), 1);
  transform: translateX(calc(clamp(0, calc(1 - (var(--typed, 0) - var(--line))), 1) * 0.55em));
}
.ecode__n { display: inline-block; width: 2.2em; color: rgba(255, 255, 255, 0.2); user-select: none; }
.c-kw  { color: #C792EA; }
.c-fn  { color: #82AAFF; }
.c-tag { color: #7FDBCA; }
.c-str { color: #ECC48D; }
.c-sel { color: #FFCB6B; }
.c-pro { color: #80CBC4; }
.c-val { color: #F78C6C; }
.c-pun { color: #8E97A6; }
.c-txt { color: #D6DEEB; }

.ecode__status {
  display: flex; align-items: center; gap: 0.9em;
  padding: 0.7em 0;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 1em; color: var(--muted-dim);
}
.ecode__progress { flex: 1; height: 0.3em; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; }
.ecode__progress i {
  display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--blue), #7FA6FF);
  box-shadow: 0 0 0.9em rgba(36, 107, 253, 0.8);
}
.ecode__pct { font-variant-numeric: tabular-nums; min-width: 3.2em; text-align: right; }

/* ---------- The site, assembling out of the panel ---------- */
.is-intro-active .enter .enter__site {
  position: absolute;
  inset: 0;
  min-height: 0;
  z-index: 3;
  background: var(--ink-900);
  opacity: var(--site-in, 0);
  overflow: hidden;
}
/* A transparent element still takes clicks, so without this the hero's two
   buttons sit invisibly over the film the whole way down. is-entered is set on
   the root element by the same driver that fades the site in. */
.is-intro-active .enter .enter__site { pointer-events: none; }
.is-entered .enter .enter__site { pointer-events: auto; }

/* Each part arrives when the code that writes it has been written. --part is
   set per element by the script; nothing here runs on a timer. */
.is-intro-active .enter [data-build-part] {
  opacity: var(--part, 0);
  transform: translateY(calc((1 - var(--part, 0)) * 0.9rem));
  filter: blur(calc((1 - var(--part, 0)) * 3px));
}

/* ---------- Whose desk this is ---------- */
.enter__brand { display: none; }
.is-intro-active .enter .enter__brand {
  display: grid;
  position: absolute;
  left: 50%;
  /* Sat just above the monitor's own top edge, which the script measures every
     frame, rather than at a percentage of a window whose shape it cannot know. */
  top: auto;
  bottom: calc(100% - var(--glass-top, 20%) + 2rem);
  transform: translateX(-50%) translateY(calc((1 - var(--in, 1)) * 0.75rem));
  z-index: 3;
  justify-items: center;
  gap: 0.6rem;
  width: min(19rem, 46vw);
  pointer-events: none;
  /* Hands over exactly as the build panel arrives, so the two never compete.
     The entrance rides in as a second multiplier rather than replacing this
     one, so the two never fight over the same property. */
  /* Two gates, not one. --code-in rises as the build panel arrives and falls
     again as it leaves, so on its own it would bring the lockup back over the
     finished hero, where the hero's own wordmark already is. --site-in only
     ever rises, so it is what keeps the lockup gone once it has handed over. */
  opacity: calc(
    clamp(0, calc(1 - var(--code-in, 0) * 1.6), 1)
    * clamp(0, calc(1 - var(--site-in, 0) * 2), 1)
    * var(--in, 1));
  transition: --in 0.9s var(--ease-out) 0.5s;
}
.enter__brand-halo {
  position: absolute;
  inset: -55% -35%;
  z-index: 0;
  background: radial-gradient(50% 50% at 50% 50%, rgba(36, 107, 253, 0.42), transparent 70%);
  filter: blur(14px);
}
.enter__brand-mark {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  /* Two shadows rather than one: a tight halo that reads as the mark being lit,
     and a wide one that lifts it off a photograph busy enough to swallow it. */
  filter:
    drop-shadow(0 0 14px rgba(36, 107, 253, 0.85))
    drop-shadow(0 0 46px rgba(36, 107, 253, 0.5))
    drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
  animation: brand-breathe 4.5s var(--ease) infinite;
}
.enter__brand-line {
  position: relative;
  z-index: 1;
  margin: 0;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: rgba(255, 255, 255, 0.82);
  text-shadow: 0 0 16px rgba(36, 107, 253, 0.75), 0 1px 10px rgba(0, 0, 0, 0.8);
}
@keyframes brand-breathe {
  0%, 100% { filter: drop-shadow(0 0 12px rgba(36, 107, 253, 0.7)) drop-shadow(0 0 38px rgba(36, 107, 253, 0.4)) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55)); }
  50%      { filter: drop-shadow(0 0 20px rgba(36, 107, 253, 0.95)) drop-shadow(0 0 60px rgba(36, 107, 253, 0.6)) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55)); }
}
@media (prefers-reduced-motion: reduce) { .enter__brand-mark { animation: none; } }

/* A short window leaves almost nothing above the monitor -- at 1600x700 the
   gap is 78px -- so the lockup gives up its tagline and shrinks to fit rather
   than sitting across the screen. */
@media (max-height: 760px) and (min-aspect-ratio: 1 / 1) {
  .is-intro-active .enter .enter__brand { width: min(13rem, 34vw); gap: 0.35rem; }
  .is-intro-active .enter .enter__brand-line { display: none; }
}

/* On a phone the mark sits above the monitor exactly as it does on a desk --
   the portrait film covers the window too, so there is no band edge to hang it
   off any more, only the rain behind the glass, which is the quietest part of
   the picture and the best place for it. */
@media (max-aspect-ratio: 1 / 1) {
  .is-intro-active .enter .enter__brand {
    width: min(17rem, 62vw);
    gap: 0.55rem;
  }
  /* The tagline is set wider than the mark it sits under, and on a 375px phone
     62vw is not enough for it: it broke after GROW. and the extra row was what
     pushed the lockup off the top. It keeps one line and is allowed to be wider
     than the mark, which is what centring it in the band is for. */
  .enter__brand-line {
    letter-spacing: clamp(0.12em, 0.9vw, 0.22em);
    white-space: nowrap;
  }
}

/* ---------- The cue ---------- */
.is-intro-active .enter .enter__cue {
  display: grid;
  position: absolute;
  left: 50%;
  bottom: clamp(1.25rem, 4vh, 2.5rem);
  transform: translateX(-50%) translateY(calc((1 - var(--in, 1)) * 0.6rem));
  z-index: 4;
  justify-items: center;
  gap: 0.7rem;
  margin: 0;
  /* Gone as soon as the visitor has taken the hint, and last to arrive on the
     way in. */
  opacity: calc(clamp(0, calc(1 - var(--p, 0) * 7), 1) * var(--in, 1));
  transition: --in 0.8s var(--ease-out) 1s;
  pointer-events: none;
}
.enter__cue-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: rgba(255, 255, 255, 0.72);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.75);
}
.enter__cue-line {
  width: 1px;
  height: 2.6rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.65), transparent);
  animation: cue-drop 2.1s var(--ease) infinite;
}
@keyframes cue-drop {
  0%, 100% { transform: scaleY(0.4); transform-origin: top; opacity: 0.35; }
  50%      { transform: scaleY(1);   transform-origin: top; opacity: 1; }
}

/* Taller than it is wide: a different film, not a crop of the wide one.

   This used to be the 16:9 frame shown whole as a band, with dark above and
   below it, because nothing that shape can cover a 9:19 window without cropping
   away everything but the middle of the monitor. The portrait cut is filmed
   720x1280, so it covers the window the way the wide one covers a desktop: rain
   at the top, the monitor across the middle, the desk below. Same rule as
   landscape, the film's own ratio and its own glass centre to push into. */
@media (max-aspect-ratio: 1 / 1) {
  .is-intro-active .enter .enter__stage {
    --stage-w: max(100vw, calc(100svh * 720 / 1280));
    height: calc(var(--stage-w) * 1280 / 720);
    top: 50%;
    transform-origin: 50.55% 49.82%;
  }
}

@media (max-width: 760px) {
  .enter__wordmark { width: 108px; margin-bottom: 1.6rem; }
  .ecode__body { gap: 0.5em; }
}

/* ==========================================================================
   The entrance

   Nothing appears at once. The film arrives first, the wordmark half a second
   behind it, the scroll cue half a second behind that. Three beats instead of
   one, which reads as composed rather than busy.

   All of it is opacity and a small lift, on elements that are laid out from the
   first paint, so the entrance cannot move the page or cost a layout: CLS stays
   at zero.

   `is-curtain` is on the root element from before the first paint, set by the
   same inline boot script that decides on the film, so the page never flashes
   its contents and then hides them. Taking the class off is what starts the
   three transitions; site.js does that as soon as the film has frames to show,
   and the boot script does it on a short timer regardless, so a visitor whose
   video never loads is not left looking at black.

   The three elements already have their opacity driven by the scroll, so the
   entrance is a separate multiplier, --in, that the scroll never touches.
   Registering it is what lets it be transitioned at all; a browser that does
   not support @property gets the same page with no fade rather than a broken
   one.
   ========================================================================== */
@property --in {
  syntax: '<number>';
  inherits: false;
  initial-value: 1;
}

.is-intro-active.is-curtain .enter .enter__stage,
.is-intro-active.is-curtain .enter .enter__brand,
.is-intro-active.is-curtain .enter .enter__cue { --in: 0; }

/* The screen box is the one thing here whose position cannot be written in CSS:
   it starts life as the monitor's glass, and where that is depends on the drawn
   size of the film, which only the script can measure. Its declared default is
   the whole window, which is what it ends as. site.js is deferred, so between
   the first paint and the first measurement the browser has a box at the wrong
   end of that journey, and it paints it often enough to cost a layout shift of
   about 0.32 on its own.

   Held back until it has been measured, it simply appears where it belongs.
   Visibility rather than opacity, because an element that was never visible has
   nothing to shift from. The curtain is already on the root from before the
   first paint and site.js takes it off in the same task that writes the four
   values, so there is no frame where this is visible and unmeasured. If site.js
   never arrives the boot script's timer lifts the curtain anyway, and the box
   appears at its declared default, which is the full-size hero. */
.is-intro-active.is-curtain .enter .enter__screen { visibility: hidden; }

/* The same rhythm for a visitor who never gets the film at all: reduced data,
   or JavaScript that never arrived. `both` means that if the animations never
   run, the hero is simply there, which is the one outcome that must never
   break. Anyone who asked for less motion gets it immediately and still. */
@media (prefers-reduced-motion: no-preference) {
  html:not(.is-intro-active) .enter__light,
  html:not(.is-intro-active) .enter__hero-glow {
    animation: enter-fade 1.1s var(--ease-out) both;
  }
  html:not(.is-intro-active) .enter__hero .enter__wordmark,
  html:not(.is-intro-active) .enter__hero .enter__eyebrow,
  html:not(.is-intro-active) .enter__hero .enter__heading,
  html:not(.is-intro-active) .enter__hero .enter__sub {
    animation: enter-rise 0.9s var(--ease-out) 0.5s both;
  }
  html:not(.is-intro-active) .enter__hero .enter__actions {
    animation: enter-rise 0.8s var(--ease-out) 1s both;
  }
}
@keyframes enter-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes enter-rise {
  from { opacity: 0; transform: translateY(0.75rem); }
  to   { opacity: 1; transform: none; }
}

/* The header is held back while the visitor is still outside the screen, then
   arrives once they are inside. `is-intro-active` is set by the inline boot
   script before first paint, so without JavaScript the header is simply always
   visible. */
.is-intro-active .site-header {
  opacity: 0;
  pointer-events: none;
  transform: translateY(-0.5rem);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.is-intro-active.is-entered .site-header {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}


/* ==========================================================================
   Homepage sections
   ========================================================================== */

/* ==========================================================================
   The card deck
   --------------------------------------------------------------------------
   One card at a time, slid left and right, used by both the paths and the
   services. The track is a plain scroll-snapping row: swipe, trackpad,
   shift-wheel and the keyboard all work with no script at all, and the arrows
   and dots ship hidden so a browser that never runs the script is left with a
   row that works rather than controls that do not.

   --near is written onto each slide per frame from scroll position: 1 when it
   is centred, 0 when it is a card's width away. It carries the scale and the
   fade, and it deliberately has no transition on it, so the cards move with the
   finger rather than easing along behind it.
   ========================================================================== */
.deck {
  --deck-gap: clamp(0.55rem, 2.2vw, 1.35rem);
  --deck-ink: var(--white);
  --deck-line: var(--line-2);
  --deck-dot: rgba(255, 255, 255, 0.24);
  --deck-dot-on: var(--blue);
  position: relative;
}
.section--light .deck {
  --deck-ink: var(--ink-text);
  --deck-line: var(--line-on-light-2);
  --deck-dot: rgba(8, 11, 16, 0.16);
  --deck-dot-on: var(--blue-ink);
}

.deck__track {
  /* Narrow enough that a sliver of the next card always shows. Centred, the
     peek either side is (track - --slide) / 2 - gap, less whatever the shrink
     on the off-centre card takes off it, so slide width, gap and that shrink
     are all the same dial: how obvious it is that these cards slide. */
  --slide: min(76vw, 20rem);
  display: flex;
  /* Each card is its own height. Stretched to match the tallest, the short
     ones open a hole between their last line and their button, which on a
     slider is a hole in the middle of the only card you can see. */
  align-items: flex-start;
  gap: var(--deck-gap);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* The first and last card centre like every other one. */
  padding-inline: max(0px, calc((100% - var(--slide)) / 2));
  /* Room for a card to lift and cast a shadow without being clipped off. */
  padding-block: 0.5rem 1rem;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.deck__track::-webkit-scrollbar { display: none; }
.deck__track:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: var(--r-lg); }

.deck__slide {
  flex: 0 0 var(--slide);
  display: flex;
  scroll-snap-align: center;
  transform-origin: center center;
  transform: scale(calc(0.94 + 0.06 * var(--near, 1)));
  opacity: calc(0.5 + 0.5 * var(--near, 1));
  will-change: transform, opacity;
}
.deck__slide > * { flex: 1; min-width: 0; }

/* ---------- Arrows and dots ---------- */
.deck__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.8rem, 3vw, 1.4rem);
  margin-top: clamp(0.9rem, 2.5vw, 1.5rem);
}
.deck__arrow {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--deck-line);
  background: transparent;
  color: var(--deck-ink);
  cursor: pointer;
  transition: background-color 0.3s var(--ease), border-color 0.3s var(--ease),
    opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.deck__arrow svg { width: 1rem; height: 1rem; }
.deck__arrow:hover { border-color: var(--blue); background: rgba(36, 107, 253, 0.12); }
.deck__arrow:active { transform: scale(0.94); }
.deck__arrow[disabled] { opacity: 0.3; cursor: default; }
.deck__arrow[disabled]:hover { border-color: var(--deck-line); background: transparent; }

.deck__dots { display: flex; align-items: center; }
/* The dot people see is the ::before. The button around it is thumb sized and
   invisible, because a 8px tap target is not one. */
.deck__dot {
  display: grid;
  place-items: center;
  height: 2.25rem;
  padding: 0 0.4rem;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.deck__dot::before {
  content: '';
  display: block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--deck-dot);
  transition: width 0.4s var(--ease-out), background-color 0.4s var(--ease);
}
.deck__dot[aria-current="true"]::before { width: 1.7rem; background: var(--deck-dot-on); }

/* Sliding is the whole point, so when it is not wanted the cards simply sit
   at full size and the row scrolls without the scale and the fade. */
@media (prefers-reduced-motion: reduce) {
  .deck__track { scroll-behavior: auto; }
  .deck__slide { transform: none; opacity: 1; }
  .deck__dot::before { transition: none; }
}

/* ---------- Choose your path ---------- */
.paths__kicker { color: var(--muted-on-light); letter-spacing: 0.16em; }
.path-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  background: var(--paper-2);
  border: 1px solid var(--line-on-light);
  border-radius: var(--r-xl);
  color: var(--ink-text);
  transition: border-color 0.3s var(--ease), box-shadow 0.4s var(--ease);
}
.path-card:hover {
  border-color: rgba(36, 107, 253, 0.32);
  box-shadow: 0 30px 60px -34px rgba(8, 16, 32, 0.4);
}
.path-card__top { display: flex; align-items: center; gap: 0.8rem; margin-bottom: 0.4rem; }
.path-card__icon { width: 28px; height: 28px; color: var(--blue); flex: none; }
.path-card__label {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--blue-ink);
}
.path-card__q {
  font-family: var(--font-display); font-size: clamp(1.3rem, 1.05rem + 1vw, 1.75rem);
  font-weight: 500; letter-spacing: -0.02em; line-height: 1.2;
}
.path-card__body { font-size: var(--fs-sm); color: var(--muted-on-light); line-height: 1.6; }
.path-card__go {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin-top: 0.8rem;
  font-size: var(--fs-sm); font-weight: 600; color: var(--blue-ink);
}
.path-card__go svg { width: 0.8rem; height: 0.8rem; transition: transform 0.35s var(--ease); }
.path-card:hover .path-card__go svg { transform: translateX(4px); }

/* Below the width where the paths stop sliding, the track runs edge to edge
   rather than sitting inside the page's gutter. The gutter is 20px a side on a
   phone, which is most of the room a peek needs, and cards sliding off the edge
   of the screen reads better than cards sliding into a margin. */
@media (max-width: 879px) {
  .deck__track {
    margin-inline: calc(50% - 50vw);
    padding-inline: max(0px, calc((100vw - var(--slide)) / 2));
  }
}

/* Three paths fit a wide screen exactly, so there is nothing to slide: the
   track stops scrolling and the script takes the controls away with it. */
@media (min-width: 880px) {
  .deck--paths .deck__track {
    --slide: calc((100% - 2 * var(--deck-gap)) / 3);
    padding-inline: 0;
  }
}

/* ---------- What we do ---------- */
.services-detail { overflow: hidden; isolation: isolate; background: var(--ink-900); }
.services-detail__glow { width: 60vw; height: 40vw; max-width: 900px; top: 0; right: -18%; opacity: 0.5; }

.deck--svc .deck__track { --slide: min(84vw, 40rem); }

.svc-card {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: clamp(1.25rem, 3.2vw, 2.25rem);
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 80% at 0% 0%, rgba(36, 107, 253, 0.14), transparent 60%),
    var(--ink-850);
  transition: border-color 0.3s var(--ease);
}
/* The number sits on the kicker's line rather than above it: as its own row it
   cost more height than it was worth on a card that has to fit a phone. */
.svc-card__meta { display: flex; align-items: baseline; gap: 0.6rem; }
.svc-card__n {
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 500; line-height: 1; letter-spacing: 0.02em;
  color: var(--blue);
}
.svc-card__kicker {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted-dim);
}
.svc-card__heading { margin: 0; max-width: 22ch; }
.svc-card__body { font-size: var(--fs-sm); color: var(--muted); line-height: 1.55; }
.svc-card__note { font-size: var(--fs-xs); color: var(--muted-dim); line-height: 1.5; }
.svc-card__platforms { margin-block: 0.1rem; }

.svc-card__groups { display: grid; gap: 0.7rem; margin-top: 0.25rem; }
.svc-card__group-title {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--blue-light);
  margin-bottom: 0.4rem;
}
.svc-card__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.35rem; }
.svc-card__chips li {
  font-size: 0.75rem; line-height: 1.25; color: var(--muted);
  padding: 0.26rem 0.6rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.035);
}
.svc-card__link { align-self: flex-start; margin-top: 0.5rem; }

@media (min-width: 620px) {
  .svc-card__groups { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 1.4rem; }
  .svc-card__groups:has(> :nth-child(3)) > :first-child { grid-column: 1 / -1; }
}

/* ---------- Automation flow ---------- */
.flow__steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 0;
  counter-reset: flow;
}
.flow__step { position: relative; padding: 0 0 2.25rem 2.5rem; }
.flow__step:last-child { padding-bottom: 0; }
/* The connector between steps, drawn as it scrolls in. */
.flow__step::before {
  content: ''; position: absolute; left: 0.47rem; top: 1.5rem; bottom: 0;
  width: 2px; background: linear-gradient(180deg, var(--blue), rgba(36, 107, 253, 0.15));
  transform-origin: top; transform: scaleY(0);
  transition: transform 0.7s var(--ease-out) 0.15s;
}
.flow__step:last-child::before { display: none; }
.flow__step.is-visible::before { transform: scaleY(1); }
.flow__dot {
  position: absolute; left: 0; top: 0.25rem;
  width: 1.05rem; height: 1.05rem; border-radius: 50%;
  border: 2px solid var(--blue); background: var(--paper);
  display: grid; place-items: center;
}
.flow__dot i {
  width: 0.35rem; height: 0.35rem; border-radius: 50%; background: var(--blue);
  transform: scale(0); transition: transform 0.45s var(--ease-out) 0.1s;
}
.flow__step.is-visible .flow__dot i { transform: scale(1); }
.flow__n {
  display: block; font-family: var(--font-display); font-size: var(--fs-xs);
  font-weight: 500; letter-spacing: 0.16em; color: var(--blue-ink); margin-bottom: 0.3rem;
}
.flow__title {
  font-family: var(--font-display); font-size: clamp(1.15rem, 1rem + 0.7vw, 1.45rem);
  font-weight: 500; letter-spacing: -0.02em; margin-bottom: 0.3rem;
}
.flow__body { font-size: var(--fs-sm); color: var(--muted-on-light); line-height: 1.6; max-width: 46ch; }
@media (min-width: 940px) {
  .flow__steps { grid-template-columns: repeat(5, 1fr); gap: 0; }
  .flow__step { padding: 3rem 1.25rem 0 0; }
  .flow__step::before {
    left: 1.05rem; right: 0; top: 0.5rem; bottom: auto; width: auto; height: 2px;
    background: linear-gradient(90deg, var(--blue), rgba(36, 107, 253, 0.15));
    transform-origin: left; transform: scaleX(0);
    transition: transform 0.7s var(--ease-out) 0.15s;
  }
  .flow__step.is-visible::before { transform: scaleX(1); }
  .flow__dot { top: 0; left: 0; }
}

/* ---------- Work, dark ---------- */
.work-dark { background: var(--ink-850); overflow: hidden; isolation: isolate; }
.work-dark__glow { width: 55vw; height: 40vw; max-width: 820px; top: 4%; left: -14%; opacity: 0.55; }
.work-dark__grid { position: relative; z-index: 2; display: grid; gap: 1.5rem; }
.wcard {
  display: grid; gap: 1.25rem;
  background: var(--ink-800);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: 1rem 1rem 1.6rem;
  transition: border-color 0.35s var(--ease), transform 0.4s var(--ease);
}
.wcard:hover { border-color: rgba(36, 107, 253, 0.34); transform: translateY(-3px); }
.wcard__media { display: block; border-radius: var(--r-md); overflow: hidden; background: #fff; }
.wcard__media img { width: 100%; display: block; }
/* Every card shows the same window on its project, whether that window holds a
   single screenshot or a comparison, so a row of three stays level. The source
   images have different proportions; the card decides, not the file. */
.wcard__media { position: relative; aspect-ratio: 16 / 10; }
.wcard__media img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
.wcard__media--compare { background: var(--ink-900); }
.wcard__media--compare .compare__viewer {
  position: absolute; inset: 0;
  aspect-ratio: auto; width: 100%; height: 100%;
  border: 0; border-radius: inherit; box-shadow: none;
}
.wcard__media--compare .compare__tag { font-size: 0.66rem; padding: 0.24rem 0.55rem; }
.wcard__media--compare .compare__grip { width: 34px; height: 34px; }
.wcard__hint {
  position: absolute; left: 50%; bottom: 0.6rem; transform: translateX(-50%);
  z-index: 3; margin: 0; padding: 0.28rem 0.7rem;
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: #fff; background: rgba(8, 11, 16, 0.72);
  border-radius: 999px; pointer-events: none;
  transition: opacity 0.3s var(--ease);
}
.wcard__media--compare:has(.is-used) .wcard__hint,
.compare__viewer.is-used ~ .wcard__hint { opacity: 0; }
.wcard__body { padding-inline: 0.5rem; }
.wcard__name { font-family: var(--font-display); font-size: 1.3rem; font-weight: 500; letter-spacing: -0.02em; margin-bottom: 0.25rem; }
.wcard__meta { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.11em; color: var(--muted-dim); margin-bottom: 0.9rem; }
.wcard__summary { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; margin-bottom: 1.1rem; }
@media (min-width: 1000px) { .work-dark__grid { grid-template-columns: repeat(3, 1fr); } }

/* ---------- Ongoing support ---------- */
.ongoing { background: var(--ink-900); }
.ongoing__grid { display: grid; gap: 1.25rem; }
.plan {
  padding: clamp(1.6rem, 2.8vw, 2.25rem);
  background: var(--ink-800);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  position: relative;
}
.plan--featured {
  background: linear-gradient(178deg, rgba(36, 107, 253, 0.14), transparent 70%), var(--ink-700);
  border-color: rgba(36, 107, 253, 0.4);
}
.plan__name { font-family: var(--font-display); font-size: 1.3rem; font-weight: 500; letter-spacing: -0.02em; margin-bottom: 0.4rem; }
.plan__line { font-size: var(--fs-sm); color: var(--muted); line-height: 1.55; margin-bottom: 1.4rem; min-height: 3em; }
.plan__list { list-style: none; margin: 0; padding: 1.3rem 0 0; display: grid; gap: 0.6rem; border-top: 1px solid var(--line); }
.plan__list li { position: relative; padding-left: 1.3rem; font-size: var(--fs-sm); color: var(--muted); line-height: 1.5; }
.plan__list li::before {
  content: ''; position: absolute; left: 0; top: 0.6em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--blue);
}
.ongoing__note {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.5rem;
  font-size: var(--fs-sm); color: var(--muted);
}
@media (min-width: 900px) { .ongoing__grid { grid-template-columns: repeat(3, 1fr); gap: 1.5rem; } }

/* ---------- Closing CTA over the horizon art ---------- */
.horizon { position: relative; overflow: hidden; isolation: isolate; background: var(--ink-900); }
.horizon__art { position: absolute; inset: 0; z-index: 0; }
.horizon__art img { width: 100%; height: 100%; object-fit: cover; object-position: center 60%; }
/* The art is busy, so the copy gets its own ground rather than relying on luck. */
.horizon__scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(180deg, rgba(8, 11, 16, 0.92) 0%, rgba(8, 11, 16, 0.72) 45%, rgba(8, 11, 16, 0.9) 100%),
    radial-gradient(70% 60% at 50% 50%, rgba(8, 11, 16, 0.55), transparent 75%);
}
.horizon__inner { position: relative; z-index: 2; }
.horizon__content { max-width: 44rem; text-align: center; margin-inline: auto; }
.horizon__heading { margin-bottom: 1.2rem; }
.horizon__body { margin: 0 auto 2.2rem; }
.horizon__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; }

/* Five process steps rather than four. */
@media (min-width: 860px) { .process__list { grid-template-columns: repeat(5, 1fr); gap: 1.75rem; } }

/* On the intro page the header must not occupy layout space, or the sticky
   intro starts below a strip of page background. Fixed behaves the same as
   sticky once scrolling begins, and takes the strip away. */
.has-intro .site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
}

/* A .glow is absolutely positioned with z-index 0. Inside a stacking context
   that puts it ABOVE static content, so any container holding text next to one
   has to be positioned too or the blur washes over the headings. */
.services-detail > .page,
.work-dark > .page-wide,
.paths > .page,
.ongoing > .page {
  position: relative;
  z-index: 2;
}

/* Keep the arrow on the baseline of every card regardless of how far the
   question wraps. */
.path-card { align-content: start; }
.path-card__go { margin-top: auto; }

.site-footer__tagline {
  margin-top: 1.25rem;
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 500; letter-spacing: -0.01em;
  color: var(--white);
}
.site-footer__tagline + .site-footer__blurb { margin-top: 0.5rem; }

/* The supplied blue light art, kept very low so the hero copy stays the
   brightest thing on the screen. */
.enter__light { position: absolute; inset: 0; z-index: 0; }
.enter__light img {
  width: 100%; height: 100%; object-fit: cover; opacity: 0.32;
  transition: opacity 0.8s var(--ease-out);
}

/* The moving version, laid exactly over the still and crossfaded with it once
   it is actually playing. Both sit at the same third of full opacity, and only
   one of them is ever visible, so the band never doubles up and brightens. */
.enter__light-video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  transition: opacity 0.8s var(--ease-out);
}
.is-light-video .enter__light-video { opacity: 0.32; }
.is-light-video .enter__light img { opacity: 0; }

/* Workspace photograph behind the ongoing support section, heavily scrimmed so
   it reads as texture rather than as an image competing with the text. */
.ongoing { position: relative; overflow: hidden; isolation: isolate; }
.ongoing__art { position: absolute; inset: 0; z-index: 0; }
.ongoing__art img { width: 100%; height: 100%; object-fit: cover; object-position: center 35%; opacity: 0.22; }
.ongoing__scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(180deg, var(--ink-900) 0%, rgba(8, 11, 16, 0.86) 35%, rgba(8, 11, 16, 0.94) 100%);
}

/* ---------- Services mega menu ---------- */
.nav__menu--mega { width: min(56rem, 92vw); }
.nav__mega {
  display: grid;
  gap: 1.75rem;
  padding: 1.6rem 1.75rem;
  background: rgba(17, 22, 29, 0.97);
  backdrop-filter: blur(22px);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lift);
  animation: menu-in 0.28s var(--ease-out);
}
.nav__mega-title {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--blue-light); margin-bottom: 0.35rem;
}
.nav__mega-blurb { font-size: var(--fs-xs); color: var(--muted-dim); line-height: 1.5; margin-bottom: 0.9rem; }
.nav__mega-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.1rem; }
.nav__mega-link {
  display: block; padding: 0.5rem 0.6rem; margin-inline: -0.6rem;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: 500; color: var(--text);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.nav__mega-link:hover, .nav__mega-link:focus-visible { background: rgba(36, 107, 253, 0.16); }
.nav__mega-link.is-current { color: var(--blue-light); }
@media (min-width: 880px) { .nav__mega { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.25rem; } }

/* Five footer columns rather than three. */
@media (min-width: 760px) { .site-footer__nav { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1020px) { .site-footer__nav { grid-template-columns: repeat(5, 1fr); gap: 1.75rem; } }

/* ==========================================================================
   Shared page blocks
   ========================================================================== */

/* Titled groups of short points. Used across every service page. */
.pcols { display: grid; gap: 1.75rem; align-content: start; }
.pcol__title {
  font-family: var(--font-display); font-size: 1rem; font-weight: 500;
  letter-spacing: -0.012em; margin-bottom: 0.45rem;
}
.pcol__note { font-size: var(--fs-sm); color: var(--muted); line-height: 1.6; margin-bottom: 0.8rem; max-width: 42ch; }
.pcol__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.pcol__list li {
  position: relative; padding-left: 1.2rem;
  font-size: var(--fs-sm); color: var(--muted); line-height: 1.55;
}
.pcol__list li::before {
  content: ''; position: absolute; left: 0; top: 0.62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--blue);
}
@media (min-width: 720px) { .pcols--2, .pcols--3, .pcols--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) {
  .pcols--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }
  .pcols--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.5rem; }
}

/* Numbered tier: one kind of website, one SEO stage, one automation group. */
.tiers { overflow: hidden; isolation: isolate; }
.tiers > .page, .tiers > .page-wide { position: relative; z-index: 2; }
.tiers__glow { width: 55vw; height: 40vw; max-width: 850px; top: 2%; right: -16%; opacity: 0.5; }
.tiers__list { display: grid; gap: clamp(2.75rem, 5vw, 4.5rem); }
.tier {
  display: grid; gap: clamp(1.5rem, 3vw, 2.75rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.tier__n {
  display: block; font-family: var(--font-display); font-size: var(--fs-xs);
  font-weight: 500; letter-spacing: 0.18em; color: var(--blue-light); margin-bottom: 0.8rem;
}
.tier__kicker {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted-dim); margin-bottom: 0.8rem;
}
.tier__heading { margin-bottom: 0.9rem; max-width: 22ch; }
/* Body copy is capped near 70 characters so it stays readable on a wide screen. */
.tier__body { font-size: var(--fs-lead); color: var(--muted); line-height: 1.68; max-width: 68ch; }
.tier__body + .tier__body { margin-top: 0.9rem; }
.tier__head > .link-arrow { margin-top: 1.2rem; }
.tier__note {
  margin-top: 1.1rem; font-size: var(--fs-xs); color: var(--muted-dim);
  line-height: 1.6; max-width: 56ch;
}
@media (min-width: 900px) { .tier { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); } }

/* Contextual closing band. Lighter than the full cinematic CTA, used to end
   interior pages with one clear next step. */
.cta-band { position: relative; overflow: hidden; isolation: isolate; background: var(--ink-850); }
.cta-band__glow { width: 55vw; height: 38vw; max-width: 800px; top: -20%; left: 50%; transform: translateX(-50%); opacity: 0.55; }
.cta-band__inner {
  position: relative; z-index: 2;
  display: grid; gap: 1.75rem; align-items: center;
}
.cta-band__heading { max-width: 20ch; }
.cta-band__body { margin-top: 0.9rem; max-width: 60ch; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; }
@media (min-width: 900px) {
  .cta-band__inner { grid-template-columns: minmax(0, 1.25fr) auto; gap: 3rem; }
  .cta-band__actions { justify-content: flex-end; }
}

/* Frontend / backend explainer. Two plain-language cards, no icons. */
.explain { display: grid; gap: 1.25rem; }
.explain__item {
  padding: clamp(1.6rem, 3vw, 2.4rem);
  background: var(--paper-2);
  border: 1px solid var(--line-on-light);
  border-radius: var(--r-xl);
}
.explain__label {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--blue-ink); margin-bottom: 0.7rem;
}
.explain__title {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.6rem);
  font-weight: 500; letter-spacing: -0.02em; line-height: 1.25;
  margin-bottom: 0.8rem;
}
.explain__body {
  font-size: var(--fs-body); color: var(--muted-on-light);
  line-height: 1.7; max-width: 62ch; margin-bottom: 1.5rem;
}
.explain .pcols { border-top: 1px solid var(--line-on-light); padding-top: 1.25rem; }
@media (min-width: 900px) { .explain { grid-template-columns: 1fr 1fr; gap: 1.5rem; } }

.custom-note {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.5rem;
  font-size: var(--fs-sm); color: var(--muted);
}
