/* ============================================================
   STACKVEL SOLUTIONS — MAIN STYLESHEET
   Design System: Blue + White Corporate Technology
   Tokens · Base · Layout · Components
   ============================================================ */

/* ============================================================
   1. DESIGN TOKENS
   ============================================================ */
:root {
  /* --- Brand blue --- sampled from the Stackvel mark itself.
     #0B5FD0 is the saturated face of the logo glyph; #4383E5 is its
     lit face; #283C78 is the shadowed facet that ties into the navy. */
  --c-primary:        #0B5FD0;
  --c-primary-dark:   #0A4EAD;
  --c-primary-darker: #093C85;
  --c-primary-light:  #4383E5;
  --c-primary-soft:   #DBE8FA;
  --c-primary-tint:   #EEF4FD;
  --c-primary-glow:   rgba(11, 95, 208, 0.22);
  --c-primary-subtle: rgba(11, 95, 208, 0.07);

  /* Secondary accent — the logo's lighter blue face. Deliberately not a
     cyan or teal: nothing outside the mark's own blues is introduced. */
  --c-sky:            #4383E5;
  --c-sky-light:      #7BA9EE;
  --c-sky-soft:       #E6EEFB;

  /* --c-primary-light reads at only 4.26:1 against the navy band, which
     is under AA for text below 24px. This is the same hue lifted until
     it clears, for accent copy sitting on the dark stage. */
  --c-accent-on-dark: #5D94E9;

  /* --- Navy scale --- built around #17295B, the wordmark's own navy,
     so dark bands read as the same family as the logotype. */
  --c-navy-deepest:   #0A1330;
  --c-navy-deep:      #0F1C41;
  --c-navy:           #17295B;
  --c-navy-mid:       #283C78;
  --c-navy-light:     #3B5391;

  /* --- Neutral / surface scale --- */
  --c-white:          #FFFFFF;
  --c-surface:        #FFFFFF;
  --c-surface-soft:   #F7F9FC;
  --c-surface-muted:  #EEF2F7;
  --c-surface-sunken: #E7ECF3;
  --c-off-white:      #F8FAFC;
  --c-light-blue:     #F0F7FF;

  /* --- Text --- */
  --c-heading:        #101E43;
  --c-text:           #46536A;
  --c-text-strong:    #1B2C55;
  --c-text-soft:      #5D6B80;
  /* Was #7C8AA0. Measured 3.50:1 on white and 3.17:1 on the process
     section's tint — both under the 4.5:1 that WCAG AA asks of text
     this size. Darkened with the hue and saturation held. The two
     places it was used on the navy footer are switched to
     --c-text-on-dark-2 below, because darkening it there would have
     taken 4.75:1 down to 3.32:1. */
  --c-text-muted:     #627087;
  --c-text-on-dark:   #E9EFF7;
  --c-text-on-dark-2: #A7B9D2;

  /* Legacy aliases — existing markup references these.
     Remapped to the light system so inline styles keep working. */
  --c-text-primary:   var(--c-heading);
  --c-text-secondary: var(--c-text);
  --c-text-dark:      var(--c-heading);
  --c-blue-gray:      var(--c-text-soft);
  --c-blue-gray-light:var(--c-text);
  --c-slate:          var(--c-text);
  --c-navy-dark:      var(--c-navy-deep);
  --c-navy-darkest:   var(--c-navy-deepest);

  /* --- Borders --- */
  --c-border:         #E4E9F0;
  --c-border-soft:    #EEF1F6;
  --c-border-strong:  #CBD5E3;
  --c-border-accent:  rgba(11, 95, 208, 0.28);
  --c-border-glow:    rgba(11, 95, 208, 0.35);
  --c-border-on-dark: rgba(255, 255, 255, 0.12);

  /* --- Status --- */
  --c-success:        #0E9F6E;
  --c-success-soft:   #E3F6EF;
  --c-warning:        #D97706;
  /* review stars: amber reads as a rating at a glance, and this
     one still sits with the navy rather than fighting it */
  --c-star:           #F2A83B;
  --c-danger:         #DC2626;

  /* --- Typography --- */
  /* Plus Jakarta Sans stands in for Google Sans Display: same geometric
     humanist construction, and it is actually available to load. Headings
     sit at 500-600 rather than 700-800 — the weight restraint is what
     makes the type read as considered instead of loud. */
  --font-display: 'Plus Jakarta Sans', 'Segoe UI', system-ui, sans-serif;
  --font-body:    'Inter', 'Segoe UI', system-ui, sans-serif;
  --font-mono:    ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-md:   1rem;       /* alias used by some inline styles */
  --text-lg:   1.125rem;
  --text-xl:   1.25rem;
  --text-2xl:  1.5rem;
  --text-3xl:  1.875rem;
  --text-4xl:  2.25rem;
  --text-5xl:  3rem;
  --text-6xl:  3.75rem;
  --text-7xl:  4.5rem;

  --leading-tight:  1.2;
  --leading-snug:   1.35;
  --leading-normal: 1.6;
  --leading-relaxed:1.75;

  /* --- Spacing --- */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-7:  1.75rem;
  --space-8:  2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* --- Border Radius (restrained, editorial) --- */
  --radius-xs: 3px;
  --radius-sm: 5px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 22px;
  --radius-full: 9999px;

  /* --- Shadows (neutral, quiet) --- */
  --shadow-xs:   0 1px 2px rgba(12, 27, 46, 0.05);
  --shadow-sm:   0 1px 3px rgba(12, 27, 46, 0.06), 0 1px 2px rgba(12, 27, 46, 0.04);
  --shadow-md:   0 4px 14px rgba(12, 27, 46, 0.07), 0 1px 3px rgba(12, 27, 46, 0.04);
  --shadow-lg:   0 12px 32px rgba(12, 27, 46, 0.09), 0 2px 8px rgba(12, 27, 46, 0.04);
  --shadow-xl:   0 24px 60px rgba(12, 27, 46, 0.12), 0 4px 14px rgba(12, 27, 46, 0.05);
  --shadow-card: 0 1px 2px rgba(12, 27, 46, 0.05);
  --shadow-card-hover: 0 16px 40px rgba(12, 27, 46, 0.11), 0 3px 10px rgba(12, 27, 46, 0.06);
  --shadow-blue: 0 8px 24px rgba(11, 95, 208, 0.20);
  --shadow-blue-lg: 0 14px 36px rgba(11, 95, 208, 0.26);
  --shadow-glow:    var(--shadow-blue);
  --shadow-glow-lg: var(--shadow-blue-lg);

  /* --- Transitions --- */
  --ease-std:    cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in:     cubic-bezier(0.4, 0, 1, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);

  --duration-fast: 180ms;
  --duration-std:  260ms;
  --duration-slow: 420ms;
  --duration-page: 600ms;

  --transition-fast: var(--duration-fast) var(--ease-std);
  --transition-std:  var(--duration-std)  var(--ease-std);
  --transition-slow: var(--duration-slow) var(--ease-std);

  /* --- Layout --- */
  /* The page used to sit in a 1240px column, which left ~100px of dead
     margin either side of a 1440 screen before the container's own padding
     even started. The layout now runs close to the viewport edge and the
     gutter scales with it. */
  --container-max: 1560px;
  --gutter:        clamp(1.25rem, 3vw, 2.75rem);
  --container-lg:  1024px;
  --container-md:  768px;

  --header-height: 76px;
  --header-height-scrolled: 64px;

  /* Vertical rhythm — sections breathe at different depths */
  --sec-pad:      clamp(4rem, 7.5vw, 6.5rem);
  --sec-pad-sm:   clamp(3rem, 6vw, 4.5rem);
  --sec-pad-lg:   clamp(6rem, 11vw, 9.5rem);

  /* --- Z-Index --- */
  --z-below:   -1;
  --z-base:     0;
  --z-raised:   10;
  --z-dropdown: 100;
  --z-sticky:   200;
  --z-header:   300;
  --z-modal:    400;
  --z-toast:    500;
}

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

html {
  font-size: 16px;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-height) + var(--space-4));
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--c-text);
  background-color: var(--c-white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, video, svg, canvas {
  display: block;
  max-width: 100%;
}

img { height: auto; }

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; }

button {
  cursor: pointer;
  font-family: inherit;
  border: none;
  background: none;
  color: inherit;
}

input, textarea, select {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--c-heading);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;

  /* Plus Jakarta Sans draws a narrow word space to begin with — about
     0.10em against Inter's 0.18em — and the negative tracking above
     takes more off it. Measured across the headings on the home page
     the result was 0.147em, roughly half the space in the body copy
     underneath, and "From idea to impact" read as "Fromidea toimpact".

     This puts it back to a little over 0.2em, which is normal. It is
     word-spacing rather than less tracking because the tight tracking
     is what the headings are meant to look like; it is only the space
     between words that was collateral. */
  word-spacing: 0.055em;
}

/* The two display-font elements that are not headings */
.hero__lead-in,
.platform-card__name { word-spacing: 0.055em; }

/* Headings wrap on their own — template line breaks were removed from the
   markup rather than hidden here, which used to weld words together. */

strong, b { color: var(--c-text-strong); font-weight: 600; }

::selection { background: var(--c-primary); color: #fff; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--c-surface-soft); }
::-webkit-scrollbar-thumb {
  background: var(--c-border-strong);
  border-radius: var(--radius-full);
  border: 3px solid var(--c-surface-soft);
}
::-webkit-scrollbar-thumb:hover { background: #A9C2DE; }

/* Accent spans inside headings are a quiet solid blue — gradients
   read as template decoration, so this class is intentionally flat. */
.text-gradient {
  color: var(--c-primary);
  -webkit-text-fill-color: currentColor;
}

/* On dark surfaces the accent flips light so it stays legible */
.on-dark .text-gradient,
.cta-panel .text-gradient,
.site-footer .text-gradient {
  color: var(--c-sky-light);
  -webkit-text-fill-color: currentColor;
}

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

.section { padding-block: var(--sec-pad); position: relative; }

.grid { display: grid; }

.flex { display: flex; }
.relative { position: relative; }

/* ============================================================
   5. HEADER / NAVIGATION
   ============================================================ */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: calc(var(--z-header) + 10);
  height: var(--header-height);
  background-color: var(--c-white);
  border-bottom: 1px solid transparent;
  transition: background-color var(--transition-std),
              box-shadow var(--transition-std),
              border-color var(--transition-std);
}

/* At the very top of a page the header sits flush on white */
.site-header.is-transparent {
  background-color: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: none;
  border-bottom-color: transparent;
}

.site-header.is-scrolled {
  background-color: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  box-shadow: 0 1px 0 var(--c-border), 0 6px 24px rgba(10, 37, 64, 0.07);
  border-bottom-color: var(--c-border-soft);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  gap: var(--space-4);
}

/* --- Logo ---------------------------------------------------
   The wordmark is the real Stackvel asset, not a redrawn letter.
   It is sized by height only so the supplied aspect ratio is never
   touched, and the explicit width/height attributes in the markup
   reserve the box so the header does not shift while it loads.
   ----------------------------------------------------------- */
.site-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
  /* Optical trim: the supplied PNG carries a little air on its left
     edge, so the glyph aligns with the container rather than the file. */
  margin-left: -2px;
}

.site-logo__img {
  display: block;
  height: 42px;
  width: auto;
  max-width: none;
  transition: opacity var(--transition-std);
}

.site-logo:hover .site-logo__img { opacity: 0.82; }

.site-logo:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 4px;
  border-radius: var(--radius-xs);
}

/* Footer sits on navy, so it uses the light lock-up. */
.site-footer .site-logo__img { height: 44px; }

/* --- Primary nav --- */
.primary-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.nav-item { position: relative; }

.nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--c-text-strong);
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast);
  white-space: nowrap;
  position: relative;
}

/* Animated underline */
.nav-link::after {
  content: '';
  position: absolute;
  left: var(--space-3);
  right: var(--space-3);
  bottom: 2px;
  height: 2px;
  border-radius: 2px;
  background: var(--c-primary);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--transition-std);
}

.nav-link:hover,
.nav-item:hover > .nav-link { color: var(--c-primary); }

.nav-link:hover::after,
.nav-item:hover > .nav-link::after { transform: scaleX(1); }

.nav-link.is-active {
  color: var(--c-primary);
  font-weight: 600;
}

.nav-link.is-active::after { transform: scaleX(1); }

.nav-link svg {
  width: 12px;
  height: 12px;
  transition: transform var(--transition-fast);
  opacity: 0.65;
}

.nav-item:hover .nav-link svg { transform: rotate(180deg); opacity: 1; }

/* --- Dropdown --- */
.nav-dropdown {
  position: absolute;
  top: calc(100% + var(--space-3));
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  min-width: 250px;
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-std), transform var(--transition-std);
  z-index: var(--z-dropdown);
}

/* Hover bridge so the pointer can travel into the panel */
.nav-dropdown::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--space-3) * -1);
  height: var(--space-3);
}

.nav-item:hover .nav-dropdown,
.nav-item:focus-within .nav-dropdown {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

.nav-dropdown__item a {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--c-text-strong);
  transition: background-color var(--transition-fast), color var(--transition-fast), transform var(--transition-fast);
}

.nav-dropdown__item a:hover {
  color: var(--c-primary);
  background-color: var(--c-primary-tint);
  transform: translateX(2px);
}

.nav-dropdown__item--icon {
  width: 32px;
  height: 32px;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-soft);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.nav-dropdown__item a:hover .nav-dropdown__item--icon {
  background: var(--c-primary-soft);
  border-color: var(--c-border-accent);
}

.nav-dropdown__item--icon svg {
  width: 15px;
  height: 15px;
  color: var(--c-primary);
}

/* Mega dropdown (Services) */
.nav-dropdown--mega {
  width: 620px;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 2px var(--space-2);
  padding: var(--space-3);
}

.nav-item:hover .nav-dropdown--mega,
.nav-item:focus-within .nav-dropdown--mega,
.nav-dropdown--mega.is-open,
.nav-item:hover .nav-dropdown--columns,
.nav-item:focus-within .nav-dropdown--columns,
.nav-dropdown--columns.is-open { transform: translateX(-50%) translateY(0); }

.nav-dropdown.is-open { opacity: 1; pointer-events: auto; }

.nav-dropdown.is-dismissed,
.nav-item:hover .nav-dropdown.is-dismissed,
.nav-item:focus-within .nav-dropdown.is-dismissed {
  opacity: 0;
  pointer-events: none;
}

/* Footer row of a dropdown — spans both columns */
.nav-dropdown__all {
  grid-column: 1 / -1;
  margin-top: var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--c-border-soft);
}

.nav-dropdown__all a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  transition: gap var(--transition-fast), background-color var(--transition-fast);
}

.nav-dropdown__all a svg { width: 14px; height: 14px; }
.nav-dropdown__all a:hover { gap: var(--space-3); background-color: var(--c-primary-tint); }

/* --- Header CTA --- */
.header-cta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

/* --- Hamburger --- */
.hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 42px;
  height: 42px;
  gap: 5px;
  background: none;
  border: 1px solid var(--c-border);
  cursor: pointer;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
  z-index: calc(var(--z-header) + 10);
  color: inherit;
}

.hamburger:hover {
  background-color: var(--c-primary-tint);
  border-color: var(--c-border-accent);
}

.hamburger__line {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--c-heading);
  border-radius: 2px;
  transition: transform var(--transition-std), opacity var(--transition-fast),
              background-color var(--transition-std);
  transform-origin: center;
}

.hamburger.is-open .hamburger__line:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger.is-open .hamburger__line:nth-child(2) { opacity: 0; transform: scaleX(0); }
.hamburger.is-open .hamburger__line:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* --- Mobile menu --- */
.mobile-menu {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--c-white);
  z-index: calc(var(--z-header) + 5);
  padding: calc(var(--header-height) + var(--space-6)) var(--space-6) var(--space-6);
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(100%);
  transition: transform var(--transition-slow);
}

.mobile-menu.is-open { transform: translateX(0); }

.mobile-menu__nav { flex: 1; }

.mobile-nav-link {
  display: block;
  padding: var(--space-4) 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--c-navy);
  border-bottom: 1px solid var(--c-border);
  transition: color var(--transition-fast), padding-left var(--transition-fast);
}

.mobile-nav-link:hover,
.mobile-nav-link.is-active { color: var(--c-primary); }

.mobile-nav-group__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-4) 0;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--c-navy);
  border-bottom: 1px solid var(--c-border);
  background: none;
  cursor: pointer;
}

.mobile-nav-group__toggle svg {
  width: 20px;
  height: 20px;
  color: var(--c-primary);
  transition: transform var(--transition-std);
}

.mobile-nav-group.is-expanded .mobile-nav-group__toggle svg { transform: rotate(180deg); }

.mobile-nav-group__content {
  display: none;
  padding: var(--space-2) 0 var(--space-3);
  padding-left: var(--space-4);
  border-left: 2px solid var(--c-primary-soft);
  margin-left: var(--space-1);
}

.mobile-nav-group.is-expanded .mobile-nav-group__content { display: block; }

.mobile-nav-sub-link {
  display: block;
  padding: var(--space-3) 0;
  font-size: var(--text-base);
  color: var(--c-text);
  transition: color var(--transition-fast);
}

.mobile-nav-sub-link:hover { color: var(--c-primary); }

.mobile-menu__footer {
  padding-top: var(--space-6);
  border-top: 1px solid var(--c-border);
  margin-top: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.mobile-menu__footer .btn { justify-content: center; }

.mobile-menu__call {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  color: var(--c-heading);
  letter-spacing: -0.01em;
}

.mobile-menu__call:hover { color: var(--c-primary); }

/* ============================================================
   6. BUTTONS
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.005em;
  transition: background-color var(--transition-std), color var(--transition-std),
              border-color var(--transition-std), box-shadow var(--transition-std),
              transform var(--transition-std);
  position: relative;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  text-decoration: none;
  line-height: 1.4;
}

/* Primary */
.btn-primary {
  background: var(--c-primary);
  color: var(--c-white);
  box-shadow: 0 2px 6px rgba(11, 95, 208, 0.22);
}

.btn-primary:hover {
  background: var(--c-primary-dark);
  box-shadow: var(--shadow-blue);
  transform: translateY(-2px);
}

.btn-primary:active { transform: translateY(0); box-shadow: 0 2px 6px rgba(11, 95, 208, 0.25); }

/* Secondary (outline) */
.btn-secondary {
  background: var(--c-white);
  color: var(--c-navy);
  border-color: var(--c-border-strong);
  box-shadow: var(--shadow-xs);
}

.btn-secondary:hover {
  border-color: var(--c-primary);
  color: var(--c-primary);
  background: var(--c-primary-tint);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* Size variants */
.btn-sm { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }
.btn-lg { padding: var(--space-4) var(--space-8); font-size: var(--text-base); }
.btn-xl { padding: var(--space-5) var(--space-10); font-size: var(--text-lg); }

/* Arrow motion */
.btn-arrow svg {
  width: 16px;
  height: 16px;
  transition: transform var(--transition-std);
}

.btn-arrow:hover svg { transform: translateX(4px); }

/* Text link with animated arrow */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  transition: gap var(--transition-std), color var(--transition-std);
}

.link-arrow svg { width: 14px; height: 14px; transition: transform var(--transition-std); }
.link-arrow:hover { gap: var(--space-3); color: var(--c-primary-dark); }
.link-arrow:hover svg { transform: translateX(3px); }

/* ============================================================
   7. MEDIA / IMAGE SYSTEM
   Every content image on the site goes through .media so that
   aspect ratio, lazy fade-in, hover zoom and overlays stay
   consistent and layout shift stays at zero.
   ============================================================ */
.media {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--c-surface-muted);
  isolation: isolate;
}

