/* Portall replica — tokens taken from www.portall.in Framer CSS */

:root {
  /* One brand orange across the site: #f16724 for every fill and every orange
     word. The role names are kept so the site reads from one place, but they
     all resolve to the brand colour.

       --orange       fills, rules, dots, icons
       --orange-text  orange words on a light ground
       --orange-deep  fills that carry white words
       --orange-alt   orange words on a dark ground (lighter, pre-existing)

     One value, by decision: #f16724 is the Portall orange and the site uses no
     other. The near-misses that had crept in (#f97316 for words on dark, and
     #ff7d24 for the banner) now resolve to it as well. #eb5105 stays, but only
     as the pressed/hover step, never as a resting colour.

     Known tradeoff, recorded so it is not rediscovered as a bug: #f16724 is
     3.13:1 against white, so white button labels and orange body text sit
     under the 4.5:1 WCAG AA asks for. #c2410c (5.18:1) is the accessible
     variant if that is ever revisited. */
  --orange: #f16724;
  --orange-600: #eb5105;
  --orange-text: #f16724;
  --orange-deep: #f16724;
  --orange-deep-600: #eb5105;
  --orange-alt: #f16724;
  --orange-banner: #f16724;
  --orange-soft: rgba(241, 103, 36, 0.08);
  --orange-tint: #fff9f6;
  --peach: #fee5d4;
  --impl-bg: #ffede0;
  --ink: #191a15;
  --ink-2: #1a1a1a;
  --heading: #001122;
  --body: #191a15;
  /* #a6a6a6 measured 2.43:1 — below the 3:1 even display type needs. */
  --muted: #8a8a8a;
  /* #657790 sat at 4.38:1 on the tinted panels it is mostly used on. */
  --slate: #5b6b82;
  --nav-link: #3c3c4399;
  --navy: #0f172a;
  --gray-300: #d1d5db;
  --gray-600: #4b5563;
  --gray-700: #374151;
  --white: #ffffff;
  --footer-bg: #242323;
  --line: #e6e6e6;
  --font-body: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  /* One family, Inter. --font-alt was Poppins for a single row on the
     governance page; a second family for one element is a cost with no
     benefit, so the role name stays and resolves to Inter. */
  --font-alt: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  /* 1200px of content + 2x16px padding, so content starts at x=120 on a 1440 viewport. */
  --container: 1264px;
  --nav-w: 1280px;
  --radius-card: 13px;
  --radius: 12px;
  --radius-lg: 20px;
  --radius-pill: 40px;
  --shadow-card: 0 20px 50px rgba(18, 17, 39, 0.08);
  --shadow-stack: 0 20px 20px rgba(18, 17, 39, 0.08);
  --nav-h: 66px;
}

*,
*::before,
*::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6em;
  letter-spacing: -0.02em;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* height:auto matters as much as max-width here. Most of the content images
   carry width and height attributes from the original export (one is
   1990x1302). Constraining only the width leaves the attribute height in
   force, and the picture stretches instead of scaling. Anything that needs a
   real height sets one in its own rule, which outranks this. */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
h1, h2, h3, h4, h5, h6 { margin: 0; color: var(--ink); font-weight: 700; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* The gutter was a flat 16px, so content ran into the screen edge on laptops
   and phones alike. It now grows with the viewport. --container was widened by
   the same 32px, so the content measure on a wide desktop is still 1200px. */
.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(20px, 2.4vw, 32px);
}

.page-shell { min-height: 40vh; overflow-x: visible; }

/* Section padding is symmetric by default; live tunes it per band, so both
   halves are overridable from the section's own style attribute. */
.section { padding: var(--section-pt, clamp(56px, 5.5vw, 88px)) 0 var(--section-pb, clamp(56px, 5.5vw, 88px)); }
.section--tight { padding: clamp(28px, 2.6vw, 40px) 0; }
.section--soft { background: #f9f9f9; }

.card {
  background: var(--white);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow-card);
}

.h-hero {
  font-size: 60px;
  line-height: 67px;
  font-weight: 700;
  color: var(--ink);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.h-hero .text-muted { color: var(--muted) !important; }

.h-section {
  font-size: 28px;
  line-height: 1.2em;
  font-weight: 700;
  letter-spacing: normal;
  color: var(--ink);
}

.h-section--left {
  font-size: 24px;
  line-height: 1.4em;
  font-weight: 600;
  letter-spacing: normal;
  color: var(--heading);
  text-align: left;
}

.h-card {
  font-size: 18px;
  line-height: 1.4em;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--ink);
}

.text-lead { font-size: 16px; line-height: 28px; color: var(--gray-600); }
.text-body { font-size: 16px; line-height: 1.6em; letter-spacing: -0.02em; color: var(--ink); }
.text-orange { color: var(--orange-text); }
.text-muted { color: var(--muted) !important; }
.text-center { text-align: center; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border: 0;
  border-radius: var(--radius-pill);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  padding: 12px 27px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .3s ease, color .3s ease, transform .25s cubic-bezier(.33, .04, .63, .93);
}

.btn--primary { background: var(--orange-deep); color: var(--white); }
.btn--primary:hover,
.btn--primary:focus {
  background: var(--orange-deep-600);
  color: var(--white);
}
.btn--white { background: var(--white); color: var(--orange-text); }
.btn--white:hover,
.btn--white:focus {
  background: #fff6f0;
  color: var(--orange);
}
.btn--sm { padding: 13px 27px; font-size: 14px; }
.btn--hero { padding: 13px 27px; font-size: 14px; }

.orb {
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  /* Was --orange-alt (#f97316): a second orange, and only 2.8:1 behind the
     white arrow, under the 3:1 a control glyph needs. The brand fill is
     3.13:1 and matches every other orange surface on the page. */
  background: var(--orange);
  color: #fff;
  display: grid;
  place-items: center;
  flex: none;
  cursor: pointer;
  transition: background-color .3s ease, transform .25s cubic-bezier(.33, .04, .63, .93);
}
.orb:hover { background: var(--orange-600); transform: scale(1.04); }
.orb svg { display: block; }

.link-more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 14px;
  font-weight: 500;
  line-height: 180%;
  color: var(--orange-text);
  transition: color .2s ease, gap .2s ease;
}
a:hover .link-more {
  color: var(--orange-deep);
  gap: 12px;
}

/* Arrow glyph shared by "Learn more" and "See all Case Studies". */
.link-more::after,
.cs__all::after {
  content: "";
  width: 20px;
  height: 20px;
  flex: none;
  background: url("../assets/images/Nt8r264OzJ9jiJul26vDxZdo2sI.svg") center / contain no-repeat;
}

.section-head { margin-bottom: 30px; }
.section-head p { margin-top: 8px; }

@media (max-width: 1199px) {
  .h-hero { font-size: 50px; line-height: 67px; }
  .h-section { font-size: 24px; }
}

@media (max-width: 949px) {
  .h-hero { font-size: 36px; line-height: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  html { scroll-behavior: auto; }
}


.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 23px;
  padding: 31px 0 0;
  overflow: visible;
}

.hero__copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 25px;
  width: min(71%, 1064px);
  padding: 0 20px;
  text-align: center;
}

.hero__title { margin: 0; }
.hero__line { display: block; }

.hero__sub {
  width: min(452px, 100%);
  font-size: 16px;
  font-weight: 500;
  line-height: 24px;
  color: var(--ink);
  letter-spacing: 0;
}

.hero__sub strong { font-weight: 700; }

/* Full-bleed to the right edge; first card lines up with the other carousels. */
/* The track is 1406px of cards that JS translates, so the stage clips it the
   way .impl__stage and .cs__stage clip theirs. Left visible, the track set the
   document width — 1439px at every viewport — and every page carrying this hero
   panned sideways on a phone. The arrows sit 20px inside the stage, so they are
   not affected. */
.hero__stage {
  position: relative;
  width: 100%;
  height: 389px;
  padding: 0 0 0 max(16px, calc(50% - 600px));
  overflow: hidden;
}

.hero__viewport {
  overflow: visible;
  height: 377px;
  display: flex;
  align-items: center;
}

.hero__track {
  display: flex;
  align-items: flex-end;
  gap: 25px;
  transition: transform .4s cubic-bezier(.22, 1, .36, 1);
  touch-action: pan-y;
}

/* One card shape for all five. The cards used to be a coloured tile with the
   artwork cut out and hung outside the bounds (the ship ran 90px past the left
   edge, the crane 40px above the top), each with its own hand-tuned inset.
   Now the card is white, the colour sits in a fixed 200px panel at the top,
   and every image is contained inside that panel. */
.hero__card {
  flex: none;
  width: 260px;
  height: 290px;
  border-radius: 13px;
  position: relative;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 5px 20px rgba(0, 0, 0, .1);
  display: flex;
  flex-direction: column;
  cursor: pointer;
  will-change: transform;
  transition: transform .25s cubic-bezier(.33, .04, .63, .93);
}
.hero__card:hover { transform: translateY(-8px); }

.hero__media {
  position: relative;
  height: 200px;
  flex: none;
  overflow: hidden;
  display: grid;
  place-items: center;
  padding: 12px;
}
.hero__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

.hero__caption {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px 16px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: var(--ink);
}

