/* ==========================================================================
   imci — 2026 redesign stylesheet

   Scoped to redesigned pages only. The legacy styles.css still serves every
   page that has not been migrated yet, so the two can coexist while the site
   moves across one page at a time. When the last page migrates, styles.css
   can be deleted and this file renamed.

   Palette note: the homepage mockup was built in Office and carried its
   default theme blues (#156082 / #4E95D9). The brand direction is white and
   navy, so those are swapped for the navy scale below. Every colour is a
   custom property — re-theming is an edit to this block, nothing more.
   ========================================================================== */

/* --- tokens --------------------------------------------------------------- */
:root {
  /* core */
  --navy:        #0c2a45;
  --navy-deep:   #06192b;
  --navy-soft:   #17456b;
  --white:       #ffffff;
  --ink:         #14181d;
  --muted:       #52616f;

  /* highlights */
  --accent:      #2e7db8;
  --accent-soft: #4e95d9;

  /* surfaces */
  --tint:        #f2f7fa;
  --tint-deep:   #e8f0f6;
  --border:      #d6e4ec;

  /* spacing scale */
  --sp-xs:  .5rem;
  --sp-sm:  .875rem;
  --sp-md:  1.5rem;
  --sp-lg:  2.5rem;
  --sp-xl:  4rem;
  --sp-2xl: 6rem;

  /* form */
  --radius:    12px;
  --radius-sm: 8px;
  --shadow:    0 1px 2px rgba(12, 42, 69, .04), 0 8px 24px rgba(12, 42, 69, .06);
  --maxw:      1120px;

  /* type ---------------------------------------------------------------
     Two families: Manrope carries the display voice, Inter does the reading.
     Swapping either is a one-line change here.                            */
  --font-display: Manrope, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-body:    Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* Optical tracking. Large type needs to be pulled tighter and small type
     left alone — one global value is wrong at both ends of the scale. */
  --track-display: -.035em;
  --track-title:   -.028em;
  --track-lead:    -.018em;
  --track-body:    -.005em;

  /* Comfortable reading measure, ~62 characters. */
  --measure: 34rem;
}

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

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Contextual alternates and proportional figures; tabular numerals are
     switched on locally where columns of numbers need to line up. */
  font-feature-settings: "cv11", "ss01";
}

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  line-height: 1.12;
  letter-spacing: var(--track-title);
  text-wrap: balance;          /* stops a lone word dropping to its own line */
}
p  { margin: 0 0 var(--sp-md); }
ul { margin: 0; padding: 0; list-style: none; }
img, svg { max-width: 100%; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

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

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--sp-md); }

.skip-link {
  position: absolute; left: -9999px;
  background: var(--navy); color: var(--white);
  padding: var(--sp-sm) var(--sp-md); border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; top: 0; z-index: 100; }

/* --- nav ------------------------------------------------------------------ */
.nav2 {
  position: sticky; top: 0; z-index: 50;
  background: var(--white);
  border-bottom: 1px solid var(--border);
}

.nav2-inner {
  max-width: var(--maxw); margin: 0 auto;
  padding: .625rem var(--sp-md);
  /* Small gap: the only pair it visibly separates is the wordmark and the
     locale, since .nav2-links is pushed away by margin-left: auto. */
  display: flex; align-items: center; gap: .625rem;
}

.nav2-brand { display: flex; align-items: center; gap: .75rem; flex-shrink: 0; }
.nav2-brand img { height: 26px; width: auto; display: block; }

/* Sits tight to the wordmark as a qualifier rather than a separate nav item,
   so the spacing comes from .nav2-inner's gap alone — no extra padding, no
   divider. Kept muted so it stays quieter than the links opposite it. */
.nav2-locale {
  font-size: .875rem; font-weight: 600; color: var(--muted);
  white-space: nowrap;
}

.nav2-links {
  display: flex; align-items: center; gap: var(--sp-md);
  margin-left: auto;
}
.nav2-links a {
  font-family: var(--font-display);
  color: var(--ink); font-size: .9375rem; font-weight: 600;
  padding: .375rem 0; white-space: nowrap;
}
.nav2-links a:hover { color: var(--navy); text-decoration: none; }
.nav2-links a[aria-current="page"] { color: var(--navy); font-weight: 600; }

.nav2-cta {
  background: var(--navy); color: var(--white) !important;
  padding: .5rem 1.125rem !important;
  border-radius: var(--radius-sm);
  font-weight: 600 !important;
}
.nav2-cta:hover { background: var(--navy-soft); text-decoration: none; }

/* --- limited-edition expo game link --------------------------------------- */
/* The Business Show Asia 2026 runs a playable game stand. This nav item is
   meant to break the calm of the rest of the bar — an animated gradient, a
   sheen that sweeps across it, and a small "Limited edition" tag underneath so
   visitors read it as temporary rather than as a new service. All of it is
   self-contained: delete this block and the matching <a> in the nav partial
   when the show ends. Every animation is disabled under prefers-reduced-motion,
   where the gradient still reads as distinct without moving. */
.nav2-limited {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: .0625rem;
  overflow: hidden;
  padding: .3125rem .875rem !important;
  border-radius: var(--radius-sm);
  color: var(--white) !important;
  line-height: 1.2;
  /* Oversized so the position animation has somewhere to travel. */
  background: linear-gradient(100deg, #7b2ff7, #f107a3, #ff7a18, #f107a3, #7b2ff7);
  background-size: 300% 100%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18) inset,
              0 2px 10px rgba(241, 7, 163, .32);
  animation: limited-drift 6s linear infinite, limited-pulse 2.4s ease-in-out infinite;
  transition: transform .18s ease;
}
.nav2-limited:hover { text-decoration: none; transform: translateY(-1px); }
.nav2-limited:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

.nav2-limited-body { display: flex; align-items: center; gap: .3125rem; }
.nav2-limited-icon { font-size: .875rem; line-height: 1; }
.nav2-limited-text {
  font-family: var(--font-display);
  font-size: .9375rem; font-weight: 800; letter-spacing: -.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .22);
}

.nav2-limited-tag {
  font-size: .5625rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: rgba(255, 255, 255, .92);
}

/* A single bright band swept across the pill on a long cycle — frequent enough
   to catch the eye, rare enough not to nag. */
.nav2-limited-sheen {
  position: absolute; top: 0; left: 0; width: 45%; height: 100%;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .55) 50%,
    rgba(255, 255, 255, 0) 100%);
  transform: translateX(-160%);
  animation: limited-sheen 3.2s ease-in-out infinite;
  pointer-events: none;
}

@keyframes limited-drift {
  from { background-position:   0% 50%; }
  to   { background-position: 300% 50%; }
}
@keyframes limited-pulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(255, 255, 255, .18) inset,
                         0 2px 10px rgba(241, 7, 163, .32); }
  50%      { box-shadow: 0 0 0 1px rgba(255, 255, 255, .28) inset,
                         0 3px 18px rgba(241, 7, 163, .62); }
}
@keyframes limited-sheen {
  0%        { transform: translateX(-160%); }
  55%, 100% { transform: translateX(320%); }
}

@media (prefers-reduced-motion: reduce) {
  .nav2-limited { animation: none; background-position: 40% 50%; }
  .nav2-limited:hover { transform: none; }
  .nav2-limited-sheen { display: none; }
}

/* --- services dropdown ---------------------------------------------------- */
.nav2-dd { position: relative; }

.nav2-dd-btn {
  display: flex; align-items: center; gap: .35rem;
  padding: .375rem 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: .9375rem; font-weight: 500;
  color: var(--ink);
}
.nav2-dd-btn:hover,
.nav2-dd.is-open .nav2-dd-btn { color: var(--navy); }

.nav2-caret { transition: transform .18s ease; }
.nav2-dd.is-open .nav2-caret { transform: rotate(180deg); }

.nav2-dd-menu {
  display: none;
  position: absolute; top: calc(100% + .625rem); left: 0; z-index: 70;
  min-width: 292px; max-width: calc(100vw - 2rem);
  padding: .375rem;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.nav2-dd.is-open .nav2-dd-menu { display: block; }

.nav2-dd-menu a {
  display: block;
  padding: .5rem .75rem;
  border-radius: var(--radius-sm);
  font-size: .9375rem; font-weight: 500; color: var(--ink);
}
.nav2-dd-menu a:hover { background: var(--tint); color: var(--navy); text-decoration: none; }
.nav2-dd-menu a[aria-current="page"] { background: var(--tint); color: var(--navy); font-weight: 700; }

/* The flagship sits above the six, visually separated. */
.nav2-dd-flagship {
  display: flex !important; align-items: flex-start; gap: .5rem;
  margin-bottom: .375rem;
  padding: .625rem .75rem !important;
  background: var(--tint) !important;
  border: 1px solid var(--border);
}
.nav2-dd-flagship strong { display: block; color: var(--navy); font-weight: 700; line-height: 1.3; }
.nav2-dd-flagship em {
  display: block; margin-top: .125rem;
  font-style: normal; font-size: .8125rem; font-weight: 400; color: var(--muted);
}
.nav2-dd-star { flex-shrink: 0; color: var(--accent); font-size: .8125rem; line-height: 1.5; }

/* --- service page hero ---------------------------------------------------- */
.svc-hero { padding: var(--sp-2xl) 0 var(--sp-xl); }
.svc-hero-eyebrow {
  margin-bottom: var(--sp-sm);
  font-size: .75rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--accent);
}
.svc-hero h1 {
  font-size: clamp(1.875rem, 4.4vw, 2.875rem);
  font-weight: 700;
  letter-spacing: var(--track-display); max-width: 18ch;
  margin-bottom: var(--sp-md);
}
.svc-hero-lead {
  max-width: 60ch; margin-bottom: var(--sp-lg);
  font-size: 1.125rem; color: var(--muted);
}