.media > img,
.media > picture > img,
.media > svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.7s var(--ease-out), filter var(--transition-slow);
}

/* Aspect ratio helpers — reserve space, so no CLS */
.media--16x9  { aspect-ratio: 16 / 9; }
.media--16x10 { aspect-ratio: 16 / 10; }

/* Framed image: layered surface + depth */
.media-frame {
  position: relative;
  border-radius: var(--radius-xl);
  padding: var(--space-3);
  background: linear-gradient(150deg, var(--c-white) 0%, var(--c-surface-soft) 100%);
  border: 1px solid var(--c-border);
  box-shadow: var(--shadow-xl);
}

.media-frame .media { border-radius: var(--radius-md); }

/* Lazy-load fade */
img[loading="lazy"] { opacity: 1; }

img.is-loaded { animation: mediaFadeIn 0.5s var(--ease-out) both; }

@keyframes mediaFadeIn {
  from { opacity: 0; transform: scale(1.015); }
  to   { opacity: 1; transform: scale(1); }
}

/* ============================================================
   8. SECTION HEADERS
   ============================================================ */
.section-header {
  text-align: center;
  max-width: 760px;
  margin-inline: auto;
  margin-bottom: var(--space-16);
}

.section-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-primary);
  margin-bottom: var(--space-4);
}

.section-eyebrow::before {
  content: '';
  display: block;
  width: 24px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--c-primary), var(--c-sky));
}

.section-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 3.6vw, var(--text-5xl));
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--c-heading);
  margin-bottom: var(--space-5);
  line-height: 1.12;
  text-wrap: balance;
}

.section-subtitle {
  font-size: var(--text-lg);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  text-wrap: pretty;
}

/* ============================================================
   9. HERO SECTION

   The home hero's own layout is in section 39 and the reaching hand
   in section 68. What was left here was a two-column grid and a
   620px text cap from the layout before last — both dead, both
   still being parsed on every page. The eyebrow pill below is not
   dead: it is what the inner-page heroes use.
   ============================================================ */

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--c-white);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-6);
  box-shadow: var(--shadow-sm);
}

.hero__eyebrow span {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--c-primary-dark);
  text-transform: uppercase;
}

.hero__eyebrow-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-success);
  box-shadow: 0 0 0 3px rgba(14, 159, 110, 0.16);
  animation: pulse-dot 2.4s ease-in-out infinite;
  flex-shrink: 0;
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(0.82); }
}

.hero__headline {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 4.3vw, 3.75rem);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--c-heading);
  margin-bottom: var(--space-6);
  max-width: 15ch;
  text-wrap: balance;
}

.hero__headline em { font-style: normal; }

.hero__subheadline {
  font-size: var(--text-lg);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-10);
  max-width: 520px;
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.hero__stats {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  margin-top: var(--space-10);
  padding-top: var(--space-7, 1.75rem);
  border-top: 1px solid var(--c-border);
  flex-wrap: wrap;
  list-style: none;
}

.hero__stat { display: flex; flex-direction: column; }
.hero__stat-value { display: block; }
.hero__stat-label { display: block; }

.hero__stat-value {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  color: var(--c-navy);
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.hero__stat-label {
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-top: 4px;
  font-weight: 500;
}

/* ============================================================
   10. SERVICE CARDS
   ============================================================ */
.services-grid {
  display: grid;
  /* minmax(0,…) rather than 1fr: a 1fr track will not shrink below its
     content, which is how these rows used to run off a phone screen. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
}

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

.service-card {
  position: relative;
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: transform var(--transition-slow), box-shadow var(--transition-slow),
              border-color var(--transition-slow);
  overflow: hidden;
  transform-style: preserve-3d;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-card);
}

/* The picture that opens each card. A fixed ratio is what keeps the row
   aligned: every image is the same height, so every title below it
   starts on the same line whatever the copy does. */
.service-card__media {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--c-surface-muted);
  border-bottom: 1px solid var(--hairline);
}

.service-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease-editorial);
}

.service-card:hover .service-card__media img { transform: scale(1.04); }

/* Blue accent rail that draws in on hover */
.service-card::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--c-primary), var(--c-sky));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--transition-slow);
  z-index: 3;
}

.service-card:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-6px);
}

.service-card:hover::after { transform: scaleX(1); }

.service-card__body {
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  flex: 1;
}

.service-card__number {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--c-primary);
  letter-spacing: 0.14em;
  font-weight: 600;
  margin-bottom: var(--space-4);
}

/* Icon floats over the image edge for a layered, premium feel */
.service-card__icon {
  width: 54px;
  height: 54px;
  background: var(--c-white);
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-5);
  transition: background-color var(--transition-std), box-shadow var(--transition-std), transform var(--transition-std);
  border: 1px solid var(--c-border);
  box-shadow: var(--shadow-sm);
}

.service-card__icon svg {
  width: 26px;
  height: 26px;
  color: var(--c-primary);
  transition: transform var(--transition-std);
}

.service-card:hover .service-card__icon {
  background: var(--c-primary);
  border-color: var(--c-primary);
  box-shadow: var(--shadow-blue);
}

.service-card:hover .service-card__icon svg {
  color: var(--c-white);
  transform: scale(1.08);
}

.service-card__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-3);
  letter-spacing: -0.02em;
  transition: color var(--transition-std);
}

.service-card:hover .service-card__title { color: var(--c-primary-dark); }

.service-card__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  flex: 1;
  margin-bottom: var(--space-6);
}

.service-card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  transition: gap var(--transition-std);
  margin-top: auto;
}

.service-card__link svg {
  width: 14px;
  height: 14px;
  transition: transform var(--transition-std);
}

.service-card:hover .service-card__link { gap: var(--space-3); }
.service-card:hover .service-card__link svg { transform: translateX(4px); }

/* --- Editorial alternating row / case study cards --- */
.case-rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.case-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-12);
  align-items: center;
  padding: var(--space-10);
  background: var(--c-white);
  border-radius: var(--radius-2xl);
  border: 1px solid var(--c-border);
  box-shadow: 0 4px 24px rgba(16, 30, 67, 0.04);
  scroll-margin-top: calc(var(--header-height) + var(--space-8));
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.35s ease,
              border-color 0.3s ease;
}

.case-row + .case-row { border-top: none; }

.case-row:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 48px rgba(16, 30, 67, 0.09), 0 4px 12px rgba(11, 95, 208, 0.04);
  border-color: rgba(11, 95, 208, 0.25);
}

.case-row--reverse .case-row__media { order: 2; }
.case-row--reverse .case-row__body  { order: 1; }

.case-row__media {
  position: relative;
  display: flex;
  width: 100%;
}

.case-row__media > * { flex: 1; min-width: 0; }

.case-row__media .work-card__frame {
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--hairline);
  box-shadow: 0 8px 24px rgba(16, 30, 67, 0.06);
}
.case-row__media .media { border-radius: var(--radius-xl); }

.case-row__tags {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.case-row__title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 2.4vw, var(--text-4xl));
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.03em;
  line-height: 1.14;
  margin-bottom: var(--space-4);
}

.case-row__lead {
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-6);
}

.case-row__block { margin-bottom: var(--space-5); }

.case-row__block-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-primary);
  font-weight: 600;
  margin-bottom: var(--space-2);
  display: block;
}

.case-row__block p,
.case-row__block li {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

.case-row__block ul { display: flex; flex-direction: column; gap: var(--space-2); }

.case-row__block li { padding-left: var(--space-5); position: relative; }

.case-row__block li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-primary);
}

/* ============================================================
   15. PROCESS / TIMELINE
   Horizontal rail on desktop, vertical on mobile.
   ============================================================ */
.process-steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-6);
  position: relative;
}

.process-steps::before {
  content: '';
  position: absolute;
  top: 27px;
  left: 8%;
  right: 8%;
  height: 2px;
  background: linear-gradient(90deg, var(--c-border-strong), var(--c-primary-soft), var(--c-border-strong));
  border-radius: 2px;
}

/* Progress fill that draws as the section scrolls into view */
.process-steps::after {
  content: '';
  position: absolute;
  top: 27px;
  left: 8%;
  height: 2px;
  width: calc(84% * var(--process-progress, 0));
  background: linear-gradient(90deg, var(--c-primary), var(--c-sky));
  border-radius: 2px;
  transition: width 0.5s var(--ease-out);
}

.process-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  position: relative;
  z-index: 1;
}

.process-step__num {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--c-white);
  border: 2px solid var(--c-border-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  flex-shrink: 0;
  position: relative;
  z-index: 1;
  transition: background-color var(--transition-std), border-color var(--transition-std),
              color var(--transition-std), box-shadow var(--transition-std), transform var(--transition-std);
  box-shadow: var(--shadow-sm);
}

.process-step:hover .process-step__num,
.process-step.is-reached .process-step__num {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-white);
  box-shadow: var(--shadow-blue);
}

.process-step:hover .process-step__num { transform: translateY(-3px); }

.process-step__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.01em;
}

.process-step__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-normal);
}

/* ============================================================
   16. VALUE / WHY SECTION
   ============================================================ */
.value-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
  margin-top: var(--space-16);
}

.value-item {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--c-white);
  border-radius: var(--radius-md);
  border: 1px solid var(--c-border);
  transition: transform var(--transition-std), box-shadow var(--transition-std), border-color var(--transition-std);
  box-shadow: var(--shadow-card);
}

.value-item:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-lg);
  transform: translateY(-3px);
}

.value-item__icon {
  width: 46px;
  height: 46px;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background-color var(--transition-std), border-color var(--transition-std);
}

.value-item__icon svg {
  width: 22px;
  height: 22px;
  color: var(--c-primary);
  transition: color var(--transition-std), transform var(--transition-std);
}

.value-item:hover .value-item__icon {
  background: var(--c-primary);
  border-color: var(--c-primary);
}

.value-item:hover .value-item__icon svg { color: var(--c-white); transform: scale(1.08); }

.value-item__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-1);
  letter-spacing: -0.01em;
}

.value-item__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* ============================================================
   17. CTA SECTION — deep navy/blue panel
   ============================================================ */
.cta-section{
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 90% at 18% 0%, rgba(14, 165, 233, 0.30) 0%, transparent 58%),
    linear-gradient(135deg, var(--c-primary-darker) 0%, var(--c-navy) 58%, var(--c-navy-deep) 100%);
  border-radius: var(--radius-2xl);
  padding: var(--space-20) var(--space-12);
  text-align: center;
  margin-block: var(--space-12);
  color: var(--c-text-on-dark);
  box-shadow: var(--shadow-xl);
  isolation: isolate;
}

/* Abstract technology grid inside the panel */
.cta-section::before{
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 80% 90% at 50% 0%, black 10%, transparent 85%);
  -webkit-mask-image: radial-gradient(ellipse 80% 90% at 50% 0%, black 10%, transparent 85%);
  pointer-events: none;
  z-index: -1;
}

.cta-section__border {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, 0.14);
  pointer-events: none;
}

.cta-section__title{
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  font-weight: 600;
  color: var(--c-white);
  letter-spacing: -0.035em;
  margin-bottom: var(--space-5);
  position: relative;
  line-height: 1.1;
  text-wrap: balance;
}

.cta-section__subtitle{
  font-size: var(--text-lg);
  color: var(--c-text-on-dark-2);
  margin-bottom: var(--space-10);
  max-width: 620px;
  margin-inline: auto;
  position: relative;
  line-height: var(--leading-relaxed);
}

.cta-section__actions{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  position: relative;
}

/* ============================================================
   18. FOOTER — deep navy
   ============================================================ */
.site-footer {
  background: var(--c-navy-deep);
  color: var(--c-text-on-dark-2);
  padding-top: var(--space-20);
  padding-bottom: var(--space-8);
  position: relative;
  overflow: hidden;
}

/* Subtle blue accent wash */
.site-footer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--c-primary), var(--c-sky), var(--c-primary-darker));
}

.site-footer::after {
  content: '';
  position: absolute;
  width: 640px;
  height: 640px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(11, 95, 208, 0.22) 0%, transparent 68%);
  top: -320px;
  right: -180px;
  pointer-events: none;
}

.site-footer .container { position: relative; z-index: 1; }

.footer-top {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1.4fr);
  gap: var(--space-12);
  padding-bottom: var(--space-12);
  border-bottom: 1px solid var(--c-border-on-dark);
  margin-bottom: var(--space-8);
}

.footer-brand__note {
  font-size: var(--text-sm);
  color: var(--c-text-on-dark-2);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-6);
  max-width: 40ch;
  opacity: 0.8;
}

.footer-brand__desc {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-base);
  color: rgba(255, 255, 255, 0.86);
  margin-top: var(--space-4);
  margin-bottom: var(--space-3);
  letter-spacing: -0.01em;
  max-width: 34ch;
}

/* The contact block is an <address>; strip the browser italic. */
.footer-contact { font-style: normal; }

.footer-contact__cta {
  margin-top: var(--space-5);
  width: 100%;
  justify-content: center;
}

.footer-social { display: flex; gap: var(--space-3); }

.footer-social__link {
  width: 38px;
  height: 38px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--c-border-on-dark);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-text-on-dark-2);
  transition: background-color var(--transition-std), border-color var(--transition-std),
              color var(--transition-std), transform var(--transition-std);
}

.footer-social__link:hover {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-white);
  transform: translateY(-2px);
}

.footer-social__link svg { width: 16px; height: 16px; }

.footer-col__title {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-white);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: var(--space-5);
}

.footer-nav { display: flex; flex-direction: column; gap: var(--space-3); }

.footer-nav__link {
  font-size: var(--text-sm);
  color: var(--c-text-on-dark-2);
  transition: color var(--transition-fast), padding-left var(--transition-fast);
}

.footer-nav__link:hover,
.footer-nav__link.is-active {
  color: var(--c-sky-light);
  padding-left: var(--space-1);
}

.footer-contact-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.footer-contact-item svg {
  width: 16px;
  height: 16px;
  color: var(--c-sky-light);
  flex-shrink: 0;
  margin-top: 3px;
}

.footer-contact-item span,
.footer-contact-item a {
  font-size: var(--text-sm);
  color: var(--c-text-on-dark-2);
  line-height: var(--leading-relaxed);
  transition: color var(--transition-fast);
}

.footer-contact-item a:hover { color: var(--c-sky-light); }

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* --c-text-on-dark-2, not --c-text-muted: this sits on the navy footer,
   and the muted token is now tuned for light surfaces. */
.footer-copyright { font-size: var(--text-sm); color: var(--c-text-on-dark-2); }

.footer-legal { display: flex; gap: var(--space-6); flex-wrap: wrap; }

.footer-legal a {
  font-size: var(--text-sm);
  color: var(--c-text-on-dark-2);
  transition: color var(--transition-fast);
}

.footer-legal a:hover { color: var(--c-sky-light); }

/* ============================================================
   19. BREADCRUMBS
   ============================================================ */
.breadcrumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
}

.breadcrumb-item {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  letter-spacing: 0.05em;
}

.breadcrumb-item a {
  color: var(--c-text-soft);
  transition: color var(--transition-fast);
  text-decoration: none;
}

.breadcrumb-item a:hover { color: var(--c-primary); text-decoration: underline; text-underline-offset: 3px; }

.breadcrumb-item.is-current { color: var(--c-primary-dark); font-weight: 500; }

.breadcrumb-sep { color: var(--c-border-strong); }

/* ============================================================
   20. INNER PAGE HERO
   ============================================================ */
.page-hero {
  position: relative;
  padding-top: calc(var(--header-height) + var(--space-16));
  padding-bottom: var(--space-16);
  overflow: hidden;
  background:
    radial-gradient(ellipse 60% 70% at 85% 10%, var(--c-sky-soft) 0%, transparent 62%),
    linear-gradient(180deg, var(--c-primary-tint) 0%, var(--c-white) 78%);
  border-bottom: 1px solid var(--c-border-soft);
}

.page-hero__content {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: var(--space-12);
  align-items: center;
}

.page-hero__title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 4.4vw, var(--text-6xl));
  font-weight: 600;
  letter-spacing: -0.035em;
  color: var(--c-heading);
  margin-bottom: var(--space-5);
  line-height: 1.06;
  text-wrap: balance;
}

.page-hero__desc {
  font-size: var(--text-lg);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-8);
  max-width: 560px;
  text-wrap: pretty;
}

/* Per-service accent: each service page gets its own hero wash so the
   six pages read as a family without looking identical.
   The rules live in section 67, after the editorial layer has settled
   the shared band they sit on. */

/* ============================================================
   21. CONTENT SECTIONS
   ============================================================ */
.content-section { padding-block: var(--space-20); position: relative; }

/* Legacy modifier names, remapped to the light system */
.content-section--dark { background: var(--c-surface-soft); }

.two-col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-16);
  /* stretch, not centre: a fixed-ratio image beside a taller column of
     copy used to float in the middle of its cell with dead space above
     and below it, which is what read as "not aligned". The media now
     takes the height of the text beside it, so the two columns start
     and finish on the same lines. */
  align-items: stretch;
}

.two-col__visual { display: flex; min-height: 320px; }
.two-col__visual > * { flex: 1; min-width: 0; }

/* the frame gives up its own ratio when it has a column to fill */
.two-col__visual .work-card__frame,
.two-col__visual .media { aspect-ratio: auto; height: 100%; }

.two-col__visual .media img { width: 100%; height: 100%; object-fit: cover; }

.two-col--reverse .two-col__visual { order: -1; }

.content-lead {
  font-size: var(--text-xl);
  color: var(--c-text-strong);
  line-height: var(--leading-relaxed);
  font-weight: 400;
  margin-bottom: var(--space-5);
  text-wrap: pretty;
}

.content-body {
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-4);
  text-wrap: pretty;
}

.content-body a,
.content-lead a {
  color: var(--c-primary);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--c-primary-soft);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--transition-fast), color var(--transition-fast);
}

.content-body a:hover,
.content-lead a:hover {
  color: var(--c-primary-dark);
  text-decoration-color: var(--c-primary);
}

/* --- Challenge cards (problem framing) --- */
.challenge-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}

.challenge-card {
  padding: var(--space-6);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-top: 3px solid var(--c-border-strong);
  border-radius: var(--radius-md);
  transition: border-top-color var(--transition-std), box-shadow var(--transition-std), transform var(--transition-std);
  box-shadow: var(--shadow-card);
}

.challenge-card:hover {
  border-top-color: var(--c-primary);
  box-shadow: var(--shadow-lg);
  transform: translateY(-3px);
}

.challenge-card__icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: #FEF2F2;
  border: 1px solid #FDE0E0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-4);
}

