/* ==========================================================================
   RinceTech AI Solutions — Header + Hero
   --------------------------------------------------------------------------
   1.  Design tokens
   2.  Reset & base
   3.  Layout helpers
   4.  Buttons (reusable)
   5.  Background stack
   6.  Header / Navbar
   7.  Mobile navigation
   8.  Hero — left column
   9.  Hero — right composition (floating cards, chips, circuits)
   10. Scroll indicator
   11. Keyframes
   S1. Section shell (decor layer, headings, shared glass surface)
   S2. Trust & achievements
   S3. Services
   S4. Section end CTA
   S5. Section responsive
   S5b. Plans & packages
   S6. Shared card & icon utilities
   S7. About
   S8. Why choose us
   S9. Process timeline
   S10. Full-width CTA panel
   S11. Section responsive (03 → CTA)
   S12. AI & emerging technologies
   S13. Section responsive (06)
   S14. (removed — portfolio & case studies)
   S15. (removed — its responsive block)
   S16. Testimonials
   S17. Results & achievements
   S18. FAQ accordion
   S19. Section responsive (08 → 10)
   S20. Contact (form, detail cards, map)
   S21. Floating actions (WhatsApp, back to top)
   S22. Footer
   S23. Section responsive (contact, footer)
   12. Responsive
   13. Reduced motion
   ========================================================================== */


/* ==========================================================================
   1. DESIGN TOKENS
   ========================================================================== */
/* --------------------------------------------------------------------------
   LIGHT / LUXURY THEME
   The site was originally near-black with a siren-red accent. It is now a warm
   off-white ground with a deep burgundy brand, which is what the token names
   below describe:

     --bg / --bg-alt    page ground and the alternating band
     --ink / --ink-soft / --ink-mute    text, in descending weight
     --card / --glass   opaque card and translucent (blurred) panel
     --stroke*          hairlines, which are now DARK on light, not light on dark

   `--black`, `--white`, `--secondary` and `--gray` were renamed to the above,
   because on a light theme a token called `--white` holding near-black ink is
   a trap for whoever edits this next.
   -------------------------------------------------------------------------- */
:root {
  /* Three colours, no fourth. Red is a true red rather than the old maroon or
     the original siren #E30613 — confident at button size, not neon. */
  --red:        #C8102E;
  --red-light:  #E01935;
  --red-deep:   #8E0B20;

  /* Ground & ink — neutral, no warm cast. The greys are pure so nothing on the
     page reads as a fourth hue. */
  --bg:         #FFFFFF;
  --bg-alt:     #F4F4F5;
  --bg-ink:     #0B0B0C;   /* the near-black band: footer, and anything anchored */
  --ink:        #0B0B0C;
  --ink-soft:   #5C5C60;
  --ink-mute:   #8E8E93;

  /* Ink on the dark band */
  --on-ink:       #FFFFFF;
  --on-ink-soft:  rgba(255, 255, 255, 0.62);
  --stroke-ink:   rgba(255, 255, 255, 0.12);

  /* Text sitting ON a brand-coloured fill. The old theme used `--white` for
     both page text and button text; on a light theme those split in two, and
     this is the half that stays white. */
  --on-brand:   #FFFFFF;

  /* Derived surfaces */
  --card:         #FFFFFF;
  --glass:        rgba(255, 255, 255, 0.70);
  --glass-strong: rgba(255, 255, 255, 0.90);
  --stroke:       rgba(11, 11, 12, 0.12);
  --stroke-soft:  rgba(11, 11, 12, 0.07);
  --red-glow:     rgba(200, 16, 46, 0.24);

  /* One shadow recipe, reused. Long, soft and low-opacity — a hard drop shadow
     is the fastest way to make a light layout look cheap. */
  --shadow-sm: 0 2px 6px -2px rgba(11, 11, 12, 0.07);
  --shadow:    0 18px 40px -26px rgba(11, 11, 12, 0.22);
  --shadow-lg: 0 34px 70px -40px rgba(11, 11, 12, 0.28);

  /* No colour gradients anywhere. These two names are kept because ~30 rules
     reference them, but both now resolve to a flat red — a gradient fill was
     the single thing making the page look busy rather than expensive. */
  --grad-red:  var(--red);
  --grad-text: var(--red);

  /* Typography */
  --font-head: "Space Grotesk", system-ui, sans-serif;
  --font-body: "Poppins", system-ui, -apple-system, sans-serif;

  /* Rhythm */
  --container: 1400px;
  --gutter: 40px;
  --header-h: 92px;
  --header-h-sm: 70px;
  /* The contact strip above the navbar. It lives inside the fixed header and
     collapses to zero once the page is scrolled, so `--header-top` is what the
     first screen of every page has to clear. */
  --topbar-h: 38px;
  --header-top: calc(var(--topbar-h) + var(--header-h));
  --radius: 18px;
  --radius-lg: 26px;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);

  --z-bg: 0;
  --z-content: 2;
  /* The header outranks the overlay so the logo and the close button stay
     reachable while the fullscreen menu is open. */
  --z-overlay: 150;
  --z-header: 200;
}


/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

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

body {
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Lenis smooth-scroll hooks */
html.lenis { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

h1, h2, h3, strong {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

::selection { background: var(--red); color: var(--on-brand); }

:focus-visible {
  outline: 2px solid var(--red-light);
  outline-offset: 3px;
  border-radius: 6px;
}

/* Custom scrollbar */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb {
  background: var(--red);
  border-radius: 10px;
  border: 3px solid var(--bg);
}

.skip-link {
  position: absolute;
  top: -100px;
  left: 20px;
  z-index: 999;
  padding: 12px 20px;
  background: var(--red);
  color: var(--on-brand);
  border-radius: 0 0 10px 10px;
  font-size: 14px;
  transition: top 0.25s var(--ease);
}
.skip-link:focus { top: 0; }


/* Pre-animation state — only applied when JS is running (see index.html head).
   script.js removes `.js-anim` if GSAP is unavailable, so nothing stays hidden. */
.js-anim .header,
.js-anim [data-anim],
.js-anim .hero__bg { opacity: 0; }
.js-anim .word > span { transform: translateY(110%); }


/* ==========================================================================
   3. LAYOUT HELPERS
   ========================================================================== */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}


/* ==========================================================================
   4. BUTTONS (reusable)
   ========================================================================== */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 17px 34px;
  border-radius: 100px;
  font-family: var(--font-head);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  isolation: isolate;
  /* No `will-change` here on purpose: there are ~30 buttons on the page and
     they only move on hover, so promoting every one of them permanently costs
     GPU memory for no gain. The browser promotes on demand. */
  transition:
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease),
    border-color 0.45s var(--ease),
    background 0.45s var(--ease);
}

.btn--sm { padding: 13px 26px; font-size: 14px; }

/* Primary — gradient red + neon glow + hover lift */
.btn--primary {
  background: var(--grad-red);
  color: var(--on-brand);
  box-shadow:
    0 8px 26px -8px var(--red-glow),
    0 0 0 1px rgba(11, 11, 12, 0.044) inset;
  /* `glowPulse` used to breathe on this shadow forever. With four or five
     primary buttons on a page it was a lot of ambient movement for no meaning;
     the button now reacts on hover and is still otherwise. */
}
.btn--primary:hover {
  transform: translateY(-4px);
  box-shadow:
    0 18px 44px -10px rgba(200, 16, 46, 0.7),
    0 0 0 1px rgba(11, 11, 12, 0.088) inset;
}
.btn--primary:active { transform: translateY(-1px); }

/* Sliding shine sweep */
.btn__shine {
  position: absolute;
  inset: 0 auto 0 -60%;
  width: 55%;
  /* Sweeps across a burgundy fill, so the sheen stays white here rather than
     following the ink tokens. */
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.34), transparent);
  transform: skewX(-20deg);
  z-index: -1;
  transition: left 0.75s var(--ease);
}
.btn:hover .btn__shine { left: 115%; }

/* Ghost / secondary — glass outline */
.btn--ghost {
  background: var(--glass);
  color: var(--ink);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.btn--ghost:hover {
  transform: translateY(-4px);
  border-color: rgba(200, 16, 46, 0.42);
  background: rgba(200, 16, 46, 0.06);
  box-shadow: 0 14px 34px -14px var(--red-glow);
}

.btn__arrow {
  display: inline-block;
  transition: transform 0.4s var(--ease);
}
.btn:hover .btn__arrow { transform: translateX(5px); }
.btn--ghost:hover .btn__arrow { transform: translate(4px, -4px); }


/* ==========================================================================
   5. BACKGROUND STACK
   ========================================================================== */
/* On the dark theme this stack was doing the heavy lifting — glowing orbs, a
   bright grid, a hard vignette. On a light ground the same intensities read as
   dirt. Everything here is now barely-there: the value of the background is
   that you should not be able to point at it. */
.bg {
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  pointer-events: none;
  overflow: hidden;
  background: var(--bg);
}

/* Hairline grid. It used to drift on a 26s loop; it is static now — a page
   ground that is permanently in motion is the thing that makes a site feel
   like a screensaver rather than a business. */
.bg__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(11, 11, 12, 0.024) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 11, 12, 0.024) 1px, transparent 1px);
  background-size: 70px 70px;
  mask-image: radial-gradient(ellipse 75% 65% at 50% 45%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 75% 65% at 50% 45%, #000 20%, transparent 78%);
}

/* The gradient mesh, the three blurred floating orbs, the drifting particle
   canvas and the vignette all used to sit in here. They were the soft colour
   washes behind the page on the old dark theme; on white they only ever read as
   smudges, so they were switched off — and their markup has now gone from the
   shell as well. Removed rather than kept as display:none rules for elements
   that no longer exist. What remains of the page ground is the hairline grid
   above and the film grain below. */

/* Noise texture (inline SVG turbulence — no extra request).
   `overlay` blending lightens as much as it darkens, which on a white ground
   just washes out; `multiply` at a very low opacity gives the faint paper
   grain that keeps a large flat area from looking like a blank canvas. */
.bg__noise {
  position: absolute;
  inset: 0;
  opacity: 0.022;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* A dark vignette is a dark-theme device. Inverted here into the faintest warm
   lift at the edges, which is what gives the page its "paper" feel. */
.bg__vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 70% at 50% 50%, transparent 45%, rgba(11, 11, 12, 0.07) 100%);
}


/* ==========================================================================
   6. HEADER / NAVBAR
   ========================================================================== */
.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: var(--z-header);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background 0.5s var(--ease-soft),
    backdrop-filter 0.5s var(--ease-soft),
    border-color 0.5s var(--ease-soft),
    box-shadow 0.5s var(--ease-soft);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  height: var(--header-h);
  transition: height 0.45s var(--ease);
}


/* ---- Top contact strip ----
   A slim business bar above the navbar: phone and email on the left, social on
   the right. It is part of the fixed header, so it never overlaps the nav and
   needs no JavaScript; on scroll it collapses to nothing using the same
   `.is-scrolled` class that shrinks the header, which hands the height back to
   the page and leaves the navbar as the only thing pinned to the top. */
.topbar {
  height: var(--topbar-h);
  overflow: hidden;
  background: #FAFAFA;
  border-bottom: 1px solid var(--stroke-soft);
  transition:
    height 0.45s var(--ease),
    opacity 0.3s var(--ease),
    border-bottom-width 0.45s var(--ease);
}
.header.is-scrolled .topbar {
  height: 0;
  opacity: 0;
  /* Width, not just colour: a border still occupies its 1px inside a
     border-box element at height 0, which left the navbar sitting one pixel
     down the page once scrolled. */
  border-bottom-width: 0;
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: var(--topbar-h);
}

.topbar__contact {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

.topbar__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: color 0.3s var(--ease);
}
.topbar__link:hover { color: var(--red); }

.topbar__icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--red);
}

.topbar__sep {
  width: 1px;
  height: 14px;
  background: var(--stroke);
}

.topbar__social {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.topbar__soc {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  color: var(--ink-mute);
  transition: color 0.3s var(--ease), background 0.3s var(--ease);
}
.topbar__soc svg { width: 16px; height: 16px; }
.topbar__soc:hover {
  color: var(--red);
  background: rgba(200, 16, 46, 0.07);
}

/* Touch hit areas.
   The toolbar links render 19-22px tall and the social marks 20px on a phone,
   under the 24px a finger needs. These transparent overlays enlarge only what
   is tappable — no size, colour or spacing changes, the bar keeps its height
   and nothing on the page moves. */
.topbar__link,
.topbar__soc { position: relative; }
.topbar__link::after,
.topbar__soc::after {
  content: "";
  position: absolute;
  inset: -4px -2px;
}

/* Scrolled state — glass + shrink */
.header.is-scrolled {
  background: rgba(255, 255, 255, 0.62);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  border-bottom-color: var(--stroke-soft);
  box-shadow: 0 14px 44px -22px rgba(11, 11, 12, 0.234);
}
.header.is-scrolled .header__inner { height: var(--header-h-sm); }
.header.is-scrolled .logo__img { height: 28px; }
.header.is-scrolled .logo__tagline { opacity: 0; transform: translateX(-6px); }

/* ---- Logo ---- */
.logo {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}

/* The header logo has no plate behind it. The navbar sits on the light page
   background and the wordmark carries its own transparent alpha, so the mark
   reads on its own — this wrapper is now only a positioning box. It keeps its
   class name because GSAP fades it in during the intro (see script.js), and
   because the footer still uses the plate treatment under its own name. */
.logo__plate {
  display: inline-flex;
  align-items: center;
}

/* White "speed plate" behind the footer wordmark. Kept: the footer sits on a
   darker ground where the logo's near-black "tech" would otherwise vanish.
   The rest of its recipe is in S12 next to the footer itself. */
.foot__logo-plate {
  display: inline-flex;
  align-items: center;
  padding: 8px 20px;
  border-radius: 12px;
  background: #FFFFFF;
  box-shadow:
    0 12px 30px -14px rgba(200, 16, 46, 0.65),
    0 0 0 1px var(--ink-mute) inset;
  transition: padding 0.45s var(--ease), box-shadow 0.45s var(--ease);
}

/* Height drives the size; width follows the 1012:236 aspect ratio so the mark
   can never be squashed. */
.logo__img {
  height: 34px;
  width: auto;
  object-fit: contain;
  transition: height 0.45s var(--ease);
}

/* Keeps the full registered name ("RinceTech AI Solutions") in the header,
   since the wordmark itself only carries "Rincetech".

   It shows only on genuinely wide screens. The header row is logo + an
   eight-item nav pill + the consultation button, and the tagline is the only
   piece of it that is decoration rather than navigation — giving it up below
   1600px is what lets Portfolio sit in the bar without squeezing the nav or
   pushing the button off the right edge. The header already drops it the moment
   you scroll, so this is the same decision, one breakpoint earlier. */
@media (max-width: 1599px) {
  .logo__tagline { display: none; }
}

.logo__tagline {
  position: relative;
  padding-left: 14px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-soft);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.logo__tagline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 1px;
  height: 22px;
  transform: translateY(-50%);
  background: linear-gradient(transparent, var(--stroke) 25%, var(--stroke) 75%, transparent);
}