/* --- buttons -------------------------------------------------------------- */
.btn2 {
  font-family: var(--font-display);
  display: inline-block;
  padding: .8125rem 1.75rem;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 1rem; font-weight: 600; line-height: 1.2;
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.btn2:hover { text-decoration: none; }

.btn2-primary   { background: var(--navy); color: var(--white); }
.btn2-primary:hover { background: var(--navy-soft); }

.btn2-secondary { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn2-secondary:hover { background: var(--navy); color: var(--white); }

.btn2-light      { background: var(--white); color: var(--navy); }
.btn2-light:hover { background: var(--tint-deep); }

.btn2-outline-light { background: transparent; color: var(--white); border-color: rgba(255,255,255,.55); }
.btn2-outline-light:hover { background: rgba(255,255,255,.12); }

.btn2-row { display: flex; flex-wrap: wrap; gap: var(--sp-sm); }

/* --- hero ----------------------------------------------------------------- */
.hero2 { padding: var(--sp-2xl) 0 var(--sp-xl); }

.hero2-lockup { display: flex; align-items: center; gap: 1rem; margin-bottom: var(--sp-lg); }
.hero2-lockup img { height: 52px; width: auto; display: block; }
.hero2-lockup span {
  font-size: 2.25rem; font-weight: 500; color: var(--ink);
  letter-spacing: -.02em; line-height: 1;
}

/* Supplied wordmark. The artwork carries its own padding, so it is sized taller
   than the old mark to land on a similar glyph height. It has no alpha channel
   and a white background, so it must sit on white — not on a tinted section. */
.hero2-lockup .hero2-wordmark {
  height: auto;
  width: clamp(200px, 26vw, 300px);
  max-width: 100%;
}

/* The h1 spans both lines so the full phrase stays one heading for search,
   while rendering as a banner panel above a plain subtitle. */
.hero2 h1 { margin-bottom: var(--sp-lg); font-weight: 800; }

.hero2-banner {
  position: relative;
  /* The wordmark is positioned absolutely, so the title is the only in-flow
     child — it is pinned to the bottom and the wordmark stacks above it. */
  display: flex; flex-direction: column; justify-content: flex-end;
  align-items: flex-start;
  min-height: var(--hero-banner-h);
  padding: var(--sp-lg);
  border-radius: var(--radius);
  overflow: hidden;
  background-color: var(--navy-deep);            /* shows if the image fails */
  background-image: url("assets/hero-banner-placeholder.svg");
  background-size: cover;
  background-position: center;
  color: var(--white);
  font-size: var(--hero-title);
  font-weight: 600;
  letter-spacing: var(--track-display);
  line-height: 1;
}

/* Background video. The still above stays as the fallback: it shows before the
   first frame paints, if the file fails, and whenever motion is reduced. */
.hero2-banner-video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  border: 0;
  pointer-events: none;
}

/* Scrim, so the heading stays legible over whatever plays behind it — a light
   or busy frame would otherwise swallow white text. Sits above the video. */
.hero2-banner::before {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(4,12,20,.78) 0%, rgba(4,12,20,.5) 55%, rgba(4,12,20,.25) 100%);
}
.hero2-banner > span { position: relative; z-index: 2; }

/* Wordmark rebuilt in white on the banner itself: the supplied "imci" mark,
   then "AI software" set in the display face. This is the
   hero's primary element — the title below it is deliberately smaller and
   italic so the brand reads first.
   Positioned into the banner from outside the heading, which keeps the brand
   name out of the <h1> text. The banner is the first thing in this figure, so
   the banner's own padding gives the offsets. */
/* Both hero sizes are declared here, on the shared ancestor, because the brand
   lockup sits outside the <h1> yet still has to be positioned against the
   title's line box. The brand leads; the title is the companion line. */
.hero2-figure {
  position: relative;
  /* Ratio held at ~0.67 across the whole range, floors included, so the title
     stays visibly secondary on phones too. "AI software" is nowrap, so the
     floors have to leave the lockup room inside the banner at 320px. */
  --hero-brand: clamp(1.5rem, 5.2vw, 3.75rem);
  --hero-title: clamp(1rem, 3.5vw, 2.5rem);
  --hero-banner-h: clamp(200px, 30vw, 360px);
}
.hero2-brand {
  position: absolute; z-index: 3;
  left: var(--sp-lg);
  /* Stacked directly above the title instead of pinned to the far corner.
     Offset from the top, not the bottom: this box is positioned against
     .hero2-figure, which runs on past the banner to include the subtitle, so
     only the top edge is common to both. Measuring down from there — banner
     height, less its bottom padding, the title's line box (line-height is 1,
     so that box is exactly --hero-title tall), a small gap, and this lockup's
     own height — lands it just above the title. */
  top: calc(
    var(--hero-banner-h) - var(--sp-lg) - var(--hero-title)
    - var(--sp-xs) - (var(--hero-brand) * 1.55)
  );
  /* Gap scales with the type rather than the viewport, so the mark and the
     word stay proportionally spaced at every size. */
  display: flex; align-items: center; gap: calc(var(--hero-brand) * .4);
}
.hero2-brand img {
  /* 1.55x the companion text — the ratio the smaller lockup was tuned at. */
  height: calc(var(--hero-brand) * 1.55);
  width: auto; display: block;
}
.hero2-brand-text {
  font-family: var(--font-display);
  font-size: var(--hero-brand);
  font-weight: 500;
  letter-spacing: .06em;
  line-height: 1;
  color: rgba(255, 255, 255, .92);
  white-space: nowrap;
}

/* Italic, so it reads as the companion line to the brand lockup above it. */
.hero2-banner-title { display: block; font-style: italic; }

/* WCAG 2.3.3 / 2.2.2: honour a reduced-motion preference by dropping the
   video entirely, which reveals the still underneath. */
@media (prefers-reduced-motion: reduce) {
  .hero2-banner-video { display: none; }
}

.hero2-h1-sub {
  display: block;
  margin-top: var(--sp-md);
  font-size: clamp(1.25rem, 2.8vw, 2rem);
  font-weight: 500;
  color: var(--muted);          /* steps back so the banner stays the anchor */
  letter-spacing: var(--track-lead);
}

/* Standfirst on the left, the capability chips stacked on the right. */
.hero2-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-lg) var(--sp-xl);
  align-items: start;
}

.hero2-list { display: grid; gap: .75rem; }
.hero2-list li {
  position: relative;
  padding-left: 1.875rem;
  font-size: 1.0625rem; font-weight: 500; color: var(--ink);
}
.hero2-list li::before {
  content: "";
  position: absolute; left: 0; top: .48em;
  width: .7rem; height: .38rem;
  border-left: 2.25px solid var(--accent);
  border-bottom: 2.25px solid var(--accent);
  transform: rotate(-45deg);
}

/* Full-width CTA row on a barely-there card. One rule for two names:
   .hero2-action is the homepage hero's block and .cta2 is the flagship page's
   repeated CTA. They are the same component, so they share one declaration
   rather than two that can drift apart. The button is deliberately the same
   navy primary every page hero uses: one action, one look. */
.hero2-action,
.cta2 {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-sm) var(--sp-lg);
  margin-top: var(--sp-lg);
  padding: var(--sp-md) var(--sp-lg);
  /* Barely-there wash and no border: the row should group the action and its
     note without reading as a boxed-off card competing with the hero. A
     translucent navy sits softer on white than the flat --tint. */
  background: rgba(12, 42, 69, .025);
  border-radius: var(--radius);
}
.hero2-action .btn2,
.cta2 .btn2 { flex: 0 0 auto; }

/* Sets the expectation up front, since the link goes to a form rather than a
   live scheduler. Wraps under the button once the row runs out of room. */
.hero2-cta-note,
.cta2-line {
  flex: 1 1 22rem;
  margin: 0;
  font-size: .9375rem; line-height: 1.5; color: var(--muted);
}

/* Risk-reducers under the action. Full basis, so the row always lands beneath
   the button and its line; quiet, so it supports the button rather than
   competing with it. Items separated by middots, as elsewhere on the site. */
.cta2-trust {
  flex: 1 1 100%;
  margin: 0;
  font-size: .85rem;
  letter-spacing: .015em;
  color: var(--muted);
}

/* Bare variant for the flagship hero: with two buttons plus microcopy, the
   boxed wash read as a slab floating under the hero, so this variant dissolves
   the card and lets the block run on from the lead — a left-flush column with
   the buttons as the focal row and the two small lines bound to them as a
   caption. The boxed base rule above is untouched for everything else. */
.cta2-bare {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding: 0;
  background: transparent;
  border-radius: 0;
}
/* Column axis flips flex-basis to heights, so the microcopy resets to natural
   size and takes caption spacing instead: close to the buttons, closer still
   to each other. */
.cta2-bare .cta2-line {
  flex: none;
  max-width: 60ch;             /* the lead's measure, so the column reads as one */
  margin-top: .8125rem;
}
.cta2-bare .cta2-trust {
  flex: none;
  margin-top: .375rem;
}

.hero2-standfirst {
  margin: 0;
  font-size: 1.125rem; line-height: 1.6; color: var(--muted);
}
.hero2-standfirst em {
  display: block; margin-top: .25rem;
  font-family: var(--font-display);
  font-size: 1.25rem; font-style: normal; font-weight: 600;
  letter-spacing: var(--track-lead);
  color: var(--navy);
}