.challenge-card__icon svg { width: 20px; height: 20px; color: #D2504A; }

.challenge-card__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-2);
}

.challenge-card__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* --- Solution list (answer framing) --- */
.solution-list { display: flex; flex-direction: column; gap: var(--space-4); }

.solution-item {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-std), box-shadow var(--transition-std), transform var(--transition-std);
}

.solution-item:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-md);
  transform: translateX(3px);
}

.solution-item__check {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--c-success-soft);
  border: 1px solid #C4EBDC;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.solution-item__check svg { width: 15px; height: 15px; color: var(--c-success); }

.solution-item__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-1);
}

.solution-item__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* --- Capabilities --- */
.capabilities-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-6);
}

.capabilities-list--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.capability-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition-std), box-shadow var(--transition-std), transform var(--transition-std);
}

.capability-item:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.capability-item__icon {
  width: 32px;
  height: 32px;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-soft);
  border-radius: var(--radius-xs);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background-color var(--transition-std);
}

.capability-item:hover .capability-item__icon { background: var(--c-primary-soft); }

.capability-item__icon svg { width: 16px; height: 16px; color: var(--c-primary); }

.capability-item__text {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--c-text-strong);
  line-height: var(--leading-snug);
}

/* --- Deliverables / features --- */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}

.feature-item {
  padding: var(--space-6);
  background: var(--c-surface-soft);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  transition: background-color var(--transition-std), border-color var(--transition-std), transform var(--transition-std);
}

.feature-item:hover {
  background: var(--c-white);
  border-color: var(--c-border-accent);
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}

.feature-item__icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-4);
  transition: background-color var(--transition-std), border-color var(--transition-std);
}

.feature-item__icon svg { width: 20px; height: 20px; color: var(--c-primary); transition: color var(--transition-std); }

.feature-item:hover .feature-item__icon { background: var(--c-primary); border-color: var(--c-primary); }
.feature-item:hover .feature-item__icon svg { color: var(--c-white); }

.feature-item__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-2);
}

.feature-item__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* --- Benefits --- */
.benefits-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}

.benefit-card {
  padding: var(--space-6);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-std), transform var(--transition-std), box-shadow var(--transition-std);
  box-shadow: var(--shadow-card);
}

.benefit-card:hover {
  border-color: var(--c-border-accent);
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}

.benefit-card__num {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  color: var(--c-primary);
  letter-spacing: -0.04em;
  margin-bottom: var(--space-3);
  line-height: 1;
}

.benefit-card__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  margin-bottom: var(--space-2);
}

.benefit-card__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* --- FAQ --- */
.faq-list { max-width: 820px; margin-inline: auto; }

.faq-item {
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  background: var(--c-white);
  margin-bottom: var(--space-3);
  transition: border-color var(--transition-std), box-shadow var(--transition-std);
}

.faq-item:hover { border-color: var(--c-border-strong); }

.faq-item.is-open {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-md);
}

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  transition: color var(--transition-fast);
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  line-height: var(--leading-snug);
}

.faq-question:hover { color: var(--c-primary); }

.faq-question__icon {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--transition-std), border-color var(--transition-std);
}

.faq-question__icon svg {
  width: 12px;
  height: 12px;
  color: var(--c-primary);
  transition: transform var(--transition-std), color var(--transition-std);
}

.faq-item.is-open .faq-question__icon { background: var(--c-primary); border-color: var(--c-primary); }
.faq-item.is-open .faq-question__icon svg { transform: rotate(45deg); color: var(--c-white); }

.faq-answer {
  display: none;
  padding: 0 var(--space-6) var(--space-6);
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

.faq-item.is-open .faq-answer { display: block; }

.faq-answer p + p { margin-top: var(--space-3); }

/* ============================================================
   22. TECH STACK DISPLAY
   ============================================================ */
.tech-grid { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.tech-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--c-white);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--c-text-strong);
  transition: border-color var(--transition-fast), color var(--transition-fast),
              background-color var(--transition-fast), transform var(--transition-fast);
}

.tech-badge:hover {
  border-color: var(--c-primary);
  color: var(--c-primary-dark);
  background: var(--c-primary-tint);
  transform: translateY(-2px);
}

/* ============================================================
   23. FORMS
   ============================================================ */
.form-group { display: flex; flex-direction: column; gap: var(--space-2); }

.form-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-text-strong);
}

.form-control {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--c-white);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--c-heading);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
  outline: none;
}

.form-control::placeholder { color: var(--c-text-muted); }

.form-control:hover { border-color: #B6CCE5; }

.form-control:focus {
  border-color: var(--c-primary);
  box-shadow: 0 0 0 3px rgba(11, 95, 208, 0.14);
}

textarea.form-control { resize: vertical; min-height: 150px; }
select.form-control { cursor: pointer; }

/* Generic surface card — used by case studies / legal pages */
.card {
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--transition-std), border-color var(--transition-std), transform var(--transition-std);
}

.card:hover { box-shadow: var(--shadow-lg); border-color: var(--c-border-strong); }

.tag {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-accent);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--c-primary-dark);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 500;
}

.highlight-box {
  padding: var(--space-6);
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-primary);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: var(--text-base);
  color: var(--c-text-strong);
  line-height: var(--leading-relaxed);
  margin-block: var(--space-6);
}

.stat-card {
  padding: var(--space-6);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  text-align: center;
  box-shadow: var(--shadow-card);
  transition: transform var(--transition-std), box-shadow var(--transition-std);
}

.stat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }

.stat-card__value {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  letter-spacing: -0.04em;
  color: var(--c-primary);
  margin-bottom: var(--space-2);
  line-height: 1;
}

.stat-card__label { font-size: var(--text-sm); color: var(--c-text); }

/* Logo / trust marquee strip */
/* ============================================================
   25. ACCESSIBILITY
   ============================================================ */
:focus-visible {
  outline: 3px solid var(--c-primary);
  outline-offset: 3px;
  border-radius: 3px;
}
.site-footer :focus-visible{ outline-color: var(--c-sky-light); }

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-4);
  background: var(--c-primary);
  color: var(--c-white);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: var(--text-sm);
  z-index: 9999;
  transition: top var(--transition-fast);
}

.skip-link:focus { top: var(--space-4); }

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

/* ============================================================
   26. PAGE-SPECIFIC: CONTACT
   ============================================================ */
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: var(--space-10);
  align-items: start;
}

.contact-info-card {
  background: var(--c-navy);
  color: var(--c-text-on-dark);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-xl);
}

.contact-info-card::before {
  content: '';
  position: absolute;
  width: 340px;
  height: 340px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(14, 165, 233, 0.25) 0%, transparent 70%);
  top: -160px;
  right: -120px;
  pointer-events: none;
}

.contact-info-card > * { position: relative; }
.contact-info-card h2,
.contact-info-card h3 { color: var(--c-white); }

.contact-form-card {
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-lg);
}

.contact-form {
  /* the honeypot inside is absolutely positioned; without this it
     would resolve against the viewport instead of against the form */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.contact-form .form-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-4);
}

/* ============================================================
   27. SCROLL REVEAL TRIGGERS
   ============================================================ */
/* The hidden start state is scoped to .js, which a small inline script
   in <head> sets. If scripting is off or reveal.js fails to run, the
   content is simply visible instead of hidden forever. */
/* These four start states carry the distance and easing the editorial
   layer wanted. They used to be declared twice: once here, and again
   about nine hundred lines further down, after the matching
   `.is-visible` rules. Both declarations had the same specificity, so
   the later one won — permanently. The end state never applied, and
   every .reveal and every .stagger-children child on the site sat 16
   to 20 pixels below where it belonged for the whole life of the page.

   Nothing looked broken standing still, because everything was offset
   by the same amount. It showed up on hover: any rule that touches
   `transform` — the card lift, or the reset that cancels it — replaces
   translateY(16px) with none, and the card jumps 16px upward into the
   one above it. That is the overlap.

   One declaration each now, with the resets after them. */
.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.8s var(--ease-editorial), transform 0.8s var(--ease-editorial);
}

.reveal.is-visible { opacity: 1; transform: translateY(0); }

.js .reveal--left  { transform: translateX(-20px); }
.reveal--left.is-visible { transform: translateX(0); }

.js .reveal--right { transform: translateX(20px); }
.reveal--right.is-visible { transform: translateX(0); }

.js .stagger-children > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.65s var(--ease-editorial), transform 0.65s var(--ease-editorial);
}

.stagger-children.is-visible > *:nth-child(1)  { transition-delay: 0ms; }
.stagger-children.is-visible > *:nth-child(2)  { transition-delay: 70ms; }
.stagger-children.is-visible > *:nth-child(3)  { transition-delay: 140ms; }
.stagger-children.is-visible > *:nth-child(4)  { transition-delay: 210ms; }
.stagger-children.is-visible > *:nth-child(5)  { transition-delay: 280ms; }
.stagger-children.is-visible > *:nth-child(6)  { transition-delay: 350ms; }
.stagger-children.is-visible > *:nth-child(7)  { transition-delay: 420ms; }
.stagger-children.is-visible > *:nth-child(8)  { transition-delay: 455ms; }
.stagger-children.is-visible > *:nth-child(9)  { transition-delay: 490ms; }
.stagger-children.is-visible > *:nth-child(10) { transition-delay: 525ms; }
.stagger-children.is-visible > *:nth-child(11) { transition-delay: 560ms; }
.stagger-children.is-visible > *:nth-child(12) { transition-delay: 595ms; }

.stagger-children.is-visible > * { opacity: 1; transform: translateY(0); }
.w-full { width: 100%; }

/* ============================================================
   29. HERO MEDIA
   ============================================================ */
/* The framed hero photograph this section used to describe is gone:
   both heroes now bleed their picture to the edge of the band behind
   the copy. What was left here was a `max-width: 620px` with a radius
   and a drop shadow, and because `.page-hero .hero__media` never
   restates max-width, that cap was still being applied — every inner
   page was rendering its hero photograph at 620px instead of the 56%
   the layout asks for, with rounded corners and a shadow on an image
   that is supposed to be clipped flush. Removed rather than
   overridden; the page hero owns its own media in section 36.2. */

/* Split panel: copy on one side, framed image on the other */
.split-media {
  position: relative;
}

.split-media .media {
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--c-border);
}

/* ============================================================
   31. INDUSTRY INDEX CARDS + LATE FIXES
   ============================================================ */

/* Missing ratio used by industry heroes and cards */
.media--16x10 { aspect-ratio: 16 / 10; }

/* Generic surface card needs breathing room by default; components
   that put an image flush to the edge opt out with .card--flush. */
.card { padding: var(--space-6); }

/* The listing byline is longer than the homepage's read-time */
.case-row__tags {
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

/* ============================================================
   34. CONTACT PAGE DETAIL LIST
   ============================================================ */
.contact-info-card .section-eyebrow { color: var(--c-sky-light); }
.contact-info-card .section-eyebrow::before {
  background: linear-gradient(90deg, var(--c-sky-light), transparent);
}
.contact-info-card .content-lead { color: var(--c-text-on-dark-2); }

.contact-detail-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin-top: var(--space-8);
}

.contact-detail {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
}

.contact-detail__icon {
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid var(--c-border-on-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-sky-light);
  flex-shrink: 0;
}

.contact-detail__title {
  font-size: var(--text-base);
  color: var(--c-white);
  margin-bottom: 2px;
}

.contact-detail__text {
  color: var(--c-text-on-dark-2);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
}

.contact-detail__text a {
  color: var(--c-sky-light);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.contact-note {
  margin-top: var(--space-8);
  padding: var(--space-5);
  background: rgba(255, 255, 255, 0.06);
  border-left: 3px solid var(--c-sky);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.contact-note__title {
  color: var(--c-white);
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}

.contact-note__text {
  color: var(--c-text-on-dark-2);
  font-size: var(--text-xs);
  line-height: var(--leading-relaxed);
}

#form-success a, #form-error a { color: inherit; text-decoration: underline; }

/* --- Trailing call to action inside a prose column ---------- */
/* Usually one button; the case rows carry two, so it wraps rather than
   relying on inline whitespace to space them. */
.content-cta {
  margin-top: var(--space-8);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* --- Whole-card link ----------------------------------------
   The heading carries the only <a>, and it covers the card. One
   link per card keeps the tab order and screen-reader list clean. */
/* Deliberately ::before: a stretched link is often also the element that
   carries a trailing arrow in ::after, and one element only has one of each. */
.stretched::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}

.service-card{ position: relative; }

.service-card__link{
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-5);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  transition: gap var(--transition-std);
}

.service-card__link svg{ width: 14px; height: 14px; }

.service-card:hover .service-card__link{ gap: var(--space-3); }

/* --- Industry card, text only -------------------------------
   Twelve near-identical drawn thumbnails carried no information
   and repeated across the site{
  padding: var(--space-6);
  gap: var(--space-2);
}

/* --- Buttons on dark panels --------------------------------- */
.btn-white {
  background: var(--c-white);
  color: var(--c-navy);
  border: 1px solid var(--c-white);
}

.btn-white:hover {
  background: var(--c-primary-tint);
  border-color: var(--c-primary-tint);
  color: var(--c-primary-darker);
}

/* --- Engineering notes --------------------------------------
   The article bodies live on this page. They were previously
   teasers whose "read" link went to a service page instead of to
   anything readable, so the content is here and <details> keeps
   the list scannable without any JavaScript. */
.notes-list {
  display: grid;
  gap: var(--space-4);
  max-width: 880px;
  margin-inline: auto;
}

.note {
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: border-color var(--transition-std), box-shadow var(--transition-std);
}

.note:hover { border-color: var(--c-border-accent); box-shadow: var(--shadow-lg); }
.note[open] { border-color: var(--c-border-accent); box-shadow: var(--shadow-lg); }

.note__summary {
  list-style: none;
  cursor: pointer;
  padding: var(--space-6) var(--space-8);
  display: grid;
  gap: var(--space-2);
}

.note__summary::-webkit-details-marker { display: none; }

.note__summary:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: -2px;
  border-radius: var(--radius-lg);
}

.note__tag {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-primary);
}

.note__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.02em;
  line-height: 1.25;
}

.note__excerpt {
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-normal);
  max-width: 68ch;
}

.note__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
}

.note__toggle::after {
  content: '';
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transition-std);
}

.note[open] .note__toggle::after { transform: rotate(-135deg) translate(-2px, -2px); }
.note[open] .note__toggle { visibility: hidden; }

.note__body {
  padding: 0 var(--space-8) var(--space-8);
  border-top: 1px solid var(--c-border-soft);
  margin-top: var(--space-2);
  padding-top: var(--space-6);
}

.note__body p {
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  max-width: 68ch;
}

.note__body p + p { margin-top: var(--space-4); }

.note__related {
  margin-top: var(--space-6) !important;
  font-size: var(--text-sm) !important;
  color: var(--c-text-muted) !important;
}

.note__related a { color: var(--c-primary); font-weight: 600; }
.note__related a:hover { text-decoration: underline; }

/* ============================================================
   35. COMPONENTS THAT HAD MARKUP BUT NO STYLES
   Each of these was already in the HTML and rendering unstyled.
   ============================================================ */

/* About page: the four-stage methodology. It was shipping as four
   runs of bare text with no card, grid or number treatment. */
.process-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-6);
}

.process-card {
  position: relative;
  padding: var(--space-6);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: border-color var(--transition-std), box-shadow var(--transition-std),
              transform var(--transition-std);
}

.process-card:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-lg);
  transform: translateY(-3px);
}

.process-card__number {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  line-height: 1;
  color: var(--c-primary);
  letter-spacing: -0.04em;
  margin-bottom: var(--space-4);
}

.process-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-3);
}

.process-card__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

/* Footer columns: the grid placed them, but neither had a rule of its
   own, so the brand column had no internal rhythm. */
.footer-brand { display: flex; flex-direction: column; }
.footer-col   { display: flex; flex-direction: column; }

/* FAQ list wrapper */
.faq-accordion {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 820px;
  margin-inline: auto;
}

/* Value item text column */
.value-item__content { display: flex; flex-direction: column; gap: var(--space-2); }

/* About page service list numerals */
.service-card__num {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: 1;
  color: var(--c-primary);
  letter-spacing: -0.04em;
  margin-bottom: var(--space-3);
}

/* ============================================================
   36. EDITORIAL LAYER
   The premium B2B direction: a deep navy stage at the top of
   every page, generous type, hairline structure instead of
   boxed cards, and one restrained reveal.

   This sits at the end of the sheet on purpose — it overrides
   the earlier component rules rather than duplicating them.
   ============================================================ */

:root {
  /* Stage gradient, built only from the logo's own blues */
  --stage-1: #0A1330;
  --stage-2: #12244F;
  --stage-3: #17295B;
  --stage-glow: rgba(67, 131, 229, 0.42);

  --hairline: rgba(16, 30, 67, 0.10);
  --hairline-strong: rgba(16, 30, 67, 0.16);
  --hairline-on-dark: rgba(255, 255, 255, 0.14);

  --ease-editorial: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ------------------------------------------------------------
   36.1  HEADER — light type over the stage, solid once scrolled
   ------------------------------------------------------------ */
.site-header {
  background-color: var(--c-white);
  border-bottom: 1px solid var(--hairline);
}

/* The hero is its own dark band below the bar, so the header does not
   need a transparent state at all — it is white at every scroll offset. */
.site-header.is-transparent {
  background-color: var(--c-white);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.site-header.is-scrolled {
  background-color: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border-bottom-color: var(--hairline);
  box-shadow: 0 8px 26px rgba(10, 19, 48, 0.06);
}

/* Nav CTA: pill plus the companion disc from the reference */
.btn-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 6px 6px var(--space-5);
  border-radius: var(--radius-full);
  background: var(--c-primary);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1;
  border: 1px solid var(--c-primary);
  transition: background-color var(--transition-std), border-color var(--transition-std),
              transform var(--transition-std);
  white-space: nowrap;
}

.btn-nav:hover { background: var(--c-primary-dark); border-color: var(--c-primary-dark); }
.btn-nav:active { transform: translateY(1px); }

/* ------------------------------------------------------------
   36.2  THE STAGE — shared dark treatment for every page top
   ------------------------------------------------------------ */
/* --- Inner page hero -----------------------------------------
   The same construction as the home page band: navy at left, the
   photograph bleeding off the right on a diagonal, one chevron.
   The home page hero keeps its own markup and rules; this covers
   every other page so the whole site opens the same way. */
.page-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--c-text-on-dark);
  border-bottom: none;
  padding-top: var(--space-20);
  padding-bottom: var(--space-20);
  background: linear-gradient(118deg, #0A1330 0%, #0C1937 52%, #102047 100%);
}

.page-hero .hero__media {
  position: absolute;
  inset: 0 0 0 auto;
  width: 56%;
  z-index: -2;
  clip-path: polygon(22% 0, 100% 0, 100% 100%, 4% 100%);
}

.page-hero .hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.page-hero .hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg, rgba(10, 19, 48, 0.94) 0%, rgba(10, 19, 48, 0.42) 22%, rgba(10, 19, 48, 0.06) 50%),
    linear-gradient(180deg, rgba(10, 19, 48, 0.24) 0%, transparent 30%, rgba(10, 19, 48, 0.28) 100%);
}