/* ---- Navigation ---- */
.nav__list {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px;
  border-radius: 100px;
  background: rgba(11, 11, 12, 0.017);
  border: 1px solid var(--stroke-soft);
}

/* The pill's blur lives on a pseudo-element, not on `.nav__list` itself.
   `backdrop-filter` on an element makes it the containing block for its
   absolutely *and* fixed positioned descendants — which would pin the mega
   panels inside this 500px pill instead of letting them span the viewport. */
.nav__list::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.nav__link {
  position: relative;
  display: block;
  padding: 9px 17px;
  /* With seven items the row gets tight at the 1081px end of the desktop nav,
     and "AI & Tech" was breaking across two lines there — which stretched the
     pill and pushed every other label out of alignment. */
  white-space: nowrap;
  border-radius: 100px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: color 0.35s var(--ease);
}
.nav__link span { position: relative; display: inline-block; }

/* Animated underline */
.nav__link span::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: var(--grad-red);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.42s var(--ease);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover span::after,
.nav__link.is-active span::after {
  transform: scaleX(1);
  transform-origin: left center;
}
.nav__link.is-active { color: var(--ink); }


/* ---- Mega dropdown (Services / AI & Tech) ---- */
.nav__item { position: relative; }

.nav__link--mega { display: flex; align-items: center; gap: 7px; }

.nav__caret {
  width: 11px;
  height: 7px;
  flex-shrink: 0;
  color: var(--ink-mute);
  transition: transform 0.4s var(--ease), color 0.35s var(--ease);
}
.nav__item--mega:hover .nav__caret,
.nav__item--mega:focus-within .nav__caret,
.nav__item--mega.is-open .nav__caret { transform: rotate(-180deg); color: var(--red); }

/* Full-bleed panel. `fixed` + `top: header height` rather than `absolute`, so it
   spans the viewport and still tucks under the bar in both header states. */
.mega {
  position: fixed;
  /* Clears the contact strip as well as the navbar while the page is at the
     top; the scrolled rule below drops it once the strip has collapsed. */
  top: var(--header-top);
  left: 0;
  right: 0;
  padding: 34px 0 38px;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
  border-top: 1px solid var(--stroke-soft);
  border-bottom: 1px solid var(--stroke-soft);
  box-shadow: 0 30px 60px -34px rgba(11, 11, 12, 0.3);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  pointer-events: none;
  transition:
    opacity 0.34s var(--ease),
    transform 0.34s var(--ease),
    visibility 0s linear 0.34s;
}
.header.is-scrolled .mega { top: var(--header-h-sm); }

/* Invisible bridge over the gap between the nav pill and the panel, so the
   pointer can travel down without the panel closing underneath it. */
.mega::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -32px;
  height: 32px;
}

.nav__item--mega:hover > .mega,
.nav__item--mega:focus-within > .mega,
.nav__item--mega.is-open > .mega {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition:
    opacity 0.34s var(--ease),
    transform 0.34s var(--ease),
    visibility 0s;
}

.mega__head { margin-bottom: 22px; }
.mega__title {
  font-family: var(--font-head);
  font-size: clamp(21px, 1.9vw, 27px);
  font-weight: 600;
  letter-spacing: -0.025em;
  margin-bottom: 6px;
}
.mega__sub {
  font-size: 14px;
  color: var(--ink-soft);
  max-width: 72ch;
}

.mega__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.mega__link {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 100%;
  padding: 13px 17px;
  border-radius: 12px;
  background: #fff;
  border: 1px solid var(--stroke-soft);
  box-shadow: var(--shadow-sm);
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  transition:
    border-color 0.35s var(--ease),
    box-shadow 0.35s var(--ease),
    transform 0.35s var(--ease),
    color 0.35s var(--ease);
}
.mega__chev {
  color: var(--red);
  font-size: 17px;
  line-height: 1;
  transition: transform 0.35s var(--ease);
}
.mega__link:hover,
.mega__link:focus-visible {
  border-color: var(--red);
  color: var(--red);
  transform: translateY(-2px);
  box-shadow: 0 16px 30px -20px var(--red-glow);
}
.mega__link:hover .mega__chev,
.mega__link:focus-visible .mega__chev { transform: translateX(3px); }

.header__actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}

/* ---- Hamburger ---- */
.burger {
  display: none;
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  background: var(--glass);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.burger__bar {
  position: absolute;
  left: 50%;
  width: 19px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  transform: translateX(-50%);
  transition: transform 0.42s var(--ease), opacity 0.25s var(--ease), width 0.42s var(--ease);
}
.burger__bar:nth-child(1) { top: 16px; }
.burger__bar:nth-child(2) { top: 22px; width: 13px; }
.burger__bar:nth-child(3) { top: 28px; }

.burger.is-open .burger__bar:nth-child(1) { transform: translateX(-50%) translateY(6px) rotate(45deg); }
.burger.is-open .burger__bar:nth-child(2) { opacity: 0; width: 0; }
.burger.is-open .burger__bar:nth-child(3) { transform: translateX(-50%) translateY(-6px) rotate(-45deg); }


/* ==========================================================================
   7. MOBILE NAVIGATION (fullscreen overlay)
   ========================================================================== */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: 120px var(--gutter) 60px;
  overflow-y: auto;              /* short/landscape screens can still reach the CTA */
  overscroll-behavior: contain;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(26px) saturate(150%);
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  clip-path: circle(0% at calc(100% - 46px) 46px);
  visibility: hidden;
}
.mobile-nav[hidden] { display: none; }
.mobile-nav.is-open { visibility: visible; }

.mobile-nav__glow {
  position: absolute;
  top: -20%;
  right: -20%;
  width: 70vw;
  height: 70vw;
  background: none;
  pointer-events: none;
}

.mobile-nav__inner {
  position: relative;
  width: 100%;
  max-width: 460px;
}

.mobile-nav__list { margin-bottom: 44px; }
.mobile-nav__list li { overflow: hidden; }
.mobile-nav__list a {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 15px 0;
  border-bottom: 1px solid var(--stroke-soft);
  font-family: var(--font-head);
  font-size: clamp(28px, 8vw, 40px);
  font-weight: 600;
  letter-spacing: -0.03em;
  transition: color 0.35s var(--ease), padding-left 0.35s var(--ease);
}
.mobile-nav__list i {
  font-size: 12px;
  font-style: normal;
  font-family: var(--font-body);
  letter-spacing: 0.2em;
  color: var(--red);
}
.mobile-nav__list a:hover { color: var(--red); padding-left: 10px; }

/* Service links nested under Services / AI & Tech — the touch equivalent of the
   desktop mega panels, which have no hover to open them. */
.mobile-nav__sub { padding: 8px 0 18px 32px; }
.mobile-nav__sub li { overflow: visible; }
.mobile-nav__sub a {
  display: block;
  padding: 9px 0;
  border-bottom: 0;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink-soft);
}
.mobile-nav__sub a::before {
  content: "›";
  margin-right: 10px;
  color: var(--red);
}
.mobile-nav__sub a:hover { color: var(--red); padding-left: 6px; }

.mobile-nav__cta { width: 100%; }

/* Lock scroll while the overlay is open */
body.is-locked { overflow: hidden; }


/* ==========================================================================
   8. HERO — LEFT COLUMN
   ========================================================================== */
.hero {
  position: relative;
  z-index: var(--z-content);
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-top: var(--header-top);
  overflow: hidden;
}

/* ---- Full-bleed showreel ---- */
/* Sits inside `.hero` (which is already a stacking context at --z-content), so
   it layers above the fixed page background but below the copy. */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Only a light knock-down. Darkening hard here *and* in the scrim below
     stacks two dimmers on the same footage and the render disappears — the
     scrim alone owns readability, this just stops the whites blowing out.
     Kept near 1: the source is a 1280x720 render that is already upscaled to
     fill the hero, and pulling brightness down flattens its edge contrast,
     which reads as softness on top of the real upscale softness. */
  filter: brightness(0.92) contrast(1.05) saturate(1.1);
}

/* Does all the readability work, and only where it is needed: a heavy reading
   gutter down the left behind the copy, falling away to almost nothing by the
   right half so the footage stays plainly visible there. Feathered top and
   bottom so the hero still melts into the header and the next section. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(96deg,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.88) 26%,
      rgba(255, 255, 255, 0.6) 44%,
      rgba(255, 255, 255, 0.3) 60%,
      rgba(255, 255, 255, 0.22) 100%),
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.72) 0%,
      transparent 20%,
      transparent 74%,
      rgba(255, 255, 255, 0.94) 100%);
}

.hero__inner {
  position: relative;
  z-index: 2;
  display: grid;
  /* Single copy column. The old 45/55 split existed for the floating
     composition on the right; that overlay is gone and the showreel now
     carries the right-hand side by itself, so the copy keeps its own
     max-width (.hero__left) instead of a second track. */
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: 40px;
  width: 100%;
}

.hero__left {
  max-width: 620px;
  padding-block: 40px;
}

/* ---- Animated badge ---- */
/* `.pill` (S6) is the same component under a name the hero timeline can't
   reach; it is grouped in here so the recipe exists once. */
.badge,
.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 28px;
  padding: 9px 18px 9px 14px;
  border-radius: 100px;
  background: var(--glass-strong);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink);
  overflow: hidden;
}
.badge__dot,
.pill__dot {
  position: relative;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 0 0 var(--red-glow);
}
.badge__sweep,
.pill__sweep {
  position: absolute;
  inset: 0 auto 0 -50%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(11, 11, 12, 0.099), transparent);
  transform: skewX(-20deg);
}

/* ---- Headline ---- */
.hero__title {
  font-size: clamp(38px, 4.1vw, 68px);
  line-height: 1.06;
  margin-bottom: 26px;
}
.hero__title .line { display: block; }

/* Word mask for the GSAP reveal */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.06em;
  margin-right: 0.24em;
}
/* The intro reveal runs once, so these are not worth a permanent layer. */
.word > span { display: inline-block; }

/* Animated gradient highlight */
/* Was a travelling gradient clipped to the text. Flat red now — at headline
   size a moving fill reads as a novelty, not as premium. */
.grad { color: var(--red); }

/* ---- Sub heading ---- */
.hero__sub {
  max-width: 540px;
  margin-bottom: 38px;
  font-size: clamp(15px, 1.05vw, 17px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

/* ---- CTA row ---- */
.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 42px;
}

/* ---- Trust badges ---- */
.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  padding-top: 26px;
  border-top: 1px solid var(--stroke-soft);
}
.trust__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 400;
  color: var(--ink-soft);
  transition: color 0.3s var(--ease);
}
.trust__item:hover { color: var(--ink); }
.trust__check {
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: rgba(200, 16, 46, 0.14);
  border: 1px solid rgba(200, 16, 46, 0.35);
  color: var(--red-light);
  font-size: 10px;
}


/* ==========================================================================
   9. HERO — RIGHT COMPOSITION  (removed)
   --------------------------------------------------------------------------
   This section held the hero's right-hand overlay: `.hero__right` / `.stage`,
   the `.circuit` SVG, the `.glass-card` + `.chip` floaters, `.spark` and the
   `.dust` particles. All of it sat on top of the showreel and has been taken
   out of the markup, so the rules are gone too — nothing else on the site used
   them (`.tech-chip` on the service pages is a separate component).
   The keyframes they drove — dashFlow, nodeBlink, drawLine, driftUp — are NOT
   dead: S3/S6/S9/S11 and the footer still use them. See section 12.
   ========================================================================== */


/* ==========================================================================
   10. SCROLL INDICATOR
   ========================================================================== */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  z-index: 3;
}
.scroll-cue__mouse {
  position: relative;
  width: 25px;
  height: 40px;
  border: 1.5px solid var(--ink-mute);
  border-radius: 14px;
  transition: border-color 0.35s var(--ease);
}
.scroll-cue:hover .scroll-cue__mouse { border-color: var(--red); }
.scroll-cue__wheel {
  position: absolute;
  top: 8px;
  left: 50%;
  width: 3.5px;
  height: 7px;
  margin-left: -1.75px;
  border-radius: 4px;
  background: var(--red);
  animation: wheelDrop 1.9s ease-in-out infinite;
}
.scroll-cue__label {
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-soft);
}


/* ==========================================================================
   11. KEYFRAMES
   ========================================================================== */
@keyframes gridDrift   { to { transform: translate3d(70px, 70px, 0); } }



@keyframes glowPulse {
  0%, 100% { box-shadow: 0 8px 26px -8px var(--red-glow), 0 0 0 1px rgba(11, 11, 12, 0.044) inset; }
  50%      { box-shadow: 0 12px 40px -8px rgba(200, 16, 46, 0.75), 0 0 0 1px rgba(11, 11, 12, 0.077) inset; }
}


@keyframes badgeSweep {
  0%   { left: -50%; }
  55%  { left: 130%; }
  100% { left: 130%; }
}


@keyframes spinZ {
  to { transform: rotateX(var(--rx, 74deg)) rotateZ(360deg); }
}

@keyframes bloomPulse {
  0%, 100% { opacity: 0.75; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.08); }
}


@keyframes dashFlow   { to { stroke-dashoffset: -160; } }

@keyframes nodeBlink {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}


@keyframes drawLine {
  0%        { stroke-dashoffset: 120; }
  45%, 100% { stroke-dashoffset: 0; }
}