/* --- section headings ----------------------------------------------------- */
.section2 { padding: var(--sp-xl) 0; }
.section2-tint { background: var(--tint); }

.section2-title {
  max-width: 22ch;
  font-size: clamp(1.75rem, 3.4vw, 2.375rem);
  font-weight: 700;
  color: var(--navy);
  margin-bottom: var(--sp-md);
}
/* A hairline rule reads more considered than the heavy bar it replaces. */
.section2-rule {
  width: 44px; height: 3px;
  background: var(--accent);
  border-radius: 2px;
  margin-bottom: var(--sp-lg);
}

/* Editorial split: heading in a narrow left column, prose in a wider right one.
   A single centred-left column at this container width strands most of the
   page, and tightening the measure only made the gap more obvious. */
@media (min-width: 940px) {
  .section2-split > .wrap {
    display: grid;
    grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
    gap: var(--sp-xl);
    align-items: start;
  }
  .section2-split .section2-head { position: sticky; top: 6rem; }
  .section2-split .section2-rule { margin-bottom: 0; }
}

/* --- prose ---------------------------------------------------------------- */
.prose2 { max-width: var(--measure); }
/* Avoid a single word stranded on the last line of a paragraph. */
.prose2 p, .hero2-standfirst, .hero2-cta-note, .svc-hero-lead { text-wrap: pretty; }
.prose2 p { font-size: 1.0625rem; line-height: 1.7; margin-bottom: var(--sp-md); }

/* The opening and closing lines are set larger and lighter rather than simply
   bolder, so emphasis comes from scale instead of more weight. */
.prose2 .lead2,
.prose2 .close2 {
  font-family: var(--font-display);
  font-size: clamp(1.1875rem, 1.9vw, 1.4375rem);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--track-lead);
  color: var(--navy);
}
.prose2 .close2 { color: var(--accent); }
.prose2 strong { color: var(--ink); font-weight: 700; }
.prose2 .close2 strong { color: inherit; }

/* --- services grid -------------------------------------------------------- */
.svc-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-md);
}

/* Advisory runs four across; the responsive rules below step it down with
   every other grid, so only the desktop count is declared here. */
.svc-grid-4 { grid-template-columns: repeat(4, 1fr); }

/* The section is split into Advisory and Technology Building rather than one
   flat list, because "we advise" and "we build" being visibly separate is what
   makes the independence claim credible. */
.svc-block { margin-top: var(--sp-xl); }

.svc-block-title {
  font-family: var(--font-display);
  font-size: 1.375rem; font-weight: 700; color: var(--navy);
  letter-spacing: var(--track-title);
  margin-bottom: .25rem;
}
.svc-block-intro {
  margin: 0 0 var(--sp-md);
  font-size: 1.0625rem; color: var(--muted);
}

.svc-card {
  position: relative;           /* anchors the feature card's tag */
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: var(--sp-lg) var(--sp-md);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.svc-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--accent);
  text-decoration: none;
}
.section2-tint .svc-card { background: var(--white); }

.svc-icon { color: var(--navy); margin-bottom: var(--sp-sm); }
.svc-icon svg { display: block; }

/* h4 on the homepage cards (they sit under a block-level h3) and h3 on the
   flagship, which has no block heading above it. Both take the same styling. */
.svc-card h3,
.svc-card h4 {
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 700; color: var(--navy);
  letter-spacing: var(--track-lead);
  margin-bottom: .375rem;
}
.svc-card p { font-size: .9375rem; color: var(--muted); margin: 0; line-height: 1.5; }

/* "Get found by ChatGPT" is the sharpest hook in the list, so this card gets an
   accent edge and a tag — a step below the flagship's navy border, not a peer
   of the two cards beside it. */
.svc-card-feature { border: 2px solid var(--accent); }

/* The tag straddles the top border rather than sitting in the card's flow —
   in flow it pushed the icon and heading down and broke the row's alignment
   with the two cards beside it. */
.svc-tag {
  position: absolute;
  top: 0; left: 50%;
  transform: translate(-50%, -50%);
  padding: .25rem .625rem;
  background: var(--navy);     /* white-on-accent is only 4.4:1 — too low here */
  border-radius: 999px;
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  white-space: nowrap;
  color: var(--white);
}

/* --- flagship service (full-width row at the foot of the grid) ------------ */
.flagship-eyebrow {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: .5rem;
  margin: var(--sp-md) 0 0;
  font-size: .75rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--navy);
}

.svc-flagship {
  grid-column: 1 / -1;          /* spans every column, whatever the breakpoint */
  display: block;
  padding: 0;
  text-align: left;
  border: 2px solid var(--navy);
  overflow: hidden;
}

.flagship-top {
  display: grid;
  grid-template-columns: 1fr minmax(180px, auto);
  gap: var(--sp-lg);
  padding: var(--sp-lg);
}
.flagship-price-col {
  padding-left: var(--sp-lg);
  border-left: 1px solid var(--border);
}

/* Homepage variant: no price rail (pricing lives on its own page), so the card
   runs as a single column and the CTA follows the chips. pricing.html keeps the
   two-column form above, which is why this is a modifier and not an edit. */
.flagship-top-wide { grid-template-columns: 1fr; }

.flagship-body {
  max-width: 68ch;
  font-size: 1rem !important;
  line-height: 1.6;
  color: var(--muted) !important;
  margin-bottom: var(--sp-md) !important;
}

.svc-flagship h3 {
  font-size: clamp(1.375rem, 3vw, 2rem);
  font-weight: 700;
  letter-spacing: var(--track-title);
  margin-bottom: .5rem;
}

/* The one line that has to land: this tier contains all six above it. */
.flagship-punch {
  font-size: clamp(1.0625rem, 1.9vw, 1.3125rem) !important;
  font-weight: 600; line-height: 1.35;
  color: var(--navy) !important;
  margin-bottom: var(--sp-md) !important;
}

.flagship-chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.flagship-chips li {
  display: flex; align-items: center; gap: .45rem;
  padding: .4rem .8rem;
  background: var(--tint);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: .8125rem; font-weight: 600; color: var(--navy);
}
.flagship-chips li::before {
  content: "";
  flex-shrink: 0; margin-top: -.15rem;
  width: .5rem; height: .28rem;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

.flagship-label {
  margin-bottom: .375rem !important;
  font-size: .7rem !important; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--navy) !important;
}
.flagship-price { font-size: 1.125rem !important; font-weight: 700; color: var(--ink) !important; }

.flagship-cta {
  display: inline-block; margin-top: var(--sp-md);
  font-size: .9375rem; font-weight: 700; color: var(--accent);
}
.svc-flagship:hover .flagship-cta { text-decoration: underline; }

/* Label and line sit on one row — a caption, not another paragraph. */
.flagship-great {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem var(--sp-md);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--tint);
  border-top: 1px solid var(--border);
}
/* The label is a <p> too, so pin it before the flex rule below can stretch it. */
.flagship-great .flagship-label { flex: 0 0 auto; margin-bottom: 0 !important; white-space: nowrap; }
.flagship-great p {
  flex: 1 1 320px;
  font-size: .9375rem !important; color: var(--muted) !important; margin: 0;
}

/* --- AI Technology Director page ------------------------------------------ */

/* Hero subhead: deliberately much smaller than the h1 and italic, so it reads
   as an aside to the headline rather than a second headline. */
.svc-hero-sub {
  margin: calc(var(--sp-md) * -1) 0 var(--sp-md);
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  font-style: italic; font-weight: 500;
  color: var(--accent);
  letter-spacing: var(--track-lead);
}

/* .cta2 and .cta2-line are declared with .hero2-action above — one shared rule
   so the flagship page's CTAs and the homepage hero's stay identical. */

.journey-framing {
  max-width: 60ch; margin: 0;
  font-size: 1.125rem; font-weight: 600; color: var(--navy);
  line-height: 1.55; text-wrap: pretty;
}

/* Container for the flow diagram. Breaks the wrap so the diagram can run wider
   than body text. The holding min-height it carried while empty is gone now
   that there is content — the diagram sets its own height — and the padding is
   back to ordinary section spacing rather than the deliberate void. Left as a
   plain block, not a flex row, so .jd fills the width; the mobile rules below
   size nodes at 100% and need a full-width parent to resolve against. */
.journey-frame { margin-top: var(--sp-lg); }
#journey-diagram { padding: var(--sp-md) 0 0; }

/* --- journey flow diagram -------------------------------------------------- */
/* Real HTML text rather than an image or SVG, so every stage is readable,
   selectable and translatable. Connectors are the exception: they carry no
   information a reader needs, so they are drawn into one decorative SVG by
   journey-diagram.js, which can curve and animate them in ways CSS borders
   cannot. Without JS the SVG stays empty and the CSS fallback rule below draws
   a plain spine, so the diagram still reads as a flow.

   Colour tells the commitment story, and only that story. Stages 1-3 are
   light cards: the advisory run every engagement starts with. Stages 4-5 are
   solid navy: the retainer, where the relationship lives — the deeper into
   the journey, the deeper the brand colour. The exit is a dashed ghost: a
   door, not a step. Wires switch from grey-blue to accent at the same hinge.
   Everything is drawn from the site palette; the old teal/purple grouping
   encoded nothing a prospect could decode. */
.jd {
  --jd-line:       #bcceda;        /* advisory wires: --border reads too faint at 2px */
  --jd-w:          330px;          /* main spine node width */
  --jd-exit-w:     264px;
  --jd-gap:        52px;           /* vertical space between rows, = wire length */
  /* The side columns mirror the exit column so the spine stays centred, which
     makes the wide layout cost node + 2*(gap + exit). Kept tight so it fits
     inside the 1120px wrap with room to spare. */
  --jd-branch-gap: 52px;           /* horizontal run of the exit branch */
}