/* Utility pages carry no photograph, so the band gets its light from a
   gradient instead of from the image. */
.page-hero:not(:has(.hero__media)) {
  background:
    radial-gradient(90% 120% at 88% 0%, rgba(11, 95, 208, 0.34) 0%, transparent 58%),
    linear-gradient(118deg, #0A1330 0%, #0C1937 52%, #102047 100%);
}

.page-hero .hero__chevron {
  position: absolute;
  top: 0;
  right: 40%;
  width: 30%;
  height: 66%;
  z-index: -1;
  pointer-events: none;
}

.page-hero .hero__chevron::before,
.page-hero .hero__chevron::after {
  content: '';
  position: absolute;
  inset: 0;
  clip-path: polygon(0 0, 46% 0, 100% 52%, 46% 100%, 0 100%, 54% 52%);
}

.page-hero .hero__chevron::before {
  background: rgba(67, 131, 229, 0.16);
  transform: translateX(14%);
}

.page-hero .hero__chevron::after {
  background: rgba(67, 131, 229, 0.10);
  transform: translateX(-16%) scale(0.86);
  transform-origin: left top;
}

/* Copy column: one column, held to a readable measure, never centred */
.page-hero__content {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 660px;
  text-align: left;
}

.page-hero__title {
  color: #fff;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.12;
  font-size: clamp(2.2rem, 3.8vw, 3.4rem);
  max-width: 15ch;
}

.page-hero__desc {
  color: rgba(226, 235, 248, 0.76);
  max-width: 48ch;
  line-height: var(--leading-relaxed);
}

.page-hero .breadcrumbs,
.page-hero .breadcrumb-item,
.page-hero .breadcrumb-sep { color: rgba(226, 235, 248, 0.52); justify-content: flex-start; }

.page-hero .breadcrumb-item a { color: rgba(226, 235, 248, 0.72); }
.page-hero .breadcrumb-item a:hover { color: #fff; }
.page-hero .breadcrumb-item.is-current { color: rgba(255, 255, 255, 0.9); }

/* The eyebrow pill sits on the dark band, so it drops the white fill
   the light layout gave it. */
.page-hero .hero__eyebrow {
  display: inline-flex;
  margin-bottom: var(--space-5);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.page-hero .hero__eyebrow span { color: rgba(255, 255, 255, 0.88); }
.page-hero .hero__eyebrow-dot { background: #6FE8B0; box-shadow: 0 0 0 3px rgba(111, 232, 176, 0.18); }

.page-hero .text-gradient,
.hero .text-gradient { color: var(--c-primary-light); }

/* Buttons on the band */
.page-hero .btn-secondary {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.28);
  color: #fff;
}

.page-hero .btn-secondary:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.5);
  color: #fff;
}

.page-hero .btn-primary {
  background: #fff;
  border-color: #fff;
  color: var(--c-navy);
  box-shadow: 0 14px 34px rgba(4, 10, 28, 0.40);
}

.page-hero .btn-primary:hover {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #fff;
}

.page-hero .btn-primary svg { color: currentColor; }

.page-hero :focus-visible,
.hero :focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

@media (max-width: 1024px) {
  .page-hero { padding-top: var(--space-16); padding-bottom: var(--space-16); }
  .page-hero .hero__media { inset: 0; width: 100%; clip-path: none; }

  .page-hero .hero__media::after {
    background: linear-gradient(180deg, rgba(10, 19, 48, 0.94) 0%, rgba(10, 19, 48, 0.88) 50%, rgba(10, 19, 48, 0.8) 100%);
  }

  .page-hero .hero__chevron { display: none; }
  .page-hero__content { max-width: none; }
}

@media (max-width: 700px) {
  .page-hero { padding-top: var(--space-12); padding-bottom: var(--space-12); }
  .page-hero__title { font-size: clamp(1.85rem, 8vw, 2.4rem); max-width: none; }
  .page-hero__desc { max-width: none; }
}

/* ------------------------------------------------------------
   36.3  SECTION RHYTHM — hairlines, not boxes
   ------------------------------------------------------------ */
.section,
.content-section { position: relative; }

/* Eyebrow becomes a small chip with a rule, as in the reference */
.section-eyebrow,
.section-header .section-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-primary);
  margin-bottom: var(--space-5);
}

.section-eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  background: currentColor;
  opacity: 0.55;
  flex-shrink: 0;
}

.section-title {
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.1;
  font-size: clamp(2rem, 3.1vw, 3.1rem);
  max-width: 20ch;
}

/* Section headers read left, against a hairline, rather than centred.
   A centred stack of eyebrow + title + subtitle is the single most
   template-looking pattern on a B2B site. */
.section-header {
  text-align: left;
  max-width: none;
  margin-inline: 0;
  margin-bottom: var(--space-12);
  padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--hairline);
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--space-4) var(--space-16);
  align-items: end;
}

.section-header > .section-eyebrow { grid-column: 1 / -1; margin-bottom: 0; }

/* A subtitle longer than the heading would otherwise push itself above
   the heading's first line. */
.section-header .section-subtitle { align-self: end; }

.section-header .section-title {
  grid-column: 1;
  margin-inline: 0;
  margin-bottom: 0;
  max-width: 18ch;
}

.section-header .section-subtitle {
  grid-column: 2;
  margin-inline: 0;
  padding-bottom: 0.35em;
}

.section-subtitle { max-width: 58ch; color: var(--c-text-soft); }

/* On a dark band the hairline has to flip too */
.bg-darker .section-header,
.content-section--dark .section-header { border-bottom-color: var(--hairline); }

/* An intro that puts the heading and the supporting copy side by side */
.section-intro {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--space-8) var(--space-16);
  align-items: start;
  padding-bottom: var(--space-10);
  margin-bottom: var(--space-12);
  border-bottom: 1px solid var(--hairline);
  text-align: left;
  max-width: none;
}

.section-intro .section-title { margin-bottom: 0; max-width: 18ch; }
.section-intro .section-subtitle { margin-inline: 0; }
.section-intro__aside { display: flex; flex-direction: column; gap: var(--space-5); align-items: flex-start; }

/* ------------------------------------------------------------
   36.4  CARDS — quieter surfaces, stronger type
   ------------------------------------------------------------ */
.service-card,
.benefit-card,
.note,
.process-card,
.value-item {
  box-shadow: none;
  border-color: var(--hairline);
  background: var(--c-white);
}

.service-card:hover,
.benefit-card:hover,
.process-card:hover {
  border-color: var(--hairline-strong);
  box-shadow: 0 18px 44px rgba(16, 30, 67, 0.09);
}

.service-card::after { background: var(--c-primary); height: 2px; }

/* Cards that wrap their content in __body get the padding there; cards
   that put content straight into .service-card get it from the card. */
.service-card__body { padding: var(--space-7, 1.75rem) var(--space-7, 1.75rem) var(--space-6); }

.service-card:not(:has(.service-card__body)) {
  padding: var(--space-7, 1.75rem) var(--space-7, 1.75rem) var(--space-6);
}

.service-card__icon {
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  background: var(--c-primary-tint);
  border-color: transparent;
  box-shadow: none;
}

.service-card__icon svg { width: 22px; height: 22px; }

.service-card__title { font-weight: 600; font-size: var(--text-lg); }
.service-card__desc { color: var(--c-text-soft); }

.benefit-card { padding: var(--space-7, 1.75rem); }
.benefit-card__num { font-weight: 600; font-size: var(--text-2xl); }
.benefit-card__title { font-weight: 600; }

/* The value row loses its boxes and becomes three columns divided
   by hairlines, which is what the reference does with its triple. */
.value-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  border-top: 1px solid var(--hairline);
  padding-top: var(--space-10);
}

.value-item {
  border: 0;
  border-left: 1px solid var(--hairline);
  border-radius: 0;
  background: transparent;
  padding: 0 var(--space-6);
  flex-direction: column;
  gap: var(--space-4);
}

.value-item:first-child { border-left: 0; padding-left: 0; }
.value-item:hover { box-shadow: none; transform: none; background: transparent; }

.value-item__icon {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-md);
  background: var(--c-primary-tint);
  color: var(--c-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.value-item__icon svg { width: 20px; height: 20px; }
.value-item__title { font-family: var(--font-display); font-weight: 600; font-size: var(--text-base); }
.value-item__desc { color: var(--c-text-soft); font-size: var(--text-sm); line-height: var(--leading-relaxed); }
.cta-section {
  background:
    radial-gradient(110% 100% at 6% 0%, var(--stage-glow) 0%, transparent 54%),
    linear-gradient(140deg, var(--stage-1) 0%, var(--stage-2) 52%, var(--stage-3) 100%);
  box-shadow: 0 34px 80px rgba(4, 10, 28, 0.28);
}
.cta-section__title { font-weight: 600; letter-spacing: -0.03em; }

.cta-panel .text-gradient,
.cta-section .text-gradient { color: var(--c-primary-light); }

/* ------------------------------------------------------------
   36.7  FOOTER
   ------------------------------------------------------------ */
.site-footer {
  background: var(--stage-1);
  border-top: 1px solid var(--hairline-on-dark);
}

.site-footer::before,
.site-footer::after { display: none; }

.footer-col__title {
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.55);
}

.footer-top { border-bottom-color: var(--hairline-on-dark); }
.footer-bottom { border-top: 0; }

/* ------------------------------------------------------------
   36.8  MOTION — one reveal, used consistently
   ------------------------------------------------------------ */

/* Headings wipe up from behind a mask. Each line is its own span so
   the mask crops per line rather than across the whole block.
   The mask has to be slightly taller than the line box or descenders
   get shaved off the bottom of every line. */
.reveal-text .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.js .reveal-text .line > span {
  display: block;
  transform: translateY(115%);
  opacity: 0;
  transition: transform 0.85s cubic-bezier(0.16, 1, 0.3, 1),
              opacity 0.6s ease;
  will-change: transform, opacity;
}

.js .reveal-text.is-visible .line > span {
  transform: translateY(0);
  opacity: 1;
}

.js .reveal-text.is-visible .line:nth-child(1) > span { transition-delay: 0.08s; }
.js .reveal-text.is-visible .line:nth-child(2) > span { transition-delay: 0.16s; }
.js .reveal-text.is-visible .line:nth-child(3) > span { transition-delay: 0.24s; }
.js .reveal-text.is-visible .line:nth-child(4) > span { transition-delay: 0.32s; }
.js .reveal-text.is-visible .line:nth-child(5) > span { transition-delay: 0.40s; }
.js .reveal-text.is-visible .line:nth-child(6) > span { transition-delay: 0.48s; }

/* The block reveal's distance and curve are declared once, with the
   rest of the reveal system in section 27. They were repeated here,
   below the `.is-visible` resets, which is what stopped those resets
   ever taking effect. */

/* On a phone the gutter is narrower than the slide distance, so a
   horizontal entrance briefly pokes past the edge and the page gains a
   few pixels of sideways scroll. Slide up instead at that width. */
@media (max-width: 768px) {
  .reveal--left,
  .reveal--right,
  .js .reveal--left,
  .js .reveal--right { transform: translateY(20px); }

  .reveal--left.is-visible,
  .reveal--right.is-visible { transform: translateY(0); }
}

/* Images resolve from a slight scale, clipped by their frame */
.js .media-reveal { overflow: hidden; }

.js .media-reveal img {
  transform: scale(1.06);
  transition: transform 1.1s var(--ease-editorial);
}

.js .media-reveal.is-visible img { transform: scale(1); }

@media (prefers-reduced-motion: reduce) {
  .js .reveal-text .line > span,
  .js .media-reveal img { transform: none !important; transition: none !important; }
}

/* ------------------------------------------------------------
   36.9  RESPONSIVE
   ------------------------------------------------------------ */
@media (max-width: 1024px) {
  .section-intro,
  .section-header { grid-template-columns: minmax(0, 1fr); align-items: start; gap: var(--space-5); }

  .section-intro .section-title,
  .section-header .section-title { max-width: 22ch; }

  .section-header .section-subtitle { grid-column: 1; padding-bottom: 0; }

  .value-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--space-8); }
  .value-item:nth-child(odd) { border-left: 0; padding-left: 0; }

  .hero { min-height: auto; padding-top: calc(var(--header-height) + var(--space-12)); }
  .hero__headline { max-width: none; }
  .hero__subheadline { max-width: 60ch; }
}

@media (max-width: 700px) {
  .value-grid { grid-template-columns: minmax(0, 1fr); padding-top: var(--space-8); }
  .value-item { border-left: 0; padding-left: 0; padding-bottom: var(--space-6); }
  .value-item + .value-item { border-top: 1px solid var(--hairline); padding-top: var(--space-6); }

  .btn-nav { padding-left: var(--space-4); }
  .page-hero { padding-bottom: var(--space-16); }
  .section-title { font-size: clamp(1.75rem, 7vw, 2.25rem); }
  .section-header { margin-bottom: var(--space-10); padding-bottom: var(--space-6); }
}

/* ============================================================
   38. HOME LAYOUT
   Dark hero band under a white header, hairline-divided feature
   rows, overlay work cards, a split "why" section, a tinted
   process band and a dark closing CTA.
   ============================================================ */

/* ------------------------------------------------------------
   38.1  Chevron motif
   The logo's mark is a chevron; these are the same angle, drawn
   large and very low contrast so they read as structure rather
   than decoration.
   ------------------------------------------------------------ */
.chevrons {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.chevrons::before,
.chevrons::after {
  content: '';
  position: absolute;
  width: 46%;
  aspect-ratio: 1;
  background: linear-gradient(135deg, rgba(67, 131, 229, 0.20), rgba(67, 131, 229, 0));
  clip-path: polygon(0 0, 48% 0, 100% 50%, 48% 100%, 0 100%, 52% 50%);
}

.chevrons--cta::before { bottom: -30%; right: 2%;  width: 26%; opacity: 0.7; }
.chevrons--cta::after  { bottom: -10%; right: -6%; width: 20%; opacity: 0.45; }

/* ------------------------------------------------------------
   38.3  Buttons used on the hero
   ------------------------------------------------------------ */
.btn-disc {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: 7px 7px 7px var(--space-6);
  border-radius: var(--radius-full);
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.3);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--transition-std), border-color var(--transition-std);
}

.btn-disc__disc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #fff;
  color: var(--c-navy);
  flex-shrink: 0;
  transition: transform 0.4s var(--ease-editorial);
}

.btn-disc__disc svg { width: 15px; height: 15px; }
.btn-disc:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.55); }
.btn-disc:hover .btn-disc__disc { transform: rotate(-45deg); }
.btn-disc:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.hero .btn-primary { box-shadow: 0 14px 32px rgba(4, 10, 28, 0.38); }

/* ------------------------------------------------------------
   38.4  Feature rows — icon, title, copy, divided by hairlines
   ------------------------------------------------------------ */
.feature-row {
  display: grid;
  gap: 0;
  list-style: none;
  padding-top: var(--space-12);
}

.feature-row--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.feature-row--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.feature {
  position: relative;
  padding: 0 var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The divider carries the detail: brand blue for its first inch, then a
   hairline, then nothing. It reads as a deliberate mark rather than as
   table ruling, and it gives the row somewhere to respond on hover. */
.feature::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 6%;
  width: 2px;
  background: linear-gradient(180deg,
    var(--c-primary) 0%,
    var(--c-primary) 22px,
    var(--hairline-strong) 22px,
    var(--hairline) 46%,
    transparent 100%);
  transition: opacity var(--transition-std);
}

.feature::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  height: 22px;
  background: var(--c-primary);
  transform: scaleY(1);
  transform-origin: top center;
  transition: transform 0.4s var(--ease-editorial);
}

.feature:hover::after { transform: scaleY(2.4); }

.feature:first-child { padding-left: 0; }
.feature:first-child::before,
.feature:first-child::after { display: none; }

.feature__icon {
  display: flex;
  align-items: center;
  color: var(--c-primary);
  margin-bottom: var(--space-2);
}

.feature__icon svg { width: 30px; height: 30px; }

.feature__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.012em;
  line-height: 1.3;
  /* two lines are reserved so a title that wraps does not push its own
     description out of line with the rest of the row */
  min-height: 2.6em;
}

.feature__desc {
  font-size: var(--text-sm);
  color: var(--c-text-soft);
  line-height: var(--leading-relaxed);
}

.feature__link {
  margin-top: auto;
  padding-top: var(--space-4);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}

.feature__link::after {
  content: '→';
  transition: transform var(--transition-std);
}

.feature:hover .feature__link::after { transform: translateX(3px); }
.feature:hover .feature__title { color: var(--c-primary); }

/* A shared inline "…→" link used in section intros */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  transition: gap var(--transition-std);
}

.link-arrow svg { width: 15px; height: 15px; }
.link-arrow:hover { gap: var(--space-3); }

/* ------------------------------------------------------------
   38.5  Work cards, the client strip and reviews
   ------------------------------------------------------------ */
.work-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
  align-items: stretch;
}

/* 2-column layout for WIP or paired card blocks */
.work-grid--2,
.wip-block .work-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 960px;
  margin-inline: auto;
}

/* Each card frames the top of a full-page screenshot. On hover the
   screenshot travels upward inside the frame, giving an interactive walkthrough. */
.work-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(16, 30, 67, 0.04);
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.35s ease,
              border-color 0.3s ease;
}

.work-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 48px rgba(16, 30, 67, 0.12), 0 4px 12px rgba(11, 95, 208, 0.06);
  border-color: rgba(11, 95, 208, 0.3);
}

.work-card__frame {
  position: relative;
  display: block;
  --frames: 3.2;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 0;
  border: none;
  border-bottom: 1px solid var(--hairline);
  background: var(--c-surface-muted);
  box-shadow: none;
  transition: none;
}

.work-card__frame img {
  display: block;
  width: 100%;
  height: auto;
  transform: translateY(0);
  /* long and eased so it reads as a walkthrough, not a jump */
  transition: transform 3.2s cubic-bezier(0.33, 0, 0.16, 1);
}

.work-card:hover .work-card__frame img,
.work-card__frame:hover img,
.work-card__frame:focus-visible img {
  /* lands with the foot of the capture on the foot of the frame */
  transform: translateY(calc(-100% + (100% / var(--frames))));
}

.work-card__live {
  position: absolute;
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background: rgba(10, 19, 48, 0.86);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 600;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--transition-std), transform var(--transition-std);
}

.work-card__live svg { width: 13px; height: 13px; }

.work-card:hover .work-card__live,
.work-card__frame:hover .work-card__live,
.work-card__frame:focus-visible .work-card__live {
  opacity: 1;
  transform: translateY(0);
}

.work-card__meta {
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-2);
}

.work-card__sector {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-primary);
  min-height: 1.4em;
}

.work-card__name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -0.018em;
  color: var(--c-heading);
  line-height: 1.3;
  min-height: 2.6em;
  display: flex;
  align-items: flex-start;
  margin-bottom: var(--space-1);
}

.work-card__line {
  font-size: var(--text-sm);
  color: var(--c-text-soft);
  line-height: var(--leading-relaxed);
  flex: 1;
}