@keyframes driftUp {
  0%   { transform: translate3d(0, 0, 0);        opacity: 0; }
  15%  { opacity: 0.85; }
  85%  { opacity: 0.6; }
  100% { transform: translate3d(24px, -110px, 0); opacity: 0; }
}

@keyframes wheelDrop {
  0%        { transform: translateY(0);    opacity: 1; }
  70%       { transform: translateY(14px); opacity: 0; }
  71%, 100% { transform: translateY(0);    opacity: 0; }
}


/* ==========================================================================
   S1. SECTION SHELL — shared by every section below the hero
   --------------------------------------------------------------------------
   `.section`  → rhythm + stacking context
   `.section__fx` → decorative grid / orbs / particles / bloom
   `.surface`  → the one glassmorphism recipe every card reuses
   ========================================================================== */
.section {
  position: relative;
  z-index: var(--z-content);
  padding-block: clamp(88px, 9vw, 148px);
  overflow: hidden;
}

/* Section divider. A full-width hairline plus a short red rule centred on it —
   flat colour, and it gives each section a deliberate opening mark instead of
   the old glow bleeding across the whole edge. */
.section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--stroke-soft);
}
.section::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 64px;
  height: 2px;
  transform: translateX(-50%);
  background: var(--red);
}

/* Alternating ground. With the washes gone the page needs banding to keep
   sections from running together — two flat neutrals, no third colour. */
.section:nth-of-type(even) { background: var(--bg-alt); }

/* ---- Decorative FX layer ---- */
.section__fx {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Hairline grid, static. It drifted on a 30s loop; a section background that
   never stops moving is what makes a page read as a demo. */
.fx-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(11, 11, 12, 0.022) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 11, 12, 0.022) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(ellipse 72% 62% at 50% 50%, #000 12%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse 72% 62% at 50% 50%, #000 12%, transparent 76%);
}

/* Everything else in the decor layer is off.
   The orbs, mesh, beam and rays were blurred colour washes that only worked on
   the old dark theme. `.fx-dot` joins them: every section carried four to seven
   glowing red dots drifting upward forever, which is a lot of movement to ask a
   visitor to ignore while they read. The markup stays on the sections — one
   rule here turns the whole layer off, which is how the orbs were already
   handled. */
.fx-orb,
.fx-mesh,
.fx-beam,
.fx-ray,
.fx-dot { display: none; }

/* ---- Section heading block ---- */
.section__head {
  position: relative;
  max-width: 760px;
  margin: 0 auto clamp(48px, 5vw, 76px);
  text-align: center;
}
.section__title {
  font-size: clamp(30px, 3.4vw, 52px);
  line-height: 1.1;
  margin-bottom: 18px;
}
.section__sub {
  font-size: clamp(14.5px, 1.05vw, 17px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

/* ---- Shared card surface ----
   On the dark theme this was frosted glass: a white film lifting off black.
   Inverted literally it becomes a grey smudge on off-white, so it is rebuilt
   rather than recoloured. A card now reads as a sheet of white paper sitting
   slightly above a warm ground — flat fill, hairline edge, one long soft
   shadow. The blur is kept so the panels that genuinely sit over the hero
   video still separate from it. */
.surface {
  position: relative;
  border-radius: var(--radius-lg);
  background: var(--card);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(18px) saturate(120%);
  -webkit-backdrop-filter: blur(18px) saturate(120%);
  box-shadow: var(--shadow);
  overflow: hidden;
  isolation: isolate;
}

/* Hover ring, faded in by each card. A neon inner glow does not exist in
   print, and this palette is pretending to be print — so it is a crisp
   burgundy hairline plus a slightly deeper lift instead. */
.surface::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow:
    0 0 0 1px rgba(200, 16, 46, 0.42) inset,
    0 0 34px rgba(200, 16, 46, 0.05) inset;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease);
}


/* ==========================================================================
   S2. TRUST & ACHIEVEMENTS
   ========================================================================== */
.stats {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 26px;
}

.stat {
  perspective: 1000px;
  will-change: transform;   /* GSAP drives the gentle float on this wrapper */
}

.stat__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  padding: 42px 26px 34px;
  text-align: center;
  transition:
    transform 0.5s var(--ease),
    border-color 0.5s var(--ease),
    box-shadow 0.5s var(--ease);
}
.stat__card:hover {
  transform: translateY(-10px);
  border-color: rgba(200, 16, 46, 0.5);
  box-shadow:
    0 40px 70px -34px rgba(200, 16, 46, 0.55),
    0 0 0 1px rgba(11, 11, 12, 0.028) inset;
}
.stat__card:hover::before { opacity: 1; }

/* Top-down bloom revealed on hover */
.stat__glow {
  position: absolute;
  top: -60%;
  left: 50%;
  width: 190%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle at 50% 42%, rgba(200, 16, 46, 0.07), transparent 58%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease);
}
.stat__card:hover .stat__glow { opacity: 1; }

.stat__value {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(38px, 3.6vw, 58px);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;   /* stops the counter jittering while it runs */
}

.stat__label {
  margin-top: 14px;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.5;
  color: var(--ink);
}

.stat__bar {
  width: 34px;
  height: 2px;
  margin-top: 18px;
  border-radius: 2px;
  background: var(--grad-red);
  box-shadow: 0 0 12px var(--red-glow);
  transition: width 0.5s var(--ease);
}
.stat__card:hover .stat__bar { width: 62px; }


/* ==========================================================================
   S3. SERVICES
   ========================================================================== */
/* Six cards, so 3 x 2. The grid was 5 across with nth-child rules centring the
   odd one out; with an even count all of that goes away, and three wider cards
   give the thumbnail and the copy room to breathe. */
.services {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

.svc {
  perspective: 1100px;
  will-change: transform;
}

.svc__card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  padding: 34px 28px 30px;
}
/* The hover lift, cursor lighting, shine sweep and icon plate used to be
   declared again here. They now live once on the shared utilities in S6,
   which `.svc__card` / `.svc__glow` / `.svc__shine` / `.svc__icon` are
   grouped into — same output, one copy. */
.svc__icon svg { width: 28px; height: 28px; }

/* ---- Animated image slot ----
   Reserves a fixed 16:10 box so the card never reflows when the real image
   arrives. The placeholder animates using keyframes the page already declares
   (gridDrift + badgeSweep), and an <img> dropped inside simply paints over it. */
.svc__media {
  position: relative;
  align-self: stretch;
  aspect-ratio: 16 / 10;
  margin-bottom: 20px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--stroke-soft);
  background: #F1F1F2;
}

.svc__media-ph {
  position: absolute;
  inset: 0;
  background:
    var(--bg-alt);
}
/* Drifting grid — 35px tiles so gridDrift's 70px travel loops seamlessly */
.svc__media-ph::before {
  content: "";
  position: absolute;
  inset: -20%;
  background-image:
    linear-gradient(rgba(11, 11, 12, 0.033) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 11, 12, 0.033) 1px, transparent 1px);
  background-size: 35px 35px;
}
/* Shimmer pass, so an empty slot still reads as "loading", not "broken" */
.svc__media-ph::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 -50%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(11, 11, 12, 0.083), transparent);
  transform: skewX(-20deg);
}

/* Sits above the placeholder purely by DOM order — no :has() needed */
.svc__media-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.85s var(--ease);
}
.svc__card:hover .svc__media-img { transform: scale(1.06); }

/* Icon plate straddles the bottom edge of the image */
.svc__card .svc__icon {
  position: relative;
  z-index: 1;
  margin-top: -44px;
  margin-bottom: 18px;
}

.svc__title {
  font-size: 19px;
  line-height: 1.25;
  margin-bottom: 12px;
}
.svc__text {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
  margin-bottom: 26px;
}

/* ---- Card-level button (smaller sibling of .btn, no page-level glow) ---- */
.card-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: auto;
  padding: 11px 21px;
  border-radius: 100px;
  background: rgba(11, 11, 12, 0.028);
  border: 1px solid var(--stroke);
  font-family: var(--font-head);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  transition:
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    color 0.4s var(--ease),
    box-shadow 0.4s var(--ease);
}
.card-btn:hover {
  background: rgba(200, 16, 46, 0.16);
  border-color: rgba(200, 16, 46, 0.6);
  color: var(--ink);
  box-shadow: 0 14px 30px -16px var(--red-glow);
}
.card-btn__arrow { transition: transform 0.4s var(--ease); }
.card-btn:hover .card-btn__arrow { transform: translateX(4px); }

/* Compact variant. The AI index rows are editorial hairline rows, not boxes —
   a full-size pill there outweighs the 18px title it sits under. */
.card-btn--sm { padding: 8px 16px; font-size: 12.5px; gap: 7px; }


/* ==========================================================================
   S4. SECTION END CTA
   ========================================================================== */
.cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 40px;
  margin-top: clamp(56px, 6vw, 92px);
  padding: clamp(34px, 4vw, 58px);
  background: var(--bg-alt);
  border: 1px solid var(--stroke);
  /* One flat red edge instead of a border. It gives the panel a direction and
     is the same device as the red rule under each footer heading. */
  border-left: 3px solid var(--red);
}

/* Was a conic gradient spinning around a 1.5px ring. With flat colour the
   sweep only ever showed as a stray red arc in one corner, so the element is
   retired rather than recoloured — the markup stays on every page. */
.cta__border,
.cta__glow { display: none; }

.cta__glow {
  position: absolute;
  top: -70%;
  right: -10%;
  width: 60%;
  aspect-ratio: 1;
  pointer-events: none;
}