/* Grid rather than a flex stack: explicit rows and columns give every node a
   position the SVG can measure reliably, and put the main spine dead centre
   without counterweights. Column 2 is the spine; column 3 holds the exit. */
.jd-flow {
  position: relative;
  display: grid;
  grid-template-columns:
    minmax(0, 1fr)
    auto
    minmax(0, 1fr);
  row-gap: var(--jd-gap);
  justify-items: center;
  align-items: center;
}

.jd-stage { grid-column: 2; position: relative; }
.jd-r1 { grid-row: 1; }
.jd-r2 { grid-row: 2; }
.jd-r3 { grid-row: 3; }
.jd-r4 { grid-row: 4; }
.jd-r5 { grid-row: 5; }

/* The exit hangs off to the right of the roadmap, on the same row. */
.jd-exit-stage {
  grid-column: 3;
  justify-self: start;
  margin-left: var(--jd-branch-gap);
}

/* ---- nodes ---- */
/* A button because the tooltip is operable with Enter and Space; it is styled
   as a card and carries no button chrome. Left-aligned behind a numbered
   kicker: centred text in uniform bordered boxes is what makes a flow read as
   slideware, so the cards read as editorial cards instead. */
.jd-node {
  display: block;
  width: var(--jd-w);
  padding: 1.0625rem 1.25rem 1.125rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  line-height: 1.4;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(12, 42, 69, .05), 0 10px 26px rgba(12, 42, 69, .07);
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.jd-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem;
  margin-bottom: .5625rem;
}
.jd-num {
  font-family: var(--font-display);
  font-size: .6875rem; font-weight: 800;
  letter-spacing: .16em; line-height: 1;
  color: var(--accent);
}
/* Same scale as the number, quieter voice: the off-ramp's whole message. */
.jd-kicker {
  font-family: var(--font-display);
  font-size: .6875rem; font-weight: 800;
  letter-spacing: .16em; line-height: 1;
  text-transform: uppercase;
  color: var(--muted);
}
/* "Free" is deliberately the loudest word in the diagram: it answers "what
   does it cost to find out?" before the question forms. Navy chip, maximum
   contrast, same voice as the site's primary buttons. */
.jd-pill {
  padding: .25rem .5625rem .1875rem;
  border-radius: 999px;
  background: var(--navy);
  color: var(--white);
  font-size: .625rem; font-weight: 700;
  letter-spacing: .14em; line-height: 1;
  text-transform: uppercase;
}
.jd-node strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 700;
  letter-spacing: var(--track-lead);
}
/* Leading keyword of a stage title: the verb carries the story, so it takes
   the accent and a heavier weight. Soft accent on the navy cards — the same
   swap the numbers make — to keep the contrast honest. */
.jd-kw { color: var(--accent); font-weight: 800; }
.jd-deep .jd-kw { color: var(--accent-soft); }
.jd-sub {
  display: block; margin-top: .3125rem;
  font-size: .875rem; font-weight: 500;
  color: var(--muted);
}

/* The retainer stages. A shallow navy gradient rather than a flat fill — just
   enough depth to read as a considered surface, not a coloured-in box. */
.jd-deep {
  border-color: var(--navy-deep);
  background: linear-gradient(160deg, var(--navy-soft) -30%, var(--navy) 52%, var(--navy-deep) 135%);
  color: var(--white);
  box-shadow: 0 1px 2px rgba(6, 25, 43, .18), 0 14px 30px rgba(6, 25, 43, .26);
}
.jd-deep .jd-num { color: var(--accent-soft); }
.jd-deep .jd-sub { color: rgba(255, 255, 255, .78); }

/* Dashed and unfilled: the one node that is a way out, not a step. Sits at the
   same weight as the others so it never reads as fine print, but stays visually
   quieter than the filled stages so it does not compete with the main path. */
.jd-exit {
  width: var(--jd-exit-w);
  border: 1.5px dashed rgba(82, 97, 111, .6);
  background: transparent;
  color: var(--ink);
  box-shadow: none;
}

/* Restrained: a small lift and a deeper shadow, no scaling. */
.jd-node:hover,
.jd-node:focus-visible {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: 0 2px 4px rgba(12, 42, 69, .06), 0 16px 36px rgba(12, 42, 69, .12);
}
.jd-deep:hover,
.jd-deep:focus-visible {
  border-color: var(--accent-soft);
  box-shadow: 0 2px 4px rgba(6, 25, 43, .2), 0 18px 38px rgba(6, 25, 43, .32);
}
.jd-exit:hover,
.jd-exit:focus-visible {
  border-color: var(--muted);
  box-shadow: none;
}

/* ---- connectors ---- */
/* Spans the grid and sits behind the nodes. Paths are injected by JS. */
.jd-wires {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 0;
}
.jd-stage { z-index: 1; }
/* Set by the JS while a stage's tooltip is open, so the bubble can never
   paint underneath a neighbouring card. */
.jd-stage.is-up { z-index: 6; }

.jd-wire {
  fill: none;
  stroke: var(--jd-line);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The spine changes colour where the commitment does: wires into the retainer
   stages run in accent, everything before the hinge stays grey-blue. The JS
   adds these classes from the target stage's row. */
.jd-wire-deep { stroke: var(--accent); }
.jd-wire-exit { stroke-dasharray: 2 6; }   /* the optional path, at every width */
.jd-wire-head { fill: var(--jd-line); stroke: none; }
.jd-head-deep { fill: var(--accent); }

/* The return loop is the retainer argument, so it is shown as motion rather
   than stated: a solid circuit with a dash travelling along it. Kept solid
   underneath on purpose — a dashed loop would borrow the exit branch's
   meaning, which is "optional". Slow and low-contrast so it never pulls the
   eye on a page people are reading. */
.jd-wire-loop-base { stroke: rgba(46, 125, 184, .3); }
.jd-wire-loop {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 4 10;
  opacity: .8;
}
.js .jd-wire-loop { animation: jd-cycle 3.2s linear infinite; }
@keyframes jd-cycle { to { stroke-dashoffset: -28; } }

/* Fallback spine for the no-JS case: one line down the middle of the grid,
   behind the nodes. Replaced by the SVG as soon as the script runs. */
.jd-flow::before {
  content: "";
  position: absolute; z-index: 0;
  top: 8%; bottom: 8%; left: 50%;
  width: 2px; margin-left: -1px;
  background: var(--jd-line);
}
.js .jd-flow::before { display: none; }

/* ---- support tag ---- */
/* The return loop's label — the one interactive element that is not a stage
   card. Grid-placed beside the loop lane (the lane runs 26px right of the
   cards; see journey-diagram.js), spanning both retainer rows so it centres
   on the lane's vertical middle. A real button, wired into the same tooltip
   system as the nodes; on narrow screens it moves under the last stage and
   stands in for the loop the SVG no longer draws. */
.jd-support-stage {
  grid-column: 3;
  grid-row: 4 / 6;
  justify-self: start;
  align-self: center;
  margin-left: 40px;           /* lane + 14px of breathing room */
}
.jd-support {
  display: block;
  width: max-content;
  max-width: 250px;
  padding: .5625rem .8125rem .625rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  line-height: 1.4;
  cursor: pointer;
  transition: transform .22s ease, border-color .22s ease;
}
.jd-support strong {
  display: block;
  font-family: var(--font-display);
  font-size: .8125rem; font-weight: 800;
  letter-spacing: .02em;
  color: var(--accent);
}
.jd-support .jd-sub {
  margin-top: .125rem;
  font-size: .75rem;
}
.jd-support:hover,
.jd-support:focus-visible {
  transform: translateY(-1px);
  border-color: var(--accent);
}

.jd-foot {
  margin: var(--sp-lg) 0 0;
  font-size: .875rem;
  color: var(--muted);
  text-align: center;
  text-wrap: pretty;
}

/* ---- tooltips ---- */
/* In the markup, not generated, so the detail is still there with JS off — it
   simply renders as a line of small print inside the card instead of on hover. */
.jd-tip {
  display: block;
  max-width: var(--jd-w);
  margin: .5rem auto 0;
  font-size: .8125rem;
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}

.js .jd-tip {
  position: absolute;
  z-index: 40;
  left: 50%;
  bottom: calc(100% + 12px);
  width: max-content; max-width: min(300px, calc(100vw - 2rem));
  margin: 0;
  padding: .6875rem .875rem .75rem;
  /* Deep navy, one step darker than the retainer cards, with a hairline edge —
     so a bubble sitting on a navy card still separates cleanly from it. */
  background: var(--navy-deep);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 10px;
  color: rgba(255, 255, 255, .95);
  line-height: 1.55;
  text-align: left;
  text-wrap: pretty;
  box-shadow: 0 4px 12px rgba(6, 25, 43, .22), 0 18px 44px rgba(6, 25, 43, .24);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 4px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
  pointer-events: none;
}
.js .jd-tip.is-on {
  opacity: 1; visibility: visible;
  transform: translate(-50%, 0);
}
/* Flipped below the node when there is no room above. */
.js .jd-tip.is-below {
  bottom: auto;
  top: calc(100% + 12px);
  transform: translate(-50%, -4px);
}
.js .jd-tip.is-below.is-on { transform: translate(-50%, 0); }

/* Little pointer, aligned by JS when the tooltip is nudged off-centre. */
.js .jd-tip::after {
  content: "";
  position: absolute;
  left: var(--jd-tip-arrow, 50%);
  margin-left: -6px;
  border: 6px solid transparent;
}
.js .jd-tip:not(.is-below)::after { top: 100%;    border-top-color: var(--navy-deep); }
.js .jd-tip.is-below::after       { bottom: 100%; border-bottom-color: var(--navy-deep); }

/* ---- scroll-in sequence ---- */
/* Supersedes the generic .reveal on this block: the stages need to arrive one
   after another down the path, which a single container fade cannot express.
   Only applied when JS is present, so nothing can get stuck invisible.

   The entry animates the NODE, never the stage: the stages are what the wires
   are measured from, so they must not move — a connector drawn against a
   translated stage lands 10px off once the reveal finishes. An animation with
   a backwards fill (rather than a transition) carries the entry, so it cannot
   fight the hover transition on the same element. */
.js .jd-flow .jd-node,
.js .jd-flow .jd-support { opacity: 0; }
.js .jd.is-in .jd-node,
.js .jd.is-in .jd-support {
  opacity: 1;
  animation: jd-node-in .5s ease backwards;
  animation-delay: var(--jd-delay, 0ms);
}
@keyframes jd-node-in {
  from { opacity: 0; transform: translateY(10px); }
}
/* Wires draw themselves in; the dash values are set per-path by JS. The exit
   branch cannot draw (it has its own dash pattern), so it fades instead —
   .jd-wire-fade is opacity-only and leaves the stroke alone. */
.js .jd-wire-draw { stroke-dashoffset: var(--jd-len, 0); }
.js .jd.is-in .jd-wire-draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .55s ease;
  transition-delay: var(--jd-delay, 0ms);
}
.js .jd-wire-head,
.js .jd-wire-fade { opacity: 0; }
.js .jd.is-in .jd-wire-head,
.js .jd.is-in .jd-wire-fade {
  opacity: 1;
  transition: opacity .3s ease;
  transition-delay: var(--jd-delay, 0ms);
}