/* --- work in progress ----------------------------------------
   These builds have nothing of ours deployed yet, so there is no
   screenshot to show and nothing worth linking to. The frame is drawn
   rather than photographed, and it says so.
   ------------------------------------------------------------ */
.work-card--wip {
  background: var(--c-surface-muted);
  border: 1px dashed var(--c-border);
}

.work-card--wip .work-card__frame {
  display: grid;
  place-items: center;
  cursor: default;
  background:
    linear-gradient(135deg, var(--c-navy) 0%, var(--c-navy-mid) 100%);
  border-bottom: 1px dashed var(--c-border);
}

.work-card--wip .work-card__name {
  min-height: auto;
}

/* a faint drafting grid, so the panel reads as a plan rather than a gap */
.work-card--wip .work-card__frame::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 34px 34px;
  mask-image: radial-gradient(120% 90% at 50% 40%, #000 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(120% 90% at 50% 40%, #000 30%, transparent 100%);
}

.wip-mark {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-3);
  justify-items: center;
  padding: var(--space-6);
  text-align: center;
}

.wip-mark__name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: #fff;
}

.wip-mark__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.86);
}

.wip-mark__status::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-primary-light);
  animation: pulse-dot 2.4s ease-in-out infinite;
}

.work-card--wip .work-card__sector { color: var(--c-text-muted); }

.work-card--wip .work-card__note {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px dashed var(--hairline);
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  font-style: italic;
}

@media (prefers-reduced-motion: reduce) {
  .wip-mark__status::before { animation: none; }
}

/* --- marquee -------------------------------------------------
   Two identical tracks side by side, each sliding left by its own
   width plus the gap. When the first has fully left, the second sits
   exactly where it started, so the loop has no seam. The second track
   is aria-hidden, or a screen reader would read everything twice.
   ------------------------------------------------------------ */
.marquee {
  --marquee-gap: var(--space-5);
  --marquee-duration: 48s;
  display: flex;
  gap: var(--marquee-gap);
  overflow: hidden;
  /* fade both ends so items enter and leave rather than being cut */
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}

.marquee__track {
  display: flex;
  flex: 0 0 auto;
  align-items: stretch;
  gap: var(--marquee-gap);
  min-width: 100%;
  animation: marquee-slide var(--marquee-duration) linear infinite;
}

@keyframes marquee-slide {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-100% - var(--marquee-gap))); }
}

/* Stop while someone is reading or tabbing through it — the cards carry
   links, and a moving target is not clickable. */
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .marquee {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    mask-image: none;
    -webkit-mask-image: none;
  }
  .marquee__track { animation: none; min-width: 0; }
  .marquee__track[aria-hidden='true'] { display: none; }
  .marquee__track > * { scroll-snap-align: start; }
}

/* --- the client strip ---------------------------------------- */
.client-strip {
  margin-top: var(--space-16);
  padding-top: var(--space-8);
  border-top: 1px solid var(--hairline);
}

.client-strip__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-bottom: var(--space-5);
}

.client-strip__list {
  --marquee-duration: 42s;
  --marquee-gap: var(--space-3);
  list-style: none;
}

.client-strip__list li { flex: 0 0 auto; }

/* Each name is a pill so the row reads as a row of businesses rather
   than a sentence running past. */
.client-strip__list a,
.client-strip__wip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-full);
  background: var(--c-white);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--c-text-strong);
  letter-spacing: -0.012em;
  white-space: nowrap;
  transition: border-color var(--transition-std), color var(--transition-std),
              box-shadow var(--transition-std);
}

.client-strip__list a:hover {
  color: var(--c-primary);
  border-color: var(--c-border-accent);
  box-shadow: 0 6px 18px rgba(16, 30, 67, 0.08);
}

/* The business's own favicon, sized down. object-fit keeps a mark that
   is not quite square from being stretched into one. */
.client-mark {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  object-fit: contain;
}

/* Used where a site has no usable icon of its own — see build_favicons.py
   for which, and why. */
.client-mark--letter {
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-soft);
  font-family: var(--font-display);
  /* two letters have to fit inside 22px: at 9.5px with tracking, a wide
     pair like MA spilled out of the circle */
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1;
  color: var(--c-primary);
}

/* Named but not linked: there is nothing live to send anyone to yet. */
.client-strip__wip {
  color: var(--c-text-soft);
  background: var(--c-surface-soft);
  border-style: dashed;
  cursor: default;
}

/* Named, not a bare `span`: the letter badge is also a span in here and
   was picking up the tag's type size and border. */
.client-strip__tag {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-primary);
  padding: 2px var(--space-2);
  border: 1px solid var(--c-border-accent);
  border-radius: var(--radius-full);
}

.wip-block {
  margin-top: var(--space-24);
  padding-top: var(--space-16);
  border-top: 1px solid var(--hairline);
}

/* --- reviews carousel -----------------------------------------
   Centre card raised, its neighbours scaled back and faded, arrows
   either side and a dot per review. Positions are set in JS because
   centring the active card depends on measured widths; everything
   else, including the fallback when JS never runs, is here.
   ------------------------------------------------------------ */
.reviews-section { background: var(--c-surface-soft); }

.testimonials { position: relative; }

/* Default is a plain scrollable row: if the script never runs, all five
   reviews are still there and still readable. */
.testimonials__viewport { overflow-x: auto; }

.js .testimonials { padding-inline: var(--space-16); }
.js .testimonials__viewport { overflow: hidden; }

.testimonials__track {
  display: flex;
  align-items: stretch;
  gap: var(--space-6);
  list-style: none;
  padding-block: var(--space-8);
  transition: transform .62s var(--ease-editorial);
}

/* draggable, but a vertical gesture still scrolls the page */
.js .testimonials__track { touch-action: pan-y; cursor: grab; }
.js .testimonials__track:active { cursor: grabbing; }

/* a drag over the copy should move the slider, not select the text */
.js .testimonial__quote,
.js .testimonial__by { user-select: none; }

.testimonial {
  flex: 0 0 clamp(290px, 32vw, 420px);
  display: flex;
  transition: opacity .5s var(--ease-editorial), transform .5s var(--ease-editorial);
}

/* the off-centre cards sit back; the script promotes one to .is-active */
.js .testimonial { opacity: .5; transform: scale(.9); }

.testimonial.is-active { opacity: 1; transform: scale(1); }

.testimonial__card {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  width: 100%;
  padding: var(--space-8) var(--space-7) var(--space-7);
  text-align: center;
  background: var(--c-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xl);
  box-shadow: 0 1px 2px rgba(16, 30, 67, .05);
  transition: border-color .5s var(--ease-editorial), box-shadow .5s var(--ease-editorial);
}

.testimonial.is-active .testimonial__card {
  border-color: var(--c-primary-soft);
  box-shadow: 0 22px 54px rgba(16, 30, 67, .14);
}

/* A portrait slot with a mark behind it. The photo is only fetched if a
   file actually exists (see loadAvatars in components.js), so until real
   photographs of these five people arrive the mark shows and nothing
   here pretends to be a face that is not theirs. */
.testimonial__avatar {
  position: relative;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  overflow: hidden;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-soft);
}

.testimonial__avatar-mark {
  font-size: 30px;
  line-height: 1;
  font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji',
               'Twemoji Mozilla', sans-serif;
}

.testimonial__avatar-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  opacity: 0;
  transition: opacity .35s var(--ease-editorial);
}

.testimonial__avatar-photo.is-loaded { opacity: 1; }

.testimonial__stars {
  display: flex;
  gap: 3px;
  color: var(--c-star);
}

.testimonial__stars svg { width: 17px; height: 17px; }

.testimonial__quote { flex: 1; }

.testimonial__quote p {
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--c-text-strong);
}

.testimonial__by { display: grid; gap: 2px; }

.testimonial__person {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--c-heading);
}

.testimonial__company {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--c-primary);
}

.testimonial__company:hover { text-decoration: underline; text-underline-offset: 3px; }

/* --- arrows --- */
.testimonials__arrow {
  display: none;
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  transform: translateY(-50%);
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--c-white);
  color: var(--c-heading);
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(16, 30, 67, .10);
  transition: background-color var(--transition-std), color var(--transition-std),
              border-color var(--transition-std), box-shadow var(--transition-std);
}

.js .testimonials__arrow { display: grid; }
.testimonials__arrow svg { width: 19px; height: 19px; }
.testimonials__arrow--prev { left: 0; }
.testimonials__arrow--next { right: 0; }

.testimonials__arrow:hover {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #fff;
  box-shadow: 0 10px 26px rgba(11, 95, 208, .28);
}

/* --- dots --- */
.testimonials__dots {
  display: none;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
}

.js .testimonials__dots { display: flex; }

.testimonials__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--c-border);
  cursor: pointer;
  transition: background-color var(--transition-std), width var(--transition-std);
}

.testimonials__dot:hover { background: var(--c-primary-light); }

.testimonials__dot.is-active {
  width: 22px;
  border-radius: var(--radius-full);
  background: var(--c-primary);
}

@media (prefers-reduced-motion: reduce) {
  .testimonials__track,
  .testimonial,
  .testimonial__card { transition: none; }
}

@media (max-width: 1024px) {
  .js .testimonials { padding-inline: var(--space-12); }
}

@media (max-width: 700px) {
  .js .testimonials { padding-inline: 0; }
  .testimonials__track { gap: var(--space-4); }
  .testimonial { flex-basis: min(80vw, 330px); }
  .testimonial__card { padding: var(--space-6) var(--space-5); }
  /* the arrows would sit on top of the cards at this width */
  .js .testimonials__arrow { display: none; }
  .client-strip__list { --marquee-duration: 30s; }
  .client-strip__list a,
  .client-strip__wip { font-size: var(--text-sm); padding: var(--space-2) var(--space-4); }
}

@media (prefers-reduced-motion: reduce) {
  .work-card__frame img { transition: none; }
  .work-card__frame:hover img,
  .work-card__frame:focus-visible img { transform: none; }
}

/* ------------------------------------------------------------
   38.6  Split section — copy left, full-bleed image right
   ------------------------------------------------------------ */
.section--split {
  padding-right: 0;
  padding-block: 0;
  overflow: hidden;
}

.section--split__copy { padding-block: var(--sec-pad); }

.section--split__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.38fr);
  gap: var(--space-16);
  align-items: center;
}

.section--split__copy { margin-inline: 0 0; padding-right: 0; }

.section--split__media {
  position: relative;
  margin: 0;
  overflow: hidden;
  align-self: stretch;
  min-height: 460px;
  background: var(--c-surface-muted);
  /* The left edge is cut on the same lean as the hero's photograph, so the
     two bleeds on the page read as one idea rather than two treatments. */
  clip-path: polygon(11% 0, 100% 0, 100% 100%, 0 100%);
}

.section--split__media img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A brand edge along the diagonal, drawn as a second clipped layer so it
   follows the cut exactly. */
.section--split__media::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--c-primary);
  clip-path: polygon(11% 0, 11.45% 0, 0.45% 100%, 0 100%);
  pointer-events: none;
}

/* ------------------------------------------------------------
   38.7  Process band
   ------------------------------------------------------------ */
.process-section { background: var(--c-primary-tint); }

.process-section__inner {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr);
  gap: var(--space-16);
  align-items: start;
}

.process-section__copy .section-title { max-width: 12ch; margin-bottom: var(--space-4); }
.process-section__copy .content-body { margin-bottom: var(--space-8); max-width: 34ch; }

.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-6);
  list-style: none;
}

.step {
  position: relative;
  display: grid;
  gap: var(--space-2);
  align-content: start;
}

/* the connector between steps */
.step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 26px;
  right: calc(var(--space-6) * -0.5 - 6px);
  width: 12px;
  height: 12px;
  border-top: 1.5px solid var(--c-primary);
  border-right: 1.5px solid var(--c-primary);
  transform: rotate(45deg);
  opacity: 0.55;
}

.step__icon {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--c-white);
  border: 1px solid var(--c-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-primary);
  margin-bottom: var(--space-3);
  transition: background-color var(--transition-std), border-color var(--transition-std),
              color var(--transition-std);
}

.step__icon svg { width: 22px; height: 22px; }

.step.is-reached .step__icon {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #fff;
}

.step__num {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--c-text-muted);
}

.step__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.015em;
}

.step__desc {
  font-size: var(--text-sm);
  color: var(--c-text-soft);
  line-height: var(--leading-relaxed);
}

/* ------------------------------------------------------------
   38.8  Closing CTA band
   ------------------------------------------------------------ */
.cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: var(--space-20);
  color: var(--c-text-on-dark);
  background:
    radial-gradient(90% 120% at 0% 0%, rgba(11, 95, 208, 0.34) 0%, transparent 56%),
    linear-gradient(135deg, #0A1330 0%, #12244F 54%, #17295B 100%);
}

.cta-band__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.95fr) auto;
  gap: var(--space-12);
  align-items: center;
}

.cta-band .section-eyebrow { color: rgba(226, 235, 248, 0.7); }
.cta-band .section-eyebrow::before { background: currentColor; }

.cta-band__title {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3vw, 2.9rem);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.028em;
  color: #fff;
  max-width: 16ch;
  margin-bottom: var(--space-4);
}

.cta-band__text {
  color: rgba(226, 235, 248, 0.74);
  line-height: var(--leading-relaxed);
  max-width: 46ch;
}

.cta-band__action {
  display: grid;
  gap: var(--space-5);
  justify-items: start;
  padding-left: var(--space-12);
  border-left: 1px solid var(--hairline-on-dark);
}

.cta-band__action p { color: rgba(226, 235, 248, 0.74); max-width: 36ch; }

.cta-band__claim {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.015em;
  color: #fff;
  text-align: right;
  white-space: nowrap;
}

/* ------------------------------------------------------------
   38.9  Responsive
   ------------------------------------------------------------ */
@media (max-width: 1280px) {
  .feature-row--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--space-10); }
  .feature-row--6 .feature:nth-child(3n + 1) { padding-left: 0; }
  .feature-row--6 .feature:nth-child(3n + 1)::before,
  .feature-row--6 .feature:nth-child(3n + 1)::after { display: none; }
}

@media (max-width: 1024px) {

  .feature-row--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--space-10); }
  .feature-row--4 .feature:nth-child(odd) { padding-left: 0; }
  .feature-row--4 .feature:nth-child(odd)::before,
  .feature-row--4 .feature:nth-child(odd)::after { display: none; }

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

  .section--split { padding-right: var(--space-6); }
  .section--split__inner { grid-template-columns: minmax(0, 1fr); gap: var(--space-12); }
  .section--split__media { border-radius: var(--radius-xl); }
  .section--split__media img { min-height: 320px; max-height: 420px; }
    .process-section__inner { grid-template-columns: minmax(0, 1fr); gap: var(--space-10); }
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-8); }
  .step:not(:last-child)::after { display: none; }

  .cta-band__inner { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .cta-band__action { padding-left: 0; border-left: 0; padding-top: var(--space-8); border-top: 1px solid var(--hairline-on-dark); }
  .cta-band__claim { text-align: left; }
}

@media (max-width: 700px) {

  .feature-row--6,
  .feature-row--4 { grid-template-columns: minmax(0, 1fr); row-gap: 0; padding-top: var(--space-8); }

  /* Stacked: the divider becomes a horizontal rule above each item. */
  .feature { padding: var(--space-6) 0 0; }
  .feature__title { min-height: 0; }

  .feature::before {
    left: 0;
    right: 0;
    top: 0;
    bottom: auto;
    width: auto;
    height: 1px;
    background: linear-gradient(90deg,
      var(--hairline-strong) 0%, var(--hairline) 46%, transparent 100%);
  }

  .feature::after {
    left: 0;
    top: 0;
    width: 30px;
    height: 2px;
    transform-origin: left center;
  }

  .feature:hover::after { transform: scaleX(1.8); }

  .feature:first-child { padding-top: 0; }
  .feature:first-child::before,
  .feature:first-child::after { display: none; }

  .work-grid,
  .work-grid--2,
  .wip-block .work-grid { grid-template-columns: minmax(0, 1fr); }

  .steps { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .cta-band { padding-block: var(--space-16); }
  .cta-band__claim { white-space: normal; }
}

/* ============================================================
   39. HERO
   Navy band at left, photograph bleeding off the right on a
   diagonal, and a Stackvel project dashboard straddling the
   two. The dashboard runs past the bottom of the band, which
   is what stops the composition sitting in a neat box.
   ============================================================ */

.hero {
  position: relative;
  display: block;
  min-height: 0;
  isolation: isolate;
  overflow: hidden;
  padding-top: var(--space-16);
  padding-bottom: var(--space-16);
  color: var(--c-text-on-dark);
  background: linear-gradient(118deg, #0A1330 0%, #0C1937 52%, #102047 100%);
}

/* The home page hero's picture is the reaching hand, which is its
   own element with its own rules — see section 68. The diagonal
   photograph panel that used to sit here is gone with it. */

/* --- Chevron motif ------------------------------------------
   Two overlapping arrows in the navy, cut at the same angle as
   the photograph's edge so they read as one geometry. */
.hero__chevron {
  position: absolute;
  top: 0;
  right: 40%;
  width: 30%;
  height: 62%;
  z-index: -1;
  pointer-events: none;
}

.hero__chevron::before,
.hero__chevron::after {
  content: '';
  position: absolute;
  inset: 0;
  clip-path: polygon(0 0, 46% 0, 100% 52%, 46% 100%, 0 100%, 54% 52%);
}

.hero__chevron::before {
  background: rgba(67, 131, 229, 0.16);
  transform: translateX(14%);
}

.hero__chevron::after {
  background: rgba(67, 131, 229, 0.10);
  transform: translateX(-16%) scale(0.86);
  transform-origin: left top;
}

/* --- Layout --------------------------------------------------
   One column. The hero used to be a two-track grid with the copy in
   one and a drawn project dashboard in the other; the dashboard is
   gone, so a second track would only be empty space the copy is
   being squeezed against.

   The column is inset from the left by section 68.1 to clear the
   hand, and held to a reading measure on the right rather than
   running to the edge of a 1560px container.
   -------------------------------------------------------------- */
.hero__content {
  position: relative;
  z-index: 1;
  display: block;
  padding-block: var(--space-8) var(--space-4);
}

.hero__text {
  /* This is the width of the headline, and the headline is what stops
     the block looking like an island.

     At 38rem it measured 608px inside a column that had 879px to give,
     which left the block's midpoint within 90px of the middle of the
     screen and 300-800px of dead space to its right — read as centred,
     however left-aligned every line inside it actually was. At 50rem
     the headline runs most of the way across the column and the copy
     reads as anchored to the left of the band.

     A block never exceeds its parent, so the narrower viewports clamp
     this themselves and it needs no breakpoint of its own. The
     paragraph keeps its own, much shorter measure below — widening
     this does not widen that. */
  max-width: 50rem;
  padding-bottom: 0;
}

/* --- Kicker -------------------------------------------------- */
.hero__kicker {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(226, 235, 248, 0.7);
}

.hero__kicker-arrow { color: rgba(226, 235, 248, 0.45); font-size: var(--text-sm); line-height: 1; }

/* --- Headline ------------------------------------------------ */
.hero__headline {
  color: #fff;
  font-family: var(--font-display);
  font-weight: 600;
  /* Sized to fill the column rather than to a number picked in the
     abstract. At the old 3.85rem cap the two lines came to about 77%
     of the 50rem column, which left a band of empty space down the
     right of the headline and was half of why the block read as
     centred. At 4.3rem they come to roughly 90%. */
  font-size: clamp(2.5rem, 4.7vw, 4.3rem);
  line-height: 1.1;
  letter-spacing: -0.028em;
  /* No ch cap. It was 12ch, which is narrower than the paragraph
     underneath — the headline wrapped to four short lines while the
     subheadline ran wider than it, so the smallest type in the block
     was setting its width. The column above is the only constraint
     now, and the headline is the widest thing in it. */
  max-width: none;
  margin-bottom: var(--space-6);
}

/* .accent is no longer used in the home hero — the blue moved to
   .hero__lead-in underneath. Kept because the class is generic and
   costs one line. */
.hero__headline .accent { color: var(--c-primary-light); }

/* --- Specialisation line ------------------------------------
   The reference carries a blue second line directly under the
   heading, naming what kind of work the company does. This is
   that line. It is the only blue in the block, which is why the
   heading above it is now plain white — two blues stacked read as
   a mistake rather than as emphasis.
   ------------------------------------------------------------ */
.hero__lead-in {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.5vw, 1.4rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
  color: var(--c-accent-on-dark);
  margin-top: calc(var(--space-6) * -1 + var(--space-2));
  margin-bottom: var(--space-6);
  text-wrap: pretty;
}

.hero__subheadline {
  color: rgba(226, 235, 248, 0.76);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  /* Inside the headline's measure on purpose, so the block steps in
     as it goes down rather than bulging in the middle. */
  max-width: 32rem;
  margin-bottom: var(--space-8);
}

/* --- Actions + hand-written aside ---------------------------- */
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
  margin-bottom: var(--space-10);
}

/* --- Stats --------------------------------------------------- */
.hero__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, max-content));
  gap: var(--space-12);
  list-style: none;
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