.cta__body { position: relative; max-width: 620px; }
.cta__title {
  font-size: clamp(24px, 2.5vw, 38px);
  line-height: 1.15;
  margin-bottom: 14px;
}
.cta__text {
  font-size: clamp(14px, 1vw, 16px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

.cta__actions {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

/* Keyframes owned by these sections */


/* ==========================================================================
   S5. SECTION RESPONSIVE
   --------------------------------------------------------------------------
   Services use a 6/4-column track so the orphan cards on the last row can be
   re-centred with `grid-column` instead of extra wrappers.
   ========================================================================== */

/* Tablet — 2 across, still an even count so nothing needs centring */
@media (max-width: 1080px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .services { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Mobile — single column */
@media (max-width: 700px) {
  .stats { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .services { grid-template-columns: minmax(0, 1fr); gap: 18px; }

  .stat__card { padding: 34px 22px 28px; }
  .svc__card  { padding: 30px 24px 26px; }

  .cta {
    flex-direction: column;
    align-items: flex-start;
    gap: 28px;
  }
  .cta__actions { width: 100%; flex-direction: column; align-items: stretch; }
}


/* ==========================================================================
   S5b. PLANS & PACKAGES
   --------------------------------------------------------------------------
   Built out of the shared utilities in S6 — `surface` + `card-hover` with a
   `.card-lite` / `.card-shine` child — so these cards lift, light and tilt
   exactly like the service cards above them. Only what is specific to a
   pricing card lives here: the category label, the feature list, and the
   footer block that pins the CTA to the bottom so buttons line up across a row.

   The section's wrapper <div> in the markup is deliberate; see the comment
   there. No pricing is shown anywhere — none was supplied.
   ========================================================================== */
.pkg-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

.pkg {
  perspective: 1100px;   /* the [data-tilt] rotation needs depth on the wrapper */
  will-change: transform;
}

.pkg__card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;          /* equal heights within a grid row */
  padding: 34px 30px 32px;
}

.pkg__cat {
  font-family: var(--font-head);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 12px;
}

.pkg__name {
  font-size: 22px;
  line-height: 1.2;
  margin-bottom: 10px;
}

.pkg__desc {
  width: 100%;
  margin-bottom: 22px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--stroke-soft);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}

.pkg__features {
  display: grid;
  gap: 11px;
  width: 100%;
  margin-bottom: 26px;
}

.pkg__feat {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* Same recipe as the hero's `.trust__check`, so a tick means the same thing
   in both places. */
.pkg__mark {
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  margin-top: 2px;
  border-radius: 50%;
  background: rgba(200, 16, 46, 0.14);
  border: 1px solid rgba(200, 16, 46, 0.35);
  color: var(--red-light);
  font-size: 10px;
}

/* "Without SSL" is a line in the list but not a thing you get, so it is crossed
   rather than ticked in brand red. The text keeps the same ink as every other
   row — `--ink-mute` at this size falls under 4.5:1, and the mark alone carries
   the distinction. */
.pkg__feat--off .pkg__mark {
  background: rgba(11, 11, 12, 0.035);
  border-color: var(--stroke);
  color: var(--ink-mute);
}

/* `margin-top: auto` on the first footer element pushes the whole footer down,
   which is what keeps every CTA on a row at the same height. */
.pkg__pricing {
  margin-top: auto;
  margin-bottom: 16px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-soft);   /* not --ink-mute: 12px at 3:1 fails AA on white */
}

.pkg__cta {
  width: 100%;
  padding: 15px 22px;
  font-size: 13.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.pkg__wa {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* ---- Highest tier ----
   A firmer edge and a warmer shadow. Deliberately not a different colour,
   a scale-up or a ribbon — it should read as the top of the range, not as an
   advert sitting inside the section. */
.pkg__card--featured {
  border-color: rgba(200, 16, 46, 0.3);
  box-shadow:
    0 30px 60px -40px rgba(200, 16, 46, 0.5),
    var(--shadow);
}

.pkg__badge {
  position: absolute;
  top: 28px;
  right: 26px;
  padding: 5px 12px;
  border-radius: 100px;
  background: rgba(200, 16, 46, 0.1);
  border: 1px solid rgba(200, 16, 46, 0.34);
  font-family: var(--font-head);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--red);
}
/* Keeps the category label clear of the badge on the one card that has one. */
.pkg__card--featured .pkg__cat { padding-right: 92px; }

/* The package name links through to its own page now that each package has one.
   It inherits the heading's type; only the hover colour is added. */
.pkg__link { color: inherit; transition: color 0.35s var(--ease); }
.pkg__link:hover { color: var(--red); }

/* "Full package details" under the inquiry button */
.pkg__more {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: color 0.35s var(--ease);
}
.pkg__more-arrow { transition: transform 0.35s var(--ease); }
.pkg__more:hover { color: var(--red); }
.pkg__more:hover .pkg__more-arrow { transform: translateX(4px); }


/* ==========================================================================
   PACKAGE DETAIL PAGES  (.pkgp-*)
   --------------------------------------------------------------------------
   One page per package. No video hero here — a package is a list of what you
   get, not a thing to film — so the hero is the type treatment from the service
   hero on the page's own light ground.
   ========================================================================== */
.pkgp-hero { padding-bottom: clamp(40px, 4.5vw, 70px); }

/* The inner pages centre their banner; this hero is left-aligned, so its
   breadcrumb has to be too. */
.pkgp-hero .pg-hero__crumb { justify-content: flex-start; }

.pkgp-hero__inner { max-width: 860px; }

.pkgp-hero__title {
  margin-bottom: 22px;
  font-size: clamp(38px, 5.6vw, 74px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.045em;
  text-wrap: balance;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6), 0 18px 40px rgba(11, 11, 12, 0.08);
}

.pkgp-hero__line {
  max-width: 30ch;
  margin-bottom: 14px;
  font-family: var(--font-head);
  font-size: clamp(17px, 1.7vw, 24px);
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.pkgp-hero__sub {
  max-width: 54ch;
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

.pkgp-hero__price {
  margin-top: 22px;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
.pkgp-hero__price span { margin-inline: 5px; color: var(--red); }

.pkgp-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 32px;
}

/* ---- Complete feature list ---- */
.pkgp-features {
  max-width: 900px;
  margin-inline: auto;
  padding: clamp(30px, 3.4vw, 48px);
}

.pkgp-feats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 15px 34px;
}

.pkgp-feat {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--ink-soft);
}
.pkgp-feat .pkg__mark { margin-top: 2px; }

.pkgp-features__note {
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--stroke-soft);
  text-align: center;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-soft);
}
.pkgp-features__note span { margin-inline: 5px; color: var(--red); }

/* A four-item deliverables grid, where the services pages run six */
.svcp-cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }


/* ==========================================================================
   CLIENT LOGOS  (.clients)
   --------------------------------------------------------------------------
   "Trusted by Leading Brands" on the home page. Fourteen client marks, each in
   its own white card so that wordmarks, circular badges and square crests all
   read as one row despite arriving at wildly different aspect ratios (1:1 up to
   5.35:1).

   The artwork is never touched: no greyscale, no recolouring, no forced mono
   treatment. A client's brand is their own, and a wall of grey logos says less
   about trust than a wall of real ones. Normalising is done by the card —
   equal box, generous padding, object-fit: contain.
   ========================================================================== */
.clients {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 18px;
}

.client {
  /* A plain block with a definite height, deliberately not a grid or flex box.
     Both of those size their single item's row/line from its content, which
     makes a percentage height on the image circular — it silently fell back to
     `auto` and the square logos rendered at 135px inside 80px of room. With a
     block parent the image's containing block is simply the padding box, so
     `height: 100%` resolves and `object-fit` does the rest. */
  display: block;
  height: clamp(104px, 8.8vw, 132px);
  padding: 15px 18px;
  border-radius: 14px;
  background: #fff;
  border: 1px solid var(--stroke-soft);
  box-shadow: var(--shadow-sm);
  transition:
    transform 0.35s var(--ease),
    border-color 0.35s var(--ease),
    box-shadow 0.35s var(--ease);
}
.client:hover {
  transform: translateY(-3px);
  border-color: rgba(200, 16, 46, 0.28);
  box-shadow: 0 16px 30px -20px rgba(11, 11, 12, 0.22);
}

/* Fill the card and let `contain` letterbox the artwork inside it. The obvious
   alternative — auto size capped by max-width/max-height — left the square
   logos at their full 135px width and overflowing the card's 82px of vertical
   room, because a percentage max-height on a replaced element in a centred grid
   area does not clamp the way you would expect. Filling the box and containing
   the pixels is exact: nothing stretches, nothing crops, nothing escapes. */
.client__logo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

/* 7 → 5 → 4 → 2. Fourteen logos land as 2 full rows at seven across. */
@media (max-width: 1279px) {
  .clients { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
/* 1079, not 1023: an iPad in landscape is exactly 1024 wide and should get the
   tablet layout, not the five-across laptop one. */
@media (max-width: 1079px) {
  .clients { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
}
@media (max-width: 700px) {
  .clients { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .client { height: 104px; padding: 16px; }
}


/* ==========================================================================
   BLOG POST  (.blogp)
   --------------------------------------------------------------------------
   The reading view for one article, rendered by blog/index.php from the
   database. Built from the page components that already exist — the banner,
   `.surface`, the closing CTA — plus a measure and a type scale for long-form
   prose, which nothing on the site needed until now.
   ========================================================================== */
.blogp__head { max-width: 820px; }
.blogp__by {
  margin-top: 14px;
  font-size: 13px;
  color: var(--ink-mute);
}

.blogp__media-wrap { padding-top: 0; }
.blogp__media-wrap::before,
.blogp__media-wrap::after { display: none; }

.blogp__media {
  max-width: 940px;
  margin: 0 auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--stroke-soft);
  box-shadow: var(--shadow);
}
.blogp__media img { display: block; width: 100%; height: auto; }

/* The article itself. One column, a comfortable measure, and the same ink the
   rest of the site uses for body copy. */
.blogp__body {
  max-width: 720px;
  margin: 0 auto;
  font-size: 16.5px;
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
}
.blogp__body > div > *:first-child { margin-top: 0; }
.blogp__body p { margin-bottom: 22px; }
.blogp__body h2,
.blogp__body h3 {
  color: var(--ink);
  line-height: 1.25;
  letter-spacing: -0.02em;
  margin: 38px 0 14px;
}
.blogp__body h2 { font-size: clamp(22px, 2.2vw, 30px); }
.blogp__body h3 { font-size: clamp(18px, 1.7vw, 22px); }
.blogp__body ul,
.blogp__body ol { margin: 0 0 22px 22px; }
.blogp__body li { margin-bottom: 9px; }
.blogp__body a { color: var(--red); text-decoration: underline; text-underline-offset: 2px; }
.blogp__body strong { color: var(--ink); font-weight: 600; }
.blogp__body blockquote {
  margin: 26px 0;
  padding: 4px 0 4px 22px;
  border-left: 3px solid var(--red);
  font-size: 17.5px;
  color: var(--ink);
}
.blogp__body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--bg-alt);
  padding: 2px 6px;
  border-radius: 5px;
}
.blogp__body pre {
  background: var(--bg-alt);
  border: 1px solid var(--stroke-soft);
  border-radius: 12px;
  padding: 18px;
  overflow-x: auto;
  margin-bottom: 22px;
}
.blogp__body hr { border: 0; border-top: 1px solid var(--stroke-soft); margin: 34px 0; }

/* Draft preview bar — only ever seen by a signed-in admin. */
.flash-preview {
  position: relative;
  z-index: var(--z-content);
  margin: 0;
  padding: calc(var(--header-top) + 12px) var(--gutter) 12px;
  background: rgba(200, 16, 46, 0.08);
  border-bottom: 1px solid rgba(200, 16, 46, 0.24);
  color: var(--red);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
}
.flash-preview + .blogp { padding-top: clamp(26px, 3vw, 50px); }


/* ==========================================================================
   PORTFOLIO  (.pf-*)
   --------------------------------------------------------------------------
   Client sites shown as browser captures. Built from the same `surface` +
   `card-hover` pair every other card grid on the site uses; what is specific
   here is the media box, because these are wide screenshots (~2.15:1) rather
   than the 16:10 the service cards expect.
   ========================================================================== */
.pf-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px;
}

.pf-card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.pf-card__media {
  position: relative;
  aspect-ratio: 2.15;
  overflow: hidden;
  background: var(--bg-alt);
  border-bottom: 1px solid var(--stroke-soft);
}
.pf-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Top of the capture is the site's header and hero — the part that makes it
     recognisable — so that is what survives the crop. */
  object-position: center top;
  transition: transform 0.7s var(--ease);
}
.pf-card:hover .pf-card__media img { transform: scale(1.04); }

.pf-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 24px 24px 26px;
}

.pf-card__cat {
  margin-bottom: 10px;
  font-family: var(--font-head);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
}

.pf-card__title {
  margin-bottom: 10px;
  font-size: 19px;
  line-height: 1.3;
}

.pf-card__text {
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--ink-soft);
}

.pf-card__btn { margin-top: 20px; }

/* Heading that exists for screen readers and search engines only — the page
   banner above already carries the visible one. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

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

@media (max-width: 700px) {
  .pf-grid { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .pf-card__body { padding: 20px 20px 22px; }
}


/* ==========================================================================
   BLOG — empty state
   --------------------------------------------------------------------------
   There are no posts yet. Rather than ship placeholder articles, the page says
   so plainly and gives the visitor somewhere useful to go.
   ========================================================================== */
.blog-empty {
  max-width: 760px;
  margin-inline: auto;
  padding: clamp(40px, 5vw, 72px) clamp(28px, 4vw, 60px);
  text-align: center;
}
.blog-empty__icon {
  display: inline-flex;
  margin-bottom: 26px;
}
.blog-empty__title {
  margin-bottom: 18px;
  font-size: clamp(24px, 2.6vw, 36px);
  line-height: 1.15;
  letter-spacing: -0.03em;
}
.blog-empty__text {
  max-width: 56ch;
  margin-inline: auto;
  font-size: clamp(14.5px, 1.05vw, 16px);
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
}
.blog-empty__text + .blog-empty__text { margin-top: 16px; }
.blog-empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin-top: 34px;
}


/* ---- Responsive: 3 → 2 → 1, matching the services grid above ---- */
@media (max-width: 1080px) {
  .pkg-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svcp-cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 700px) {
  .pkg-grid { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .pkg__card { padding: 30px 24px 28px; }
  .pkg__name { font-size: 20px; }

  .svcp-cards--4 { grid-template-columns: minmax(0, 1fr); }
  .pkgp-feats { grid-template-columns: minmax(0, 1fr); }
  .pkgp-hero__title { font-size: clamp(32px, 10vw, 46px); }
  .pkgp-hero__line, .pkgp-hero__sub { max-width: none; }
  .pkgp-hero__actions { flex-direction: column; align-items: stretch; }
  .pkgp-hero__actions .btn { width: 100%; }
  .blog-empty__actions { flex-direction: column; align-items: stretch; }
  .blog-empty__actions .btn { width: 100%; }
}


/* ==========================================================================
   S6. SHARED CARD & ICON UTILITIES
   --------------------------------------------------------------------------
   Generalised versions of the one-off card effects used by the services
   cards, so About / Why / Process cards share a single implementation.
   Compose them: `class="surface card-hover"` + a `.card-lite` / `.card-shine`
   child + an `.icon-plate` wrapping an `.ic` SVG.
   ========================================================================== */
/* `.svc__card` (S3) predates these utilities and had a byte-identical copy of
   every rule below. It is grouped in here instead so there is exactly one
   implementation of the card hover behaviour on the site. */
.card-hover,
.svc__card {
  transition:
    transform 0.5s var(--ease),
    border-color 0.5s var(--ease),
    box-shadow 0.5s var(--ease);
}
.card-hover:hover,
.svc__card:hover {
  transform: translateY(-10px);   /* GSAP takes this over on pointer devices */
  border-color: rgba(200, 16, 46, 0.32);
  box-shadow:
    0 40px 70px -38px rgba(11, 11, 12, 0.34),
    0 0 0 1px rgba(200, 16, 46, 0.06) inset;
}
.card-hover:hover::before,
.svc__card:hover::before { opacity: 1; }   /* the .surface neon ring */

/* Cursor-tracked gradient lighting (--mx / --my written by script.js) */
.card-lite,
.svc__glow {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s var(--ease);
}
.card-lite { background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 0%), rgba(200, 16, 46, 0.07), transparent 62%); }
.svc__glow { background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 0%), rgba(200, 16, 46, 0.07), transparent 62%); }

.card-hover:hover .card-lite,
.svc__card:hover .svc__glow { opacity: 1; }

/* Diagonal shine sweep */
.card-shine,
.svc__shine {
  position: absolute;
  inset: 0 auto 0 -70%;
  width: 60%;
  background: linear-gradient(100deg, transparent, rgba(11, 11, 12, 0.022), transparent);
  transform: skewX(-20deg);
  pointer-events: none;
  transition: left 0.9s var(--ease);
}
.card-hover:hover .card-shine,
.svc__card:hover .svc__shine { left: 125%; }

/* ---- Icon plate + animated SVG icon ---- */
.icon-plate,
.svc__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: 17px;
  background: rgba(200, 16, 46, 0.07);
  border: 1px solid rgba(200, 16, 46, 0.18);
  color: var(--red-light);
  box-shadow:
    0 14px 32px -18px var(--red-glow),
    0 0 0 1px rgba(11, 11, 12, 0.028) inset;
  transition:
    transform 0.5s var(--ease),
    color 0.5s var(--ease),
    box-shadow 0.5s var(--ease);
}
.svc__icon { width: 58px; height: 58px; margin-bottom: 22px; }
.icon-plate--sm { width: 46px; height: 46px; border-radius: 14px; }

.card-hover:hover .icon-plate,
.ai-card__inner:hover .icon-plate,
.svc__card:hover .svc__icon {
  transform: translateY(-4px) scale(1.08);
  color: var(--ink);
  box-shadow:
    0 20px 40px -16px rgba(200, 16, 46, 0.8),
    0 0 0 1px rgba(11, 11, 12, 0.066) inset;
}

.ic { width: 26px; height: 26px; }
.icon-plate--sm .ic { width: 22px; height: 22px; }

/* Two reusable icon animations, both on keyframes the hero already defines */
.ic__pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation-delay: var(--d, 0s);
}
.ic__flow {
  stroke-dasharray: 5 7;
}

/* `.pill` exists as a separate name only so the hero's intro timeline — which
   targets `.badge` globally — cannot reveal these early. The styling itself is
   shared with `.badge` (see S8/S11 groupings above); only the deltas live here. */
.pill { margin-bottom: 26px; }
.pill__dot { flex-shrink: 0; }


/* ==========================================================================
   S7. ABOUT
   ========================================================================== */
.about__inner {
  display: grid;
  grid-template-columns: minmax(0, 52fr) minmax(0, 48fr);
  align-items: center;
  gap: clamp(40px, 5vw, 80px);
}