/* ---- narrow: exit branch drops below, loop becomes a note ---- */
/* 1023px, not a phone breakpoint: the side-by-side layout needs roughly 980px
   of room (node + twice the exit column that centres it), so anything narrower
   has to stack or it pushes the page sideways. */
@media (max-width: 1023px) {
  .jd {
    --jd-w: 100%;
    --jd-exit-w: 100%;
    --jd-gap: 34px;
  }
  .jd-flow {
    grid-template-columns: 1fr;
  }
  /* Source order already is the reading order, so auto flow is correct. Every
     stage stretches: mixed widths in one column read as accident, not intent. */
  .jd-stage,
  .jd-exit-stage { grid-column: 1; grid-row: auto; justify-self: stretch; }
  .jd-exit-stage { margin-left: 0; }
  .jd-support-stage { justify-self: center; margin-left: 0; }
  .jd-support { text-align: center; }
  .js .jd-tip { max-width: calc(100vw - 2.5rem); }
}

/* ---- reduced motion ---- */
/* Everything lands in its final state. Tooltips keep working — they are
   interaction, not decoration — they simply appear without the fade. */
@media (prefers-reduced-motion: reduce) {
  /* Both states listed so this outranks the .jd.is-in entry rule. */
  .js .jd-flow .jd-node,
  .js .jd.is-in .jd-node,
  .js .jd-flow .jd-support,
  .js .jd.is-in .jd-support { opacity: 1; animation: none; }
  .js .jd-wire-draw { stroke-dashoffset: 0; }
  .js .jd-wire-head,
  .js .jd-wire-fade { opacity: 1; }
  .js .jd-wire-loop { animation: none; }
  .jd-node:hover, .jd-node:focus-visible,
  .jd-support:hover, .jd-support:focus-visible { transform: none; }
}

/* Not a footnote: this line is the section's whole argument, so it carries more
   weight than a caption while staying under the cards it summarises. */
.svc-grid-caption {
  max-width: 54ch; margin: var(--sp-lg) 0 0;
  font-family: var(--font-display);
  font-size: 1.125rem; font-weight: 600;
  color: var(--navy);
  letter-spacing: var(--track-lead);
  text-wrap: pretty;
}

/* Compact service card — flagship page only.
   On the homepage these six are a menu and each card is working to earn a
   click. Here they are inventory: proof that "everything included" is
   substantial, for a reader who is already deep in the flagship offer. Six
   strong hooks at this point would be six invitations to leave towards a
   cheaper product, so the cards are dialled down to read as evidence and hand
   the reader on to the CTA below.

   A variant class, not an edit to .svc-card — the homepage depends on those
   rules. Doubled up (.svc-card.svc-card-compact) where it has to outrank the
   base hover, which otherwise wins on source order. */
.svc-card-compact { padding: var(--sp-md) var(--sp-sm); }
.svc-card-compact h3 { font-size: .9375rem; margin-bottom: .25rem; }
.svc-card-compact p  { font-size: .8125rem; }
.svc-card-compact .svc-icon { margin-bottom: .625rem; }

/* No lift and no shadow: a quiet surface and border shift is enough to show
   these are links, without the cards presenting themselves as offers. */
.svc-card.svc-card-compact:hover,
.svc-card.svc-card-compact:focus-visible {
  transform: none;
  box-shadow: none;
  border-color: var(--accent);
  background: var(--tint);
}

/* Comparison table. A real table so the row/column relationships are announced;
   the scroll wrapper is a safety net for very narrow desktop windows, since the
   mobile rules below turn it into stacked cards well before that. */
.cmp2-scroll { overflow-x: auto; }
.cmp2 {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}
.cmp2 th, .cmp2 td {
  padding: var(--sp-sm) var(--sp-md);
  border-bottom: 1px solid var(--border);
  font-size: .9375rem;
  vertical-align: top;
}
.cmp2 thead th {
  font-family: var(--font-display);
  font-size: .8125rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--navy);
  border-bottom: 2px solid var(--navy);
}
.cmp2 tbody th {
  font-weight: 600; color: var(--navy);
  /* The questions run to a dozen words, so they wrap over a couple of lines
     inside a fixed track instead of dictating the whole table's width. */
  white-space: normal;
  min-width: 13rem;
}
.cmp2 td { color: var(--muted); }
/* Our column is tinted the whole way down so the eye can follow it. */
.cmp2 .cmp2-us { background: var(--tint); color: var(--ink); }
.cmp2 thead .cmp2-us { background: var(--tint-deep); }
/* Scoped so it outranks `.cmp2 td`, which would otherwise win on specificity
   and leave the corner with the thin row rule instead of the header rule.
   The label echoes the column headers' scale but muted and lighter — a cue
   for reading the rows, not a fourth column vying for attention. */
.cmp2 .cmp2-corner {
  border-bottom: 2px solid var(--navy);
  font-family: var(--font-display);
  font-size: .8125rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
}

/* Equal weight by construction: same grid track, same card treatment. The
   "isn't for you" column is what makes the other one credible. */
.fit-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--sp-md);
  margin-top: var(--sp-xl);
}
.fit {
  padding: var(--sp-lg);
  background: var(--tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.fit h3 {
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 700; color: var(--navy);
  letter-spacing: var(--track-lead);
  margin-bottom: var(--sp-md);
}
.fit ul { list-style: none; padding: 0; margin: 0; }
.fit li {
  position: relative;
  padding-left: 1.5rem; margin-bottom: .625rem;
  font-size: .9375rem; color: var(--muted);
}
.fit li::before {
  content: "";
  position: absolute; left: 0; top: .55em;
  width: .5rem; height: .5rem;
  border-radius: 50%;
  background: var(--accent);
}

/* Founder bio: portrait beside the copy, stacking on mobile. */
.bio2 {
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: var(--sp-lg) var(--sp-xl);
  align-items: start;
}
/* Robust to a missing or slow portrait: aspect-ratio holds the box at the right
   size so the two-column layout cannot collapse, the tint fills it in the
   meantime, and transparent text suppresses the browser's broken-image label.
   The alt attribute is untouched, so assistive tech still announces it. */
.bio2-photo {
  width: 100%; height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--tint-deep);
  border-radius: var(--radius);
  display: block;
  color: transparent;
}
.bio2-body p { max-width: 62ch; margin-bottom: var(--sp-md); }

/* Terms of engagement, not another credential — so it is lifted out of both the
   prose above and the list below. White on the tinted section with an accent
   edge: the same vocabulary as the site's other callouts, its own class because
   it is doing a different job from any of them. */
.bio2-commitment {
  max-width: 62ch;
  margin: 0 0 var(--sp-md);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--white);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
}
.bio2-commitment strong {
  display: block;
  margin-bottom: .25rem;
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 700; color: var(--navy);
  letter-spacing: var(--track-lead);
}
.bio2-commitment span {
  display: block;
  font-size: .9375rem; line-height: 1.55; color: var(--muted);
}

.closing2-note {
  margin: var(--sp-md) 0 0;
  font-size: .9375rem;
  color: rgba(255, 255, 255, .72);
}

/* Sticky CTA, phones only. Revealed by app-2026.js once the hero has left the
   viewport. Hidden with visibility rather than the hidden attribute, so it
   stays out of the tab order and the accessibility tree while off-screen but
   can still animate in — the attribute would be overridden by the display
   rule in the phone media query. */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  display: none;
  padding: .75rem var(--sp-md);
  padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
  background: rgba(255, 255, 255, .96);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(4, 12, 20, .08);
}
.sticky-cta .btn2 { display: block; width: 100%; text-align: center; }

/* --- service page content components -------------------------------------- */