.hero__stat { display: flex; flex-direction: column; gap: 4px; }

.hero__stat-value {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #fff;
  line-height: 1;
}

.hero__stat-label { font-size: var(--text-sm); color: rgba(226, 235, 248, 0.64); }

/* ============================================================
   39.2  Responsive
   ============================================================ */
@media (max-width: 1380px) {
  .hero__headline { font-size: clamp(2.3rem, 4.4vw, 3.6rem); }
  .hero__subheadline { max-width: 30rem; }

  /* keep the three figures on one line */
  .hero__stats { gap: var(--space-7, 1.75rem); }
  .hero__stat-value { font-size: var(--text-2xl); }
}

@media (max-width: 1024px) {
  .hero { padding-top: var(--space-12); padding-bottom: var(--space-16); }

  .hero__chevron { display: none; }

}

@media (max-width: 760px) {
  .hero { padding-top: var(--space-10); padding-bottom: var(--space-12); }

  .hero__headline { font-size: clamp(2rem, 8.6vw, 2.6rem); max-width: none; }
  .hero__kicker { margin-bottom: var(--space-6); letter-spacing: 0.16em; }

  .hero__actions { gap: var(--space-3); margin-bottom: var(--space-10); }
  .hero__actions .btn { width: 100%; justify-content: center; }

  .hero__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
  .hero__stat-value { font-size: var(--text-2xl); }
  .hero__stat-label { font-size: 0.75rem; line-height: 1.3; }
}

/* The drawer control stays available on desktop, beside the CTA, as in the
   reference. It opens the same panel the phone layout uses. */
@media (min-width: 1025px) {
  .hamburger {
    display: flex;
    width: 44px;
    height: 44px;
    border-color: var(--c-border);
  }

  .hamburger:hover { background: var(--c-surface-soft); }
  .mobile-menu { display: flex; }
}

/* ============================================================
   40. SECTOR DIRECTORY
   The twelve industries live on one page. A card grid would be
   the site's fourth, so this is a directory instead: a sticky
   rail of sectors beside a numbered editorial stack.
   ============================================================ */

.sector-directory {
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: var(--space-10);
  align-items: start;
}

/* --- the rail ------------------------------------------------ */
.sector-rail {
  position: sticky;
  top: calc(var(--header-height) + var(--space-6));
  background: var(--c-white);
  border: 1px solid rgba(16, 30, 67, 0.08);
  border-radius: var(--radius-xl);
  padding: var(--space-5);
  box-shadow: 0 8px 24px rgba(16, 30, 67, 0.04);
}

.sector-rail__title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--hairline);
}

.sector-rail__badge {
  font-family: var(--font-display);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--c-primary);
  background: var(--c-primary-tint);
  border: 1px solid rgba(11, 95, 208, 0.12);
  padding: 2px 8px;
  border-radius: var(--radius-full);
  text-transform: none;
}

.sector-rail ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sector-rail__item a {
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid transparent;
  color: var(--c-text-soft);
  font-size: var(--text-sm);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  transition: all 0.2s ease;
}

.sector-rail__num {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--c-text-muted);
  transition: color var(--transition-std);
}

.sector-rail__label { font-weight: 500; }

.sector-rail__item a:hover,
.sector-rail__item a:focus-visible {
  color: var(--c-primary);
  border-left-color: var(--c-primary);
  padding-left: var(--space-4);
  background: var(--c-primary-tint);
}

.sector-rail__item a.is-active {
  color: var(--c-primary);
  border-left-color: var(--c-primary);
  padding-left: var(--space-4);
  background: var(--c-primary-tint);
  font-weight: 600;
}

.sector-rail__item a.is-active .sector-rail__num {
  color: var(--c-primary);
  font-weight: 700;
}

/* --- the stack ----------------------------------------------- */
.sector-list {
  display: grid;
  gap: var(--space-8);
}

.sector {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.65fr);
  gap: var(--space-6) var(--space-10);
  align-items: start;
  padding: var(--space-8);
  background: var(--c-white);
  border-radius: var(--radius-2xl);
  border: 1px solid rgba(16, 30, 67, 0.07);
  box-shadow: 0 4px 20px rgba(16, 30, 67, 0.03);
  scroll-margin-top: calc(var(--header-height) + var(--space-8));
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.35s ease,
              border-color 0.3s ease;
}

.sector:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 44px rgba(16, 30, 67, 0.08), 0 4px 12px rgba(11, 95, 208, 0.04);
  border-color: rgba(11, 95, 208, 0.25);
}

.sector__body { grid-column: 1; }

.sector__media {
  grid-column: 2;
  grid-row: 1 / span 2;
  margin: 0;
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--c-surface-muted);
  border: 1px solid rgba(16, 30, 67, 0.08);
  box-shadow: 0 8px 24px rgba(16, 30, 67, 0.06);
}

.sector__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}

.sector:hover .sector__media img {
  transform: scale(1.04);
}

.sector__caps { grid-column: 1; }
.sector__cta  { grid-column: 1 / -1; }

.sector__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
  margin-bottom: var(--space-4);
}

.sector__num {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--c-primary);
  background: var(--c-primary-tint);
  border-radius: var(--radius-md);
  padding: var(--space-1) var(--space-3);
  line-height: 1.2;
}

.sector__name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--c-heading);
  line-height: 1.2;
}

.sector__lead {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  letter-spacing: -0.01em;
  line-height: 1.4;
}

.sector__desc {
  color: var(--c-text-soft);
  line-height: var(--leading-relaxed);
  font-size: var(--text-base);
  margin-bottom: var(--space-2);
}

/* Capabilities list: modern structured cards */
.sector__caps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3) var(--space-4);
  list-style: none;
  padding-top: var(--space-5);
  border-top: 1px solid var(--hairline);
  margin-top: var(--space-4);
}

.sector__caps > li {
  position: relative;
  background: rgba(246, 248, 252, 0.7);
  border: 1px solid rgba(16, 30, 67, 0.05);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  transition: all 0.25s ease;
}

.sector__caps > li:hover {
  background: var(--c-white);
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(16, 30, 67, 0.06);
  border-color: rgba(11, 95, 208, 0.2);
}

.sector__caps > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--c-primary);
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  opacity: 0.6;
  transition: opacity 0.2s ease, width 0.2s ease;
}

.sector__caps > li:hover::before {
  opacity: 1;
  width: 4px;
}

.sector__cap-title {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.01em;
  margin-bottom: 2px;
}

.sector__cap-desc {
  font-size: var(--text-xs);
  color: var(--c-text-soft);
  line-height: var(--leading-normal);
}

.sector__cta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px dashed var(--hairline);
}

.sector__cta .link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--c-primary);
  padding: var(--space-2) var(--space-4);
  background: var(--c-primary-tint);
  border: 1px solid rgba(11, 95, 208, 0.12);
  border-radius: var(--radius-full);
  transition: all 0.25s ease;
}

.sector__cta .link-arrow:hover {
  background: var(--c-primary);
  color: var(--c-white);
  border-color: var(--c-primary);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(11, 95, 208, 0.25);
}

.sector__cta .link-arrow:hover svg {
  transform: translateX(4px);
}

@media (max-width: 1024px) {
  .sector-directory { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }

  /* Horizontal swipeable chip bar on mobile & tablet */
  .sector-rail {
    /* The twelve chips are nowrap and add up to about 1500px. As a grid
       item this element's automatic minimum is its min-content, so the
       track grew to fit all twelve instead of letting the list inside
       scroll — the page laid out 1518px wide on a 390px phone. Zero
       here is what lets the ul below actually become the scroller. */
    min-width: 0;
    position: sticky;
    top: var(--header-height);
    z-index: 20;
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(12px);
    border: 0;
    border-bottom: 1px solid var(--c-border);
    border-radius: 0;
    padding: var(--space-3) var(--space-4);
    margin: 0 calc(var(--space-4) * -1) var(--space-4);
    box-shadow: 0 4px 16px rgba(16, 30, 67, 0.05);
  }

  .sector-rail__title { display: none; }

  .sector-rail ul {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: var(--space-2);
    padding: 2px;
  }

  .sector-rail ul::-webkit-scrollbar { display: none; }

  .sector-rail__item {
    flex-shrink: 0;
  }

  .sector-rail__item a {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-full);
    background: var(--c-white);
    font-size: var(--text-xs);
    font-weight: 500;
    white-space: nowrap;
  }

  .sector-rail__item a:hover {
    border-color: var(--c-primary);
    background: var(--c-primary-tint);
  }

  .sector-rail__item a.is-active {
    background: var(--c-primary);
    color: var(--c-white);
    border-color: var(--c-primary);
    box-shadow: 0 2px 8px rgba(11, 95, 208, 0.3);
  }

  .sector-rail__item a.is-active .sector-rail__num {
    color: rgba(255, 255, 255, 0.85);
  }

  .sector-rail__num {
    font-size: 0.7rem;
    opacity: 0.7;
  }

  .sector {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--space-6);
    gap: var(--space-6);
    scroll-margin-top: calc(var(--header-height) + 64px);
  }

  .sector__body, .sector__caps, .sector__cta { grid-column: 1; }
  .sector__media { grid-column: 1; grid-row: auto; max-width: 100%; }
}

@media (max-width: 700px) {
  .sector__caps { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .sector__cta { flex-direction: column; align-items: stretch; gap: var(--space-3); }
  .sector__cta .link-arrow { justify-content: center; }
}

/* ============================================================
   60. SITE ASSISTANT (chat widget)
   Markup is built by assets/js/chatbot.js. Everything here uses
   the same tokens as the rest of the site, so the widget reads as
   part of the page rather than as a bolt-on.

   Stacking: the header sits at --z-header + 10 and the mobile
   drawer at + 5. The assistant deliberately sits below both, so an
   open navigation always covers it.
   ============================================================ */
.sv-chat {
  /* --sv-size and --sv-gap come from the floating-control tokens in
     section 69, so the back-to-top button can measure against the
     same numbers instead of repeating them. */
  position: fixed;
  right: var(--sv-gap);
  bottom: var(--sv-gap);
  z-index: calc(var(--z-sticky) + 50);
  font-family: var(--font-body);
}

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

/* --- launcher ------------------------------------------------ */
.sv-chat__launcher {
  position: relative;
  width: var(--sv-size);
  height: var(--sv-size);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-full);
  background: var(--c-primary);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(11, 95, 208, 0.34);
  transition: background-color var(--transition-std),
              transform var(--transition-std),
              box-shadow var(--transition-std);
}

.sv-chat__launcher:hover {
  background: var(--c-primary-dark);
  transform: translateY(-2px);
  box-shadow: 0 14px 38px rgba(11, 95, 208, 0.44);
}

.sv-chat__launcher:focus-visible {
  outline: 3px solid var(--c-primary-light);
  outline-offset: 3px;
}

.sv-chat__launcher-icon {
  position: absolute;
  display: grid;
  place-items: center;
  transition: opacity var(--transition-std), transform var(--transition-std);
}

.sv-chat__launcher-icon svg { width: 25px; height: 25px; }

/* one icon swaps for the other as the panel opens */
.sv-chat__launcher-icon--close { opacity: 0; transform: rotate(-90deg) scale(.7); }
.sv-chat.is-open .sv-chat__launcher-icon--open { opacity: 0; transform: rotate(90deg) scale(.7); }
.sv-chat.is-open .sv-chat__launcher-icon--close { opacity: 1; transform: none; }

/* --- panel --------------------------------------------------- */
.sv-chat__panel {
  position: absolute;
  right: 0;
  bottom: calc(var(--sv-size) + 0.875rem);
  width: min(384px, calc(100vw - 2rem));
  max-height: min(540px, calc(100vh - var(--header-height) - 6rem));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--c-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xl);
  box-shadow: 0 28px 70px rgba(16, 30, 67, 0.22);
  opacity: 0;
  transform: translateY(12px) scale(.98);
  transform-origin: bottom right;
  transition: opacity .24s var(--ease-editorial),
              transform .24s var(--ease-editorial);
}

.sv-chat.is-open .sv-chat__panel { opacity: 1; transform: none; }

/* `display: flex` above outranks the browser's own [hidden] rule, which
   left the closed panel invisible but still focusable and still able to
   swallow clicks. Both of those are put back here. */
.sv-chat__panel[hidden] { display: none; }
.sv-chat:not(.is-open) .sv-chat__panel { pointer-events: none; }

/* while the mobile drawer is open the assistant gets out of the way */
.sv-chat.is-eclipsed { opacity: 0; pointer-events: none; }

.sv-chat__header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--c-navy);
  color: #fff;
}

.sv-chat__logo { flex: 0 0 auto; width: 22px; height: 24px; object-fit: contain; }

.sv-chat__id { flex: 1; min-width: 0; }

.sv-chat__title {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #fff;
}

.sv-chat__sub {
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.68);
  margin-top: 1px;
}

.sv-chat__close {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  transition: background-color var(--transition-std);
}

.sv-chat__close:hover { background: rgba(255, 255, 255, 0.24); }
.sv-chat__close svg { width: 15px; height: 15px; }
.sv-chat__close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* --- conversation -------------------------------------------- */
.sv-chat__log {
  flex: 1;
  min-height: 148px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-4);
  background: var(--c-surface-soft);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.sv-chat__log:focus-visible { outline: 2px solid var(--c-primary); outline-offset: -2px; }

.sv-chat__msg { max-width: 88%; }
/* the enquiry form is a form, not a remark: it gets the full width */
.sv-chat__msg.sv-chat__msg--wide { max-width: 100%; width: 100%; }
.sv-chat__msg--bot { align-self: flex-start; }
.sv-chat__msg--user { align-self: flex-end; }

.sv-chat__bubble {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  overflow-wrap: anywhere;
}

.sv-chat__msg--bot .sv-chat__bubble {
  background: var(--c-white);
  border: 1px solid var(--hairline);
  border-bottom-left-radius: var(--radius-xs);
  color: var(--c-text-strong);
}

.sv-chat__msg--user .sv-chat__bubble {
  background: var(--c-primary);
  border-bottom-right-radius: var(--radius-xs);
  color: #fff;
}

.sv-chat__bubble p + p,
.sv-chat__bubble ul { margin-top: var(--space-2); }
.sv-chat__bubble ul { padding-left: var(--space-4); list-style: disc; }
.sv-chat__bubble li + li { margin-top: 2px; }

.sv-chat__bubble a {
  color: var(--c-primary);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sv-chat__bubble a:hover { color: var(--c-primary-dark); }
.sv-chat__msg--user .sv-chat__bubble a { color: #fff; }

.sv-chat__time {
  margin-top: 3px;
  font-size: var(--text-xs);
  color: var(--c-text-muted);
}

.sv-chat__msg--user .sv-chat__time { text-align: right; }

.sv-chat__fine { font-size: var(--text-xs); color: var(--c-text-soft); }

.sv-chat__cta {
  display: inline-block;
  margin-top: var(--space-1);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background: var(--c-primary);
  color: #fff !important;
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none !important;
}

.sv-chat__cta:hover { background: var(--c-primary-dark); }

/* typing indicator */
.sv-chat__dots { display: inline-flex; gap: 4px; padding: 3px 0; }

.sv-chat__dots i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--c-text-muted);
  animation: sv-chat-dot 1.3s ease-in-out infinite;
}

.sv-chat__dots i:nth-child(2) { animation-delay: .18s; }
.sv-chat__dots i:nth-child(3) { animation-delay: .36s; }

@keyframes sv-chat-dot {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30%           { opacity: 1;  transform: translateY(-3px); }
}

/* --- suggested questions ------------------------------------- */
.sv-chat__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5) 0;
  background: var(--c-white);
}

/* setChips() clears this rather than hiding it; without this the
   padding stayed behind as a grey strip above the composer. */
.sv-chat__chips:empty { display: none; }

.sv-chat__chip {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--c-border-accent);
  border-radius: var(--radius-full);
  background: var(--c-primary-tint);
  color: var(--c-primary);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  transition: background-color var(--transition-std), color var(--transition-std);
}

.sv-chat__chip:hover { background: var(--c-primary); color: #fff; }
.sv-chat__chip:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }

/* --- composer ------------------------------------------------ */
.sv-chat__composer {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--c-white);
  border-top: 1px solid var(--hairline);
}

.sv-chat__input {
  flex: 1;
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-full);
  background: var(--c-surface-soft);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--c-text-strong);
}

.sv-chat__input::placeholder { color: var(--c-text-muted); }

.sv-chat__input:focus {
  outline: none;
  border-color: var(--c-primary);
  background: var(--c-white);
  box-shadow: 0 0 0 3px var(--c-primary-tint);
}

.sv-chat__send {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-full);
  background: var(--c-primary);
  color: #fff;
  cursor: pointer;
  transition: background-color var(--transition-std);
}

.sv-chat__send:hover { background: var(--c-primary-dark); }
.sv-chat__send:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
.sv-chat__send svg { width: 18px; height: 18px; }

/* --- enquiry form -------------------------------------------- */
.sv-chat__lead {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--c-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
}

.sv-chat__field { display: grid; gap: 4px; }