.about__title { margin-bottom: 20px; text-align: left; }
.about__text,
.ai__text {
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
}

/* ---- Feature cards ---- */
.feats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 34px 0 38px;
}
.feat { perspective: 900px; will-change: transform; }
.feat__card {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 100%;
  padding: 18px 20px;
}
.feat__title {
  font-size: 15px;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.about__cta { display: flex; flex-wrap: wrap; gap: 16px; }

/* ---- Left composition ---- */
.about__visual {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 520px;
}

.av {
  position: relative;
  width: min(100%, 560px);
  aspect-ratio: 1 / 1;
  perspective: 1200px;
}

/* Parallax layers — script.js moves these on x/y, their children float on y */
.av__layer {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

.av__bloom {
  position: absolute;
  inset: 14%;
  border-radius: 50%;
  background: none;
}

/* Rotating rings — reuse the hero's spinZ, which reads --rx for the tilt */
.av__ring {
  position: absolute;
  top: 50%;
  left: 50%;
  border: 1px solid rgba(11, 11, 12, 0.066);
  border-radius: 50%;
  transform: rotateX(var(--rx, 72deg)) rotateZ(0deg);
}
.av__ring--1 {
  width: 300px; height: 300px; margin: -150px 0 0 -150px;
  border-color: rgba(200, 16, 46, 0.38);
}
.av__ring--2 {
  width: 400px; height: 400px; margin: -200px 0 0 -200px;
}
.av__ring--3 {
  width: 500px; height: 500px; margin: -250px 0 0 -250px;
  border-style: dashed;
  border-color: rgba(11, 11, 12, 0.05);
}

/* Animated connection lines */
.av__net {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 0 8px rgba(200, 16, 46, 0.55));
}
/* A white halo had nothing to glow against once the ground went light. */
.av__net .ic__pulse { filter: drop-shadow(0 0 5px rgba(200, 16, 46, 0.45)); }

/* Glowing core */
.av__core {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 130px;
  height: 130px;
  margin: -65px 0 0 -65px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, rgba(224, 25, 53, 0.85) 0%, rgba(200, 16, 46, 0.55) 46%, rgba(142, 11, 32, 0.9) 100%);
  border: 1px solid rgba(11, 11, 12, 0.055);
  box-shadow:
    inset 0 0 52px rgba(200, 16, 46, 0.32),
    0 0 84px -12px var(--red-glow);
}
.av__core-ring {
  position: absolute;
  inset: -16%;
  border-radius: 50%;
  background: radial-gradient(circle, transparent 58%, rgba(200, 16, 46, 0.24) 66%, transparent 74%);
}
/* Sits on the red sphere, so it overrides `.grad` (red on red is invisible now
   that the gradient fill is gone). */
.av__core-label {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 30px;
  letter-spacing: 0.05em;
  color: var(--on-brand);
}

/* Floating glass panels */
.av__panel {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 17px;
  border-radius: var(--radius);
  white-space: nowrap;
  will-change: transform;
}
.av__panel strong { display: block; font-size: 14px; font-weight: 600; }
.av__panel em {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-style: normal;
  color: var(--ink-soft);
}
.av__panel-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 11px;
  background: rgba(200, 16, 46, 0.16);
  border: 1px solid rgba(200, 16, 46, 0.34);
  color: var(--red-light);
  font-size: 15px;
}
.av__panel--1 { top: 9%;  right: -2%; }
.av__panel--2 { bottom: 8%; left: -4%; }

/* Floating code snippets */
.av__code {
  position: absolute;
  padding: 8px 14px;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.66);
  border: 1px solid rgba(200, 16, 46, 0.30);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  box-shadow: 0 0 24px -8px var(--red-glow);
  white-space: nowrap;
  will-change: transform;
}
.av__code b { color: var(--red-light); font-weight: 600; }
.av__code--1 { top: 4%;   left: 0; }
.av__code--2 { top: 44%;  right: -3%; }
.av__code--3 { bottom: 20%; right: 12%; }


/* ==========================================================================
   S8. WHY CHOOSE US
   ========================================================================== */
/* Shared 3-up card grid. The Why and Testimonial grids are identical at this
   breakpoint, so they are declared here once; each keeps its own tablet and
   mobile overrides further down. (The portfolio grid was the third selector
   here before that section was removed — see the S14/S15 tombstone.) */
.why,
.tst-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.why__item { perspective: 1100px; will-change: transform; }
.why__card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  padding: 34px 28px;
}
.why__title {
  margin: 22px 0 12px;
  font-size: 19px;
  line-height: 1.25;
}
.why__text,
.ai-card__text {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}


/* ==========================================================================
   S9. PROCESS TIMELINE
   ========================================================================== */
.steps-wrap { position: relative; }

/* Connector rail — the node dots sit on this line */
.steps__rail {
  position: absolute;
  top: 8px;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: rgba(11, 11, 12, 0.055);
  overflow: hidden;
  pointer-events: none;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
/* --fill is scrubbed 0 → 1 by ScrollTrigger; it defaults to 1 so the rail is
   still complete if GSAP never loads. */
.steps__fill {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform: scaleX(var(--fill, 1));
  background: var(--grad-red);
  box-shadow: 0 0 14px var(--red-glow);
}

.steps {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 20px;
}
.step {
  display: flex;
  flex-direction: column;
  align-items: center;
  perspective: 1000px;
}

.step__node {
  position: relative;
  width: 18px;
  height: 18px;
  margin-bottom: 30px;
  border-radius: 50%;
  background: var(--grad-red);
  border: 2px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 0 var(--red-glow);
  animation-delay: var(--d, 0s);
}
.step:nth-child(2) .step__node { --d: .35s; }
.step:nth-child(3) .step__node { --d: .7s; }
.step:nth-child(4) .step__node { --d: 1.05s; }
.step:nth-child(5) .step__node { --d: 1.4s; }
.step:nth-child(6) .step__node { --d: 1.75s; }

/* `flex: 1` (not height:100%) so the card fills the column *below* the node
   instead of overflowing by the node's height. */
.step__floater { width: 100%; flex: 1; will-change: transform; }

.step__card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  padding: 28px 22px 26px;
}

/* The large ghost 01..06 that floated in each card's top-right corner was
   removed on request, along with the numbering on the service pages. The step
   order is carried by the timeline rail above the row. */

.step__title {
  margin: 20px 0 10px;
  font-size: 17px;
  line-height: 1.25;
}
.step__text {
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.7;
  color: var(--ink-soft);
}


/* ==========================================================================
   S10. FULL-WIDTH CTA PANEL (centred variant of .cta)
   ========================================================================== */
.cta--center {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 30px;
  margin-top: 0;
  padding: clamp(42px, 5vw, 72px) clamp(28px, 5vw, 64px);
}
.cta--center .cta__body { max-width: 720px; }
.cta--center .cta__actions { justify-content: center; }


/* ==========================================================================
   S11. RESPONSIVE — sections 03 → CTA
   ========================================================================== */

/* Laptop */
@media (max-width: 1280px) {
  .av__panel--1 { right: -6%; }
  .av__panel--2 { left: -6%; }
  .step__card { padding: 26px 18px 24px; }
}

/* Tablet — stack About, 2-up grids, timeline goes vertical */
@media (max-width: 1080px) {
  .about__inner { grid-template-columns: minmax(0, 1fr); gap: 56px; }
  .about__content { order: 1; }
  .about__visual  { order: 2; min-height: 460px; }
  .about__title, .about__text { text-align: left; }

  .why { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Vertical timeline: the rail rotates to the left gutter and each step
     becomes a full-width card with its node pinned beside it. */
  .steps { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .steps__rail {
    top: 12px;
    bottom: 12px;
    left: 8px;
    right: auto;
    width: 2px;
    height: auto;
    mask-image: linear-gradient(180deg, transparent, #000 5%, #000 95%, transparent);
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 5%, #000 95%, transparent);
  }
  .steps__fill { transform-origin: center top; transform: scaleY(var(--fill, 1)); }

  .step {
    display: block;
    position: relative;
    padding-left: 52px;
  }
  .step__node {
    position: absolute;
    left: 0;
    top: 22px;
    margin: 0;
  }
  .step__card { padding: 26px 24px; }
}

/* Mobile */
@media (max-width: 700px) {
  .about__visual { min-height: 380px; }
  .av { width: min(100%, 340px); }
  .av__ring--1 { width: 200px; height: 200px; margin: -100px 0 0 -100px; }
  .av__ring--2 { width: 265px; height: 265px; margin: -132px 0 0 -132px; }
  .av__ring--3 { width: 330px; height: 330px; margin: -165px 0 0 -165px; }
  .av__core { width: 96px; height: 96px; margin: -48px 0 0 -48px; }
  .av__core-label { font-size: 22px; }
  .av__panel { padding: 10px 13px; gap: 9px; }
  .av__panel strong { font-size: 12.5px; }
  .av__panel em { font-size: 10px; }
  .av__panel-icon { width: 28px; height: 28px; font-size: 13px; }
  .av__panel--1 { right: -8%; }
  .av__panel--2 { left: -8%; }
  .av__code { font-size: 10.5px; padding: 6px 11px; }
  .av__code--3 { display: none; }

  .feats { grid-template-columns: minmax(0, 1fr); gap: 12px; margin: 28px 0 32px; }
  .about__cta { flex-direction: column; align-items: stretch; gap: 12px; }

  .why { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .why__card { padding: 30px 24px; }

  .step { padding-left: 44px; }
  .steps__rail { left: 6px; }
  .cta--center { align-items: center; text-align: center; }
}


/* ==========================================================================
   S12. AI & EMERGING TECHNOLOGIES
   --------------------------------------------------------------------------
   Sticky 40/60 split. The only new keyframe in this block is `marquee` —
   the mesh, rays, circuits and network all ride on keyframes the hero and
   the earlier sections already declare.
   ========================================================================== */

/* `.section` sets `overflow: hidden`, which would turn this section into the
   nearest scrollport and stop the left column from sticking. The decorative
   layer clips itself, so this section can safely opt out. */
.section--ai { overflow: visible; }

/* ---- Extra background layers ---- */
/* `.fx-mesh` was the section-level version of the page mesh — three blurred
   colour blobs breathing on a 24s loop. Switched off with the rest of the decor
   layer above, and its rule removed with it. */

.fx-circuit,
.fx-net {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* These were neon traces glowing off a black ground. On white the drop-shadow
   has nothing to glow into and just muddies the line, so it goes, and the
   opacity drops to where the circuitry reads as watermark rather than as
   content competing with the cards on top of it. */
.fx-circuit { opacity: 0.16; }
.fx-net     { opacity: 0.14; }

/* Dash periods chosen so dashFlow's -160 offset lands on a whole number of
   dashes — otherwise the loop visibly jumps. */
.fx-circuit .ic__flow { stroke-dasharray: 6 10; }
.fx-net .ic__flow     { stroke-dasharray: 4 6; }

.fx-node {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0.4;
  animation-delay: var(--d, 0s);
}

/* Moving light rays — reuse the badge sweep, which already pauses between
   passes instead of scanning continuously. */
.fx-ray {
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: -40%;
  width: 12%;
  background: linear-gradient(100deg, transparent, rgba(200, 16, 46, 0.05), rgba(11, 11, 12, 0.012), transparent);
  transform: skewX(-18deg);
  filter: blur(6px);
}
.fx-ray--2 {
  width: 7%;
  background: linear-gradient(100deg, transparent, rgba(11, 11, 12, 0.018), transparent);
  animation-duration: 15s;
  animation-delay: 3s;
}
.fx-ray--3 { width: 16%; animation-duration: 19s; animation-delay: 6.5s; }

/* Denser grid — reads as a digital environment rather than page furniture */
.section--ai .fx-grid { background-size: 48px 48px; }

/* ---- Section head ----
   The heading used to be a sticky 40% column beside a 60% list. The card grid
   wants the full container width to fit three across, so the heading moved
   above it and uses the shared centred `.section__head` instead. `.pill` is
   inline-flex, so it centres with the text without extra rules. */
.ai__head { max-width: 820px; }

/* ---- Technology cards ----
   A 3-up grid of self-contained cards: icon plate, title, one-line summary,
   the four capabilities that sit under it, and the link to that service's own
   page. This replaced an editorial row index inside a single glass panel — the
   capability tags are the reason: four sub-items per service read as a list
   inside a card, but as clutter inside a hairline row. */
.ai-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

/* The <li> is only a grid cell; `.ai-card__inner` is the card, and it stretches
   so every card in a row ends at the same height regardless of copy length. */
.ai-card { display: flex; }

.ai-card__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  padding: 32px 28px;
  transition:
    transform 0.55s var(--ease),
    border-color 0.55s var(--ease);
}
.ai-card__inner:hover {
  transform: translateY(-6px);
  border-color: rgba(200, 16, 46, 0.4);
}
/* `.surface::before` is the shared neon ring, faded in per card on hover */
.ai-card__inner:hover::before { opacity: 0.55; }

.ai-card__title {
  margin: 20px 0 11px;
  font-size: 18.5px;
  line-height: 1.28;
}
/* .ai-card__text is grouped with .why__text in S8 */

/* ---- Capability tags ---- */
/* Stacked rather than wrapped inline: the labels are phrases, not one-word
   chips, so a wrapping row breaks them at unpredictable points and the cards
   in a row stop aligning. */
.ai-card__tags {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin: 20px 0 26px;
}
.ai-card__tags li {
  padding: 8px 13px;
  border-radius: 10px;
  background: rgba(11, 11, 12, 0.022);
  border: 1px solid var(--stroke-soft);
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.45;
  color: var(--ink-soft);
  transition:
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    color 0.4s var(--ease);
}
.ai-card__inner:hover .ai-card__tags li {
  border-color: rgba(200, 16, 46, 0.22);
  color: var(--ink);
}

/* Pushed to the bottom edge so the link sits on one line across the row even
   when the cards above it hold different amounts of copy. */
.ai-card__link { margin-top: auto; }

.ai-card .icon-plate { width: 52px; height: 52px; border-radius: 15px; }
.ai-card .ic { width: 24px; height: 24px; }

/* ---- Tech stack marquee ---- */
.tech { margin-top: clamp(60px, 6vw, 96px); }

.tech__label {
  margin-bottom: 26px;
  text-align: center;
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.tech-strip {
  display: flex;
  overflow: hidden;
  padding-block: 6px;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

/* Two identical tracks sit side by side and both slide one full width left,
   so the second lands exactly where the first started. */
.tech-track {
  display: flex;
  flex-shrink: 0;
  gap: 14px;
  padding-right: 14px;
  will-change: transform;
  animation: marquee 52s linear infinite;
}
.tech-strip:hover .tech-track,
.tech-strip:focus-within .tech-track { animation-play-state: paused; }

.tech-chip {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  flex-shrink: 0;
  padding: 9px 20px 9px 9px;
  border-radius: 100px;
  background: rgba(11, 11, 12, 0.025);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  font-size: 13.5px;
  font-weight: 500;
  white-space: nowrap;
  color: var(--ink-soft);
  transition:
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    color 0.4s var(--ease),
    box-shadow 0.4s var(--ease);
}
.tech-chip:hover {
  background: rgba(200, 16, 46, 0.12);
  border-color: rgba(200, 16, 46, 0.55);
  color: var(--ink);
  box-shadow: 0 14px 32px -18px var(--red-glow);
}

.tech-chip__mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 10px;
  background: rgba(200, 16, 46, 0.08);
  border: 1px solid rgba(200, 16, 46, 0.20);
  font-family: var(--font-head);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--red-light);
}

@keyframes marquee { to { transform: translateX(-100%); } }

/* The centred CTA zeroes its margin so it can sit flush; this section wants
   breathing room above it. */
.section--ai .cta--center { margin-top: clamp(60px, 6vw, 96px); }


/* ==========================================================================
   S13. RESPONSIVE — AI & Emerging Technologies
   ========================================================================== */

/* Tablet — two cards across */
@media (max-width: 1080px) {
  .ai-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Mobile — single column */
@media (max-width: 700px) {
  .ai-cards { grid-template-columns: minmax(0, 1fr); }
  .ai-card__inner { padding: 26px 22px; }
  /* The lift reads as a glitch on a card that is already the full width */
  .ai-card__inner:hover { transform: none; }
  .ai-card__link { width: 100%; justify-content: center; }

  .tech-track { gap: 10px; padding-right: 10px; animation-duration: 38s; }
  .tech-chip { font-size: 12.5px; padding: 7px 16px 7px 7px; gap: 9px; }
  .tech-chip__mark { width: 28px; height: 28px; font-size: 11px; border-radius: 9px; }
  .tech__label { margin-bottom: 20px; }
}


/* ==========================================================================
   S14 + S15. PORTFOLIO & CASE STUDIES  ·  REMOVED
   --------------------------------------------------------------------------
   The portfolio grid, its filter bar and the featured case study were removed
   from index.html on request, so their rules are gone too. The S-numbers are
   deliberately not renumbered: S16 onward still match their own headers, the
   map at the top of this file, and the section comments in index.html.

   The portfolio selector was also dropped from the shared 3-up card grid it
   used to share with .why and .tst-grid in S8.
   ========================================================================== */


/* ==========================================================================
   S16. TESTIMONIALS
   ========================================================================== */
/* .tst-grid's base 3-up grid is grouped with .why in S8 */
.tst { perspective: 1100px; will-change: transform; }

.tst__card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 30px 28px 26px;
}

/* Oversized decorative quote mark */
.tst__mark {
  position: absolute;
  top: 6px;
  right: 20px;
  font-family: var(--font-head);
  font-size: 110px;
  font-weight: 700;
  line-height: 1;
  color: rgba(200, 16, 46, 0.14);
  pointer-events: none;
  transition: color 0.5s var(--ease);
}
.card-hover:hover .tst__mark { color: rgba(200, 16, 46, 0.3); }

.tst__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 18px;
}

.tst__stars { display: inline-flex; gap: 3px; color: var(--red-light); }
.tst__star {
  width: 15px;
  height: 15px;
  filter: drop-shadow(0 0 6px rgba(200, 16, 46, 0.55));
}

.tst__verified {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px 4px 7px;
  border-radius: 100px;
  background: rgba(200, 16, 46, 0.12);
  border: 1px solid rgba(200, 16, 46, 0.34);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--red-light);
  white-space: nowrap;
}
.tst__verified svg { width: 11px; height: 11px; }

.tst__text {
  flex: 1;
  margin-bottom: 24px;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

.tst__foot {
  display: flex;
  align-items: center;
  gap: 13px;
  padding-top: 20px;
  border-top: 1px solid var(--stroke-soft);
}

/* Initials stand in for a photo — no broken images, always on-brand */
.tst__avatar {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--grad-red);
  border: 1px solid rgba(11, 11, 12, 0.077);
  box-shadow: 0 10px 24px -12px var(--red-glow);
  font-family: var(--font-head);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--on-brand);
}

.tst__who { display: block; min-width: 0; }
.tst__name {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.tst__co {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--ink-soft);
}

/* Logo marquee — the tech strip, slowed and reversed so the two marquees on
   the page never read as the same element. */
.tech-strip--logos .tech-track {
  animation-duration: 38s;
  animation-direction: reverse;
}


/* ==========================================================================
   S17. RESULTS & ACHIEVEMENTS
   ========================================================================== */

/* auto-fit means no breakpoints of its own: 5 across on desktop, then 3, 2, 1 */
.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 22px;
}