/* Bulleted benefits with a bold lead-in. */
.feat-list { max-width: 74ch; }
.feat-list li {
  position: relative;
  padding-left: 1.75rem;
  margin-bottom: .875rem;
  font-size: 1.0625rem;
}
.feat-list li::before {
  content: "";
  position: absolute; left: 0; top: .62em;
  width: .75rem; height: 2px;
  background: var(--accent);
}
.feat-list strong { color: var(--navy); }

/* Body copy / summary panel side by side. */
.two-col {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: var(--sp-xl);
  align-items: start;
}
.panel2 {
  padding: var(--sp-lg);
  background: var(--tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.panel2 h3 { font-size: 1.125rem; color: var(--navy); margin-bottom: var(--sp-md); }
.panel2 .feat-list li { font-size: 1rem; }

/* Numbered process stages. The circles are generated from a counter, so the
   list's own markers have to go or every step is numbered twice. */
.stage-list { counter-reset: stage; max-width: 74ch; list-style: none; padding: 0; margin: 0; }
.stage-list li {
  counter-increment: stage;
  position: relative;
  padding-left: 3.25rem;
  margin-bottom: var(--sp-md);
}
.stage-list li::before {
  content: counter(stage);
  position: absolute; left: 0; top: 0;
  display: flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem;
  background: var(--navy); color: var(--white);
  border-radius: 50%;
  font-size: .9375rem; font-weight: 700;
}
.stage-list strong { display: block; color: var(--navy); font-size: 1.0625rem; margin-bottom: .125rem; }
.stage-list span { color: var(--muted); }

/* Category grid — a heading plus the jobs under it. */
.quad-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); }
.quad {
  padding: var(--sp-md) var(--sp-lg);
  background: var(--white);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
}
.quad h3 { font-size: 1.0625rem; color: var(--navy); margin-bottom: .5rem; }
.quad li { padding-left: 1rem; position: relative; font-size: .9375rem; color: var(--muted); margin-bottom: .25rem; }
.quad li::before { content: "·"; position: absolute; left: .25rem; color: var(--accent); font-weight: 700; }

/* App cards. */
.app-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-md); }
.app-card {
  padding: var(--sp-lg) var(--sp-md);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.app-card h3 { font-size: 1rem; color: var(--navy); margin-bottom: .5rem; }
.app-card p { font-size: .9375rem; color: var(--muted); margin: 0; }
.app-card-more {
  display: flex; align-items: center; justify-content: center;
  border-style: dashed;
  color: var(--muted); font-weight: 600;
}

/* A single number worth pulling out of the prose. */
.callout2 {
  margin-top: var(--sp-lg);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--navy); color: var(--white);
  border-radius: var(--radius);
  font-size: 1.125rem; font-weight: 600;
}

/* --- what's included grid ------------------------------------------------- */
.incl-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); }
.incl {
  display: flex; align-items: flex-start; gap: .75rem;
  padding: var(--sp-md);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.incl::before {
  content: "";
  flex-shrink: 0; margin-top: .45rem;
  width: .6rem; height: .34rem;
  border-left: 2.5px solid var(--accent);
  border-bottom: 2.5px solid var(--accent);
  transform: rotate(-45deg);
}
.incl strong { display: block; color: var(--navy); font-size: 1rem; }
.incl span { font-size: .9375rem; color: var(--muted); }
.incl-flag { border-color: var(--navy); border-width: 2px; }

/* --- before / after comparison -------------------------------------------- */
.compare2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-md); }
.compare2 > div { padding: var(--sp-lg); border-radius: var(--radius); }
.compare2-bad { background: var(--tint); border: 1px solid var(--border); }
.compare2-good { background: var(--navy); color: var(--white); }
.compare2 h3 { font-size: 1.0625rem; margin-bottom: var(--sp-md); }
.compare2-bad h3 { color: var(--muted); }
.compare2-good h3 { color: var(--white); }
.compare2 li { position: relative; padding-left: 1.25rem; margin-bottom: .5rem; font-size: .9375rem; }
.compare2-bad li { color: var(--muted); }
.compare2-bad li::before { content: "\00d7"; position: absolute; left: 0; color: var(--muted); }
.compare2-good li { color: rgba(255,255,255,.9); }
.compare2-good li::before { content: "\2713"; position: absolute; left: 0; color: var(--accent-soft); }

/* --- FAQ accordion -------------------------------------------------------- */
/* Accordion built from real buttons rather than <details>/<summary>: the state
   is carried by aria-expanded, which is what assistive tech announces, and the
   behaviour does not depend on native disclosure support. Toggling lives in
   app-2026.js; without JS every panel simply stays open and readable. */
.faq2 { max-width: 76ch; }

.faq2-item { border-bottom: 1px solid var(--border); }

/* The question is a heading for navigation, and a button for operation. The
   heading carries no visual styling of its own — the button is the control. */
.faq2-q { margin: 0; font-size: inherit; font-weight: inherit; }

.faq2-btn {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--sp-md);
  width: 100%;
  padding: var(--sp-md) 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 600; color: var(--navy);
  text-align: left;
}
.faq2-btn::after {
  content: "+";
  flex-shrink: 0;
  font-size: 1.375rem; font-weight: 400; color: var(--accent);
  line-height: 1;
}
.faq2-btn[aria-expanded="true"]::after { content: "\2013"; }

/* The slide. A single-row grid animated 0fr -> 1fr, which transitions to the
   content's natural height — no max-height guess to outgrow, and no measuring
   in JS. Every collapsing rule is scoped to .js (set by app-2026.js), so with
   scripting off the panels render open instead of sealed shut. The global
   reduced-motion rule already neutralises the duration. */
.faq2-a p { margin: 0; color: var(--muted); max-width: 68ch; }
/* Longer answers run to two paragraphs; without this they butt together, since
   the margin above sits at 0 and only the last child is spaced. */
.faq2-a p + p { margin-top: .75rem; }

.js .faq2-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s ease;
}
.js .faq2-a.is-open { grid-template-rows: 1fr; }

/* overflow clips the copy mid-slide; visibility keeps a collapsed panel out of
   the tab order and the accessibility tree, and is delayed on the way out so
   it does not blink away before the slide finishes. */
.js .faq2-a-inner {
  overflow: hidden;
  min-height: 0;
  visibility: hidden;
  transition: visibility 0s linear .3s;
}
.js .faq2-a.is-open .faq2-a-inner {
  visibility: visible;
  transition-delay: 0s;
}

/* Spacing goes on the copy, never on the collapsing wrapper. A 0fr track is
   floored by its item's min-content height, and padding counts towards that —
   so padding here would leave every closed row holding that much dead space.
   A margin on the content is clipped by overflow and collapses to nothing. */
.js .faq2-a-inner > :last-child { margin-bottom: var(--sp-md); }

.faq2-a { padding-bottom: var(--sp-md); }   /* no-JS: panels are simply open */
.js .faq2-a { padding-bottom: 0; }

/* --- blog / insights index ------------------------------------------------
   The class names below are a contract with automation/publish_due.py, which
   injects new cards as literal HTML. Renaming blog-grid or any blog-card* class
   silently breaks the weekly auto-publish. Restyle freely; do not rename.      */
.blog-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-md); }

.blog-card {
  display: flex; flex-direction: column;
  padding: var(--sp-lg);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.blog-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--accent);
  text-decoration: none;
}
.blog-card-meta {
  margin-bottom: .5rem;
  font-size: .75rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent);
}
.blog-card-title { font-size: 1.1875rem; font-weight: 700; color: var(--navy); margin-bottom: .5rem; }
.blog-card-excerpt { font-size: .9375rem; color: var(--muted); margin-bottom: var(--sp-md); }
.blog-card-more { margin-top: auto; font-size: .9375rem; font-weight: 700; color: var(--accent); }

/* --- price list ----------------------------------------------------------- */
.price-group { margin-bottom: var(--sp-xl); }
.price-group-h {
  padding-bottom: var(--sp-sm);
  border-bottom: 2px solid var(--navy);
  margin-bottom: 0;
  font-size: 1.125rem; font-weight: 800;
  letter-spacing: .18em; text-transform: uppercase; color: var(--navy);
}