.sv-chat__field label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--c-heading);
}

.sv-chat__field span[aria-hidden] { color: var(--c-primary); }
.sv-chat__field input,
.sv-chat__field select,
.sv-chat__field textarea {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  background: var(--c-white);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--c-text-strong);
}

.sv-chat__field textarea { resize: vertical; min-height: 56px; }

.sv-chat__field input:focus,
.sv-chat__field select:focus,
.sv-chat__field textarea:focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: 0 0 0 3px var(--c-primary-tint);
}

.sv-chat__field .is-invalid {
  border-color: var(--c-danger);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
}

.sv-chat__err {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--c-danger);
}

.sv-chat__err a { color: var(--c-danger); text-decoration: underline; }

.sv-chat__lead-actions { display: flex; gap: var(--space-2); margin-top: var(--space-1); }

.sv-chat__submit,
.sv-chat__cancel {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--transition-std), border-color var(--transition-std);
}

.sv-chat__submit { flex: 1; border: 0; background: var(--c-primary); color: #fff; }
.sv-chat__submit:hover { background: var(--c-primary-dark); }
.sv-chat__submit:disabled { opacity: .65; cursor: default; }

.sv-chat__cancel {
  border: 1px solid var(--c-border);
  background: var(--c-white);
  color: var(--c-text-soft);
}

.sv-chat__cancel:hover { border-color: var(--c-border-accent); color: var(--c-primary); }

/* --- the back-to-top button shares this corner --------------- */
/* --- narrow screens ------------------------------------------ */
@media (max-width: 560px) {
  .sv-chat__panel {
    position: fixed;
    right: var(--sv-gap);
    left: var(--sv-gap);
    width: auto;
    bottom: calc(var(--sv-size) + var(--sv-gap) + 0.625rem);
    max-height: min(540px, calc(100vh - var(--header-height) - var(--sv-size) - 3rem));
  }

  .sv-chat__log { padding: var(--space-4); }
  .sv-chat__chips { padding: var(--space-3) var(--space-4) 0; }
  .sv-chat__msg { max-width: 92%; }
}

@media (prefers-reduced-motion: reduce) {
  .sv-chat__panel,
  .sv-chat__launcher,
  .sv-chat__launcher-icon { transition: none; }
  .sv-chat__dots i { animation: none; }
}

@media print { .sv-chat { display: none; } }

/* ============================================================
   61. PAGE LOADER
   Hidden by default and only revealed once the inline head script
   has set `.js` on <html>. With scripting off it therefore never
   appears at all, so it can never be left covering the page.
   main.js clears it on load, with a hard cap in case a slow asset
   never settles.
   ============================================================ */
.sv-preloader { display: none; }

.js .sv-preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-toast);
  display: grid;
  place-items: center;
  gap: var(--space-6);
  background: var(--c-white);
  transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.5s;
}

.sv-preloader__inner {
  display: grid;
  justify-items: center;
  gap: var(--space-5);
}

.sv-preloader__mark {
  width: 48px;
  height: 53px;
  object-fit: contain;
  filter: drop-shadow(0 0 16px rgba(11, 95, 208, 0.24));
  animation: sv-preload-pulse 1.8s ease-in-out infinite;
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.45s ease;
}

.sv-preloader__bar {
  width: 154px;
  height: 3px;
  border-radius: var(--radius-full);
  background: rgba(16, 30, 67, 0.08);
  overflow: hidden;
  position: relative;
}

.sv-preloader__bar::after {
  content: '';
  display: block;
  width: 45%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--c-primary), #6FE8B0);
  box-shadow: 0 0 8px rgba(11, 95, 208, 0.35);
  animation: sv-preload-sweep 1.2s var(--ease-editorial) infinite;
}

.sv-preloader.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.sv-preloader.is-done .sv-preloader__mark {
  transform: scale(1.06);
  opacity: 0;
}

@keyframes sv-preload-pulse {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%      { opacity: 0.65; transform: scale(0.95); }
}

@keyframes sv-preload-sweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* A loading screen is exactly the thing someone with a vestibular
   disorder does not want moving. Keep the screen, drop the motion. */
@media (prefers-reduced-motion: reduce) {
  .sv-preloader__mark,
  .sv-preloader__bar::after { animation: none; }
  .js .sv-preloader { transition: none; }
  .sv-preloader__bar::after { width: 100%; }
}

@media print { .sv-preloader { display: none !important; } }

/* ============================================================
   62. SHARED UTILITIES + LATE CORRECTIONS
   Classes for patterns that were repeated as inline styles on
   individual pages, plus fixes to rules that did not hold at
   every breakpoint. This sits last so it settles the earlier
   sections rather than duplicating them.
   ============================================================ */

/* ------------------------------------------------------------
   62.1  Tokens the sheet referenced but never declared
   ------------------------------------------------------------ */
:root {
  --space-14: 3.5rem;
}

/* ------------------------------------------------------------
   62.2  Clearing the fixed header

   The bar is `position: fixed`, so it takes no space in flow and
   every opening band has to reserve its height itself. The hero
   padding used to be a flat value that happened to exceed the
   header at desktop and fell short of it between 769px and
   1024px, which tucked the breadcrumb under the bar. Both heroes
   now measure the reservation from --header-height, so the
   clearance is the same at every width and the home page and the
   inner pages start their copy on the same line.
   ------------------------------------------------------------ */
.hero {
  padding-top: calc(var(--header-height) + var(--space-6));
  /* The copy column carries a blue specialisation line that it did
     not used to, so the band takes a little back at the foot to keep
     the figures near the fold on a laptop. */
  padding-bottom: var(--space-12);
}

.page-hero {
  padding-top: calc(var(--header-height) + var(--space-12));
}

@media (max-width: 1024px) {
  .hero { padding-top: calc(var(--header-height) + var(--space-8)); }
  .page-hero { padding-top: calc(var(--header-height) + var(--space-10)); }
}

@media (max-width: 700px) {
  .hero { padding-top: calc(var(--header-height) + var(--space-6)); }
  .page-hero { padding-top: calc(var(--header-height) + var(--space-8)); }
}

/* ------------------------------------------------------------
   62.3  Containers and copy columns
   ------------------------------------------------------------ */
/* A reading measure inside the standard container. Legal text,
   FAQ stacks and single-column prose all used an inline
   max-width of 820px; this is that value, named. */
.container--narrow { max-width: 880px; }

/* The copy block inside an inner-page hero. Replaces the inline
   `max-width:820px;position:relative;z-index:2` that every page
   carried its own copy of. */
.page-hero__copy {
  position: relative;
  z-index: 1;
  max-width: 820px;
}

.page-hero__copy--center {
  margin-inline: auto;
  text-align: center;
  max-width: 700px;
}

.page-hero__copy--center .page-hero__title,
.page-hero__copy--center .page-hero__desc {
  max-width: none;
  margin-inline: auto;
}

.page-hero__copy--center .breadcrumbs { justify-content: center; }

/* A utility page with no photograph and no long body sits on a
   shallower band, so the document below it starts sooner. */
.page-hero--plain { padding-bottom: var(--space-16); }

/* Timestamp line under a hero description */
.page-hero__meta {
  font-size: var(--text-sm);
  color: rgba(226, 235, 248, 0.62);
  margin-top: calc(var(--space-6) * -1);
  margin-bottom: 0;
  letter-spacing: 0.01em;
}

.page-hero__meta time { color: rgba(255, 255, 255, 0.86); font-weight: 500; }

/* The eyebrow pill is always an inline-flex chip with the same
   gap beneath it; it does not need saying on each page. */
.hero__eyebrow { display: inline-flex; }
.page-hero .hero__eyebrow { margin-bottom: var(--space-5); }

/* ------------------------------------------------------------
   62.4  Button rows
   Replaces `display:flex;gap:var(--space-4);flex-wrap:wrap`
   repeated across the service pages, the industries page and 404.
   ------------------------------------------------------------ */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
}

.btn-row--center { justify-content: center; }
.btn-row--spaced { margin-top: var(--space-6); }

/* A full-width submit button keeps its label centred */
.btn.w-full { justify-content: center; }

/* ------------------------------------------------------------
   62.5  Heading and card alignment helpers
   ------------------------------------------------------------ */
/* Section titles are left-aligned by default in the editorial
   layer; this states it for the ones sitting inside a centred
   `.section-header`. */
.section-title--left { text-align: left; }

/* A service card used as a cross-link at the foot of a page
   carries no image, so it should not reserve a card's height. */
.service-card--compact { min-height: auto; }

/* A glyph standing in for a number on a benefit card */
.benefit-card__num--glyph {
  font-size: 1.75rem;
  line-height: 1;
  font-variant-emoji: text;
}

/* Arrow link used as a block element at the foot of a card */
.link-arrow--block { margin-top: var(--space-4); }

/* A card that is itself a link */
.card-link { display: block; text-decoration: none; }

/* An auto-fitting stat row */
.stat-grid--auto {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-10);
}

/* ------------------------------------------------------------
   62.6  Platform / technology tiles
   Used on the mobile app page for the Kotlin / Swift / Flutter /
   React Native row. Previously four inline-styled divs carrying a
   cyan border (rgba(14,165,233,…)) that belongs to no part of the
   Stackvel palette; these use the brand hairline instead.
   ------------------------------------------------------------ */
.platform-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}

.platform-card {
  background: var(--c-surface-soft);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  transition: border-color var(--transition-std),
              box-shadow var(--transition-std),
              transform var(--transition-std);
}

.platform-card:hover {
  border-color: var(--c-border-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}

.platform-card__label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: var(--c-primary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-3);
}

.platform-card__name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  /* 600, not 700: the loaded Plus Jakarta Sans stops at 600 and a
     heavier request is synthesised by the browser, which is what
     made these four names look different from every other
     heading on the site. */
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-2);
}

.platform-card__desc {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-normal);
  margin: 0;
}

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

/* ------------------------------------------------------------
   62.7  Form helpers (contact page)
   ------------------------------------------------------------ */
.form-card__title {
  font-size: var(--text-xl);
  margin-bottom: var(--space-2);
}

.form-card__lead {
  color: var(--c-text);
  font-size: var(--text-sm);
  margin-bottom: var(--space-6);
}

.form-note {
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  text-align: center;
  margin-top: var(--space-3);
  line-height: var(--leading-normal);
}

.form-note a {
  color: var(--c-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--c-primary-soft);
}

.form-note a:hover { text-decoration-color: var(--c-primary); }

/* Honeypot. Hidden from people but present in the DOM, because a
   bot that fills every field it finds will fill this one and a
   `display: none` field is the one bots learned to skip.

   It used to sit at `left: -9999px`. That works, but it puts a box
   ten thousand pixels to the left of the page and relies on
   `overflow-x: hidden` on <body> to hide the consequences — which
   is a wide document held back by one declaration. The standard
   clip approach takes up no space at all and needs nothing else to
   be true. */
.form-gotcha {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
}

/* ------------------------------------------------------------
   62.8  404 error code
   The number was an inline gradient clipped to text, which is the
   one decoration the rest of the site deliberately does without —
   `.text-gradient` is a flat blue everywhere else. It is now a
   solid navy numeral with the chevron blue picked up underneath.
   ------------------------------------------------------------ */
.error-code {
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 11vw, 8rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.05em;
  color: #fff;
  margin-bottom: var(--space-4);
  position: relative;
  display: inline-block;
}

.error-code::after {
  content: '';
  display: block;
  width: 56px;
  height: 3px;
  margin: var(--space-4) auto 0;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--c-primary-light), var(--c-sky-light));
}

.error-hero { min-height: 72vh; display: flex; align-items: center; }

/* ============================================================
   63. LEGAL DOCUMENTS
   Privacy Policy · Terms & Conditions · Disclaimer ·
   Cookie Policy · Refund & Cancellation Policy.

   Five pages with the same shape: a cross-link rail, a table of
   contents, numbered sections, and a closing note. They were
   previously a stack of inline-styled divs, which is why the two
   that existed did not match each other.
   ============================================================ */
.legal-section { padding-block: var(--space-16) var(--space-20); }

/* --- Cross-link rail ---------------------------------------- */
.legal-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-bottom: var(--space-8);
  margin-bottom: var(--space-8);
  border-bottom: 1px solid var(--hairline);
}

.legal-nav__link {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  border: 1px solid var(--c-border);
  background: var(--c-white);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--c-text-soft);
  transition: color var(--transition-fast),
              border-color var(--transition-fast),
              background-color var(--transition-fast);
}

.legal-nav__link:hover {
  color: var(--c-primary);
  border-color: var(--c-border-accent);
  background: var(--c-primary-tint);
}

.legal-nav__link.is-current {
  color: var(--c-white);
  background: var(--c-primary);
  border-color: var(--c-primary);
  cursor: default;
}

/* --- Table of contents -------------------------------------- */
.legal-toc {
  background: var(--c-surface-soft);
  border: 1px solid var(--c-border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-7);
  margin-bottom: var(--space-12);
}

.legal-toc__title {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-bottom: var(--space-4);
}

.legal-toc__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-8);
  list-style: none;
  counter-reset: none;
}

.legal-toc__list a {
  font-size: var(--text-sm);
  color: var(--c-text);
  line-height: var(--leading-snug);
  display: inline-block;
  padding-block: 2px;
  border-bottom: 1px solid transparent;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.legal-toc__list a:hover {
  color: var(--c-primary);
  border-bottom-color: var(--c-border-accent);
}

@media (max-width: 700px) {
  .legal-toc { padding: var(--space-5); }
  .legal-toc__list { grid-template-columns: minmax(0, 1fr); }
}

/* --- The document itself ------------------------------------ */
.legal-doc { counter-reset: legal-section; }

.legal-doc__section + .legal-doc__section {
  margin-top: var(--space-10);
  padding-top: var(--space-10);
  border-top: 1px solid var(--hairline);
}

/* An anchored section must not land under the fixed header */
.legal-doc__section { scroll-margin-top: calc(var(--header-height) + var(--space-6)); }

.legal-doc__heading {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--c-heading);
  letter-spacing: -0.02em;
  line-height: var(--leading-snug);
  margin-bottom: var(--space-5);
  text-wrap: pretty;
}

.legal-doc__num {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--c-primary);
  min-width: 2ch;
  letter-spacing: 0.04em;
}

.legal-doc__body > * + * { margin-top: var(--space-4); }

.legal-doc__body p {
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
  text-wrap: pretty;
}

.legal-doc__body a {
  color: var(--c-primary);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--c-primary-soft);
  text-underline-offset: 3px;
  transition: color var(--transition-fast), text-decoration-color var(--transition-fast);
}

.legal-doc__body a:hover {
  color: var(--c-primary-dark);
  text-decoration-color: var(--c-primary);
}

.legal-doc__body code {
  font-family: var(--font-mono);
  font-size: 0.8125em;
  background: var(--c-surface-muted);
  border: 1px solid var(--c-border-soft);
  border-radius: var(--radius-xs);
  padding: 0.1em 0.4em;
  color: var(--c-text-strong);
  overflow-wrap: anywhere;
}

/* Lists carry a marker the browser will not give a reset <ul> */
.legal-doc__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-left: var(--space-1);
}

.legal-doc__list li {
  position: relative;
  padding-left: var(--space-6);
  font-size: var(--text-base);
  color: var(--c-text);
  line-height: var(--leading-relaxed);
}

.legal-doc__list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.68em;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--c-primary);
  opacity: 0.55;
}

/* --- Contact block ------------------------------------------ */
.legal-doc__contact {
  font-style: normal;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-border-soft);
  border-left: 3px solid var(--c-primary);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-6);
  color: var(--c-text);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

.legal-doc__contact strong {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--text-base);
  color: var(--c-heading);
  margin-bottom: var(--space-1);
}

/* --- Table (cookie inventory) ------------------------------- */
.legal-doc__table-wrap {
  overflow-x: auto;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-md);
  -webkit-overflow-scrolling: touch;
}

.legal-doc__table {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  font-size: var(--text-sm);
  text-align: left;
}

.legal-doc__table th,
.legal-doc__table td {
  padding: var(--space-4) var(--space-5);
  vertical-align: top;
  border-bottom: 1px solid var(--c-border-soft);
  line-height: var(--leading-normal);
}

.legal-doc__table thead th {
  background: var(--c-surface-soft);
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--c-heading);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.legal-doc__table tbody th {
  font-weight: 600;
  color: var(--c-text-strong);
}

.legal-doc__table tbody tr:last-child th,
.legal-doc__table tbody tr:last-child td { border-bottom: 0; }

/* --- Closing note ------------------------------------------- */
.legal-note {
  margin-top: var(--space-12);
  padding: var(--space-6) var(--space-7);
  background: #FFFBEB;
  border: 1px solid #FCE9B6;
  border-radius: var(--radius-lg);
}

.legal-note__title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: #8A5A00;
  margin-bottom: var(--space-2);
}

.legal-note p {
  font-size: var(--text-sm);
  color: #7A5510;
  line-height: var(--leading-relaxed);
  margin: 0;
}

@media (max-width: 700px) {
  .legal-section { padding-block: var(--space-12) var(--space-16); }
  .legal-doc__heading { font-size: var(--text-xl); gap: var(--space-3); }
  .legal-doc__contact,
  .legal-note { padding: var(--space-5); }
}

/* ============================================================
   64. CORRECTIONS TO EARLIER RULES
   ============================================================ */

/* A keyboard-opened dropdown was given `is-open` but never the
   matching transform reset, so the Our Work panel appeared 8px
   above where the pointer-opened one sits. Both land in the same
   place now. */
.nav-dropdown.is-open { transform: translateX(-50%) translateY(0); }

/* Footer legal rail: five links rather than two, so it needs to
   wrap cleanly and sit apart from the copyright line. */
.footer-legal { row-gap: var(--space-3); column-gap: var(--space-6); }

/* Footer link hover picks up a travelling underline, matching the
   nav rather than only changing colour. */
.footer-nav__link {
  position: relative;
  display: inline-block;
  width: fit-content;
}

.footer-nav__link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 0;
  height: 1px;
  background: currentColor;
  transition: width var(--duration-std) var(--ease-out);
}

.footer-nav__link:hover::after { width: 100%; }

/* ============================================================
   65. PRINT — legal documents
   ============================================================ */