.metric { perspective: 1000px; will-change: transform; }

.metric__card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 32px 26px 28px;
}

.metric__value {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(30px, 2.8vw, 42px);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.metric__label {
  margin-top: 13px;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink);
}

/* Glowing progress bar. The track is the ScrollTrigger trigger; the fill is
   sized to its own --val and scaled 0 → 1 by the shared [data-rail] scrub. */
.metric__track {
  position: relative;
  display: block;
  height: 6px;
  margin-top: 26px;
  border-radius: 6px;
  background: rgba(11, 11, 12, 0.044);
  overflow: hidden;
}
.metric__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--val, 100%);
  border-radius: 6px;
  background: var(--grad-red);
  box-shadow: 0 0 14px var(--red-glow);
  transform-origin: left center;
  transform: scaleX(var(--fill, 1));
}


/* ==========================================================================
   S18. FAQ ACCORDION
   ========================================================================== */
.faq {
  display: grid;
  gap: 14px;
  max-width: 920px;
  margin-inline: auto;
}

.faq__item {
  transition:
    border-color 0.45s var(--ease),
    box-shadow 0.45s var(--ease);
}
.faq__item:hover { border-color: rgba(200, 16, 46, 0.34); }
.faq__item.is-open {
  border-color: rgba(200, 16, 46, 0.5);
  box-shadow:
    0 34px 66px -36px rgba(200, 16, 46, 0.55),
    0 0 0 1px rgba(11, 11, 12, 0.022) inset;
}
.faq__item.is-open::before { opacity: 1; }   /* the .surface neon ring */

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  padding: 22px 26px;
  text-align: left;
  font-family: var(--font-head);
  font-size: 16.5px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink);
  transition: color 0.4s var(--ease);
}
.faq__q:hover { color: var(--red-light); }

/* Plus that rotates into a minus as the panel opens */
.faq__icon {
  position: relative;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 50%;
  background: rgba(200, 16, 46, 0.12);
  border: 1px solid rgba(200, 16, 46, 0.4);
  transition:
    transform 0.5s var(--ease),
    background 0.5s var(--ease),
    box-shadow 0.5s var(--ease);
}
.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  border-radius: 2px;
  background: var(--red-light);
  transform: translate(-50%, -50%);
  transition: opacity 0.4s var(--ease), background 0.4s var(--ease);
}
.faq__icon::before { width: 13px; height: 2px; }
.faq__icon::after  { width: 2px; height: 13px; }

.faq__item.is-open .faq__icon {
  transform: rotate(180deg);
  background: var(--grad-red);
  box-shadow: 0 0 20px -4px var(--red-glow);
}
.faq__item.is-open .faq__icon::before { background: var(--on-brand); }
.faq__item.is-open .faq__icon::after  { opacity: 0; }

/* GSAP animates this element's height; it must clip while it does */
.faq__panel { overflow: hidden; }
.faq__panel[hidden] { display: none; }

.faq__a {
  padding: 0 26px 24px;
  max-width: 76ch;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
}

.section--faq .cta--center { margin-top: clamp(60px, 6vw, 96px); }


/* ==========================================================================
   S19. RESPONSIVE — sections 08 → 10
   ========================================================================== */

/* Tablet */
@media (max-width: 1080px) {
  .tst-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Mobile */
@media (max-width: 700px) {
  .tst-grid { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .tst__card { padding: 26px 22px 24px; }
  .tst__mark { font-size: 88px; right: 14px; }

  .metrics { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .metric__card { padding: 26px 22px 24px; }
  .metric__track { margin-top: 20px; }

  .faq__q { padding: 19px 20px; font-size: 15px; gap: 14px; }
  .faq__icon { width: 30px; height: 30px; }
  .faq__a { padding: 0 20px 22px; font-size: 14px; }
}


/* ==========================================================================
   S20. CONTACT — form, detail cards, map
   ========================================================================== */
.ct {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: clamp(24px, 2.6vw, 36px);
}

.ct__main { padding: clamp(26px, 3vw, 40px); }

.ct-form { display: grid; gap: 22px; }
/* `display: grid` outranks the UA's [hidden] rule, so the swap to the success
   panel needs this or the form would stay on screen. */
.ct-form[hidden] { display: none; }
.ct-form__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

/* ---- Field with floating label ---- */
.field { position: relative; }

.field__input {
  width: 100%;
  padding: 23px 16px 9px;
  border-radius: 14px;
  background: rgba(11, 11, 12, 0.022);
  border: 1px solid var(--stroke);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.5;
  appearance: none;
  -webkit-appearance: none;
  transition:
    border-color 0.35s var(--ease),
    background 0.35s var(--ease),
    box-shadow 0.35s var(--ease);
}
.field__input:hover { border-color: rgba(11, 11, 12, 0.099); }

/* Red glow focus. The global :focus-visible outline is left intact on top of
   this, so keyboard focus is never weaker than mouse focus. */
.field__input:focus {
  border-color: rgba(200, 16, 46, 0.65);
  background: rgba(200, 16, 46, 0.07);
  box-shadow:
    0 0 0 3px rgba(200, 16, 46, 0.16),
    0 14px 32px -20px var(--red-glow);
}

.field__input--area {
  min-height: 148px;
  padding-top: 27px;
  resize: vertical;
  line-height: 1.7;
}

/* Native option lists inherit the OS palette, so they need an explicit
   dark background or they render white-on-white on some platforms. */
.field__input option { background: var(--bg-alt); color: var(--ink); }

.field__label {
  position: absolute;
  top: 15px;
  left: 17px;
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-soft);
  pointer-events: none;
  transform-origin: left top;
  transition: transform 0.3s var(--ease), color 0.3s var(--ease);
}
.field__input:focus ~ .field__label,
.field__input:not(:placeholder-shown) ~ .field__label,
.field--select .field__label {
  transform: translateY(-9px) scale(0.78);
  color: var(--red-light);
}

/* Selects always show a value, so their label stays lifted; the chevron is
   drawn here because `appearance: none` removes the native one. */
.field--select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 19px;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--ink-soft);
  border-bottom: 2px solid var(--ink-soft);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
  transition: border-color 0.3s var(--ease);
}
.field--select:focus-within::after { border-color: var(--red-light); }
.field--select .field__input { padding-right: 40px; }

/* ---- Validation states ---- */
.ct-form { --ok: #35C87A; }

.field__error {
  margin-top: 7px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--red-light);
}
.field__error[hidden] { display: none; }

.field.is-invalid .field__input {
  border-color: rgba(224, 25, 53, 0.75);
  background: rgba(224, 25, 53, 0.07);
}
.field.is-invalid .field__label { color: var(--red-light); }
.field.is-valid .field__input { border-color: rgba(53, 200, 122, 0.5); }
.field.is-valid .field__label { color: var(--ok); }

/* ---- Submit button states ---- */
.ct-form__submit { width: 100%; }
.ct-form__submit[disabled] { cursor: progress; opacity: 0.85; }

.btn__spinner {
  display: none;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 2px solid var(--ink-mute);
  border-top-color: var(--ink);
  animation: spin 0.8s linear infinite;
}
.ct-form__submit.is-loading .btn__spinner { display: block; }
.ct-form__submit.is-loading .btn__arrow  { display: none; }

/* ---- Enquiry result + honeypot ----
   The note the PHP handler shows after a submission. Built from tokens the page
   already uses, so it reads as part of the existing form rather than as a new
   component. The honeypot below it is a bot trap and must never be seen or
   focused by a person. */
.ct-note {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 22px;
  padding: 14px 18px;
  border-radius: 16px;
  border: 1px solid var(--stroke-soft);
  background: var(--bg-alt);
  outline: none;
}
.ct-note--ok  { border-color: rgba(53, 200, 122, 0.35); background: rgba(53, 200, 122, 0.08); }
.ct-note--err { border-color: rgba(200, 16, 46, 0.28); background: rgba(200, 16, 46, 0.06); }
.ct-note__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 13px;
  font-weight: 600;
  color: #FFFFFF;
  background: var(--red);
}
.ct-note--ok .ct-note__icon { background: #35C87A; }
.ct-note__text {
  margin: 0;
  font-size: 13.5px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--ink);
}

/* Moved off-screen rather than display:none — a bot that skips hidden inputs
   still fills this one. Never reachable by tab or by a screen reader. */
.ct-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.ct-form__status {
  margin-top: -6px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--red-light);
  min-height: 1em;
}

/* ---- Success panel ---- */
.ct-done {
  display: grid;
  justify-items: center;
  gap: 14px;
  padding: 44px 20px 40px;
  text-align: center;
}
.ct-done[hidden] { display: none; }

.ct-done__check { width: 72px; height: 72px; }
/* pathLength="120" normalises both shapes so the hero's drawLine keyframe
   draws each of them exactly once, end to end. */
.ct-done__ring,
.ct-done__tick {
  fill: none;
  stroke-dasharray: 120;
  stroke-dashoffset: 120;
  animation: drawLine 1.1s var(--ease) forwards;
}
.ct-done__tick { animation-delay: 0.35s; }