.price-row {
  display: grid;
  grid-template-columns: 1.1fr 1.6fr 1.4fr auto;
  gap: var(--sp-md);
  align-items: start;
  padding: var(--sp-md) 0;
  border-bottom: 1px solid var(--border);
}
.price-head {
  padding: .625rem 0;
  border-bottom: 1px solid var(--border);
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.price-name { font-size: 1.0625rem; font-weight: 700; color: var(--navy); }
.price-desc, .price-for { font-size: .9375rem; color: var(--muted); }
.price-amt { text-align: right; min-width: 7.5rem; }
.price-from { display: block; font-size: .75rem; color: var(--muted); }
.price-value { font-feature-settings: "tnum"; font-size: 1.375rem; font-weight: 800; color: var(--navy); white-space: nowrap; }
.price-unit { display: block; font-size: .75rem; color: var(--muted); }
.price-note { margin-top: var(--sp-lg); font-size: .9375rem; color: var(--muted); }

/* --- legal / long-form prose ---------------------------------------------- */
.legal2 { max-width: 72ch; }
.legal2 h2 {
  margin: var(--sp-lg) 0 var(--sp-sm);
  font-size: 1.25rem; font-weight: 700; color: var(--navy);
}
.legal2 p { color: var(--muted); }
.legal2 > p:first-child { font-size: .9375rem; }

/* Only the handout disclaimer carries sub-headings and lists. Sized a step
   below h2 so the hierarchy reads without introducing another type scale. */
.legal2 h3 {
  margin: var(--sp-md) 0 var(--sp-xs);
  font-size: 1.0625rem; font-weight: 700; color: var(--navy);
  text-wrap: pretty;
}
/* The global reset strips markers from every list; restore them here the same
   way .post-body does, since these are read as enumerated caveats. */
.legal2 ul {
  margin: 0 0 var(--sp-md); padding-left: 1.25rem;
  color: var(--muted); list-style: disc;
}
.legal2 li { margin-bottom: var(--sp-xs); }

/* A leading paragraph that introduces the page rather than dating it, so it
   opts out of the small-print sizing the first-child rule above applies. */
.legal2 > p.legal2-intro:first-child { font-size: 1rem; }

/* Closing note: small print, set off from the body above it. */
.legal2-note { margin-top: var(--sp-lg); font-size: .875rem; }

/* --- utility pages (thanks, 404) ------------------------------------------ */
.util2 { padding: var(--sp-2xl) 0; text-align: center; }
.util2 h1 {
  font-size: clamp(1.75rem, 4vw, 2.75rem); font-weight: 800;
  margin-bottom: var(--sp-md);
}
.util2 p { max-width: 52ch; margin: 0 auto var(--sp-lg); color: var(--muted); }
.util2 .btn2-row { justify-content: center; }

/* --- blog post ------------------------------------------------------------
   Post bodies are authored HTML in automation/bodies/ and their inline SVG
   charts reference these four variable names directly. The legacy stylesheet
   defined them for a dark background (--ink was white); redefined here for a
   light one, which re-themes all 11 charts without touching their markup.     */
:root {
  --ink-dim:   #52616f;   /* chart labels, secondary text */
  --ink-rule:  #d6e4ec;   /* axis and divider lines */
  --grad-blue: #0c2a45;   /* primary data series */
  --grad-teal: #2e7db8;   /* secondary data series */
}

.post2 { padding: var(--sp-xl) 0; }
.post2-back { display: inline-block; margin-bottom: var(--sp-md); font-size: .9375rem; font-weight: 600; }
.post2-meta {
  margin-bottom: .5rem;
  font-size: .75rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent);
}
.post2-title {
  max-width: 22ch; margin-bottom: var(--sp-lg);
  font-size: clamp(1.875rem, 4.4vw, 3rem); font-weight: 700;
  letter-spacing: var(--track-display);
}

.post-body { max-width: 68ch; }
.post-body p { font-size: 1.0625rem; line-height: 1.7; color: var(--ink); }
.post-body h2 {
  margin: var(--sp-lg) 0 var(--sp-sm);
  font-size: 1.5rem; font-weight: 700; color: var(--navy);
}
.post-body h3 {
  margin: var(--sp-md) 0 var(--sp-xs);
  font-size: 1.1875rem; font-weight: 700; color: var(--navy);
}
.post-body ul, .post-body ol { margin: 0 0 var(--sp-md); padding-left: 1.25rem; }
.post-body ul { list-style: disc; }
.post-body ol { list-style: decimal; }
.post-body li { margin-bottom: .5rem; font-size: 1.0625rem; line-height: 1.7; }
.post-body strong { color: var(--navy); }

.post-body .post-figure { margin: var(--sp-lg) 0; }
.post-body .post-figure svg { display: block; width: 100%; height: auto; }
.post-body .post-figure figcaption {
  margin-top: var(--sp-xs); font-size: .875rem; color: var(--muted);
}

/* Wide tables scroll inside their own box rather than pushing the page out. */
.post-body .post-table {
  display: block; overflow-x: auto;
  width: 100%; border-collapse: collapse;
  margin: var(--sp-md) 0;
  font-size: .9375rem;
}
.post-body .post-table th,
.post-body .post-table td {
  padding: .625rem .75rem;
  text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border);
}
.post-body .post-table th { font-weight: 700; color: var(--navy); border-bottom-width: 2px; white-space: nowrap; }
.post-body .post-table td { color: var(--muted); }
.post-body .post-table-note { margin: -.25rem 0 var(--sp-md); font-size: .875rem; color: var(--muted); }

.author-bio {
  max-width: 68ch; margin: var(--sp-xl) 0 0;
  padding: var(--sp-lg);
  background: var(--tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.author-bio-label {
  margin-bottom: .5rem !important;
  font-size: .7rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--navy);
}
.author-bio-name { font-weight: 700; color: var(--navy); margin-bottom: .25rem !important; }
.author-bio-text { font-size: .9375rem; color: var(--muted); margin: 0 !important; }

.post2-footer { max-width: 68ch; margin-top: var(--sp-xl); }
.post2-disclaimer {
  max-width: 68ch; margin-top: var(--sp-lg);
  font-size: .875rem; color: var(--muted);
}

/* --- guide hub: cluster link cards ---------------------------------------- */
.guide-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); }
.guide-link {
  display: block;
  padding: var(--sp-md);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.guide-link:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  border-color: var(--accent);
  text-decoration: none;
}
.guide-link strong { display: block; margin-bottom: .25rem; font-size: 1rem; color: var(--navy); }
.guide-link span { font-size: .9375rem; color: var(--muted); }


/* --- impact assessment (preserved from the previous homepage) ------------- */
.assess2 {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-soft) 100%);
  color: var(--white);
  border-radius: var(--radius);
  padding: var(--sp-xl) var(--sp-lg);
}
.assess2 h2 { font-size: clamp(1.5rem, 3vw, 2.125rem); font-weight: 700; letter-spacing: var(--track-display); margin-bottom: var(--sp-md); }
.assess2 > p { font-size: 1.0625rem; color: rgba(255,255,255,.88); max-width: 72ch; }

.assess2-badge {
  display: inline-block;
  padding: .3125rem .875rem;
  margin-bottom: var(--sp-md);
  border: 1px solid rgba(255,255,255,.4);
  border-radius: 999px;
  font-size: .75rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
}

.assess2-steps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-md);
  margin: var(--sp-lg) 0;
}
.assess2-step {
  background: rgba(255,255,255,.09);
  border: 1px solid rgba(255,255,255,.18);
  border-radius: var(--radius-sm);
  padding: var(--sp-md);
}
.assess2-num {
  display: flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; margin-bottom: var(--sp-sm);
  background: var(--white); color: var(--navy);
  border-radius: 50%; font-weight: 700; font-size: .9375rem;
}
.assess2-step strong { display: block; margin-bottom: .25rem; font-size: 1.0625rem; font-weight: 600; }
.assess2-step span { color: rgba(255,255,255,.78); font-size: .9375rem; }

/* --- closing CTA (preserved) ---------------------------------------------- */
.closing2 {
  background: var(--navy-deep);
  color: var(--white);
  padding: var(--sp-2xl) 0;
  text-align: center;
}
.closing2 h2 {
  font-size: clamp(1.5rem, 3.4vw, 2.25rem); font-weight: 700;
  letter-spacing: var(--track-display);
  max-width: 24ch; margin: 0 auto var(--sp-lg);
}
.closing2 .btn2-row { justify-content: center; }

/* --- contact form --------------------------------------------------------- */
.contact2 { max-width: 640px; }
.contact2 .field { margin-bottom: var(--sp-md); }
.contact2 label {
  display: block; margin-bottom: .375rem;
  font-size: .9375rem; font-weight: 600; color: var(--navy);
}
.contact2 .optional { font-weight: 400; color: var(--muted); }

.contact2 input,
.contact2 textarea {
  width: 100%;
  padding: .75rem .875rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
}
.contact2 input:focus,
.contact2 textarea:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px rgba(46,125,184,.18); }
.contact2 textarea { resize: vertical; }

.contact2 .hp { position: absolute; left: -9999px; }
.form2-note { margin-top: var(--sp-sm); font-size: .875rem; color: var(--muted); }

/* --- footer --------------------------------------------------------------- */
.footer2 { background: var(--navy-deep); color: rgba(255,255,255,.75); padding: var(--sp-xl) 0 var(--sp-md); }
.footer2 a { color: rgba(255,255,255,.75); }
.footer2 a:hover { color: var(--white); }

.footer2-inner { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: var(--sp-lg); }
.footer2-logo { height: 30px; width: auto; margin-bottom: var(--sp-sm); }
.footer2-tagline { color: var(--white); font-weight: 500; margin-bottom: var(--sp-sm); }
.footer2 p { margin: 0 0 .375rem; font-size: .9375rem; }

.footer2-h {
  color: var(--white); font-size: .75rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; margin-bottom: var(--sp-sm) !important;
}
.footer2-col li { margin-bottom: .375rem; font-size: .9375rem; }

.footer2-cta {
  display: inline-block; margin-bottom: var(--sp-sm);
  padding: .625rem 1.25rem;
  background: var(--white); color: var(--navy) !important;
  border-radius: var(--radius-sm); font-weight: 600; font-size: .9375rem;
}
.footer2-cta:hover { background: var(--tint-deep); text-decoration: none; }
.footer2-note { font-size: .8125rem !important; color: rgba(255,255,255,.6); }

.footer2-bottom {
  display: flex; flex-wrap: wrap; gap: var(--sp-sm); justify-content: space-between;
  margin-top: var(--sp-lg); padding-top: var(--sp-md);
  border-top: 1px solid rgba(255,255,255,.14);
  font-size: .8125rem;
}
.footer2-bottom p { margin: 0; font-size: .8125rem; }

/* --- WhatsApp float (preserved) ------------------------------------------- */
.wa-float2 {
  position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  width: 54px; height: 54px;
  background: #25d366; color: var(--white);
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(0,0,0,.22);
  transition: transform .18s ease;
}
.wa-float2:hover { transform: scale(1.06); text-decoration: none; }