@media print {
  .legal-nav,
  .legal-toc { display: none; }

  .legal-doc__section + .legal-doc__section {
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    break-inside: avoid;
  }

  .legal-doc__contact,
  .legal-note { border: 1px solid #ccc; background: none; }

  .legal-doc__table-wrap { overflow: visible; }
  .legal-doc__table { min-width: 0; }
}

/* ------------------------------------------------------------
   66. LATE ADDITIONS — classes introduced when the inline styles
       on individual pages were consolidated
   ------------------------------------------------------------ */
/* Vertical stack of capability rows. The ERP and SaaS pages held
   this in an inline flex column while their four sibling service
   pages used a grid, which is why the same section did not match
   across the six. */
.capabilities-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.capabilities-stack .capability-item { width: 100%; }

/* A technology grid that is narrower than its row centres itself */
.tech-grid--center { justify-content: center; }

/* A FAQ stack held to a reading measure */
.faq-accordion--narrow { max-width: 880px; margin-inline: auto; }

/* Lead paragraph at body size, used where it sits beside a form */
.content-lead--sm { font-size: var(--text-base); }

/* Callout that follows a stat grid rather than opening a block */
.highlight-box--spaced { margin-top: var(--space-6); }

/* Shorter page title for the 404 and other utility pages */
.page-hero__title--sm {
  font-size: clamp(var(--text-2xl), 3vw, var(--text-4xl));
  max-width: none;
}

/* ------------------------------------------------------------
   66.1  One hero copy column, one measure

   Seven service pages held their hero copy in .page-hero__content
   (660px) while the other thirteen used an inline 820px block, so
   the opening of a service page was visibly narrower than the
   opening of every other page. All twenty now use
   .page-hero__copy; the old name is kept as an alias so any page
   added from an older template still lands in the right place.
   ------------------------------------------------------------ */
.page-hero__content {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 820px;
  text-align: left;
}

/* ============================================================
   67. PER-SERVICE HERO ACCENT

   The six service pages have carried .page-hero--web, --erp,
   --saas, --mobile, --marketing and --ai on their hero since they
   were written, and section 20 promises "each service page gets
   its own hero wash so the six pages read as a family without
   looking identical" — but the rules that were meant to follow
   that comment were never written, so all six opened identically.

   Here they are. Each is one radial highlight over the shared
   navy band, differing only in where the light falls and how far
   it reaches. Every colour is a brand blue: #0B5FD0 (the mark's
   saturated face) or #4383E5 (its lit face). Nothing new is
   introduced, and on a page that has a photograph the wash sits
   under it rather than over it, so the image is unaffected.
   ============================================================ */
.page-hero[class*="page-hero--"]::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  background: var(--hero-wash, none);
}

/* Website Development — light from the upper left, where the copy is */
.page-hero--web {
  --hero-wash: radial-gradient(70% 90% at 6% 0%, rgba(11, 95, 208, 0.38) 0%, transparent 62%);
}

/* Custom Software & ERP — a deeper, more structural glow, low and left */
.page-hero--erp {
  --hero-wash: radial-gradient(64% 104% at 0% 78%, rgba(40, 60, 120, 0.62) 0%, transparent 66%),
               radial-gradient(52% 72% at 18% 4%, rgba(11, 95, 208, 0.26) 0%, transparent 60%);
}

/* SaaS — the widest wash of the six, reaching across the band */
.page-hero--saas {
  --hero-wash: radial-gradient(86% 120% at 12% 18%, rgba(67, 131, 229, 0.30) 0%, transparent 66%);
}

/* Android & iOS — a narrow vertical shaft, the shape of a handset */
.page-hero--mobile {
  --hero-wash: radial-gradient(38% 118% at 14% 42%, rgba(67, 131, 229, 0.34) 0%, transparent 64%);
}

/* Digital Marketing & SEO — brightest of the six, rising from below */
.page-hero--marketing {
  --hero-wash: radial-gradient(74% 96% at 4% 100%, rgba(11, 95, 208, 0.42) 0%, transparent 62%);
}

/* AI & Automation — two overlapping fields rather than one */
.page-hero--ai {
  --hero-wash: radial-gradient(46% 66% at 2% 14%, rgba(67, 131, 229, 0.30) 0%, transparent 62%),
               radial-gradient(54% 78% at 26% 96%, rgba(11, 95, 208, 0.30) 0%, transparent 64%);
}

/* The services overview keeps the plain band, so the six detail
   pages are what carry the variation. */

@media (max-width: 1024px) {
  /* Stacked, the photograph covers the whole band and the wash
     would only muddy it. */
  .page-hero[class*="page-hero--"]:has(.hero__media)::before { opacity: 0.5; }
}

/* ============================================================
   68. HERO — THE REACHING HAND

   The hand enters from the left edge and reaches toward the
   headline; the hero's existing copy and project dashboard move
   across to the right of it. The navy band underneath is
   unchanged — section 39 still owns it, and nothing here paints
   a background.

   How it disappears into the band
   -------------------------------
   The photograph is graded so its field is pure black, and it is
   composited with `mix-blend-mode: screen`. Screen keeps the
   lighter of the two layers, so black contributes nothing and the
   navy shows straight through: no frame, no seam, no cut-out. A
   mask fades the right and bottom edges as well, so the picture
   ends where the light ends rather than where the file does.

   Why three elements
   ------------------
   .hero__hand         position, perspective, mask
   .hero__hand-inner   the pointer tilt, written by animations.js
   img                 the entrance, then a slow idle drift

   One transform per element. Stacking all three on one node means
   whichever runs last wins and the other two vanish.
   ============================================================ */
.hero__hand {
  position: absolute;
  inset: 0 0 0 auto;
  /* --hand-col is declared on .hero and drives both this and the
     inset on .hero__content, so the two cannot drift apart. The lit
     part of the photograph stops at 80.6% of its own width, which is
     what leaves the fingertips clear of the headline. */
  width: var(--hand-col);
  z-index: -2;
  pointer-events: none;

  /* the stage the tilt happens in */
  perspective: 1100px;
  perspective-origin: 70% 50%;

  /* Black is transparent under screen, so the whole layer can sit
     over the band without a clip-path cutting it to shape. */
  mix-blend-mode: screen;

  /* Ends the picture on light rather than on the file's edge.

     Both horizontal stops matter, and they are mirrored from the
     version that had the hand on the left. The forearm now runs off
     the right of the frame, where the pixels are near-white, so
     without the 91% stop the arm would be cut by a hard vertical
     line at the edge of the screen and read as a broken image
     rather than as a hand reaching in out of the dark. The 16% stop
     is the other end, where the fingertips approach the copy. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0%, #000 16%, #000 91%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
  mask-image:
    linear-gradient(90deg, transparent 0%, #000 16%, #000 91%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

.hero__hand-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;

  /* animations.js writes these four. The defaults mean the hand is
     correctly placed before any script runs, and stays correct if
     none ever does. */
  transform:
    rotateX(var(--hand-rx, 0deg))
    rotateY(var(--hand-ry, 0deg))
    translate3d(var(--hand-tx, 0px), var(--hand-ty, 0px), 0);
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

.hero__hand img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;

  /* `contain`, not `cover`. The picture is 3:2 and the column it
     sits in is taller than that at every width, so contain always
     resolves to "full column width, letterboxed top and bottom" —
     and the letterbox is black, which is to say invisible. Cover
     would crop the frame by an amount that changes with the
     viewport, and the first thing it crops is the fingertips. */
  object-fit: contain;
  object-position: right center;
}

/* Entrance: the hand reaches in from off the right edge rather than
   appearing where it ends up. It travels a fifth of its own width,
   turned four degrees away and slightly oversized, and settles over
   a second and a half — slow enough to read as a reach.

   Held at opacity 0 until <html> gets `is-loaded`, which main.js adds
   as the page loader lifts. Without that gate the whole entrance plays
   behind the loader and is over before anyone sees it. */
.js .hero__hand img { opacity: 0; }

.js.is-loaded .hero__hand img {
  animation: handReach 1.55s cubic-bezier(0.22, 1, 0.36, 1) both,
             handDrift 11s ease-in-out 2s infinite;
}

@keyframes handReach {
  from {
    opacity: 0;
    transform: translate3d(20%, 3%, 0) rotate(4deg) scale(1.08);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
  }
}

/* A long, shallow drift so the hand is never quite still. Amplitude
   is deliberately under 1% — enough to read as alive, not enough to
   notice as movement. */
@keyframes handDrift {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%      { transform: translate3d(-0.7%, -0.9%, 0) rotate(-0.5deg); }
}

/* ------------------------------------------------------------
   68.1  The copy moves right to clear the hand
   ------------------------------------------------------------ */
/* Both of these resolve against .hero, which has no horizontal
   padding, so one token can drive the picture's width and the inset
   that clears it. Capped at 820px because the photograph is: an
   uncapped inset kept walking right on ultra-wide screens and opened
   a band of dead navy between the fingertips and the headline. */
.hero { --hand-col: min(38%, 820px); }

/* The copy sits on the left and stops before the picture.

   It stays an ordinary centred .container, so its left edge lines up
   with every section below it rather than floating at the viewport
   gutter. The inset is on the right instead, which is what keeps the
   measure clear of the fingertips: without it the 50rem text block
   runs under the hand from about 1100px down.

   Both this and --hand-col resolve against .hero, which has no
   horizontal padding, so the two cannot drift apart. */
.hero__content {
  padding-right: calc(var(--hand-col) - 2.5%);
}

/* ------------------------------------------------------------
   68.2  Stacked layout

   Below 1024px the copy is full width, so the hand stops being a
   column and becomes a light source behind the top of the band —
   still visibly a hand, no longer competing with the headline.
   ------------------------------------------------------------ */
@media (max-width: 1024px) {
  /* The hand is no longer a column here, so the inset that held the
     copy clear of it goes back to the container's own gutter. */
  .hero__content { padding-right: var(--gutter); }

  .hero__hand {
    inset: 0 0 auto auto;
    width: 88%;
    max-width: 620px;
    height: 56%;

    /* The copy is full width here, which means it sits on top of the
       picture rather than beside it. The hand drops to a texture so
       the headline keeps its contrast — it is worth less than the
       words are. The fade runs downward, so the brightest part is
       above the first line of type rather than behind it. */
    opacity: 0.35;

    -webkit-mask-image:
      linear-gradient(90deg, transparent 0%, #000 28%),
      linear-gradient(180deg, #000 40%, transparent 96%);
    mask-image:
      linear-gradient(90deg, transparent 0%, #000 28%),
      linear-gradient(180deg, #000 40%, transparent 96%);
  }
}

@media (max-width: 700px) {
  .hero__hand {
    width: 96%;
    height: 42%;
    opacity: 0.25;
  }
}

/* ------------------------------------------------------------
   68.3  Reduced motion

   The hand stays — it is the picture, not the animation. What
   stops is everything that moves: the entrance, the drift, and
   the tilt. animations.js never attaches the pointer listener in
   this case, so --hand-rx and the rest keep their defaults.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .js .hero__hand img,
  .js.is-loaded .hero__hand img {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .hero__hand-inner { transition: none; transform: none; }
}

/* Screen blending is a compositing trick, not ink. In print the
   band is dropped anyway, so the hand goes with it. */
@media print {
  .hero__hand { display: none; }
}

/* ============================================================
   69. FLOATING CONTROLS + FORM STATES

   The back-to-top button and the form validation styles used to be
   assembled as a string in main.js and injected into <head>. They
   are here instead, so the button can be positioned against the
   chat launcher's own size rather than guessing at it.

   The two controls were pinned to the same corner with the same
   offsets — right: 1.75rem, bottom: 1.75rem — and only differed in
   stacking order, so the assistant sat directly on top of the
   back-to-top button and hid it. They now share one column, the
   launcher at the bottom and the button above it.
   ============================================================ */
:root {
  /* Owned here rather than on .sv-chat, so both controls can measure
     against the same numbers. The chat widget reads them back. */
  --float-gap:  1.75rem;
  --float-size: 58px;
  --float-stack: 0.75rem;
}

@media (max-width: 560px) {
  :root { --float-gap: 1rem; --float-size: 52px; }
}

.sv-chat {
  --sv-size: var(--float-size);
  --sv-gap: var(--float-gap);
}

.back-to-top {
  position: fixed;
  right: var(--float-gap);
  /* clear of the launcher below it, not on top of it */
  bottom: calc(var(--float-gap) + var(--float-size) + var(--float-stack));
  width: 46px;
  height: 46px;
  /* centred on the launcher's column, whatever size that is */
  margin-right: calc((var(--float-size) - 46px) / 2);
  background: var(--c-primary);
  border: none;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: var(--z-sticky);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s,
              background-color 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 6px 20px rgba(11, 95, 208, 0.32);
}

.back-to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.back-to-top svg { width: 20px; height: 20px; color: #fff; }

.back-to-top:hover {
  background: var(--c-primary-dark);
  box-shadow: 0 10px 28px rgba(11, 95, 208, 0.42);
  transform: translateY(-2px);
}

@media (max-width: 480px) {
  .back-to-top { width: 42px; height: 42px; margin-right: calc((var(--float-size) - 42px) / 2); }
}

/* An open assistant covers the corner on a phone. The button behind
   it has nothing to scroll and nothing to be tapped through. */
body:has(.sv-chat.is-open) .back-to-top {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

@media print { .back-to-top { display: none; } }

@media (hover: none) {
  .back-to-top:hover { transform: translateY(0); box-shadow: 0 6px 20px rgba(11, 95, 208, 0.32); }
}

@media (prefers-reduced-motion: reduce) {
  .back-to-top { transition: opacity 0.01ms, visibility 0.01ms; transform: none; }
  .back-to-top.is-visible { transform: none; }
  .back-to-top:hover { transform: none; }
}

/* --- Form states, applied by forms.js ----------------------- */
.form-control.is-invalid {
  border-color: var(--c-danger);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
}

.form-error {
  font-size: var(--text-xs);
  color: var(--c-danger);
  margin-top: var(--space-1);
  display: block;
  font-weight: 500;
}

#form-success {
  padding: var(--space-4) var(--space-5);
  background: var(--c-success-soft);
  border: 1px solid #C4EBDC;
  border-radius: var(--radius-sm);
  color: #0B7A55;
  font-size: var(--text-sm);
  margin-bottom: var(--space-4);
}

#form-error {
  padding: var(--space-4) var(--space-5);
  background: #FEF2F2;
  border: 1px solid #FDE0E0;
  border-radius: var(--radius-sm);
  color: #B42318;
  font-size: var(--text-sm);
  margin-bottom: var(--space-4);
}

/* ============================================================
   70. TAP TARGETS AND MINIMUM TEXT SIZE

   Both of these were measured in a real engine across twenty pages
   at thirteen widths, not estimated. The numbers in the comments
   are what was rendering before each fix.

   Target size is keyed on `pointer: coarse` rather than on a width,
   because the thing that makes a 22px link hard to hit is a
   fingertip, not a narrow screen — a touch laptop at 1280px has the
   same problem and a mouse at 380px does not.

   WCAG 2.5.8 (AA) asks for 24x24 CSS pixels. That is the floor used
   here; the controls that can comfortably take 44px are given 44px.
   ============================================================ */

/* --- Text that was under 12px ------------------------------- */

/* was 8.5px. Two letters inside a 22px circle is what forced it
   that small, so the circle grew rather than the type shrinking
   further. The image marks in the same strip use the same token,
   so they grow with it and the row stays even. */
.client-mark { width: 28px; height: 28px; }
.client-mark--letter { font-size: 0.75rem; letter-spacing: -0.03em; }

/* was 10.9px and 11.2px */
.sector-rail__badge { font-size: 0.75rem; }

@media (max-width: 1024px) {
  .sector-rail__num { font-size: 0.75rem; }
}

/* was 11px — uppercase and tracked, but still 11px */
.platform-card__label { font-size: 0.75rem; }

/* was 11.4px inside 14px body copy */
.legal-doc__body code { font-size: 0.875em; }

/* --- Tap targets -------------------------------------------- */
@media (pointer: coarse) {
  /* was 22px tall: the eight footer links, the five legal links and
     the contact rows underneath them */
  .footer-nav__link,
  .footer-legal a,
  .footer-contact-item a,
  .legal-toc__list a,
  .link-arrow,
  .testimonial__company,
  .note__related a,
  .breadcrumb-item a {
    min-height: 24px;
    display: inline-flex;
    align-items: center;
  }

  /* .link-arrow keeps its icon beside the label */
  .link-arrow { gap: var(--space-2); }

  /* The testimonial carousel sits its off-centre cards back at
     scale(.9). A transform scales what is painted, not what is
     laid out, so a link measuring 24px in the box model rendered
     at 21.6px and was that much smaller under a fingertip — and
     those cards are tappable, not decoration. The fade still marks
     which card is current; the shrink is what has to go on touch. */
  .js .testimonial { transform: none; }

  /* was 29px — a phone number is the one thing in the drawer most
     likely to be tapped in a hurry */
  .mobile-menu__call {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* was 30px square */
  .footer-social__link { width: 44px; height: 44px; }

  /* was 35px — the small button in the footer contact column */
  .btn-sm { min-height: 44px; padding-block: var(--space-3); }

  /* was 8x8, which fails even the 24px minimum. The visible dot
     stays 8px: the padding is what grows, and background-clip keeps
     the colour off it, so the control is 24px and looks unchanged. */
  .testimonials__dot {
    width: 8px;
    height: 8px;
    padding: 8px;
    background-clip: content-box;
    box-sizing: content-box;
  }

  .testimonials__dot.is-active { width: 22px; }

  /* the dots now carry their own spacing */
  .testimonials__dots { gap: 0; margin-top: var(--space-4); }
}

/* ============================================================
   71. HOME PROCESS TIMELINE ON NARROW SCREENS

   The home page's process list is `.steps > .step`; the six
   service pages use `.process-steps > .process-step`. The list
   items carry both classes, because animations.js drives the
   progress fill off `.process-step`.

   That shared class is where this went wrong. responsive.css
   turns the timeline sideways at 1024px by styling
   `.process-step` — including a connecting rail drawn at
   `left: 27px`, which lines up with the centre of the 56px
   circle in the service-page layout.

   On the home page only half of that landed. The container is
   `.steps`, not `.process-steps`, so the rule that reshapes the
   list never matched, and `.step` is a grid rather than a flex
   column, so `flex-direction: row` did nothing either. The rail
   was drawn anyway, straight down a column of full-width text:
   the line ran through "Discover", through "Plan", and through
   the first characters of every description under them.

   Rather than delete the rail, the home page now gets the row
   layout it was drawn for — icon in a fixed first column, copy
   in the second, rail behind the icons where it belongs. It is
   also about a third the height the stacked version was.
   ============================================================ */
@media (max-width: 1024px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    max-width: 560px;
    margin-inline: auto;
  }

  /* icon column, then copy. The icon spans all three rows so the
     rail can run from under it to the next step. */
  .step {
    grid-template-columns: 52px minmax(0, 1fr);
    column-gap: var(--space-5);
    row-gap: var(--space-1);
    align-items: start;
    padding-bottom: var(--space-8);
  }

  .step__icon {
    grid-column: 1;
    grid-row: 1 / span 3;
    margin-bottom: 0;
  }

  .step__num   { grid-column: 2; grid-row: 1; }
  .step__title { grid-column: 2; grid-row: 2; }
  .step__desc  { grid-column: 2; grid-row: 3; }

  /* The rail sits on the centre line of the 52px icon: 26px, less
     half the 2px stroke. responsive.css puts it at 27px for the
     service pages' 56px circle, so it is restated here rather
     than shared — the two circles are different sizes. */
  .step.process-step::before {
    left: 25px;
    top: 60px;
  }

  .step:last-child { padding-bottom: 0; }

  /* the desktop chevron between columns has no meaning stacked */
  .step:not(:last-child)::after { display: none; }
}

@media (max-width: 480px) {
  .step { column-gap: var(--space-4); }
  .step__desc { font-size: var(--text-sm); }
}