/* The variants carry the panel colour and nothing else. */
.hero__card--pcs  .hero__media { background: #5fc09b; }
.hero__card--tos  .hero__media { background: #c2aee6; }
.hero__card--pmis .hero__media { background: #ebd424; }
.hero__card--tsm  .hero__media { background: #30bed1; }

/* MSW is a photograph, not a cutout on a colour: it fills the panel edge to
   edge, so it crops rather than fits and takes no padding. */
.hero__card--msw .hero__media { background: #fff; padding: 0; }
.hero__card--msw .hero__media img { object-fit: cover; }

.hero__arrows {
  position: absolute;
  top: 50%;
  left: 20px;
  right: 20px;
  transform: translateY(-50%);
  display: flex;
  justify-content: space-between;
  pointer-events: none;
  z-index: 3;
}
.hero__arrows .orb { pointer-events: auto; }
.orb.is-disabled {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

/* trade platform */
.platform { padding: clamp(56px, 5.5vw, 88px) 0; }

.platform__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 465px);
  gap: 30px;
  align-items: stretch;
}

.platform__left {
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 687px;
}

.platform__title { text-align: left; max-width: none; }

.platform__list { display: grid; gap: 20px; }

.platform__card {
  display: grid;
  grid-template-columns: 85px 1fr 35px;
  gap: 24px;
  align-items: center;
  width: 100%;
  padding: 24px 15px;
  background: #fff;
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  transition: transform .25s cubic-bezier(.33, .04, .63, .93), box-shadow .25s ease, background-color .2s ease;
}
.platform__card:hover {
  transform: translateY(-4px);
  box-shadow: 0 24px 56px rgba(18, 17, 39, .12);
  background: var(--orange-tint);
}

.platform__icon-wrap {
  width: 85px;
  height: 85px;
  display: grid;
  place-items: center;
}
.platform__icon {
  width: 56px;
  height: 56px;
  object-fit: contain;
  border-radius: 14px;
  background: rgba(241, 103, 36, 0.12);
  padding: 10px;
  box-sizing: border-box;
}
.platform__name { font-size: 18px; font-weight: 600; line-height: 1.2em; margin-bottom: 6px; }
.platform__chevron {
  width: 35px;
  height: 35px;
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
  display: grid;
  place-items: center;
  flex: none;
  transition: background-color .2s ease;
}
.platform__card:hover .platform__chevron { background: var(--orange-600); }

.platform__art {
  width: 100%;
  height: 100%;
  min-height: 286px;
  object-fit: cover;
  border-radius: 16px;
  justify-self: end;
}

/* The card rows need real width: the right column holds its 280px minimum, so
   below this the left column collapses to ~48px and the art overlaps the
   heading. Same breakpoint as .os__inner, the structurally identical section. */
@media (max-width: 900px) {
  .platform__inner { grid-template-columns: 1fr; gap: 24px; }
  .platform__art { min-height: 220px; max-height: 300px; justify-self: stretch; }
}

/* The same shrink .os__item already gets, which .platform__card never did:
   85px of icon and 35px of chevron, two 24px gaps and 30px of padding left the
   label 90px on a 320px phone, and the card would not go below its 112px
   min-content — so index.html scrolled sideways at that width. */
@media (max-width: 639px) {
  .platform__card { grid-template-columns: 60px 1fr 28px; gap: 16px; padding: 20px 14px; }
  .platform__icon-wrap { width: 60px; height: 60px; }
  .platform__icon { max-width: 100%; height: auto; }
}

/* operating systems */
.os { padding: clamp(64px, 6vw, 96px) 0; }
.os__heading { margin-bottom: 28px; }

.os__inner {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: 26px;
  align-items: stretch;
}

.os__art { border-radius: 16px; overflow: hidden; }
.os__art img { width: 100%; height: 100%; min-height: 360px; object-fit: cover; display: block; }

.os__list {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid #EDF1F6;
  border-radius: 16px;
  box-shadow: 0 10px 34px rgba(16, 29, 54, .06);
  overflow: hidden;
}

.os__item {
  display: grid;
  grid-template-columns: 83px 1fr;
  gap: 17px;
  align-items: center;
  flex: 1;
  padding: 24px 28px;
  text-decoration: none;
  transition: background .2s ease;
}
.os__item + .os__item { border-top: 1px solid #EDF1F6; }
.os__item:hover { background: #FFF8F4; }

.os__icon-wrap {
  width: 83px; height: 82px;
  display: grid; place-items: center;
  background: #FDECE3;
  border-radius: 14px;
}
.os__icon { width: 48px; height: 48px; object-fit: contain; }

.os__name { margin: 0 0 6px; font-size: 18px; font-weight: 700; color: #0B2545; }
.os__desc { margin: 0 0 10px; font-size: 15px; line-height: 1.5; color: #5A6B84; }
.os__item .link-more { font-size: 14px; font-weight: 600; color: var(--orange-text); }

@media (max-width: 900px) {
  .os__inner { grid-template-columns: 1fr; }
  .os__art img { min-height: 220px; }
  .os__item { padding: 20px; gap: 16px; grid-template-columns: 52px 1fr; }
  .os__icon-wrap { width: 52px; height: 52px; border-radius: 12px; }
  .os__icon { width: 26px; height: 26px; }
}
.nav {
  position: sticky;
  top: 0;
  z-index: 60;
  background: #fff;
  display: flex;
  justify-content: center;
  padding: 6px 0;
}

/* Same rail as .container (1232px box, 16px gutter) so the logo and the CTA
   line up with every section below. */
.nav__inner {
  width: 100%;
  max-width: var(--container);
  min-height: 54px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 16px;
  position: relative;
}

.nav__logo {
  width: 20%;
  min-height: 50px;
  display: flex;
  align-items: center;
}
.nav__logo img { height: 50px; width: auto; max-width: none; object-fit: contain; }

.nav__links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
}

.nav__links > a,
.nav__dropdown-trigger {
  font-size: 14px;
  font-weight: 500;
  line-height: 24px;
  color: var(--nav-link);
  background: none;
  border: 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color .2s ease;
}

.nav__links > a.is-active { color: var(--navy); }
.nav__links > a:hover,
.nav__links > a.is-active:hover,
.nav__dropdown-trigger:hover,
.nav__dropdown-trigger.is-open { color: var(--orange-text); }

/* This padding is the tallest item in the bar, so it sets the header height. */
.nav__dropdown { position: static; padding: 14px 0; }
.nav__dropdown-trigger svg { color: var(--nav-link); }

.nav__mega {
  position: absolute;
  top: calc(100% - 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 70;
  width: 1046px;
  max-width: min(1046px, 90vw);
  height: 370px;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 16px 50px rgba(0, 0, 0, 0.12);
  padding: 25px 30px;
  display: flex;
  align-items: flex-start;
  gap: 30px;
  overflow: hidden;
}

.nav__mega-col {
  flex: 1 1 0;
  max-width: 485px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.nav__mega-heading {
  margin: 0;
  padding: 0 8px 4px;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--orange-text);
}

.nav__mega-item {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 16px;
  align-items: center;
  padding: 12px 8px;
  border-radius: 12px;
  transition: background-color .2s ease;
}
.nav__mega-item:hover { background: var(--orange-soft); }
.nav__mega-item:hover .nav__mega-title { color: var(--orange-text); }

.nav__mega-icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: rgba(241, 103, 36, 0.12);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.nav__mega-icon img {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.nav__mega-copy { min-width: 0; }
.nav__mega-title { display: block; font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.nav__mega-blurb { display: block; margin-top: 4px; font-size: 12px; line-height: 18px; color: #666; }

/* Articles menu: case studies and articles side by side, three of each, each
   column closing on a "View more" link to its full page. The case-study
   thumbnail is a photo, cropped to fill; an article's is usually an icon,
   so it is shown whole on the same tint as the solution icons. */
.nav__mega--articles { height: auto; }
.nav__mega-item--article { grid-template-columns: 72px 1fr; }
.nav__mega-thumb {
  width: 72px;
  height: 54px;
  border-radius: 10px;
  overflow: hidden;
  background: rgba(241, 103, 36, 0.12);
  display: grid;
  place-items: center;
}
.nav__mega-thumb img { width: 100%; height: 100%; object-fit: cover; }
/* Articles carry a photo like the case studies, so their menu thumbs look the same. */
.nav__mega-title--clamp,
.nav__mega-blurb--clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
.nav__mega-empty { margin: 0; padding: 12px 8px; font-size: 13px; line-height: 20px; color: #666; }
.nav__mega-more {
  align-self: flex-start;
  margin: 10px 8px 0;
  display: inline-flex;
  align-items: center;
  padding: 8px 18px;
  border: 1px solid var(--orange-text);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  line-height: 20px;
  color: var(--orange-text);
  transition: background-color .2s ease, color .2s ease;
}
.nav__mega-more:hover { background: var(--orange-text); color: #fff; }
/* The Articles trigger stands for the Case Studies and Articles pages. */
.nav__dropdown-trigger.is-active:not(:hover):not(.is-open) { color: var(--navy); }

.nav__cta { width: 20%; display: flex; justify-content: flex-end; }

/* 44px: the primary mobile nav control, held to the iOS/Android tap minimum. */
.nav__burger { display: none; width: 44px; height: 44px; border: 0; background: transparent; padding: 10px; }
.nav__burger span { display: block; height: 2px; background: var(--ink); border-radius: 2px; margin: 5px 0; }
.nav__burger.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__burger.is-open span:nth-child(2) { opacity: 0; }
.nav__burger.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav__drawer {
  display: none;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  max-width: var(--container);
  padding: 12px 16px 22px;
  border-top: 1px solid #eceff3;
  background: #fff;
}

.nav__drawer > a,
.nav__drawer-toggle {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  padding: 12px 2px;
  border: 0;
  background: none;
  text-align: left;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #f2f2f2;
  transition: color .2s ease;
}
.nav__drawer > a:hover,
.nav__drawer-toggle:hover { color: var(--orange-text); }

.nav__drawer-sub { display: grid; padding: 4px 0 8px 12px; }
.nav__drawer-sub a { font-size: 14px; color: var(--slate); padding: 10px 0; transition: color .2s ease; }
.nav__drawer-sub a:hover { color: var(--orange-text); }
.nav__drawer-cta { margin-top: 14px; width: 100%; }

@media (max-width: 1199px) {
  .nav__links, .nav__cta { display: none; }
  .nav__burger { display: block; }
  .nav__drawer { display: flex; }
  .nav__logo { width: auto; }
}


/* Sits directly under the logo strip, sharing that section's rhythm. */
.stats { padding: 26px 16px 60px; }

.stats__title { margin-bottom: 30px; }

/* The stats row is wider than the page container, so it opts out of it. */
.stats .container {
  max-width: none !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}

.stats__row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  max-width: 1300px;
  margin: 0 auto;
}

.stats__item {
  flex: 1 0 0;
  text-align: center;
  padding: 8px;
}

.stats__rule {
  flex: none;
  width: 1px;
  height: 78px;
  background: var(--orange);
}

.stats__row--cards { gap: 24px; }
.stats__row--cards .stats__item {
  padding: 22px 18px;
  border: 1px solid var(--line);
  border-radius: 12px;
}

.stats__label {
  font-size: 24px;
  line-height: 36px;
  font-weight: 400;
  color: var(--ink);
}

.stats__value {
  font-size: 24px;
  line-height: 36px;
  font-weight: 700;
  color: var(--orange-text);
}

@media (max-width: 949px) {
  .stats__row { flex-direction: column; }
  .stats__rule { width: 80px; height: 3px; }
}


.marquee {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: clamp(56px, 5.5vw, 88px) 0 0;
}

/* This band's heading runs looser leading than the shared .h-section value. */
.marquee__title { margin: 0; line-height: 1.4em; }

.marquee__line {
  width: 205px;
  height: 4px;
  margin: 10px 0 22px;
  display: block;
}

.marquee__track {
  width: 100%;
  height: 90px;
  overflow: hidden;
  display: flex;
  align-items: center;
  /* Greyscale keeps the strip calm, but .53 left the logos too faint to read —
     which defeats the point of a "trusted by" band. */
  filter: grayscale(1);
  opacity: .75;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 12.5%, #000 87.5%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 12.5%, #000 87.5%, transparent 100%);
}

.marquee__row {
  display: flex;
  align-items: center;
  gap: 50px;
  width: max-content;
  padding: 10px 0;
  animation: slide-left 40s linear infinite;
}

/* Each logo carries its own box size inline, as on live — they are not
   normalised to a common height. */
.marquee__row img {
  object-fit: contain;
  flex-shrink: 0;
}

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

@keyframes slide-left {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}


.trust {
  background: var(--orange-tint);
  padding: clamp(24px, 2.4vw, 36px) 0;
}

.trust__inner {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 50px;
  align-items: start;
  max-width: 1200px;
}

.trust__left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 32px;
  padding-bottom: 15px;
}

.trust__intro {
  max-width: 580px;
  font-size: 16px;
  line-height: 1.6em;
  letter-spacing: -0.02em;
  text-align: left;
  color: var(--ink);
}

.trust__cert {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 15px;
}

.trust__cert img:nth-child(1) { width: 73px; height: 73px; object-fit: contain; }
.trust__cert img:nth-child(2) { width: 78px; height: 62px; object-fit: contain; }
.trust__cert img:nth-child(3) { width: 60px; height: 60px; object-fit: cover; border-radius: 5px; }
/* Caption sits on its own line beneath the logos. */
.trust__cert span {
  width: 100%;
  margin-top: 6px;
  font-size: 16px;
  font-weight: 400;
  color: var(--slate);
}

.trust__right {
  display: flex;
  flex-direction: column;
  gap: 23px;
  max-width: 509px;
}

.trust__pillar {
  display: grid;
  grid-template-columns: 60px 1fr;
  gap: 20px;
  align-items: flex-start;
}

.trust__icon {
  width: 60px;
  height: 61px;
  background: #fff;
  box-shadow: 0 4px 9px #0000000d;
  border-radius: 8px;
  display: grid;
  place-items: center;
}

.trust__pillar h3 { margin-bottom: 6px; }
.trust__pillar .text-body { text-align: left; }

@media (max-width: 1199px) {
  .trust__inner { grid-template-columns: 1fr; gap: 28px; }
  .trust__right { max-width: none; }
}


/* Brand band. Pinned to #ff7d24 by an earlier request, it is the brand orange
   now like every other orange surface. White copy on it measures 3.13:1,
   under the 4.5:1 AA wants. */
.consult {
  position: relative;
  overflow: hidden;
  background: var(--orange-banner);
  padding: clamp(56px, 5.5vw, 84px) 0 clamp(64px, 6.5vw, 96px);
  display: flex;
  align-items: center;
}

/* Flowing line-work, fitted to the band and centred; the strokes are white at
   10% so they read as a faint texture over the orange. */
.consult::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: url("../assets/images/WvBCdaxy1Od47GtlhEQNrU62znw.svg") center / contain no-repeat;
}

.consult__art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 40%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}

/* 53% of the 1200 column, whose left edge sits on the shared header rail. */
.consult__copy {
  position: relative;
  z-index: 2;
  width: calc(min(100% - 32px, 1200px) * .53);
  margin-left: max(16px, calc((100% - 1200px) / 2));
  margin-right: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7.8px;
}

.consult__title {
  color: #fff;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: normal;
  line-height: 36px;
}

.consult__text {
  font-size: 16px;
  line-height: 23px;
  letter-spacing: normal;
  color: #fff;
  text-align: left;
}

/* Button sits further from the copy than the title/text gap. */
.consult__copy .btn--white {
  padding: 13px 27px;
  margin-top: 31.2px;
}

@media (max-width: 949px) {
  .consult { padding: 40px 16px; }
  .consult__art { display: none; }
  .consult__copy { width: 100%; margin-left: 0; }
}


.impl {
  padding: clamp(56px, 5.5vw, 88px) 0;
  background: var(--impl-bg) url("../assets/images/uxm8eBe37AKYtll6rnKBeG678.webp") center top / cover no-repeat;
}

.impl__head { max-width: 620px; margin-bottom: 30px; }
.impl__head p { margin-top: 8px; }

/* Track bleeds to the right viewport edge; its left edge lines up with .container. */
.impl__stage {
  position: relative;
  max-width: none;
  margin: 0;
  padding: 0 0 0 max(16px, calc(50% - 600px));
}

.impl__viewport { overflow: hidden; }

.impl__track {
  display: flex;
  gap: 40px;
  transition: transform .4s cubic-bezier(.22, 1, .36, 1);
  touch-action: pan-y;
}

.impl__card {
  flex: none;
  width: 360px;
  /* Flat 500px, not clamp(360px, 32vw, 460px): the viewport-tied height came out
     around 450px on a laptop, which cut "Total Ports Covered" off the bottom of
     the longer cards. 500px clears the tallest body with room to spare. */
  height: 500px;
  background: #fff;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: var(--shadow-stack);
  display: flex;
  flex-direction: column;
  transition: transform .25s cubic-bezier(.33, .04, .63, .93), box-shadow .25s ease;
}
/* The lift used to be a translateY(-8px). In a carousel the pointer often rests
   near a card's lower edge, and moving the card out from under it ends the
   hover, which drops the card back under the pointer and starts it again: the
   card judders. The shadow alone carries the hover, and the box never moves. */
.impl__card:hover {
  box-shadow: 0 24px 40px rgba(18, 17, 39, .14);
}

.impl__thumb { height: 218px; background: #eef1f4; }
.impl__thumb img { width: 100%; height: 100%; object-fit: cover; }

.impl__body { padding: 15px 16px; display: flex; flex-direction: column; gap: 12px; flex: 1; }

.impl__region {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 500;
  line-height: 180%;
  color: #464646;
}
.impl__flag { width: 38px; height: 38px; object-fit: cover; border-radius: 50%; }

.impl__text {
  font-size: 15px;
  letter-spacing: -0.02em;
  line-height: 148%;
  text-align: justify;
  hyphens: auto;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.impl__ports { font-size: 14px; }
.impl__ports strong { color: var(--orange-text); }

.impl__prev,
.impl__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
}
.impl__prev { left: 22px; }
.impl__next { right: 22px; }

@media (max-width: 949px) {
  .impl__stage { padding: 0 0 0 16px; }
  /* The card narrows to 86vw here, so the body takes more lines than 500px
     allows on a small phone — let it grow, the flex row keeps them level. */
  .impl__card { width: min(360px, 86vw); height: auto; min-height: 500px; }
}


/* ---------- articles + case studies ---------- */
/* The homepage Articles section (#operational-challenges, the CRM's operational
   challenges) is built exactly like the Case Studies section below it: same
   head, same bleeding carousel, same feature cards. It ships `hidden` and
   site-content.js shows it once an article is published. */
.cs { padding: clamp(48px, 4.5vw, 72px) 0 clamp(56px, 5.5vw, 88px); }

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

.cs__all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 26px;
  color: var(--orange-text);
  transition: color .2s ease, gap .2s ease;
}
.cs__all:hover { color: var(--orange-deep); gap: 12px; }

/* Track bleeds to the right viewport edge; its left edge lines up with .container. */
.cs__stage {
  position: relative;
  max-width: none;
  margin: 0;
  padding: 0 0 0 max(16px, calc(50% - 600px));
  /* was a flat 560px: the thumbs stretch to this, so a landscape photo was
     cropped to a 325x560 portrait. Now it tracks the viewport. */
  min-height: clamp(360px, 32vw, 460px);
}

.cs__viewport { overflow: hidden; }

/* Cards abut: the visual separation is the card body's own right padding. */
.cs__track {
  display: flex;
  gap: 0;
  transition: transform .4s cubic-bezier(.22, 1, .36, 1);
  touch-action: pan-y;
}

.cs__feature-card {
  flex: none;
  width: 650px;
  /* was 560px flat, which stretched the thumb into a 325x560 portrait */
  height: clamp(330px, 30vw, 430px);
  display: flex;
  gap: 20px;
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform .25s cubic-bezier(.33, .04, .63, .93), box-shadow .25s ease;
}
/* Same judder as .impl__card:hover — shadow only, the box stays put. */
.cs__feature-card:hover {
  box-shadow: 0 24px 56px rgba(18, 17, 39, .12);
}

.cs__feature-card .cs__thumb {
  flex: 0 0 50%;
  height: 100%;
}
/* Articles and Case Studies cards give the text more room: the image takes a quarter of
   the card, not half. Desktop only — below 950px the card stacks with the image full width
   on top. */
@media (min-width: 950px) {
  .cs__feature-card .cs__thumb { flex-basis: 25%; }
}

.cs__thumb { background: #f4f5f7; overflow: hidden; }
.cs__thumb img { width: 100%; height: 100%; object-fit: cover; }

.cs__feature-card .cs__body {
  flex: 1;
  padding: 20px 23px 20px 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.cs__title {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 36px;
  color: #001e1d;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cs__excerpt {
  font-size: 16px;
  line-height: 26px;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cs__meta { display: flex; flex-direction: column; gap: 2px; }
.cs__meta-label { font-size: 16px; font-weight: 700; color: var(--ink); }
.cs__meta-value { font-size: 13px; line-height: 26px; color: var(--ink); }

.cs__prev,
.cs__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
}
.cs__prev { left: 20px; }
.cs__next { right: 20px; }

/* .orb:hover sets `transform: scale(1.04)`, which replaces the whole transform —
   the centring translate included — so on hover these arrows dropped half their
   height and snapped back on leave. Restate the offset alongside the scale. */
.impl__prev:hover,
.impl__next:hover,
.cs__prev:hover,
.cs__next:hover { transform: translateY(-50%) scale(1.04); }

.cs__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px; }

.cs__card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform .25s cubic-bezier(.33, .04, .63, .93), box-shadow .25s ease;
}
.cs__card:hover {
  transform: translateY(-6px);
  box-shadow: 0 24px 56px rgba(18, 17, 39, .12);
}

.cs__card .cs__thumb { aspect-ratio: 16 / 9; }
.cs__card .cs__body { padding: 22px 24px 26px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
.cs__card .cs__title { font-size: 18px; line-height: 1.4em; }

@media (max-width: 949px) {
  .cs__grid { grid-template-columns: 1fr; }
  .cs__stage { padding: 0 0 0 16px; }
  .cs__track { gap: 16px; }
  .cs__feature-card { width: min(650px, 88vw); height: auto; flex-direction: column; }
  .cs__feature-card .cs__thumb { flex: none; height: 220px; }
  /* The desktop card sets padding-left:0 because the thumbnail occupies that
     edge. Stacked, nothing is there any more and the copy ran flush against
     the card border while the right side kept 23px. */
  .cs__feature-card .cs__body { padding: 18px 20px 22px; }
  .cs__head { flex-direction: column; align-items: flex-start; }
}


.contact {
  background: var(--peach);
  padding: 50px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 33px;
  scroll-margin-top: var(--nav-h);
}

.contact__copy {
  width: 81%;
  max-width: 720px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.contact__title {
  text-align: center;
  font-size: 28px;
  line-height: 1.4em;
  font-weight: 700;
}

.contact__sub {
  font-size: 16px;
  line-height: 28px;
  text-align: center;
  color: var(--gray-600);
}

.contact__form { width: 100%; max-width: 600px; }


.form-card {
  background: #fff;
  /* Deeper below the submit button than above the heading, as on live. */
  padding: 30px 30px 38px;
  box-shadow: 0 1px 8px #191e2629;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* Name/Mobile and Email/Company pair up; everything after spans the full width. */
.form-card form {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 10px;
}

.form-card form > .field:nth-child(n+5),
.form-card__consent,
.form-card__submit { grid-column: 1 / -1; }

.form-card__title {
  font-size: 18px;
  font-weight: 600;
  line-height: 26px;
  color: var(--ink-2);
  margin-bottom: 18px;
  text-align: left;
  width: 100%;
}

.field { margin-bottom: 14px; display: flex; flex-direction: column; gap: 5px; width: 100%; }

/* The labels were --gray-700 (#374151), a cool blue-grey, which is what made
   the form read as though it came from a different site than the orange band
   behind it. Warm dark grey, 9.7:1 on white. */
.field label {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.005em;
  color: #3f3d38;
}

/* The asterisk sets its own gap, so the label reads the same whether or not
   the markup happens to have a space before it. */
.field label span { color: var(--orange-text); margin-left: 3px; }
/* "(optional)" is the opposite signal to the required asterisk, so it reads as
   quiet grey rather than borrowing the orange that means "you must". */
.field label .field__opt {
  color: #6f6a62;
  font-weight: 400;
  margin-left: 4px;
}

/* Border was rgb(184,187,211), a lavender, and the radius 4px while the submit
   button under it is 8px and the card 12px. Now a warm grey that still clears
   the 3:1 a control boundary needs (3.0:1), and one radius shared with the
   button. 14px text because 12px in a 50px box reads as a caption in a field
   rather than as an answer. */
.field input,
.field select,
.field textarea {
  width: 100%;
  height: 44px;
  font-family: inherit;
  font-size: 13px;
  color: var(--ink);
  background: #fff;
  border: 1px solid #9a948b;
  border-radius: 8px;
  padding: 10px 12px;
  transition: border-color .2s ease, box-shadow .2s ease;
}

/* A hint that the box is live before it is focused. */
.field input:hover,
.field select:hover,
.field textarea:hover { border-color: #6f6a62; }

/* Native select chrome varies by platform, so the chevron is drawn instead. */
.field select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: 46px;
  /* Chevron stroke matches the label colour; it was #384152, the same cool
     blue-grey the labels used. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='9' viewBox='0 0 16 9' fill='none'%3E%3Cpath d='M1 1L8 8L15 1' stroke='%233f3d38' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 14px 8px;
}

/* Explicit leading: inherited body leading pushes the first line too far down. */
.field textarea { height: 68px; min-height: 68px; line-height: 1.4; resize: vertical; }
/* #9ca3af was both cool and faint (2.5:1). This is warm and readable while
   staying clearly lighter than a typed answer. */
.field input::placeholder,
.field textarea::placeholder { color: #78736b; }

.field input:hover,
.field select:hover,
.field textarea:hover { border-color: #d1d5db; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  /* Was #f97316, the second orange this site no longer uses, with a 2px glow
     that read as a blur. Brand orange, and a soft ring instead. */
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(241, 103, 36, .16);
}

/* #d92d20 measured 4.4:1, just under what 12px text needs. */
.field__error { font-size: 11px; line-height: 1.4; color: #b42318; }

/* The box that is wrong should look wrong. Until now only the message under
   it changed, which on a form with five required fields means reading five
   lines of text to find the one that failed. */
.field.is-invalid input,
.field.is-invalid select,
.field.is-invalid textarea { border-color: #b42318; }

.field.is-invalid input:focus,
.field.is-invalid select:focus,
.field.is-invalid textarea:focus {
  border-color: #b42318;
  box-shadow: 0 0 0 3px rgba(180, 35, 24, .14);
}

/* A failure that isn't about one field (network error, CRM rejected the
   enquiry), shown above the submit button by main.js's showSubmitError. */
.form-error { font-size: 12px; color: #d92d20; margin: 0 0 12px; }
.form-error[hidden] { display: none; }

/* Small print under the form. It was --slate (#5b6b82), a blue-grey sitting in
   a warm orange-and-black palette, and the link inside it was bold near-black
   with no underline, which read as a heading rather than something to click.
   Now one quiet warm-grey sentence (7.2:1 on white) with an underlined link in
   the body colour: the underline is what says "link", and at 12px the brand
   orange would sit at 3.1:1, well under what small text needs. Orange arrives
   on hover, where it is an accent rather than the only signal. */
.form-card__consent {
  font-size: 11px;
  line-height: 17px;
  color: #5a574f;
  margin: 4px 0 14px;
  width: 100%;
}

.form-card__consent button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 500;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  cursor: pointer;
  transition: color .2s ease;
}
.form-card__consent button:hover { color: var(--orange-text); }

/* ---------- contact modal ---------- */
/* Opened from the header CTA; the page behind it is blurred back. */
.cmodal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  background: rgba(0, 0, 0, .09);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.cmodal[hidden] { display: none; }

.cmodal__close {
  position: absolute;
  top: 10px;
  right: 30px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  color: #1a1a1a;
  background: none;
  border: 0;
  cursor: pointer;
}

.cmodal__close svg { display: block; }

.cmodal__card {
  width: 100%;
  max-width: 600px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
}

.form-card--modal { padding: 40px; box-shadow: 0 10px 40px rgba(25, 30, 38, .18); }

/* Submit is a full-width rounded rectangle, not the pill used elsewhere. It
   used to carry its own orange (#f97316); it is the brand orange now, like
   every other orange surface. */
.form-card__submit {
  width: 100%;
  padding: 16px 24px;
  font-size: 14px;
  border-radius: 8px;
  background: var(--orange);
  transition: background-color .5s ease, transform .25s cubic-bezier(.33, .04, .63, .93);
}

@media (max-width: 639px) {
  .form-card { padding: 20px 20px 24px; }
  .form-card form { grid-template-columns: 1fr; }
  .form-card__title { font-size: 20px; margin-bottom: 20px; }
}

.form-success {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(25, 26, 21, .35);
  backdrop-filter: blur(8px);
  display: grid;
  place-items: center;
  padding: 24px;
}

.form-success__card {
  position: relative;
  width: min(600px, 100%);
  background: #fff;
  border: 1px solid rgba(241, 103, 36, .53);
  border-radius: 5px;
  padding: 36px 28px 28px;
  text-align: center;
}

.form-success__card h3 { font-size: 22px; margin-bottom: 8px; }
.form-success__card p { margin-bottom: 20px; }

.form-success__close {
  position: absolute;
  top: 8px;
  right: 12px;
  border: 0;
  background: none;
  font-size: 28px;
  color: var(--slate);
}


.footer {
  background: var(--footer-bg);
  color: var(--gray-300);
  padding: 50px 16px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 19px;
}

.footer__grid {
  width: 100%;
  max-width: 1280px;
  display: grid;
  grid-template-columns: 1.74fr 1fr 1.74fr 1.87fr;
  gap: 24px;
  align-items: start;
  padding: 4px 0;
}

/* Nav column carries no heading, so nudge it onto the other columns' baseline. */
.footer__col--nav { padding-top: 3px; }
.footer__col--nav a.is-active { color: var(--orange); }

.footer__logo img { width: 87px; height: 42px; object-fit: fill; }

.footer__about {
  margin-top: 16px;
  width: 97%;
  font-size: 16px;
  line-height: 24px;
  color: var(--gray-300);
  letter-spacing: normal;
}

.footer__social { display: flex; gap: 16px; margin-top: 20px; }
.footer__social a { color: #9ca3af; display: grid; place-items: center; width: 20px; height: 20px; }
.footer__social a:hover { color: var(--orange); }

.footer__col { display: flex; flex-direction: column; gap: 13px; }

.footer__heading {
  font-size: 18px;
  font-weight: 700;
  line-height: 28px;
  color: #fff;
  font-family: var(--font-body);
}

.footer__col a,
.footer__col p,
.footer__linkbtn {
  font-size: 16px;
  line-height: 1.6em;
  letter-spacing: -0.02em;
  color: var(--gray-300);
  transition: color .15s ease;
}

.footer__col a:hover,
.footer__linkbtn:hover { color: var(--orange); }

.footer__linkbtn {
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  font-family: inherit;
}

.footer__company { color: var(--gray-300); font-weight: 400; }
.footer__col--contact a { color: var(--gray-300); }
.footer__col--contact strong { color: #fff; font-weight: 700; }

.footer__bottom {
  width: 100%;
  max-width: 1218px;
  margin-top: 0;
  padding-top: 13px;
  border-top: 1px solid #1f2937;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  font-family: var(--font-alt);
  font-size: 14px;
  line-height: 24px;
  letter-spacing: normal;
}

.footer__legal { display: flex; gap: 24px; flex-wrap: wrap; width: 35%; justify-content: flex-end; }
.footer__legal button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.footer__legal button:hover { color: var(--orange); }

@media (max-width: 1023px) {
  .footer__grid { grid-template-columns: 1fr 1fr; width: 100%; }
  .footer__legal { width: auto; justify-content: flex-start; }
}

@media (max-width: 639px) {
  .footer__grid { grid-template-columns: 1fr; }
  .footer__bottom { flex-direction: column; align-items: flex-start; }
}


.legal {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(25, 26, 21, .45);
  backdrop-filter: blur(10px);
  display: grid;
  place-items: center;
  padding: 24px;
}

.legal__dialog {
  width: min(950px, 100%);
  max-height: min(86vh, 820px);
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
}

.legal__head {
  background: var(--orange-deep);
  color: #fff;
  padding: 18px 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.legal__head h2 {
  color: #fff;
  font-size: 20px;
  font-weight: 700;
}

.legal__close {
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .18);
  color: #fff;
  font-size: 26px;
  line-height: 1;
}

.legal__body {
  padding: 22px;
  overflow-y: auto;
  display: grid;
  gap: 12px;
}

.legal__body p {
  font-size: 14px;
  line-height: 24px;
  color: var(--body);
}

.legal__item {
  display: grid;
  grid-template-columns: 36px 1fr;
  gap: 14px;
  padding: 14px 16px;
  background: #f269241a;
  border: 1px solid #f26924;
  border-radius: 10px;
}

.legal__badge {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
  font-weight: 700;
  display: grid;
  place-items: center;
}

.legal__item h3 {
  font-size: 15px;
  margin-bottom: 4px;
}

.legal__item p { font-size: 13px; line-height: 20px; }

.legal__foot {
  margin-top: 8px;
  font-size: 13px !important;
  color: var(--slate) !important;
}


/* Two equal columns: copy, stats and the India map on the left; the photo
   collage and the J M Baxi heritage note on the right. */
.about-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 0 16px 29px;
}

.about-hero__inner {
  width: 100%;
  max-width: 1200px;
  display: flex;
  align-items: flex-start;
  gap: 40px;
}

.about-hero__col { flex: 1 1 0; min-width: 0; }
.about-hero__side { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 30px; padding-bottom: 16px; }

.about-hero__p + .about-hero__p { margin-top: 18px; }
.about-hero__p { text-align: left; }

.about-hero__stats { display: flex; gap: 32px; }
.about-stat { flex: 1 1 0; }

.about-stat__value { font-size: 47px; line-height: 1.1em; font-weight: 700; color: #191a15; }
.about-stat__label { font-size: 20px; line-height: 1.4em; font-weight: 500; color: #191a15; margin-top: 3px; }

/* 1156x1026 intrinsic: at 580px wide it drew 515px tall. Contain, not fill,
   so capping the height crops nothing. */
.about-hero__map { display: block; width: 100%; height: auto; max-height: clamp(260px, 30vw, 420px); object-fit: contain; }

/* The collage is a single image; it sits letterboxed in a 530px-tall box. */
.about-hero__collage { display: block; width: 100%; height: clamp(200px, 28vw, 400px); object-fit: contain; }

.about-hero__team { display: block; width: 100%; max-width: 1200px; height: clamp(220px, 30vw, 420px); object-fit: cover; }

.heritage { display: flex; flex-direction: column; align-items: flex-start; gap: 18px; }
.heritage__logo { width: 196px; height: 68px; object-fit: contain; }
.heritage__text { text-align: left; }

@media (max-width: 949px) {
  .about-hero__inner { flex-direction: column; }

}

/* No card chrome: a square portrait above an orange name, a bold dark role
   and a justified bio. */
.people { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 55px; }

.person { background: none; padding: 0; text-align: left; }

.person__photo {
  width: 162px;
  height: 162px;
  max-width: 100%;
  border-radius: 0;
  object-fit: contain;
  margin: 0 0 14px;
}

/* The people headings sit closer to their row than the shared 30px default. */
body[data-page="about"] .section-head { margin-bottom: 17px; }

.person__name { font-size: 18px; font-weight: 700; line-height: 22px; letter-spacing: normal; color: var(--orange-text); }

.person__role {
  font-size: 18px;
  font-weight: 700;
  line-height: 22px;
  letter-spacing: normal;
  color: #191a15;
  margin: 12px 0 0;
}

.person__bio {
  margin-top: 14px;
  font-size: 16px;
  line-height: 22px;
  letter-spacing: normal;
  text-align: left;
}

@media (max-width: 1023px) {
  .about-hero__inner,
  .heritage { grid-template-columns: 1fr; gap: 30px; }
  .people { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .about-hero__title { font-size: 28px; }
}

@media (max-width: 809px) {
  .people { grid-template-columns: 1fr; }
  .about-hero__title { font-size: 26px; }
  .about-stat__value { font-size: 32px; }
}


/* ---------- hero ---------- */
/* Full-bleed photo band with an orange wash; the form card overhangs below it. */
/* Band height, wash depth, title offset and card width are configured per page
   on the section itself, alongside --p-hero-img; the defaults below are PCS's. */
.p-hero {
  position: relative;
  padding: 0;
  height: var(--p-hero-h, 415px);
  background: var(--p-hero-img) center / cover no-repeat;
}

.p-hero__tint {
  position: absolute;
  left: 0;
  right: 0;
  top: 89px;
  height: var(--p-hero-tint-h, 257px);
  background: rgba(241, 103, 36, .659);
}

.p-hero__inner {
  position: relative;
  height: 100%;
}

.p-hero__title {
  position: absolute;
  top: var(--p-hero-title-top, 140px);
  left: 16px;
  max-width: 560px;
  font-size: 40px;
  line-height: 1.4em;
  font-weight: 700;
  color: #fff;
}

.p-hero__form {
  position: absolute;
  top: 89px;
  right: 16px;
  width: var(--p-hero-form-w, 592px);
  z-index: 3;
}

/* The hero card runs a smaller heading and squarer padding than the standalone
   contact form further down the page. */
.p-hero__form .form-card { padding: 30px 40px 4px; }
.p-hero__form .form-card__title {
  font-size: 18px;
  line-height: 32px;
  font-weight: 600;
  margin-bottom: 25px;
}

/* ---------- what is ---------- */
/* Indented a further 16px from the container edge, and kept clear of the
   overhanging hero form card. */
.p-what { padding-top: var(--p-what-pt, 0); padding-bottom: var(--p-what-pb, 0); }
.p-what > * { max-width: var(--p-what-w, 534px); margin-left: 16px; }
/* The heading can sit on a knife-edge against the column width — TOS breaks it
   onto two lines, so that page holds the heading a few px narrower. */
.p-what > h2 { max-width: var(--p-what-head-w, var(--p-what-w, 534px)); }

/* MSW's intro sits in a wider 1248px column starting at x=96, with only the
   first paragraph held narrow beside the overhanging hero card. */
.container.p-what--wide {
  max-width: none !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.p-what.p-what--wide > * {
  max-width: 1248px;
  margin-left: max(16px, calc(50% - 624px));
}
.p-what.p-what--wide > h2,
.p-what.p-what--wide > .p-what__p:first-of-type { max-width: 543px; }
.p-what.p-what--wide > .p-what__p + .p-what__p { margin-top: 0; }

/* Once the hero card stacks, nothing is overlapping the first paragraph. */
@media (max-width: 1023px) {
  .p-what.p-what--wide > h2,
  .p-what.p-what--wide > .p-what__p:first-of-type { max-width: none; }
  .p-what.p-what--wide > .p-what__p + .p-what__p { margin-top: 16px; }
}
.p-what__p {
  margin-top: var(--p-what-p-mt, 16px);
  text-align: left;
  /* .text-lead's 28px leading is the homepage value; the intro runs 1.6em. */
  line-height: 1.6em;
}

/* Product-page section headings carry an orange rule. Scoped to section.section
   so the shared trust / implementations / case-study headings stay plain. */
/* How far the rule drops below its heading varies per band on live, so the
   padding it hangs off is overridable from the heading or any ancestor. */
body[data-page="product"] section.section .h-section--left {
  position: relative;
  padding-bottom: var(--head-rule-pb, 14px);
}
body[data-page="product"] section.section .h-section--left::after {
  content: "";
  position: absolute;
  left: 0;
  /* The rule sits 6px clear of the padding edge, not flush with it. */
  bottom: 6px;
  width: 100px;
  height: 3px;
  background: var(--orange);
}

/* ---------- diagram ---------- */
/* It used to opt out of the page rail: the container was flattened with
   !important and the art hand-positioned with calc(50% - 646px), a number tied
   to the old rail. It drew 1248px wide where every other section is 1200px, sat
   off-centre, and pushed the MSW page into horizontal scroll at 1024px. It
   rides the normal rail now, centred, capped in height. */
.p-diagram { padding: 8px 0 40px; }
.p-diagram .container {
  max-width: var(--container) !important;
  padding-left: clamp(20px, 2.4vw, 32px) !important;
  padding-right: clamp(20px, 2.4vw, 32px) !important;
}
.p-diagram__art {
  display: block;
  width: auto;
  /* both caps bite: the height for the tall radial hubs, the width for the wide
     flow diagrams, and the ratio is preserved either way. 1200px is the rail's
     own content width, so the art fills it without forcing a scrollbar. */
  max-width: min(100%, 1200px);
  height: auto;
  max-height: clamp(200px, 22vw, 340px);
  margin-inline: auto;
}

/* Below the width where the offset above bottoms out at 16px, the 192px
   deduction would leave a lopsided gap on the right — go symmetric instead. */
@media (max-width: 1323px) {
  .p-diagram__art {
  display: block;
  width: auto;
  max-width: min(100%, 1200px);
  height: auto;
  max-height: clamp(200px, 22vw, 340px);
  margin-inline: auto;
}
}

/* PMIS's hub is a symmetric radial graphic with the "PMIS Benefits" node at its
   optical centre, so it is centred in the band rather than run on the left
   offset the other product diagrams use. Unlike the flow diagrams it carries
   fine labels at the rim, so the 340px height clamp squeezed it to ~574px wide
   and left it unreadable. It stays on the page rail and keeps the 1000px width
   cap; only the height clamp is lifted, so the width is what sizes it. */
.p-diagram--center .p-diagram__art {
  display: block;
  width: 100%;
  max-width: min(100%, 1000px);
  height: auto;
  max-height: none;
  margin-inline: auto;
}

/* This used to hold the hub at 780px and let the band scroll sideways, so its
   rim labels stayed legible. Every image fits the screen now instead: a
   sideways-scrolling band is easy to miss entirely, and half a diagram reads
   as a broken page rather than as something to drag. The labels are small at
   this width; the caption below carries the same information in text. */
@media (max-width: 809px) {
  .p-diagram--center .container {
    overflow-x: visible;
  }
  .p-diagram--center .p-diagram__art {
    width: 100%;
    min-width: 0;
    max-width: 100%;
  }
}

/* ---------- benefits ---------- */
/* Two columns of check-marked items, not cards. Row rhythm and the drop below
   the heading are per page; --p-benefits-mt collapses against the heading's own
   30px margin, so it reads as the resulting gap. */
.p-benefits {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--p-benefits-row-gap, 30px) 54px;
  margin-top: var(--p-benefits-mt, 0);
}

.p-benefit {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 19px;
  align-items: start;
}

.p-benefit__icon { width: 48px; height: 48px; }
.p-benefit__title {
  font-size: 18px;
  font-weight: 700;
  /* Tight line box: the title sits 4px below the icon's top edge, not 6. */
  line-height: 21px;
  letter-spacing: normal;
  color: var(--ink);
  margin-bottom: 10px;
}
.p-benefit__text {
  font-size: 16px;
  line-height: 1.6;
  /* Slight negative tracking; only visible on the unjustified last line
     of each paragraph, since the justified lines fill the column either way. */
  letter-spacing: -0.015em;
  color: var(--body);
  text-align: left;
}

.p-more {
  margin-top: 26px;
  background: none;
  border: 0;
  padding: 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--orange-text);
}
.p-more:hover { color: var(--orange-deep); }

/* ---------- capabilities ---------- */
/* The tinted panel is baked into the artwork; the caption sits below it. */
.p-caps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 44px; }

.p-cap {
  padding: 0;
  border: 0;
  background: none;
}

/* Each illustration is a 546x654 PNG with its tinted panel baked in and
   transparent corners. Left to run at the column width it drew 447px tall —
   taller than the caption it belongs to — and three soft-edged panels floated
   on white with nothing holding them as a set. So: a card frame from the
   system, and the art capped inside it on the same #f7f7fc the artwork's own
   panel uses, which is what makes capping it invisible rather than letterboxed. */
.p-cap {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 22px 26px;
  transition: border-color .25s ease, box-shadow .25s ease;
}
.p-cap:hover { border-color: var(--gray-300); box-shadow: var(--shadow-card); }

.p-cap__art {
  width: 100%;
  height: clamp(200px, 19vw, 250px);
  display: block;
  object-fit: contain;
  background: #f7f7fc;
  border-radius: 8px;
  margin-bottom: 20px;
}
.p-cap .h-card { margin: 0 0 8px; }

.p-cap h3 {
  margin-bottom: 8px;
  letter-spacing: normal;
}

.p-cap p {
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: normal;
  text-align: left;
}

/* ---------- how it helps ---------- */
/* Photo column at natural width beside the copy. */
.p-help {
  display: grid;
  grid-template-columns: 442px 1fr;
  gap: 33px;
  align-items: start;
}

.p-help__art {
  width: 100%;
  max-width: 442px;
  height: clamp(220px, 26vw, 400px);
  object-fit: cover;
  display: block;
  border-radius: 4px;
}

.p-help__p {
  margin-top: 18px;
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: normal;
  text-align: left;
  color: var(--body);
}

@media (max-width: 1023px) {
  .p-help { grid-template-columns: 1fr; gap: 26px; }
  /* height:auto would run past 1100px once it spans the full width. */
  .p-help__art { width: 100%; height: 320px; }
}

/* ---------- modules ---------- */
/* Five per row: line-art icon above its label, no tile or border. */
.p-modules {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--p-modules-row-gap, 58px) var(--p-modules-col-gap, 54px);
}

.p-module {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--p-module-gap, 10px);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  font-size: 16px;
  font-weight: 400;
  /* Wrapped labels sit on a 19px rhythm, not the 22px a 1.4 factor would give. */
  line-height: 1.2;
  letter-spacing: normal;
  color: var(--heading);
  text-align: left;
}

.p-module__icon { width: 80px; height: auto; display: block; }

/* Modules that have their own page. Underline only the label on hover. */
.p-module--link {
  text-decoration: none;
  color: var(--heading);
  transition: color .18s ease;
}

.p-module--link:hover,
.p-module--link:focus-visible { color: var(--orange-text); text-decoration: underline; text-underline-offset: 3px; }

.p-module--link:hover .p-module__icon,
.p-module--link:focus-visible .p-module__icon { text-decoration: none; }

@media (max-width: 1023px) {
  .p-modules { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 36px 32px; }
}

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

/* ---------- statistics ---------- */
/* Full-bleed band over a port photograph. Opts out of .container entirely. */
.p-stats {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 60px;
  padding: 50px 16px;
}

.p-stats__bg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.p-stats__head {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--p-stats-head-gap, 5px);
  padding-bottom: var(--p-stats-head-pb, 15px);
}

.p-stats__title {
  font-size: 24px;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: normal;
  color: #fff;
  text-align: center;
}

.p-stats__rule { display: block; width: 100px; height: 3px; background: var(--orange); }

.p-stats__grid {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--p-stats-max, 800px);
  display: grid;
  grid-template-columns: var(--p-stats-cols, repeat(2, minmax(50px, 1fr)));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 57px 10px;
}

/* Cells sit at the top-left of their track; TSM holds them to 90% of it,
   TOS lets them fill. */
.p-stats__cell {
  width: var(--p-stats-cell-w, 90%);
  align-self: start;
  justify-self: start;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.p-stats__value {
  font-size: 50px;
  line-height: 1.2;
  font-weight: 600;
  letter-spacing: normal;
  color: #fff;
  text-align: center;
}

.p-stats__label {
  font-size: 18px;
  line-height: 30px;
  font-weight: 500;
  letter-spacing: normal;
  color: #fff;
  text-align: center;
}

/* The TAT figure sits in a taller box than the other three, which drops its
   caption 9px below theirs. */
.p-stats__cell--tat { gap: 5px; }
.p-stats__cell--tat .p-stats__value { height: 74px; }

@media (max-width: 809px) {
  .p-stats { gap: 40px; padding: 40px 16px; }
  .p-stats__grid { grid-template-columns: 1fr; grid-template-rows: none; gap: 30px 10px; }
  .p-stats__cell { width: 100%; }
  /* Release the fixed caption widths some cells carry, so they stay centred. */
  .p-stats__label { width: auto !important; max-width: none !important; }
  .p-stats__cell--tat { gap: 10px; }
  .p-stats__cell--tat .p-stats__value { height: auto; }
}

/* ---------- stakeholders ---------- */
.p-stake { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px; }

/* Plain columns — no card chrome; each item is an icon beside its label. */
.p-stake__group {
  border: 0;
  border-radius: 0;
  padding: 0;
  background: none;
}

.p-stake__title {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.2; /* was Bootstrap's heading default; kept when Bootstrap was dropped */
  letter-spacing: normal;
  color: var(--heading);
  margin-bottom: 22px;
}

.p-stake__list { display: grid; gap: 10px; }

.p-stake__list li {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 19px;
  align-items: center;
  min-height: 32px;
  padding-left: 0;
  font-size: 16px;
  line-height: 1.4;
  letter-spacing: normal;
  color: var(--heading);
}

.p-stake__list li::before { content: none; }

.p-stake__icon { width: 32px; height: 32px; object-fit: contain; }

/* PMIS uses a single bordered panel of three columns, under a centred heading. */
.p-stake--panel { display: block; }

.p-stake--panel .p-stake__group {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 34px 35px;
  background: #fff;
}

.p-stake--panel .p-stake__list {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 24px;
  row-gap: 30px;
}

/* Must outrank the product-page heading rule, which sets a left-aligned 100px bar. */
body[data-page="product"] section.section .h-section--left.p-stake__heading { text-align: center; }
body[data-page="product"] section.section .h-section--left.p-stake__heading::after {
  width: 205px;
  left: 50%;
  transform: translateX(-50%);
}

/* TSM fits four columns in the same panel, so its gutters are far tighter.
   Its heading is also a distinct component from the one PMIS uses: thicker
   rule, and noticeably more air between that rule and the panel. */
body[data-page="product"] section.section .h-section--left.p-stake__heading--cols4 { margin-bottom: 47px; }
body[data-page="product"] section.section .h-section--left.p-stake__heading--cols4::after { height: 4px; bottom: 5px; }

.p-stake--cols4 .p-stake__group { border-radius: 20px; }
.p-stake--cols4 .p-stake__list { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 10px; }
.p-stake--cols4 .p-stake__list li { gap: 18px; }

@media (max-width: 1023px) {
  .p-stake--panel .p-stake__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .p-stake--panel .p-stake__group { padding: 24px; }
  .p-stake--cols4 .p-stake__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; }
}

@media (max-width: 639px) {
  .p-stake--panel .p-stake__list { grid-template-columns: 1fr; }
}

/* MSW arranges its groups as bordered cards in a mosaic: two small cards over a
   wide one on the left, with Government Agencies spanning both rows at right. */
/* The gutter between the two small cards (13px) is tighter than the one before
   the tall card (22px), so the third track carries the extra 9px as margin. */
.p-stake--mosaic {
  grid-template-columns: 1fr 1fr 647px;
  column-gap: 13px;
  row-gap: 20px;
  align-items: start;
}

.p-stake--mosaic .p-stake__group {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 20px 22px;
  background: #fff;
}

.p-stake__group--custodians { grid-column: 1; grid-row: 1; }
.p-stake__group--service    { grid-column: 2; grid-row: 1; }
.p-stake__group--cargo      { grid-column: 1 / 3; grid-row: 2; }
.p-stake__group--gov        { grid-column: 3; grid-row: 1 / 3; margin-left: 9px; }

.p-stake__group--cargo .p-stake__title { text-align: center; }

/* MSW sets its item labels a step larger than the other product pages. */
.p-stake--mosaic .p-stake__list li { font-size: 18px; }

.p-stake__group--cargo .p-stake__list,
.p-stake__group--gov .p-stake__list {
  grid-template-columns: 1fr 1fr;
  column-gap: 20px;
}

/* 1199, not 1023: the 647px fixed track plus two others still overflowed a
   1024px viewport, which is where the MSW page picked up horizontal scroll. */
@media (max-width: 1199px) {
  .p-stake--mosaic { grid-template-columns: 1fr; }
  .p-stake--mosaic .p-stake__group { grid-column: 1 !important; grid-row: auto !important; }
}

/* The four groups share one column below 1024px, so the track is sized by the
   widest of them — the two-up lists in Cargo Carriers and Government Agencies.
   Two tracks plus a 32px icon apiece could not fit a 358px container, so those
   cards held themselves at 406px and pushed the whole MSW page 32px wider than
   the phone. One track each below 640px. Placed after the 1fr 1fr rule above:
   the two selectors carry the same specificity, so order decides. */
@media (max-width: 639px) {
  .p-stake__group--cargo .p-stake__list,
  .p-stake__group--gov .p-stake__list { grid-template-columns: 1fr; }
}

/* Labels with no icon of their own still align to the label column. */
.p-stake__list li.p-stake__li--plain { grid-template-columns: 32px 1fr; }
.p-stake__list li.p-stake__li--plain::before {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  margin: 0 auto;
  border-radius: 50%;
  background: var(--orange);
}

@media (max-width: 1023px) {
  /* Too narrow for the overhanging card: stack the hero instead. */
  .p-hero { height: auto; padding: 40px 0; }
  .p-hero__tint { top: 0; height: 100%; }
  .p-hero__inner { height: auto; }
  .p-hero__title {
    position: static;
    max-width: none;
    margin-bottom: 24px;
    font-size: 28px;
  }
  .p-hero__form { position: static; width: 100%; }
  .p-what > * { max-width: none; }
  .p-benefits,
  .p-caps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .p-stake { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 809px) {
  .p-benefits,
  .p-caps,
  .p-stake { grid-template-columns: 1fr; }
  .p-hero__title { font-size: 24px; }
}


/* Shared page header: centred title over its rule, then the strapline (and,
   on Case Studies, the category filter). Spacing is set per page. */
.page-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--page-hero-gap, 27px);
  padding: var(--page-hero-pt, 31px) 16px var(--page-hero-pb, 50px);
}

.page-hero__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--page-hero-head-gap, 5px);
}

.page-hero__title {
  font-size: 40px;
  line-height: 1.2em;
  font-weight: 700;
  color: #191a15;
  text-align: center;
}

.page-hero__rule { display: block; width: 120px; height: 3px; background: var(--orange); }

.page-hero__sub {
  width: var(--page-hero-sub-w, 598px);
  max-width: 100%;
  font-size: 24px;
  line-height: 1.2em;
  text-align: center;
  color: #191a15;
}

/* The case-studies sub sits on one line at desktop width; 598px broke it in
   two above a heading that can itself run to two lines once a solution is
   picked. Still max-width:100%, so it wraps normally on a phone. */
body[data-page="case-studies"] .page-hero__sub { --page-hero-sub-w: 1000px; }

.page-hero__filter { width: 100%; max-width: 441px; }

.page-hero__filter select {
  width: 100%;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 20px;
  line-height: 22px;
  color: #191a15;
  background-color: #fff;
  border: 1px solid #e0e3eb;
  border-radius: 8px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='9' viewBox='0 0 16 9' fill='none'%3E%3Cpath d='M1 1L8 8L15 1' stroke='%233f3d38' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 18px center;
  background-size: 14px 8px;
}

/* Custom filter dropdown (built by enhanceSelect in main.js). The closed state
   repeats .page-hero__filter select above exactly, so nothing moves when the
   script upgrades it; the open panel is the part a native select would not let
   us style, since its popup is drawn by the OS. */
.fsel { position: relative; width: 100%; }

/* The select stays in the DOM as the value's source of truth. */
.fsel__native {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
}

.fsel__button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 20px;
  line-height: 22px;
  text-align: left;
  color: #191a15;
  background-color: #fff;
  border: 1px solid #e0e3eb;
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .18s ease;
}
.fsel__button:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
/* Open: the control darkens and squares off its bottom corners so it reads as
   one object with the panel below it. */
.fsel.is-open .fsel__button { border-color: #191a15; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

.fsel__chev {
  flex: none;
  width: 14px;
  height: 8px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='9' viewBox='0 0 16 9' fill='none'%3E%3Cpath d='M1 1L8 8L15 1' stroke='%233f3d38' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / 14px 8px;
  transition: transform .18s ease;
}
.fsel.is-open .fsel__chev { transform: rotate(180deg); }

.fsel__panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 8px 0 12px;
  list-style: none;
  background: #fff;
  border: 1px solid #e0e3eb;
  border-top: 0;
  border-radius: 0 0 8px 8px;
  box-shadow: 0 18px 34px rgba(18, 17, 39, .12);
}
.fsel:not(.is-open) .fsel__panel { display: none; }

/* Unselected entries sit back in grey; the current one is the only dark line. */
.fsel__option {
  padding: 11px 16px;
  font-size: 18px;
  line-height: 24px;
  color: #767676;
  cursor: pointer;
}
.fsel__option[aria-selected="true"] { color: #191a15; }
.fsel__option:hover,
.fsel__option.is-active { background: #f7f7f7; color: #191a15; }

@media (prefers-reduced-motion: reduce) {
  .fsel__button, .fsel__chev { transition: none; }
}

/* Listing rows: one card per line, copy left of a half-width image. */
.cs--list { padding: 0 16px 87px; }
.cs--list-2 { padding: 76px 16px 87px; }

.cs__list {
  width: 100%;
  max-width: 908px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.cs--list-2 .cs__list { gap: 7px; }
/* The rows below the banner set their titles ragged-right, unlike the first two. */
.cs--list-2 .cs__card--row .cs__title { text-align: left; }

.cs__card--row {
  flex-direction: row;
  align-items: center;
  gap: 40px;
  border-radius: 24px;
  padding: 18px 22px;
  overflow: visible;
  box-shadow: 0 5px 30px 5px #0000000a;
}

.cs__card--row:hover { transform: none; box-shadow: 0 5px 30px 5px #00000014; }

.cs__card--row .cs__body {
  flex: 1 1 0;
  min-width: 0;
  justify-content: center;
  gap: 20px;
  padding: 0 23px 0 0;
}

.cs__card--row .cs__thumb {
  flex: none;
  width: 50%;
  height: clamp(200px, 22vw, 330px);
  aspect-ratio: auto;
  border-radius: 20px;
  box-shadow: 0 20px 50px #00000014;
}

.cs__card--row .cs__title {
  display: block;
  overflow: visible;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 32px;
  text-align: left;
  color: #001e1d;
}

/* Only the title carries the -0.02em tracking; body copy runs untracked. */
.cs__card--row .cs__excerpt {
  display: block;
  overflow: visible;
  font-size: 15px;
  line-height: 26px;
  letter-spacing: normal;
  text-align: left;
  color: #4b5563;
}

.cs__card--row .cs__meta { padding-top: 15px; }
.cs__card--row .cs__meta-label,
.cs__card--row .cs__meta-value {
  font-size: 15px;
  line-height: 26px;
  letter-spacing: normal;
  color: #4b5563;
}
.cs__card--row .link-more { margin-top: 0; padding-top: 20px; }

/* The Articles page: the same rows as the case studies listing, filled from
   the CRM by site-content.js. An article's image is more often an icon than a
   photo, so it sits whole on a tint rather than cropped to fill. */
.art__list {
  width: 100%;
  max-width: 908px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 30px;
}
.art__card { color: inherit; text-decoration: none; scroll-margin-top: 110px; }
/* An article thumbnail is a photo, shown exactly like a case study's. */
.art__thumb img { width: 100%; height: 100%; object-fit: cover; }
.art__empty { max-width: 908px; margin: 0 auto; padding: 24px 16px 8px; text-align: center; font-size: 16px; line-height: 26px; color: #4b5563; }
.art__empty[hidden] { display: none; }

@media (max-width: 949px) {
  .cs__card--row { flex-direction: column; align-items: stretch; gap: 20px; }
  .cs__card--row .cs__body { padding: 0; }
  .cs__card--row .cs__thumb { width: 100%; height: clamp(180px, 46vw, 280px); order: -1; }
}

.chip {
  font-size: 13px;
  font-weight: 500;
  color: var(--slate);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 9px 16px;
  transition: all .15s ease;
}
.chip:hover { border-color: var(--orange-text); color: var(--orange-text); }
.chip--active { background: var(--orange-deep); border-color: var(--orange-deep); color: #fff; }

@media (max-width: 809px) {
  .page-hero { padding: 40px 0 4px; }
  .page-hero__title { font-size: 26px; }
}


/* Centred breadcrumb and title over the rule; the banner runs full-bleed. */
.detail-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
  padding: 50px 16px 53px;
}

.crumb {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-size: 15px;
  line-height: 22.5px;
  letter-spacing: -0.02em;
  color: #191a15;
}
.crumb a { color: inherit; }
.crumb a:hover { color: var(--orange-text); }
.crumb__current { color: #191a15; }

.detail-hero__head { display: flex; flex-direction: column; align-items: center; gap: 12px; width: 100%; }

.detail-hero__title {
  width: 100%;
  max-width: 1200px;
  font-size: 40px;
  line-height: 1.2em;
  font-weight: 700;
  text-align: center;
  color: #191a15;
}

.detail-hero__rule { display: block; width: 120px; height: 3px; background: var(--orange); }

.detail-hero__media { width: 100%; height: clamp(220px, 30vw, 420px); }
.detail-hero__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 949px) {
  .detail-hero__title { font-size: 28px; }
  .detail-hero__media { height: 300px; }
}

.detail-body__inner { max-width: 880px; }

.block + .block { margin-top: 38px; }

.block__heading {
  font-size: 22px;
  line-height: 1.35em;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 12px;
}

.block__p { text-align: left; }
.block__p + .block__p { margin-top: 14px; }

/* Diagrams and screenshots sit inline in the article column. Full width put
   the 1281x591 core-modules ring at 1200x554 — it filled the viewport and ran
   off the fold. Capped and centred; the ratio is preserved. */
.block__figure {
  display: block;
  width: auto;
  max-width: min(100%, 1100px);
  height: auto;
  max-height: clamp(280px, 36vw, 520px);
  margin: 18px auto 0;
}
/* Some lists on live are numbered rather than bulleted. */
.block__list--num { counter-reset: block-item; }
.block__list--num li { counter-increment: block-item; }
/* Must outrank .block__list li::before, which sits later in the file. */
.block__list.block__list--num li::before {
  content: counter(block-item) ".";
  position: absolute;
  left: 0;
  top: 0;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  color: var(--body);
  font-size: 15px;
  line-height: 26px;
}

.block__link { color: var(--orange-text); text-decoration: underline; }
.block__link:hover { color: var(--orange-deep); }

.block__list { margin-top: 14px; display: grid; gap: 10px; list-style: none; }

.block__list li {
  position: relative;
  padding-left: 22px;
  font-size: 15px;
  line-height: 26px;
  color: var(--body);
}

.block__list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 11px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--orange);
}

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }

.impact-table { width: 100%; border-collapse: collapse; min-width: 620px; }

.impact-table th,
.impact-table td {
  text-align: left;
  padding: 14px 16px;
  font-size: 14px;
  line-height: 22px;
  border-bottom: 1px solid var(--line);
}

.impact-table th { background: var(--orange-tint); color: var(--ink); font-weight: 700; }
.impact-table td { color: var(--body); }
.impact-table tbody tr:last-child td { border-bottom: 0; }

.detail-nav {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 48px;
}

.detail-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--orange-text);
  transition: color .2s ease, gap .2s ease;
}
.detail-nav__link:hover { color: var(--orange-deep); gap: 12px; }

.detail-nav__link--next { margin-left: auto; }

@media (max-width: 809px) {
  .detail-hero { padding: 28px 0 0; }
  .detail-hero__title { font-size: 24px; }
  .block__heading { font-size: 19px; }
}


.gov__title { font-size: 36px; line-height: 1.25em; font-weight: 700; color: var(--ink); }
.gov__company { margin-top: 10px; font-size: 18px; font-weight: 600; color: var(--body); }

.gov__docs { margin-top: 28px; display: grid; gap: 12px; max-width: 460px; }
.gov__docs[hidden] { display: none; }
.gov__status { margin-top: 28px; font-size: 16px; color: var(--body); }

.gov__docs a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  background: #fff;
  transition: border-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.gov__docs a:hover { border-color: var(--orange); color: var(--orange-text); box-shadow: var(--shadow-card); }

@media (max-width: 809px) {
  .gov__title { font-size: 26px; }
}

/* Bootstrap overrides — keep Framer widths, not Bootstrap defaults */
html { scroll-padding-top: 76px; }

h1, h2, h3, h4, h5, h6,
p,
ul, ol { margin-bottom: 0; }

ul, ol { padding-left: 0; }

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

/* Overrides Bootstrap's own .container, so it has to repeat the rail rather
   than only reset the gutters — and it must stay in step with the .container
   rule at the top of this file, or that one silently does nothing. */
.container {
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
  max-width: var(--container) !important;
  padding-left: clamp(20px, 2.4vw, 32px) !important;
  padding-right: clamp(20px, 2.4vw, 32px) !important;
}

header.nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-wrap: nowrap;
  padding: 6px 0;
  margin-bottom: 0;
  width: 100%;
}

header.nav .nav__inner { width: 100%; }
header.nav .nav__drawer { width: 100%; }

button.btn,
a.btn {
  --bs-btn-padding-x: 27px;
  --bs-btn-padding-y: 12px;
  --bs-btn-font-size: 14px;
  --bs-btn-font-weight: 700;
  --bs-btn-line-height: 1;
  --bs-btn-border-width: 0;
  --bs-btn-border-radius: 40px;
  line-height: 1;
  border: 0;
  box-shadow: none;
  text-decoration: none;
}

.btn:focus,
.btn:active,
.btn:focus-visible { box-shadow: none !important; }

[hidden] { display: none !important; }

.legal { display: none; }
.legal.is-open { display: grid; }
.form-success { display: none; }
.form-success.is-open { display: grid; }
.nav__drawer { display: none !important; }
.nav.is-open .nav__drawer { display: flex !important; }
.nav__drawer-sub { display: none; }
.nav__drawer-sub.is-open { display: grid; }
.eyebrow { font-size: 14px; font-weight: 500; line-height: 24px; color: var(--slate); }
.field.is-invalid .field__error { display: block; }
.field__error { display: none; }
.p-benefit.is-hidden { display: none; }

@media (max-width: 1199px) {
  .nav__drawer { display: none !important; }
  .nav.is-open .nav__drawer { display: flex !important; }
}

/* Live Framer hover tokens — must come after Bootstrap `a:hover` reset */
a.btn.btn--primary:hover,
a.btn.btn--primary:focus,
button.btn.btn--primary:hover,
button.btn.btn--primary:focus {
  background: var(--orange-deep-600);
  color: #fff;
}
a.btn.btn--white:hover,
button.btn.btn--white:hover {
  background: #fff6f0;
  color: #f16724;
}
.form-card__submit:hover { background: #eb5105; color: #fff; }
.form-success__close:hover { color: var(--orange-text); }
.text-muted { color: var(--muted) !important; }
.chip { transition: border-color .15s ease, color .15s ease, background-color .15s ease; }
.chip:hover { border-color: var(--orange-text); color: var(--orange-text); }
.chip.chip--active:hover { background: var(--orange-deep); border-color: var(--orange-deep); color: #fff; }

/* ---------- carousel controls on small screens ---------- */
/* The prev/next orbs are 56px and sit over the track at top:50%. That works on
   a desktop, where a card is narrower than the rail and the orb falls on the
   photo. At 949px the cards stack — image on top, heading below — so the orbs
   land on the heading instead, and on a phone a card is 86vw, so they cover it
   outright at top:50%. From 949px down they ride the thumbnail band instead,
   and shrink a step. */
@media (max-width: 949px) {
  .orb { width: 46px; height: 46px; }
  .orb svg { width: 18px; height: 18px; }

  /* Pinned to the middle of the thumbnail band (218-220px tall on both
     carousels), where the card edges show, rather than docked under the
     track: at top:50% a stacked card puts them down in the body copy. */
  .impl__prev,
  .impl__next,
  .cs__prev,
  .cs__next {
    top: 110px;
    bottom: auto;
    transform: translateY(-50%);
  }
  .impl__prev,
  .cs__prev { left: 12px; right: auto; }
  .impl__next,
  .cs__next { right: 12px; left: auto; }

  /* the hero stage is a fixed 389px box, so it needs the room made first */
  .hero__stage { height: auto; padding-bottom: 62px; }
  .hero__arrows {
    top: auto;
    bottom: 0;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    justify-content: center;
    gap: 16px;
  }
}

/* =========================================================================
   MOBILE REFINEMENT
   =========================================================================
   Appended last so it settles the type scale, spacing and touch targets for
   phones without unpicking the breakpoints above, which handle structure
   (nav collapses to a drawer, stats stack, carousels narrow).

   The scale here is deliberately small and tight: 26 / 20 / 17 / 14 / 12 in
   Inter. On a 360px screen a 36px headline eats a third of the first
   viewport, and every heading competing at 24px leaves nothing leading the
   page. One exception is argued in place - form inputs.
   ========================================================================= */

@media (max-width: 809px) {
  /* Nothing may exceed the viewport. Media is the usual culprit, and a
     stray fixed width in one section should not put the whole page into
     sideways scroll. */
  img,
  svg,
  video,
  iframe { max-width: 100%; }

  .container { padding-left: 16px; padding-right: 16px; }

  /* Sections carry desktop breathing room that reads as dead space on a
     phone, where the screen is the constraint rather than the eye. */
  .section { padding: 34px 0; }
  .cs { padding: 34px 0 40px; }
  .impl { padding: 34px 0; }
  .contact { padding: 34px 16px; gap: 22px; }

  /* Anything a finger has to hit gets 44px, the smallest reliable target. */
  .btn,
  .nav__burger,
  .footer__linkbtn,
  .form-card__submit { min-height: 44px; }

  /* The stage goes to auto height at 949px, but the viewport inside it kept
     the desktop 377px while holding 290px cards: 87px of empty band. */
  .hero__viewport { height: auto; }

  /* The consultation band lays a photo across the right 40% and gives the
     copy 53% of the width. A fair split on a desktop; a 190px column with a
     picture behind it on a phone. The photo is decoration, so it stands down
     and the copy takes the width. The line-work behind stays. */
  .consult { display: block; }
  .consult__art { display: none; }
  .consult__copy {
    width: auto;
    margin-left: 16px;
    margin-right: 16px;
  }

  /* Editorial images sized for a desktop column. */
  .detail-hero__media { height: 220px; }
  .p-help__art { height: 220px; }
}

@media (max-width: 639px) {
  /* ---- type scale ---- */
  body,
  .text-body,
  .text-lead { font-size: 14px; line-height: 1.6; }

  .h-hero { font-size: 26px; line-height: 1.18; letter-spacing: -0.02em; }

  .h-section,
  .h-section--left { font-size: 20px; line-height: 1.25; }

  .about-hero__title,
  .page-hero__title,
  .detail-hero__title,
  .p-hero__title,
  .gov__title,
  .contact__title,
  .consult__title { font-size: 21px; line-height: 1.25; }

  /* Numbers still need to read as the loudest thing in their band, just not
     at 50px on a 360px screen. */
  .p-stats__value { font-size: 26px; line-height: 1.2; }
  .about-stat__value { font-size: 24px; line-height: 1.2; }
  .stats__value { font-size: 20px; line-height: 1.3; }
  .stats__label { font-size: 13px; line-height: 1.4; }

  .p-stats__title,
  .form-card__title,
  .p-benefit__title,
  .cs__title,
  .cs__card--row .cs__title,
  .impl__title { font-size: 16px; line-height: 1.35; }

  .cs__excerpt,
  .impl__text,
  .p-benefit__text,
  .p-what__p,
  .trust__intro,
  .consult__text,
  .page-hero__sub,
  .contact__sub { font-size: 14px; line-height: 1.6; }

  .cs__meta-label,
  .cs__meta-value,
  .impl__region,
  .impl__ports,
  .link-more,
  .footer__col a,
  .footer__bottom { font-size: 13px; }

  /* Justified text needs a column wide enough to absorb the spacing. At
     14px on a 320px column it opens rivers between words instead. */
  .impl__text,
  .cs__excerpt,
  .p-benefit__text { text-align: left; hyphens: none; }

  /* ---- forms ----
     Sized down on request. Note the consequence, since it is not obvious:
     iOS Safari zooms the page in whenever a focused input is under 16px, so
     tapping a field nudges the layout. 16px is the only value that avoids it;
     everything below trades that for a smaller-looking form. */
  .field input,
  .field select,
  .field textarea {
    font-size: 14px;
    height: 42px;
    padding: 10px 12px;
  }
  .field textarea { height: auto; min-height: 76px; }
  .field label { font-size: 12px; }
  .field { margin-bottom: 12px; }
  .form-card { padding: 18px 16px 22px; }
  .form-card__title { font-size: 16px; line-height: 22px; margin-bottom: 14px; }
  .form-card__consent { font-size: 11px; line-height: 1.5; }

  .btn,
  .btn--sm,
  .btn--hero { font-size: 14px; padding: 12px 22px; }

  /* ---- headings and spacing ---- */
  .impl__head,
  .cs__head,
  .cs__head { gap: 10px; }

  /* ---- cards ---- */

  /* The hero carousel cards are a fixed 260px, which fits, but the caption
     needs to hold two lines of a long product name without clipping. */
  .hero__caption { font-size: 13px; line-height: 1.3; padding: 10px 12px; }

  /* ---- footer ---- */
  .footer__heading { font-size: 14px; }
  .footer__company,
  .footer__col p { font-size: 13px; line-height: 1.6; }

  /* A touch more room under the submit button than the 22px the card started
     with; it is the last thing on the card and wants air beneath it. */
  .form-card { padding-bottom: 28px; }

  /* ---- controls that were sized for a desktop rail ---- */
  /* The case-studies filter was set at 20px, larger than the heading above
     it once that came down to 20px. It is a control, not a headline. */
  .page-hero__filter select,
  .fsel__button { font-size: 15px; }
  .fsel__list li { font-size: 15px; }
  .about-stat__label { font-size: 13px; line-height: 1.4; }
}
/* The product-page hero form is absolutely positioned inside the hero band on
   a desktop, and its 4px of bottom padding is what keeps the card from
   overrunning that band. Below 1023px it drops into normal flow, where it can
   be as tall as it needs, so that 4px stops being a constraint and becomes a
   submit button sitting on the card's bottom edge. */
@media (max-width: 1023px) {
  .p-hero__form .form-card { padding: 26px 22px 30px; }
}

/* The hero card lives here on a phone (main.js placeHeroForm): a section
   after the product content, tucked against the consultation band. */
.p-hero-form-after { padding-top: 0; }
@media (max-width: 1023px) {
  .p-hero__title:last-child { margin-bottom: 0; }
}

/* =========================================================================
   ICONS ON SMALL SCREENS
   =========================================================================
   Every icon on the site is sized for a desktop column. Dropped into a
   320px one they stop being marks beside a label and start competing with
   it: an 80px module icon over a two-word caption, a 48px tick beside a
   line of 14px text. These bring them back into proportion with the type
   scale, and where an icon sits in a grid column the column comes with it.

   The carousel orbs are left at 46px: they are targets, not decoration, and
   44px is the floor for something a thumb has to hit.
   ========================================================================= */
@media (max-width: 639px) {
  /* Module tiles: the icon led at 80px over its own caption. */
  .p-module__icon { width: 44px; }

  /* Icon-beside-text rows. The grid column has to shrink with the icon or
     the text keeps its old indent and the gap looks like a mistake. */
  .p-benefit { grid-template-columns: 34px 1fr; gap: 13px; }
  .p-benefit__icon { width: 34px; height: 34px; }


  .p-stake__icon { width: 26px; height: 26px; }

  /* Section marks. */
  .trust__icon { width: 40px; height: 40px; }
  .platform__icon-wrap { width: 44px; height: 44px; }
  .platform__icon { width: 32px; }
  .os__icon-wrap { width: 40px; height: 40px; }
  .os__icon { width: 22px; height: 22px; }

  /* Flags on the implementation cards, and the numbered badges in the legal
     dialog: both were sized to sit beside larger type than they now do. */
  .impl__flag { width: 28px; height: 28px; }
  .legal__badge { width: 28px; height: 28px; font-size: 13px; }

  /* Logos. The heritage lockup is nearly 200px wide, over half the screen. */
  .heritage__logo { width: auto; max-width: 140px; height: auto; }
  .footer__logo img { width: 72px; height: 35px; }
}

/* The 404 page: the site's main pages as a way back in. */
.notfound { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 32px; max-width: 908px; margin: 0 auto; padding: 0 16px 87px; }

/* ==========================================================================
   UX layer — appended last on purpose.
   Source order does the work here, so nothing below needs !important to win
   against the Bootstrap-era override block further up the file. Each rule
   notes what it fixes.
   ========================================================================== */

/* ---------- 1. Motion preferences -----------------------------------------
   The marquee already had its own reduced-motion rule. This generalises it:
   anything that moves is reduced to a near-instant state change rather than
   removed outright, so transitions still signal "something happened" without
   animating. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- 2. Visible focus ----------------------------------------------
   `.btn:focus { box-shadow: none !important }` above was written to kill
   Bootstrap's focus glow, and it took the only visible focus indicator with
   it. An outline is used here instead of a box-shadow precisely so that
   !important rule cannot reach it. :focus-visible keeps the ring off mouse
   clicks and on for keyboard traversal. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--orange-600);
  outline-offset: 2px;
  border-radius: 4px;
}
/* On an orange ground the orange ring disappears, so invert it there. */
.btn--primary:focus-visible,
.form-card__submit:focus-visible,
.orb:focus-visible {
  outline-color: #fff;
  outline-offset: -4px;
}

/* ---------- 3. Logo strip: pause control ----------------------------------
   WCAG 2.2.2 — motion that starts on its own and runs indefinitely needs a
   way to stop it. The button is built by main.js so every page carrying the
   band gets it. Hover and keyboard focus pause it too, so a visitor reading a
   logo is not chasing it across the screen. */
.marquee { position: relative; }
/* Sits below the rail rather than over it: .marquee is a flex column and the
   button is appended last, so aligning it to the end keeps it clear of the
   logos and out of the mask gradient. */
.marquee__pause {
  align-self: flex-end;
  margin: 4px clamp(16px, 4vw, 40px) 0 0;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 50%;
  background: #fff;
  color: var(--slate);
  cursor: pointer;
  opacity: .55;
  transition: opacity .2s ease, color .2s ease, border-color .2s ease;
}
.marquee__pause:hover,
.marquee__pause:focus-visible { opacity: 1; color: var(--orange-text); border-color: var(--orange-text); }
.marquee:hover .marquee__row,
.marquee:focus-within .marquee__row,
.marquee.is-paused .marquee__row { animation-play-state: paused; }

/* ---------- 4. Touch targets ----------------------------------------------
   Everything in the enquiry path was under the 44px minimum: the modal close
   was 32px, and the success-dialog close had no box at all — just a 28px
   glyph. A missed close button on a phone is a visitor who leaves. */
.cmodal__close,
.form-success__close {
  min-width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  line-height: 1;
}
.orb { min-width: 44px; min-height: 44px; }

/* ---------- 5. Mobile form fields -----------------------------------------
   iOS Safari zooms the page whenever a focused input is under 16px, then
   leaves it zoomed and panned. The file already documented accepting that at
   14px; it costs real form completions, so the size goes back to 16px and the
   visual weight comes off the padding instead. 44px min-height in the same
   breath. */
@media (max-width: 639px) {
  .field input,
  .field select,
  .field textarea {
    font-size: 16px;
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
  }
}

/* ---------- 6. Dialogs on a phone -----------------------------------------
   100vh is the *large* viewport: with the browser toolbar showing, a card
   sized to it overflows and the submit button lands under the chrome. dvh
   tracks the toolbar. */
@supports (height: 100dvh) {
  .cmodal__card { max-height: calc(100dvh - 48px); }
}

/* ---------- 7. A CTA in the header on mobile ------------------------------
   `.nav__cta` was hidden below 1199px, leaving the burger as the only route
   to the contact form on every phone — on a site whose whole job is enquiries.
   It comes back from 360px up: mark, button and burger measure ~230px of a
   360px bar, so the common phone widths (360, 390, 393, 430) all clear it. */
@media (min-width: 360px) and (max-width: 1199px) {
  /* width:auto, not the desktop `width: 20%`: at 360px that 20% is 66px while
     the nowrap button inside is 103px, so the label spilled out across the
     burger. The 12px gap between wrapper and burger was correct all along —
     the wrapper was simply narrower than its own contents. */
  .nav__cta {
    display: flex;
    justify-content: flex-end;
    width: auto;
    flex: 0 0 auto;
    margin-left: auto;
    margin-right: 12px;
  }
  .nav__cta .btn { padding: 10px 16px; font-size: 13px; white-space: nowrap; }
  .nav__burger { margin-left: 0; flex: 0 0 44px; }
  /* The J M BAXI + portall lockup renders 215px wide, which on a 360px bar
     leaves too little for a button and the burger — they overlapped by 25px.
     Capping it here buys the room back; it is still the largest thing in the
     bar. Measured fit at 360px: 16 + 150 + 12 + 100 + 12 + 44 + 16 = 350. */
  .nav__logo { width: auto; max-width: 150px; flex: 0 1 auto; }
  .nav__logo img { width: 100%; height: auto; }
  /* With the drawer open the burger becomes a close X and the pill sits under
     it. The drawer carries its own full-width Contact Us, so the bar's copy
     stands down while it is open. */
  .nav.is-open .nav__cta { display: none; }
}

/* ---------- 8. Text setting -----------------------------------------------
   balance stops a two-word orphan on the last line of a heading; pretty does
   the same for paragraphs without the line-count limit. Replaces the
   justification hack at the small breakpoint. */
.h-hero, .h-section, .h-section--left, .h-card, .p-hero__title, .cs__title, .impl__title {
  text-wrap: balance;
}
.text-body, .hero__sub, .trust__intro, .cs__excerpt, .impl__text { text-wrap: pretty; }

/* ---------- 9. Below-the-fold rendering cost ------------------------------
   Removed: `content-visibility: auto` on .impl/.cs/.footer. It implies paint
   containment, which clipped every card shadow inside those sections, and its
   600px placeholder left the sections blank or the wrong height until they
   scrolled near. The images already load lazily, which is most of the saving. */

/* ---------- 9a. Cards read as cards ---------------------------------------
   The old card shadow was a single 8%-alpha blur that all but vanished on
   white, and two row cards used a 4% one. One two-layer token now: a tight
   contact shadow for the edge plus a soft drop for the lift. */
:root {
  --shadow-card: 0 1px 3px rgba(16, 24, 40, .08), 0 12px 32px rgba(16, 24, 40, .10);
  --shadow-card-hover: 0 2px 6px rgba(16, 24, 40, .08), 0 24px 48px rgba(16, 24, 40, .14);
  --shadow-stack: var(--shadow-card);
}
.os__list,
.cs__card--row { box-shadow: var(--shadow-card); }
.cs__card:hover,
.cs__card--row:hover,
.cs__feature-card:hover,
.impl__card:hover,
.platform__card:hover { box-shadow: var(--shadow-card-hover); }

/* The carousels clip at the viewport (they have to — the track is wider than
   the page), and that clip was cutting the shadows off. The viewport grows
   into the space around the cards and gives it straight back with a negative
   margin, so the layout does not move but the shadow has room to render. */
.cs__viewport,
.impl__viewport {
  padding: 24px 0 56px 24px;
  margin: -24px 0 -56px -24px;
}

/* Case-study / article feature cards used to abut (gap 0), so a row of them
   read as one long strip. main.js reads the track gap when it steps. */
.cs__track { gap: 24px; }
/* The stage's min-height was taller than the cards, adding dead space under
   every carousel. The cards set the height now. */
.cs__stage { min-height: 0; }

/* ---------- 9b. One vertical rhythm ---------------------------------------
   Section padding ranged from 26px to 96px depending on who wrote the block,
   and two white sections in a row stacked both paddings (160-170px of empty
   page). Every section now uses --section-y, and a white section that follows
   another white section drops its top padding, so the gap is always one
   --section-y. Page-level --section-pt/-pb overrides still win. */
:root { --section-y: clamp(56px, 5.5vw, 88px); }
.section { padding: var(--section-pt, var(--section-y)) 0 var(--section-pb, var(--section-y)); }
.platform, .os, .impl, .cs, .trust, .contact, .p-stats {
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
}
.stats { padding-bottom: var(--section-y); }
.marquee { padding-top: var(--section-y); }
/* The hero's card stage already carries ~56px of air under the cards. */
.hero + .marquee { padding-top: 24px; }

body:not([data-page="articles"][data-root=".."]) :is(.page-hero, .platform, .os, .cs:not([hidden]), .p-stats, .section:not(.section--soft):not(.ba-solution):not(.ba-dark))
  + :is(.platform, .os, .cs, .p-stats) { padding-top: 0; }
body:not([data-page="articles"][data-root=".."]) :is(.page-hero, .platform, .os, .cs:not([hidden]), .p-stats, .section:not(.section--soft):not(.ba-solution):not(.ba-dark))
  + .section:not(.section--soft):not(.ba-solution):not(.ba-dark) { --section-pt: 0; }
/* The two long-form article pages (articles/*.html) are designed band by band with their
   own spacing and coloured sections, so the collapse above leaves them alone. */
/* A hidden homepage Articles block must not collapse the Case Studies after it. */
.impl + .cs[hidden] + .cs { padding-top: var(--section-y); }

/* ---------- 10. Accessible orange (opt-in) --------------------------------
   Recorded, not applied — this is a brand decision, not a CSS one.
   The brand orange #f16724 is 3.13:1 against white. WCAG AA asks 4.5:1 for
   text below 18.66px bold, which is exactly what the CTA labels are, so
   "Request a Consultation" and "Send Message" currently fail. #c2410c is
   5.18:1 and passes. Uncommenting the block below switches the button fill
   and the orange-on-white words without touching decorative fills and rules,
   which stay brand orange.

:root {
  --orange-deep: #c2410c;
  --orange-deep-600: #9a3412;
  --orange-text: #c2410c;
}
*/

/* ---------- 9c. Former inline style="" attributes ---------------------------
   Generated when the CSP dropped style-src 'unsafe-inline': each page-specific
   style attribute became one of these classes. !important keeps the precedence the
   inline style had over the rest of this file. url()s resolve the same from css/ as
   from the one-folder-deep pages that use them. */
.is-b36d185 { --page-hero-gap:31px !important; --page-hero-pt:27px !important; --page-hero-pb:27px !important; --page-hero-head-gap:0px !important; --page-hero-sub-w:677px !important; }
.is-6aab02d { --ba-band-img:url('../assets/images/Z8yODpX5okPcehNcll8lQMFZjjU.webp') !important; }
.is-709e7c8 { --section-pt:60px !important; --section-pb:60px !important; }
.is-a529dec { --ct-band-img:url('../assets/images/Z8yODpX5okPcehNcll8lQMFZjjU.webp') !important; }
.is-5c5bee2 { --section-pb:20px !important; }
.is-ed8e39c { --section-pt:40px !important; }
.is-064007e { --p-hero-img:url('../assets/images/hero-berthing.webp') !important; }
.is-9b8999a { --p-what-w:820px !important; }
.is-bb3f8e6 { --p-benefits-mt:30px !important; --p-benefits-row-gap:40px !important; }
.is-b969206 { --p-hero-img:url('../assets/images/v7nVgr6WRyDlqQxGYpFty4Wj4.webp') !important; }
.is-91acd22 { --p-benefits-row-gap:27px !important; }
.is-6e1486c { --p-hero-img:url('../assets/images/Z8yODpX5okPcehNcll8lQMFZjjU.webp') !important; }
.is-bfb3473 { --p-hero-img:url('../assets/images/3b43MUgdX7OW4u0Zyg1bhMrnao.webp') !important; }
.is-d23f225 { --p-benefits-row-gap:41px !important; }
.is-58681ab { --p-hero-img:url('../assets/images/hero-berthing.webp') !important; --p-hero-h:460px !important; --p-hero-tint-h:202px !important; --p-hero-title-top:133px !important; --p-hero-form-w:600px !important; }
.is-1607baf { --section-pb:0 !important; }
.is-f7168e5 { --p-what-pt:16px !important; --p-what-pb:16px !important; --p-what-w:496px !important; --p-what-head-w:490px !important; --head-rule-pb:23px !important; --p-what-p-mt:8px !important; }
.is-5174efb { --section-pt:38px !important; }
.is-5c29bb0 { --p-benefits-mt:36px !important; --p-benefits-row-gap:23px !important; }
.is-37fa4dc { --section-pt:0 !important; }
.is-c4dacba { --head-rule-pb:22px !important; }
.is-cc539b0 { --p-modules-row-gap:58px !important; }
.is-095844c { --p-stats-head-gap:14px !important; --p-stats-head-pb:19px !important; --p-stats-max:1200px !important; --p-stats-cols:repeat(3, minmax(50px, 1fr)) !important; --p-stats-cell-w:100% !important; margin-bottom:50px !important; }
.is-aaf295a { max-width:350px !important; }
.is-83d7b5c { width:340px !important; }
.is-79b64e5 { --p-hero-img:url('../assets/images/nz6vFPdKbgBHDRW5tseyZI0bK0.webp') !important; }
.is-1b7d67f { --p-benefits-mt:49px !important; --p-benefits-row-gap:23px !important; }
.is-f4a6bc6 { --p-modules-row-gap:61px !important; }