/* --- reveal on scroll ----------------------------------------------------- */
.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s ease; }
.js .reveal.is-in { opacity: 1; transform: none; }

/* --- responsive ----------------------------------------------------------- */
@media (max-width: 900px) {
  .svc-grid,
  .assess2-steps,
  .blog-grid,
  .app-grid { grid-template-columns: repeat(2, 1fr); }
  .guide-grid { grid-template-columns: repeat(2, 1fr); }
  .footer2-inner { grid-template-columns: 1fr 1fr; }
  .two-col { grid-template-columns: 1fr; gap: var(--sp-lg); }
  /* Portrait above the copy rather than a narrow column beside it. */
  .bio2 { grid-template-columns: 1fr; }
  .bio2-photo { max-width: 260px; }
}

@media (max-width: 760px) {
  /* Stack the flagship's headline and price, or the text column gets crushed. */
  .flagship-top { grid-template-columns: 1fr; gap: var(--sp-md); }
  .flagship-price-col {
    padding-left: 0; padding-top: var(--sp-md);
    border-left: 0; border-top: 1px solid var(--border);
  }
}

@media (max-width: 640px) {
  :root { --sp-xl: 3rem; --sp-2xl: 4rem; }

  .flagship-top,
  .flagship-great { padding: var(--sp-md); }

  .nav2-inner { flex-wrap: wrap; gap: var(--sp-sm); padding: .625rem var(--sp-md); }
  .nav2-locale { display: none; }
  .nav2-links {
    width: 100%; margin-left: 0;
    justify-content: space-between;
    /* The expo pill is a fifth item on a row that was already full at this
       width. Wrapping lets it drop to its own line instead of squeezing the
       other four past legibility. The column gap tightens from --sp-sm so the
       original four still clear one row — at 375px they were within a few
       pixels of wrapping even before the pill existed. */
    flex-wrap: wrap;
    column-gap: .5rem; row-gap: .5rem;
  }
  /* Buys back the last of that margin without touching the desktop CTA. */
  .nav2-cta { padding: .5rem .875rem !important; }

  /* Full-width bar below the nav row: still the loudest thing in the header,
     but no longer competing for horizontal space. The tag sits inline here
     rather than stacked, which suits the wider, shorter shape. */
  .nav2-limited {
    order: 1;
    width: 100%;
    flex-direction: row; justify-content: center; gap: .5rem;
    padding: .4375rem .75rem !important;
  }
  .nav2-limited-tag {
    padding-left: .5rem;
    border-left: 1px solid rgba(255, 255, 255, .35);
  }

  /* The four ordinary links keep their intrinsic width on their own row. */
  .nav2-links > a:not(.nav2-limited),
  .nav2-links > .nav2-dd { flex-shrink: 0; }

  .hero2-lockup img { height: 40px; }
  .hero2-lockup span { font-size: 1.75rem; }

  /* Standfirst above the chips rather than beside them. */
  .hero2-cols { grid-template-columns: 1fr; gap: var(--sp-md); }

  .svc-grid,
  .assess2-steps,
  .quad-grid,
  .blog-grid,
  .incl-grid,
  .compare2,
  .guide-grid,
  .fit-grid,
  .app-grid { grid-template-columns: 1fr; }

  /* The comparison table becomes one card per row: a four-column table cannot
     be read on a phone, and horizontal scrolling hides the column that matters
     most. Roles are declared in the markup, so display:block does not cost the
     table its semantics. */
  .cmp2, .cmp2 tbody, .cmp2 tr, .cmp2 th, .cmp2 td { display: block; }
  .cmp2 thead { display: none; }
  .cmp2 tbody tr {
    margin-bottom: var(--sp-md);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
  }
  .cmp2 tbody th {
    background: var(--tint-deep);
    border-bottom: 1px solid var(--border);
    white-space: normal;
    min-width: 0;               /* the desktop track hint has no place in a card */
  }
  .cmp2 td {
    display: flex; justify-content: space-between; gap: var(--sp-md);
  }
  .cmp2 td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-weight: 600; color: var(--navy);
  }
  .cmp2 tbody tr td:last-child { border-bottom: 0; }

  /* Phones only — on larger screens the in-page CTAs are never far away. */
  .sticky-cta {
    display: block;
    visibility: hidden;
    transform: translateY(100%);
    transition: transform .25s ease, visibility .25s ease;
  }
  .sticky-cta.is-on { visibility: visible; transform: none; }
  .sticky-cta.is-on ~ .wa-float2,
  .sticky-cta.is-on + .wa-float2 { bottom: 5.25rem; }
  .footer2-inner { grid-template-columns: 1fr; }
  .panel2 { padding: var(--sp-md); }
  .compare2 > div { padding: var(--sp-md); }

  /* The price table becomes a stack of cards; its column headings only make
     sense above columns, so they go. */
  .price-head { display: none; }
  .price-row { grid-template-columns: 1fr; gap: .5rem; padding: var(--sp-md) 0; }
  .price-amt { text-align: left; }
  .price-from { display: inline; }
  .price-unit { display: inline; }
  .assess2 { padding: var(--sp-lg) var(--sp-md); }
  .btn2 { width: 100%; text-align: center; }
}

/* --- accessibility -------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}

/* --- news feed ------------------------------------------------------------
   The class names below are a contract with automation/build_news.py, which
   renders cards and filters as literal HTML between markers in news.html.
   Restyle freely; do not rename. The ph-* classes colour the image-fallback
   placeholder per tag.                                                       */
.news-updated { font-size: .875rem; font-weight: 600; color: var(--muted); }

.news-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--sp-lg);
  align-items: start;
}

.news-side { position: sticky; top: 92px; }
.news-side-h {
  margin-bottom: .75rem;
  font-size: .75rem; font-weight: 800;
  letter-spacing: .18em; text-transform: uppercase; color: var(--navy);
}
.news-filters { display: flex; flex-direction: column; gap: .375rem; }

.news-filter {
  display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  padding: .5rem .75rem;
  font: inherit; font-size: .9375rem; font-weight: 600; text-align: left;
  color: var(--muted);
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.news-filter:hover { background: var(--tint); color: var(--navy); }
.news-filter.is-active { background: var(--tint-deep); border-color: var(--border); color: var(--navy); }
.news-filter span {
  padding: .1rem .5rem;
  font-size: .75rem; font-weight: 700; color: var(--muted);
  background: var(--tint); border-radius: 999px;
}
.news-filter.is-active span { background: var(--white); color: var(--navy); }

.news-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); }
.news-card[hidden] { display: none; }

.news-card-link {
  display: flex; flex-direction: column; height: 100%;
  background: var(--white);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden;
  color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.news-card-link:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--accent);
  text-decoration: none;
}

.news-card-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--tint-deep);
  overflow: hidden;
}
.news-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.news-card-media.is-fallback img { display: none; }

.news-ph-label {
  position: absolute; inset: 0;
  display: none; align-items: center; justify-content: center;
  padding: 0 var(--sp-md);
  font-family: var(--font-display); font-size: .875rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; text-align: center;
  color: var(--white); opacity: .92;
}
.news-card-media.is-fallback .news-ph-label { display: flex; }

/* Placeholder gradients, one per tag (first tag on the story wins). */
.news-card-media.is-fallback.ph-singapore        { background: linear-gradient(135deg, #8f2d3c, #b34a59); }
.news-card-media.is-fallback.ph-global           { background: linear-gradient(135deg, var(--navy), var(--accent)); }
.news-card-media.is-fallback.ph-claude           { background: linear-gradient(135deg, #9a5b3c, #c07a54); }
.news-card-media.is-fallback.ph-new-products     { background: linear-gradient(135deg, #1b6f6a, #2fa39b); }
.news-card-media.is-fallback.ph-events           { background: linear-gradient(135deg, #5b3c8a, #7d5bb3); }
.news-card-media.is-fallback.ph-research         { background: linear-gradient(135deg, var(--navy-soft), var(--accent-soft)); }
.news-card-media.is-fallback.ph-business-funding { background: linear-gradient(135deg, #2d6b3c, #4a9159); }
.news-card-media.is-fallback.ph-policy-regulation{ background: linear-gradient(135deg, #4a5561, #6b7885); }
.news-card-media.is-fallback.ph-open-source      { background: linear-gradient(135deg, #8a6a1f, #b08f3c); }

.news-card-body {
  display: flex; flex-direction: column; gap: .375rem;
  padding: var(--sp-md);
  flex: 1;
}
.news-card-meta {
  display: flex; align-items: baseline; gap: .625rem;
  margin: 0;
}
.news-card-src {
  font-size: .75rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent);
}
.news-card-meta time { font-size: .8125rem; font-weight: 600; color: var(--muted); }
.news-card-title { font-size: 1.0625rem; font-weight: 700; color: var(--navy); margin: 0; line-height: 1.3; }
.news-card-sum { font-size: .9375rem; color: var(--muted); margin: 0; }
.news-card-tags {
  display: flex; flex-wrap: wrap; gap: .375rem;
  margin: auto 0 0; padding-top: .5rem;
}
.news-card-tags span {
  padding: .15rem .55rem;
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--navy-soft);
  background: var(--tint); border: 1px solid var(--border); border-radius: 999px;
}

.news-empty { margin-top: var(--sp-md); color: var(--muted); }

@media (max-width: 900px) {
  .news-layout { grid-template-columns: 1fr; gap: var(--sp-md); }
  .news-side { position: static; }
  .news-filters { flex-direction: row; flex-wrap: wrap; }
  .news-filter { padding: .4rem .7rem; border-color: var(--border); }
}
@media (max-width: 640px) {
  .news-grid { grid-template-columns: 1fr; }
}