.ct-done__title { font-size: 22px; }
.ct-done__text {
  max-width: 42ch;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

/* ---- Detail cards ---- */
.ct__side { display: grid; gap: 16px; }

.ct-card {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 22px 24px;
}
.ct-card__title {
  margin-bottom: 7px;
  font-size: 15px;
  line-height: 1.3;
}
.ct-card__text {
  font-size: 13.5px;
  font-style: normal;   /* <address> defaults to italic */
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}
.ct-card__link {
  position: relative;
  color: var(--ink-soft);
  transition: color 0.35s var(--ease);
}
.ct-card__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--grad-red);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.4s var(--ease);
}
.ct-card__link:hover { color: var(--ink); }
.ct-card__link:hover::after { transform: scaleX(1); transform-origin: left center; }
/* Touch hit area. ::after already draws the hover underline, so this uses
   ::before. The two phone numbers sit on consecutive lines, so the vertical
   reach is kept to 3px: enough to clear 24px, not enough for one number's hit
   area to swallow the other's. */
.ct-card__link::before {
  content: "";
  position: absolute;
  inset: -3px -2px;
}

/* ---- Map ---- */
.ct-map {
  position: relative;
  margin-top: 6px;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--stroke);
  background: rgba(11, 11, 12, 0.017);
}
.ct-map__glow {
  position: absolute;
  inset: -30%;
  background: radial-gradient(circle at 50% 40%, rgba(200, 16, 46, 0.08), transparent 60%);
  filter: blur(40px);
  pointer-events: none;
}
.ct-map__ph { position: absolute; inset: 0; }
.ct-map__art { width: 100%; height: 100%; object-fit: cover; }

.ct-map__cta {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 12px;
  background: var(--card);
}
.ct-map__note {
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
/* Injected on demand — nothing third-party is requested before then */
.ct-map iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

@keyframes spin { to { transform: rotate(360deg); } }


/* ==========================================================================
   S21. FLOATING ACTIONS — WhatsApp + back to top
   ========================================================================== */
.fab {
  position: fixed;
  right: 24px;
  z-index: 250;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  color: var(--ink);
  transition: box-shadow 0.4s var(--ease), background 0.4s var(--ease);
}
.fab__icon { width: 26px; height: 26px; }

.fab__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
}

.fab--wa {
  bottom: 24px;
  background: linear-gradient(150deg, #2BE07A 0%, #25D366 45%, #128C7E 100%);
  box-shadow: 0 14px 34px -12px rgba(37, 211, 102, 0.6);
}
.fab--wa:hover { box-shadow: 0 20px 44px -12px rgba(37, 211, 102, 0.85); }
.fab--wa .fab__ring { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0.55); }

.fab--top {
  bottom: 92px;
  background: var(--glass-strong);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 14px 34px -14px rgba(11, 11, 12, 0.234);
  /* Only opacity/visibility animate here — GSAP owns this element's transform */
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.4s var(--ease),
    visibility 0.4s var(--ease),
    border-color 0.4s var(--ease),
    box-shadow 0.4s var(--ease);
}
.fab--top.is-visible { opacity: 1; visibility: visible; }
.fab--top:hover {
  border-color: rgba(200, 16, 46, 0.6);
  box-shadow: 0 18px 40px -14px var(--red-glow);
}
.fab--top::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(200, 16, 46, 0.35) inset;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.fab--top:hover::after { opacity: 1; }

.fab__tip {
  position: absolute;
  top: 50%;
  right: calc(100% + 14px);
  padding: 8px 14px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 400;
  white-space: nowrap;
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
  transform: translate(8px, -50%);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.fab:hover .fab__tip,
.fab:focus-visible .fab__tip { opacity: 1; transform: translate(0, -50%); }



/* ==========================================================================
   S22. FOOTER
   ========================================================================== */
/* The footer is the one place the black in "black, white and red" gets to be a
   surface rather than a text colour. A solid near-black band closes the page,
   gives the whole layout a base to sit on, and is what most of the difference
   between "clean" and "expensive" actually comes down to. Everything inside it
   flips to the `--on-ink` set. */
.foot {
  position: relative;
  z-index: var(--z-content);
  overflow: hidden;
  padding-block: clamp(64px, 7vw, 100px) 0;
  background: var(--bg-ink);
  color: var(--on-ink);
}

/* A single flat red rule across the top edge — the page's one loud line. */
.foot__divider {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--red);
}

/* Inside the dark band every hairline and every muted text colour has to
   invert, or it disappears. */
.foot .foot__about,
.foot .foot__link,
.foot .foot__bottom,
.foot .foot__soc { color: var(--on-ink-soft); }

.foot .foot__title {
  color: var(--on-ink);
  /* A small red tick above each column heading — cheap, and it stops four
     identical grey lists from reading as a sitemap dump. */
  padding-top: 16px;
  border-top: 2px solid var(--red);
  display: inline-block;
}

.foot .foot__link:hover { color: var(--on-ink); }
.foot .foot__soc {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--stroke-ink);
}
.foot .foot__soc:hover {
  background: var(--red);
  border-color: var(--red);
  color: var(--on-ink);
  box-shadow: none;
}
.foot .foot__bottom { border-top-color: var(--stroke-ink); }

/* The logo plate is a white chip, which is correct on a dark ground — it just
   does not need a red halo behind it any more. */
.foot .foot__logo-plate { box-shadow: none; }
.foot .foot__logo:hover .foot__logo-plate { box-shadow: none; }

.foot__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  gap: clamp(30px, 4vw, 56px);
  padding-bottom: clamp(40px, 4vw, 56px);
}

.foot__logo { display: inline-block; margin-bottom: 20px; }
/* Base recipe is in S6; only the deltas are here. It keeps a separate name from
   the header logo because GSAP owns `.logo__plate` during the hero intro and
   would otherwise reach down here too — and because the header no longer has a
   plate at all, while the footer still does. */
.foot__logo-plate {
  padding: 7px 17px;
  border-radius: 11px;
  box-shadow: 0 12px 30px -14px rgba(200, 16, 46, 0.65);
}
.foot__logo:hover .foot__logo-plate { box-shadow: 0 16px 38px -12px rgba(200, 16, 46, 0.9); }
.foot__logo-plate img { height: 30px; width: auto; object-fit: contain; }

.foot__about {
  max-width: 42ch;
  margin-bottom: 24px;
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
}

.foot__social { display: flex; flex-wrap: wrap; gap: 10px; }
.foot__soc {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: rgba(11, 11, 12, 0.025);
  border: 1px solid var(--stroke);
  color: var(--ink-soft);
  transition:
    transform 0.4s var(--ease),
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    color 0.4s var(--ease),
    box-shadow 0.4s var(--ease);
}
.foot__soc svg { width: 18px; height: 18px; }
.foot__soc:hover {
  transform: translateY(-4px);
  background: rgba(200, 16, 46, 0.14);
  border-color: rgba(200, 16, 46, 0.55);
  color: var(--ink);
  box-shadow: 0 14px 30px -14px var(--red-glow);
}

.foot__title {
  margin-bottom: 20px;
  font-family: var(--font-head);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.foot__list { display: grid; gap: 12px; }

/* Underline grows from the left on hover */
.foot__link {
  position: relative;
  display: inline-block;
  font-size: 13.5px;
  font-weight: 300;
  color: var(--ink-soft);
  transition: color 0.35s var(--ease), transform 0.35s var(--ease);
}
.foot__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1px;
  background: var(--grad-red);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.4s var(--ease);
}
.foot__link:hover { color: var(--ink); transform: translateX(3px); }
.foot__link:hover::after { transform: scaleX(1); transform-origin: left center; }
/* Touch hit area — see the note on .topbar__link. ::after already draws the
   hover underline here, so the overlay uses ::before. Nothing visible changes. */
.foot__link::before {
  content: "";
  position: absolute;
  inset: -3px -4px;
}

.foot__bottom {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block: 24px 28px;
  border-top: 1px solid var(--stroke-soft);
  font-size: 12.5px;
  font-weight: 300;
  color: var(--ink-soft);
}
.foot__heart { display: inline-block; animation: bloomPulse 2.4s ease-in-out infinite; }


/* ==========================================================================
   S23. RESPONSIVE — contact, floating actions, footer
   ========================================================================== */

/* Tablet */
@media (max-width: 1080px) {
  .ct { grid-template-columns: minmax(0, 1fr); }
  .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot__col--brand { grid-column: 1 / -1; }
}

/* Mobile */
@media (max-width: 700px) {
  .ct-form__row { grid-template-columns: minmax(0, 1fr); }
  .ct__main { padding: 24px 20px; }
  .ct-card { padding: 20px; gap: 14px; }
  .ct-map { aspect-ratio: 4 / 3; }

  .fab { right: 16px; width: 52px; height: 52px; }
  .fab--wa { bottom: 16px; }
  .fab--top { bottom: 80px; }
  .fab__icon { width: 23px; height: 23px; }
  /* Tooltips would sit under the thumb on a phone */
  .fab__tip { display: none; }

  .foot__grid { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .foot__bottom { justify-content: flex-start; }
}


/* ==========================================================================
   12. RESPONSIVE
   ========================================================================== */

/* Laptop */
@media (max-width: 1280px) {
  :root { --gutter: 32px; }
  .nav__link { padding: 9px 13px; font-size: 13.5px; }

  .nav__list { gap: 3px; }
  /* Four columns here leaves the longer service names wrapping onto a second
     line, which makes one row of the grid taller than the rest. */
  .mega__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Small laptop — nav collapses to the overlay menu.
   Raised from 1080px as the bar grew: "Packages" made it seven items and
   "Portfolio" eight. Logo + an eight-item pill + the consultation button need
   1200px to sit at their designed gutter, and below that the button starts
   eating into it. Collapsing earlier keeps the bar identical wherever it is
   shown instead of compressing its spacing on small laptops.
   script.js's resize guard tracks this number. */
@media (max-width: 1199px) {
  .nav { display: none; }
  .burger { display: block; }
}

/* Tablet — stack the layout */
@media (max-width: 900px) {
  :root { --header-h: 78px; --header-h-sm: 64px; --topbar-h: 34px; }

  .header__actions .btn--primary { display: none; }

  /* The strip stays, tightened: smaller type, less gap, and the separator goes
     so the phone and email keep their breathing room. */
  .topbar__inner { gap: 12px; }
  .topbar__contact { gap: 12px; }
  .topbar__link { font-size: 12px; gap: 6px; }
  .topbar__icon { width: 14px; height: 14px; }
  .topbar__sep { display: none; }
  .topbar__soc { width: 24px; height: 24px; }
  .topbar__soc svg { width: 15px; height: 15px; }

  /* Stacked hero: the copy now runs the full width instead of hugging the left,
     so the left-weighted gutter is swapped for an even vertical one — heavy
     behind the headline up top, lighter over the composition below. */
  .hero__scrim {
    background:
      linear-gradient(180deg,
        rgba(255, 255, 255, 0.86) 0%,
        rgba(255, 255, 255, 0.8) 38%,
        rgba(255, 255, 255, 0.55) 66%,
        rgba(255, 255, 255, 0.92) 100%);
  }

  .hero { padding-top: calc(var(--header-h) + 12px); padding-bottom: 80px; }
  .hero__inner {
    grid-template-columns: 1fr;
    gap: 0;
    text-align: center;
  }
  /* Tighter vertical rhythm so the composition still reads above the fold */
  .hero__left { max-width: 700px; margin-inline: auto; order: 1; padding-block: 16px; }
  .hero__title { margin-bottom: 18px; }
  .hero__sub { margin-bottom: 26px; }
  .hero__cta { margin-bottom: 26px; }
  .trust { padding-top: 18px; }
  .hero__sub { margin-inline: auto; }
  .hero__cta, .trust { justify-content: center; }
}

/* Mobile */
@media (max-width: 620px) {
  :root { --gutter: 20px; }

  /* Wordmark only — the tagline would crowd the burger on small screens */
  .logo__plate { padding: 6px 14px; border-radius: 10px; }
  .logo__img { height: 26px; }
  .logo__tagline { display: none; }

  .hero { padding-bottom: 110px; }
  .hero__title { font-size: clamp(30px, 8.6vw, 44px); }
  .hero__sub { font-size: 14.5px; line-height: 1.75; }
  .hero__cta { flex-direction: column; align-items: stretch; gap: 12px; }
  .btn { width: 100%; padding: 16px 26px; }

  .trust { gap: 10px 16px; }
  .trust__item { font-size: 12.5px; }

  .scroll-cue { bottom: 18px; }

  /* Phone: the email address is far too long to sit next to a phone number and
     three icons at 390px, so it collapses to its envelope. The link, the
     mailto: and the aria-label are all unchanged — only the text is dropped. */
  .topbar__email-text { display: none; }
  .topbar__link--email { padding: 2px; }
  .topbar__link--email .topbar__icon { width: 16px; height: 16px; }
}

/* Short screens (landscape phones) */
@media (max-height: 680px) and (max-width: 900px) {
  .hero { min-height: auto; padding-bottom: 70px; }
  .scroll-cue { display: none; }
}


/* ==========================================================================
   13. REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .bg__particles { display: none; }
}


/* ==========================================================================
   14. SERVICE DETAIL PAGES  (service-*.html)
   --------------------------------------------------------------------------
   Seven standalone pages, one per row of the AI & Tech index, reached from the
   "Learn More" button on each row. They reuse the whole shell — background
   stack, header, mobile nav, footer, FABs, `.section`, `.surface`, `.btn`,
   `.tech-chip` — so only the page-specific pieces live here, prefixed `svcp-`.

   No `[data-anim]` anywhere on these pages: the intro timeline in script.js
   pre-hides that attribute and only reveals the hero elements it knows about,
   so a `data-anim` node on a page without a hero would stay at opacity 0
   forever. `[data-reveal-group]`/`[data-reveal]` is the attribute to use — it
   is generic and ScrollTrigger-driven.
   ========================================================================== */

/* ==========================================================================
   SERVICE PAGE HERO  (.svch)
   --------------------------------------------------------------------------
   Replaces the old two-column hero (title + "At a glance" fact panel).

   This started as a full-bleed video hero with the headline set in HTML over a
   white scrim. All thirteen service pages now have finished banner artwork
   instead, so the only hero in use is `.svch--banner` further down: the artwork
   already contains the eyebrow, headline, sub-line and chips, and the HTML copy
   is hidden on desktop so the page never says the same thing twice.

   The video hero's own pieces — `.svch__bg`, `.svch__video`, `.svch__scrim`,
   `.svch__cue*` and the svchBob/svchWheel keyframes — were removed with it. The
   clips are still in assets/videos and services.html still plays four of them
   in its service cards; nothing here referenced those.
   ========================================================================== */
.svch {
  position: relative;
  z-index: var(--z-content);
  overflow: hidden;
}

.svch__inner {
  position: relative;
  z-index: 2;
  max-width: min(var(--container), 1080px);
}

/* Breadcrumb (kept from the old hero — it is how you get back to the index) */
.svch__crumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 30px;
  font-size: 12.5px;
  font-weight: 300;
  color: var(--ink-soft);
}
.svch__crumb a { color: var(--ink-soft); transition: color 0.35s var(--ease); }
.svch__crumb a:hover { color: var(--red); }
.svch__crumb span[aria-current] { color: var(--ink); }
.svch__crumb i { font-style: normal; color: rgba(11, 11, 12, 0.22); }

.svch__eyebrow {
  display: inline-block;
  margin-bottom: 20px;
  padding: 7px 16px;
  border-radius: 100px;
  background: rgba(200, 16, 46, 0.08);
  border: 1px solid rgba(200, 16, 46, 0.28);
  font-family: var(--font-head);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--red);
}

/* The luxury type moment of the page. Space Grotesk at display size with the
   tracking pulled in — a bigger, tighter cut of the same family the rest of
   the site already uses, rather than a new font that would read as a
   different brand. */
.svch__title {
  max-width: 15ch;
  margin-bottom: 24px;
  font-size: clamp(40px, 6.4vw, 84px);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.045em;
  text-wrap: balance;
  /* Depth, not glow: one tight highlight and one long soft shadow. */
  text-shadow:
    0 1px 0 rgba(255, 255, 255, 0.6),
    0 18px 40px rgba(11, 11, 12, 0.1);
}

.svch__line {
  max-width: 30ch;
  margin-bottom: 16px;
  font-family: var(--font-head);
  font-size: clamp(17px, 1.75vw, 25px);
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-wrap: balance;
}

.svch__sub {
  max-width: 54ch;
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

.svch__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 38px;
}

/* WhatsApp glyph inside an inquiry button */
.btn__wa {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
}

/* ==========================================================================
   BANNER HERO  (.svch--banner)
   --------------------------------------------------------------------------
   Used by the service pages that have finished banner artwork. The banner is a
   complete hero design — it carries the eyebrow, the headline, the sub-line and
   the feature chips as part of the image — so it is shown whole and uncropped,
   and the page does NOT print the same words over the top of it.

   `object-fit: cover` is deliberately not used here. Cover would crop the sides
   on a narrow screen, and the sides are where the headline is.
   ========================================================================== */
.svch--banner {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Close to a full first screen, so the banner is what the visitor lands on
     rather than something floating in the middle of a tall empty section. */
  min-height: 100svh;
  /* Tight top gap: the banner is the hero, so it starts right under the header
     rather than sitting in the middle of a tall empty band. */
  padding-top: calc(var(--header-top) + clamp(8px, 0.9vw, 16px));
  padding-bottom: clamp(24px, 3vw, 44px);
}

.svch--banner .svch__inner {
  max-width: none;   /* the banner sets its own width; the container does not cap it */
  width: 100%;
  text-align: center;
}

/* Full-bleed gutter for the hero only. `.container`'s own 40px-a-side reading
   gutter was the second thing capping the banner — at 1440px it left 1360px of
   room, so even an unrestricted banner could not reach 96vw. Narrowed on desktop
   only: below 901px the copy comes back underneath the banner and needs the
   normal page gutter, so the phone and small-tablet layout is left alone. */
@media (min-width: 901px) {
  .svch--banner .svch__inner {
    padding-left: clamp(16px, 2vw, 32px);
    padding-right: clamp(16px, 2vw, 32px);
  }
}
.svch--banner .svch__actions { justify-content: center; margin-top: clamp(22px, 2.6vw, 34px); }

.svch__banner {
  /* The hero is driven by viewport WIDTH alone.

     There used to be a third, height-derived limit here
       calc((100svh - var(--header-top) - 16px) * var(--banner-ratio))
     so the banner would always fit inside one screen. That term is why this was
     reported as a "small centred card": a maximised browser reports a viewport
     around 740px tall, not the 900px a test harness defaults to, and at 1440x740
     the height term resolved to 1057px — 73vw — winning over 96vw every time.
     On a 1366x625 laptop it fell to 62vw.

     The banner is the page's hero, so it now takes the width it is given and is
     allowed to run past the fold on a short screen. Nothing is cropped: the
     image is width:100%/height:auto inside this box, so the complete artwork —
     headline, sub-line and feature chips — stays visible, just further down.

     The cap is a little above the artwork's own 1672px so a wide monitor still
     gets a full-bleed hero without upscaling the file into softness. */
  width: 100%;
  max-width: 1760px;
  margin: 0 auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  /* No outline. A 1px frame around a full-width hero is what reads as a card;
     the soft drop shadow alone is enough to lift it off the page. */
  box-shadow: 0 40px 80px -48px rgba(11, 11, 12, 0.28);
  background: var(--bg-alt);
}
.svch__banner img {
  display: block;
  width: 100%;
  height: auto;
}

/* Desktop: the artwork is already saying this, so the copy is taken out of the
   visual layer only — never `display: none`, which would drop the <h1> out of
   the accessibility tree and weaken the page for search. */
@media (min-width: 901px) {
  .svch--banner .svch__copy {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* Phone and small tablet: the banner is still shown, but its built-in type was
   drawn for a 1672px canvas and is unreadable at 390px — so the real copy comes
   back underneath it. The hero stops being a full screen here, because banner +
   heading + description + two buttons is taller than one. */
@media (max-width: 900px) {
  .svch--banner {
    display: block;
    min-height: 0;
    padding-top: calc(var(--header-top) + 20px);
  }
  .svch--banner .svch__inner { text-align: left; }
  .svch--banner .svch__actions { justify-content: flex-start; }
  .svch--banner .svch__copy { margin-top: clamp(26px, 4vw, 38px); }
  .svch--banner .svch__title { max-width: none; }
  .svch--banner .svch__line { max-width: none; }
  .svch__banner { width: 100%; }
}

/* ==========================================================================
   MULTI-PAGE SHELL  (.pg-*)
   --------------------------------------------------------------------------
   The site is now a real multi-page site rather than one long index.html, so a
   few pieces exist that a single page never needed: a banner at the top of each
   inner page (it has to clear the fixed header, which `.section`'s symmetric
   padding does not), a breadcrumb, and the "view all" link under a home page
   preview grid. Everything else on these pages is the components that were
   already here.
   ========================================================================== */
.pg-hero {
  padding-top: calc(var(--header-top) + clamp(26px, 3vw, 50px));
  padding-bottom: clamp(30px, 3.5vw, 54px);
}
.pg-hero::before { display: none; }   /* no divider above the first section */
.pg-hero::after  { display: none; }

.pg-hero__head { margin-bottom: 0; }

.pg-hero__crumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-bottom: 26px;
  font-size: 12.5px;
  font-weight: 300;
  color: var(--ink-soft);
}
.pg-hero__crumb a { position: relative; color: var(--ink-soft); transition: color 0.35s var(--ease); }
.pg-hero__crumb a:hover { color: var(--red); }
/* Touch hit area — see the note on .topbar__link. Breadcrumb links render about
   37x20; the gap between them is 10px, so a 4px overlay still leaves 2px
   between neighbours. Nothing visible changes. */
.pg-hero__crumb a::after {
  content: "";
  position: absolute;
  inset: -4px -3px;
}
.pg-hero__crumb span[aria-current] { color: var(--ink); }
.pg-hero__crumb i { font-style: normal; color: rgba(11, 11, 12, 0.22); }

/* "View all services / packages" under a home page preview grid */
.pg-more {
  display: flex;
  justify-content: center;
  margin-top: clamp(38px, 4vw, 58px);
}

/* ---- Section kicker above each heading ---- */
.svcp-kicker {
  margin-bottom: 14px;
  font-family: var(--font-head);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--red);
}

/* ---- Overview prose ---- */
/* `.section__head` centres its text, which is right for a two-line subtitle and
   wrong for two full paragraphs — centred rag makes every line start in a new
   place. Same measure, left aligned. */
.svcp-overview {
  max-width: 820px;
  margin: 0 auto;
  text-align: left;
}
.svcp-overview p + p { margin-top: 20px; }

/* ---- What we build — 3-up card grid ---- */
.svcp-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.svcp-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  padding: 32px 28px;
  transition: transform 0.55s var(--ease), border-color 0.55s var(--ease);
}
.svcp-card:hover { transform: translateY(-6px); border-color: rgba(200, 16, 46, 0.4); }
.svcp-card:hover::before { opacity: 0.55; }
.svcp-card__title {
  margin: 20px 0 11px;
  font-size: 17.5px;
  line-height: 1.3;
}
.svcp-card__text {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* ---- "How it helps your business" — benefit cards ---- */
.svcp-benefits {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 22px;
}
.svcp-benefit {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  padding: 34px 28px 30px;
  perspective: 1000px;   /* [data-tilt] rotates the card itself */
}
.svcp-benefit .icon-plate { margin-bottom: 22px; }
.svcp-benefit__title {
  margin-bottom: 11px;
  font-size: 17.5px;
  line-height: 1.3;
}
.svcp-benefit__text {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* ---- Why RinceTech — icon + copy rows ---- */
.svcp-why {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px 34px;
  max-width: 1100px;
  margin-inline: auto;
}
.svcp-why__item {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  padding: 22px 22px 22px 20px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  border-left: 2px solid rgba(200, 16, 46, 0.32);
  transition: border-color 0.45s var(--ease), background 0.45s var(--ease);
}
.svcp-why__item:hover {
  background: rgba(200, 16, 46, 0.035);
  border-left-color: var(--red);
}
.svcp-why__title {
  margin-bottom: 8px;
  font-size: 16.5px;
  line-height: 1.3;
}
.svcp-why__text {
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--ink-soft);
}

/* ---- Closing "Ready to grow" panel ---- */
.svcp-final {
  padding: clamp(44px, 5.5vw, 82px) clamp(28px, 4vw, 64px);
  text-align: center;
  background: var(--bg-alt);
  border-left: 3px solid var(--red);
}
.svcp-final__title {
  margin-bottom: 16px;
  font-size: clamp(28px, 3.6vw, 52px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.svcp-final__text {
  max-width: 52ch;
  margin: 0 auto;
  font-size: clamp(14.5px, 1.1vw, 17px);
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}
.svcp-final__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin-top: 34px;
}

/* ---- Our process — numbered steps ---- */
.svcp-steps {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 18px;
}
.svcp-step {
  position: relative;
  padding: 28px 24px;
  border-radius: var(--radius);
  background: rgba(11, 11, 12, 0.017);
  border: 1px solid var(--stroke-soft);
  transition: border-color 0.5s var(--ease), background 0.5s var(--ease);
}
.svcp-step:hover {
  border-color: rgba(200, 16, 46, 0.36);
  background: rgba(200, 16, 46, 0.05);
}
/* The step number is back, because the process section is now five ordered
   stages a client reads as a sequence — and on tablet and mobile they stop
   sitting in one left-to-right row, so the order stops being implied. */
.svcp-step__num {
  display: block;
  margin-bottom: 12px;
  font-family: var(--font-head);
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: rgba(200, 16, 46, 0.34);
  transition: color 0.5s var(--ease);
}
.svcp-step:hover .svcp-step__num { color: var(--red); }

.svcp-step__title {
  margin-bottom: 10px;
  font-size: 16px;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.svcp-step__text {
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.72;
  color: var(--ink-soft);
}

/* ---- Stack chips ---- */
/* The home page runs these as an infinite marquee; a detail page has a fixed,
   readable list, so they simply wrap. */
.svcp-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

/* `.svcp-cta*` (the old left-aligned closing panel) and `.svcp-crumb` were
   removed with the hero rebuild — the closing panel is now `.svcp-final` and
   the breadcrumb moved into the hero as `.svch__crumb`. */

/* ---- Other services strip ---- */
.svcp-more {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}
.svcp-more__link {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-radius: var(--radius);
  background: rgba(11, 11, 12, 0.017);
  border: 1px solid var(--stroke-soft);
  font-family: var(--font-head);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
  transition:
    border-color 0.45s var(--ease),
    background 0.45s var(--ease),
    color 0.45s var(--ease),
    transform 0.45s var(--ease);
}
.svcp-more__link:hover {
  border-color: rgba(200, 16, 46, 0.42);
  background: rgba(200, 16, 46, 0.06);
  color: var(--ink);
  transform: translateX(5px);
}
/* `.svcp-more__num` was the "01".."07" prefix on each link. Gone with the rest;
   the service name is the label, the number never was. */
.svcp-more__arrow {
  margin-left: auto;
  color: var(--ink-soft);
  transition: transform 0.45s var(--ease), color 0.45s var(--ease);
}
.svcp-more__link:hover .svcp-more__arrow { transform: translateX(4px); color: var(--red-light); }


/* ---- Responsive ---- */
@media (max-width: 1080px) {
  .svcp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svcp-benefits { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svcp-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .svcp-why { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svcp-more { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* The hero copy takes the full measure once the viewport narrows. */
  .svch__title { max-width: 18ch; }
  .svch__line  { max-width: 42ch; }
}

@media (max-width: 700px) {
  .svcp-cards,
  .svcp-benefits,
  .svcp-steps,
  .svcp-why,
  .svcp-more { grid-template-columns: minmax(0, 1fr); }

  .svch { padding-top: calc(var(--header-top) + 22px); }
  .svch__title { max-width: none; font-size: clamp(34px, 10.5vw, 48px); }
  .svch__line  { max-width: none; }
  .svch__crumb { margin-bottom: 22px; }
  .svch__actions { margin-top: 30px; }
  .svch__actions .btn { width: 100%; }

  .svcp-final__actions { flex-direction: column; align-items: stretch; }
  .svcp-final__actions .btn { width: 100%; }
}
