/* ==========================================================================
   ai-platform.css
   Self-contained design system for ai-platform.php.
   Does NOT reuse any token/class name from assets/css/style.css -
   this page runs its own visual language end to end.
   ========================================================================== */

/* ------------------------------------------------------------------------
   FONT - reuse the project's self-hosted Inter variable font. No CDN.
   ------------------------------------------------------------------------ */
@font-face {
  font-family: 'APInter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/Inter-Variable.woff2') format('woff2-variations'),
       url('../fonts/Inter-Variable.woff2') format('woff2');
}

/* ------------------------------------------------------------------------
   DESIGN TOKENS
   ------------------------------------------------------------------------ */
:root {
  /* Color */
  /* Site-wide accent for index.php - a neutral near-black, the value
     the header button uses. Replaced the desaturated slate-plum
     (#4A4266 / #322C47) this used to be, and the
     --ap-navy/--ap-navy-dark/--ap-emerald token names that carried
     it: no navy or navy-adjacent hue is used anywhere on the site
     now. Named "ink" because that is what it is - the darkest value
     in the palette, used for type, fills and borders alike - rather
     than after a hue it does not have.

     Neutral, not warm: an earlier pass took this to a warm brown-
     black (#24100F) and every neutral with it, which read as brown
     across the page. The whole family is held at this hue instead.

     index-warm.php and index-black.php each override these same
     token names in their own file with their own (terracotta /
     copper) accent, so this value is index.php-only even though it
     is set here in the shared/base file. */
  /* The lighter of the two accent weights, one step up from
     --ap-ink-dark. Only a handful of things use it as a base, and
     they darken to --ap-ink-dark on hover. */
  --ap-ink: #262524;
  /* #191817 itself - the header button, and the value most of the
     site's type and solid fills resolve to. It is --ap-ink-dark
     rather than --ap-ink that carries it because this is the token
     the bulk of the file already referenced; anchoring it here is
     what puts the named colour on the button and the headings
     without rewriting 60-odd rules. */
  --ap-ink-dark: #191817;
  /* Hover/active target for anything based on --ap-ink-dark - one
     step darker again: black. */
  --ap-ink-deepest: #000000;
  /* Tint backgrounds (icon chips, badges, hover fills) - same RGB as
     --ap-ink (25, 24, 23) at low alpha. Only one strength is used
     anywhere in this file, so only one is defined. */
  --ap-ink-tint-10: rgba(25, 24, 23, 0.10);
  /* Nav + mega-menu accent - kept as its own name (it is scoped to
     the nav) but pointed at the same ink family, so the nav doesn't
     clash with the rest of the page. */
  --ap-nav-accent: #191817;
  --ap-nav-accent-deep: #000000;
  --ap-white: #FFFFFF;
  /* Surface background (nav/hero/cards/footer/section bg) - separate
     from --ap-white so a dark theme can repoint just the surfaces
     dark while --ap-white stays literal white for text-on-accent
     (button labels, dark-panel headings, etc.), which must stay
     white regardless of theme. Defaults to --ap-white so every
     existing page (index.php, index-warm.php) is pixel-identical. */
  --ap-surface: var(--ap-white);
  /* Neutral off-white. Was #F6F8FA, a blue-tinted grey - every
     neutral in this palette used to carry a cool cast to sit with
     the old navy accent, and they are all held at --ap-ink's neutral
     hue now. */
  --ap-soft: #F7F7F6;
  /* Warm bone ground for the ecosystem section, which sits as a
     large rounded panel between two white sections. Its own token
     rather than a literal, because index-black.php would otherwise
     get a bright cream slab in the middle of a near-black page -
     both themes repoint it to their own --ap-soft. */
  --ap-eco-bg: #F4F3EF;
  /* Was #EEF1F4 (blue-tinted). */
  --ap-light-gray: #F0F0EE;
  /* Type. Was #18212B / #667085 - a dark blue-slate and a blue-grey.
     Both are neutral now: the same near-black as --ap-ink for
     primary copy, and a neutral grey for secondary. The ecosystem
     panel briefly had its own warm-brown pair
     (--ap-eco-heading/--ap-eco-body) taken from its reference
     screenshot; that was rolled back and the section reads these
     two like every other section. */
  --ap-text: #191817;
  --ap-text-secondary: #6B6A67;
  /* Sparse checker-cell tint for .ap-hero__grid-bg - same family as
     the fine grid lines below it, echoing style.css's --clr-checker
     technique (a handful of large, very faint grid-aligned squares,
     not a dense checkerboard). */
  /* Back down to 0.04. The 0.06 above it was compensating for a
     vignette that washed each cell by a wildly different amount
     (one cell visible, the rest missing) - that vignette has since
     been rebuilt with a gradual multi-stop falloff, so the cells are
     washed evenly and no longer need to shout over it. At 0.06 with
     the smoother wash they read as stray gray blocks rather than
     texture. */
  --ap-checker: rgba(25, 24, 23, 0.04);
  /* Hero ambient-glow color, as bare "r, g, b" so .ap-hero__glow can
     set its own alpha per layer. Its own token rather than reusing
     --ap-ink because index-warm.php / index-black.php repoint the
     accent to hues that need a different glow strength on their own
     surfaces - they override this alongside it. */
  --ap-hero-glow-rgb: 25, 24, 23;
  /* The hero's own background. Separate from --ap-surface because
     index-warm.php gives the hero a warm cream that the rest of its
     surfaces don't use, and .ap-hero::after has to fade to whatever
     that is or the fade shows as a band of the wrong color. */
  --ap-hero-bg: var(--ap-surface);
  /* Same color as --ap-hero-bg, as bare "r, g, b", because
     .ap-hero__vignette needs it at five different alphas and a
     solid token can't be faded. Kept in sync by hand in each
     theme file - the wash MUST be the hero's own background or it
     bleaches the section instead of clearing the texture behind
     the content. */
  --ap-hero-wash-rgb: 255, 255, 255;
  --ap-border: rgba(25, 24, 23, 0.09);
  --ap-border-strong: rgba(25, 24, 23, 0.16);
  /* Was #DDE2E8 (blue-tinted). */
  --ap-line: #E1E1DF;

  /* Shadow - cast in the ink's own RGB, not the old blue-slate, so
     shadows on white read warm-grey rather than faintly blue. */
  --ap-shadow-sm: 0 1px 2px rgba(25, 24, 23, 0.04);
  --ap-shadow-md: 0 8px 24px rgba(25, 24, 23, 0.06);
  --ap-shadow-lg: 0 16px 40px rgba(25, 24, 23, 0.09);

  /* Radius */
  --ap-radius-card: 14px;
  --ap-radius-btn: 10px;
  --ap-radius-pill: 999px;
  --ap-radius-sm: 8px;

  /* Layout */
  --ap-max-width: 1320px;
  --ap-shell: 1280px;   /* header + hero shell - narrower than page sections */
  --ap-nav-h: 68px;
  --ap-gutter: 24px;
  --ap-section-pad-y: 72px;

  /* Motion */
  --ap-fast: 180ms ease;
  --ap-fast-2: 220ms ease;

  /* Font */
  --ap-font: 'APInter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

@media (max-width: 768px) {
  :root {
    --ap-gutter: 20px;
    --ap-section-pad-y: 48px;
  }
}

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

html:has(body.ai-platform) {
  overflow-x: hidden;
}

body.ai-platform {
  overflow-x: hidden;
  font-family: var(--ap-font);
  color: var(--ap-text);
  background: var(--ap-surface);
  line-height: 1.6;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.ai-platform img,
.ai-platform svg {
  max-width: 100%;
  display: block;
}

.ai-platform a {
  color: inherit;
  text-decoration: none;
}

.ai-platform ul {
  list-style: none;
}

.ai-platform button {
  font-family: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

.ai-platform h1,
.ai-platform h2,
.ai-platform h3,
.ai-platform h4 {
  /* 500. Was 700 (which outweighed the hero headline), then 600.
     Note this is only the inherited default - the hero headline,
     card titles and step titles each set their own weight
     explicitly and are unaffected by this value. */
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--ap-text);
}

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

.ai-icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

/* Downloaded full-color agent icons (see $ai_platform_icon_images in
   icons.php) - a class of its own, not .ai-icon, on purpose: every
   card context sets its own SVG glyph size with a "<wrapper> .ai-icon"
   rule (.uc-card__icon .ai-icon is 28px, .usecase-card__icon .ai-icon
   is 26px, and so on), and those all share .ai-icon's specificity, so
   reusing that class here would leave the outcome up to each rule's
   position in the file instead of a fixed size. This one class holds
   every one of these images to the same 25px everywhere, in every
   card, with nothing to out-specificity. object-fit: contain keeps the
   square source from ever stretching if a future icon isn't 1:1. */
.ai-icon-img {
  width: 17px;
  height: 17px;
  object-fit: contain;
  flex-shrink: 0;
}

/* --- Duotone agent/category glyphs ---
   ai_icon() renders these as two layers over a per-instance
   gradient whose stops are these two rules; the wrapper supplies
   --icon-color / --icon-color-2 (see ai_icon_style_attr() in
   icons.php). Offset 0 is the lighter secondary and offset 1 the
   primary, so a glyph reads as lit from the top left.

   The fill layer is the soft body and the line layer the crisp
   detail over it - that contrast between a 30%-opacity mass and a
   full-strength outline is what gives these depth at 22-26px,
   where a single-weight outline just reads flat. Falls back to the
   neutral ink if a key has no mapped color. */
.ai-icon__stop-a {
  stop-color: rgb(var(--icon-color-2, 90 88 86));
}

.ai-icon__stop-b {
  stop-color: rgb(var(--icon-color, 25 24 23));
}

.ai-icon--duo .ai-icon__fill {
  opacity: 0.3;
}

/* ------------------------------------------------------------------------
   LAYOUT PRIMITIVES
   ------------------------------------------------------------------------ */
.ap-container {
  width: 100%;
  max-width: var(--ap-max-width);
  margin: 0 auto;
  padding: 0 32px;
}

@media (max-width: 768px) {
  .ap-container {
    padding: 0 var(--ap-gutter);
  }
}

.ap-section {
  padding: var(--ap-section-pad-y) 0;
  background: var(--ap-surface);
  position: relative;
}

.ap-section--soft {
  background: var(--ap-soft);
}

/* ------------------------------------------------------------------------
   SECTION HEADERS
   ------------------------------------------------------------------------ */
.eyebrow {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ap-ink-dark);
  margin-bottom: 14px;
}

.section-header {
  max-width: 700px;
  margin: 0 auto 40px;
  text-align: center;
}

.section-header--left {
  margin: 0 0 36px;
  text-align: left;
}

.section-heading {
  font-size: clamp(28px, 3.6vw, 42px);
  margin-bottom: 16px;
}

.section-body {
  font-size: 17px;
  color: var(--ap-text-secondary);
  line-height: 1.65;
}

@media (max-width: 768px) {
  .section-header {
    margin-bottom: 30px;
  }
  .section-heading {
    font-size: 26px;
  }
  .section-body {
    font-size: 15.5px;
  }
}

/* ------------------------------------------------------------------------
   BUTTONS
   ------------------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14.5px;
  font-weight: 600;
  padding: 12px 22px;
  border-radius: var(--ap-radius-btn);
  transition: background var(--ap-fast), color var(--ap-fast), border-color var(--ap-fast), transform var(--ap-fast), box-shadow var(--ap-fast);
  white-space: nowrap;
}

/* Scoped with .ai-platform so the white label outranks the
   `.ai-platform a { color: inherit }` reset - these buttons are
   anchors, which would otherwise render dark-on-dark. */
.ai-platform .btn--primary {
  background: var(--ap-ink);
  color: var(--ap-white);
  box-shadow: var(--ap-shadow-sm);
}

.ai-platform .btn--primary:hover {
  background: var(--ap-ink-dark);
  transform: translateY(-2px);
  box-shadow: var(--ap-shadow-md);
}

.btn--outline {
  background: var(--ap-surface);
  color: var(--ap-text);
  border: 1px solid var(--ap-line);
  box-shadow: var(--ap-shadow-sm);
}

.btn--outline:hover {
  border-color: var(--ap-border-strong);
  background: var(--ap-soft);
}

.btn--lg {
  padding: 0 26px;
  height: 46px;
  font-size: 15px;
}

.btn--block {
  width: 100%;
}

/* ------------------------------------------------------------------------
   NAVBAR
   ------------------------------------------------------------------------ */
.ap-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ap-surface);
  border-bottom: 1px solid var(--ap-line);
  transition: box-shadow var(--ap-fast-2);
}

.ap-nav.is-scrolled {
  box-shadow: var(--ap-shadow-sm);
}

.ap-nav__inner {
  position: relative;
  max-width: var(--ap-shell);
  margin: 0 auto;
  padding: 0 var(--ap-gutter);
  height: var(--ap-nav-h);
  display: flex;
  align-items: center;
}

/* Base colors here are the FOOTER's (light bg, footer.php reuses
   these same .ap-nav__logo/__mark/__wordmark classes for its own
   brand block) - the header needs the opposite treatment now that
   its bar is dark, applied below scoped to #ap-nav specifically so
   the footer's copy of this markup is untouched. */
.ap-nav__logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--ap-text);
  flex-shrink: 0;
}

.ap-nav__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--ap-ink);
  color: var(--ap-white);
}

.ap-nav__mark .ai-icon {
  width: 17px;
  height: 17px;
}

.ap-nav__wordmark {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ap-ink);
}

/* Sits immediately to the right of the logo (not centered on the bar)
   so logo + links read as one left-hand cluster and the actions own
   the right edge. */
.ap-nav__links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 26px;
}

.ap-nav__item {
  position: relative;
}

.ap-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 15.5px;
  font-weight: 400;
  color: var(--ap-text);
  padding: 8px 12px;
  border-radius: var(--ap-radius-sm);
  transition: background var(--ap-fast), color var(--ap-fast);
}

.ap-nav__link:hover {
  background: var(--ap-light-gray);
}

.ap-nav__chevron {
  display: inline-flex;
  color: var(--ap-text-secondary);
  transition: transform var(--ap-fast);
}

.ap-nav__chevron .ai-icon {
  width: 13px;
  height: 13px;
  stroke-width: 2;
}

.ap-nav__item--dropdown.is-open .ap-nav__chevron {
  transform: rotate(180deg);
}

.ap-nav__dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  min-width: 280px;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  box-shadow: var(--ap-shadow-lg);
  padding: 10px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--ap-fast), transform var(--ap-fast), visibility var(--ap-fast);
}

.ap-nav__item--dropdown.is-open .ap-nav__dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.ap-nav__dropdown-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--ap-radius-sm);
  transition: background var(--ap-fast);
}

.ap-nav__dropdown-link:hover {
  background: var(--ap-soft);
}

.ap-nav__dropdown-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  flex-shrink: 0;
}

.ap-nav__dropdown-icon .ai-icon {
  width: 17px;
  height: 17px;
}

.ap-nav__dropdown-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ap-nav__dropdown-name {
  font-size: 14px;
  font-weight: 600;
}

.ap-nav__dropdown-count {
  font-size: 12.5px;
  color: var(--ap-text-secondary);
}

/* ------------------------------------------------------------------------
   NAV MEGA MENU ("AI Agents") - wider variant of .ap-nav__dropdown,
   left category list + right preview cards, footer stats/CTA bar.
   Ported from includes/nav-dropdown-menu.php's layout, re-skinned
   with this page's own icon system (no photos) and color tokens.
   JS (ai-platform.js) centers this on the viewport when open, since
   it's much wider than the trigger's own position in the bar.
   ------------------------------------------------------------------------ */
.ap-nav__dropdown--mega {
  width: 860px;
  max-width: calc(100vw - 48px);
  padding: 20px;
  left: 0;
}

.ap-mega {
  display: grid;
  grid-template-columns: 220px 1px 1fr;
  gap: 24px;
}

.ap-mega__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ap-mega__eyebrow {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  padding: 4px 14px 16px;
}

.ap-mega__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ap-text-secondary);
  border-radius: var(--ap-radius-sm);
  padding: 12px 16px;
  transition: background var(--ap-fast), color var(--ap-fast);
}

.ap-mega__item:hover,
.ap-mega__item.is-active {
  background: var(--ap-soft);
  color: var(--ap-text);
}

.ap-mega__item-arrow {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--ap-text-secondary);
  opacity: 0;
  transform: translateX(-3px);
  transition: opacity var(--ap-fast), transform var(--ap-fast);
}

.ap-mega__item-arrow .ai-icon {
  width: 16px;
  height: 16px;
}

.ap-mega__item.is-active .ap-mega__item-arrow {
  opacity: 1;
  transform: translateX(0);
  color: var(--ap-ink-dark);
}

.ap-mega__divider {
  width: 1px;
  background: var(--ap-border);
}

.ap-mega__panels {
  position: relative;
}

.ap-mega__panel {
  display: none;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}

.ap-mega__panel.is-active {
  display: grid;
}

.ap-mega__card {
  display: flex;
  flex-direction: column;
  transition: transform var(--ap-fast);
}

.ap-mega__card:hover {
  transform: translateY(-3px);
}

.ap-mega__card-image {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 2.5;
  border-radius: var(--ap-radius-sm);
  overflow: hidden;
  margin-bottom: 16px;
  box-shadow: var(--ap-shadow-sm);
}

.ap-mega__card-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.ap-mega__card:hover .ap-mega__card-image img {
  transform: scale(1.06);
}

.ap-mega__card-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--ap-text);
  margin-bottom: 6px;
}

.ap-mega__card-desc {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ap-text-secondary);
}

.ap-mega__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 20px -20px -20px;
  padding: 16px 20px;
  background: #ddd;
  border-top: 1px solid var(--ap-border);
  border-radius: 0 0 var(--ap-radius-card) var(--ap-radius-card);
}

.ap-mega__footer-stats {
  display: flex;
  align-items: center;
  gap: 10px;
}

.ap-mega__footer-stat {
  font-size: 13px;
  color: var(--ap-text-secondary);
  white-space: nowrap;
}

.ap-mega__footer-stat strong {
  color: var(--ap-text);
  font-weight: 800;
  margin-right: 4px;
}

.ap-mega__footer-dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ap-text-secondary);
  flex-shrink: 0;
}

.ai-platform .ap-mega__footer-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ap-white);
  background: var(--ap-ink-dark);
  padding: 9px 16px;
  border-radius: var(--ap-radius-pill);
  white-space: nowrap;
  transition: background var(--ap-fast);
}

.ai-platform .ap-mega__footer-link:hover {
  background: var(--ap-ink-deepest);
}

@media (max-width: 1220px) {
  .ap-nav__dropdown--mega {
    width: 560px;
    padding: 16px;
  }

  .ap-mega {
    grid-template-columns: 156px 1px 1fr;
    gap: 16px;
  }

  .ap-mega__eyebrow {
    padding: 4px 10px 10px;
  }

  .ap-mega__item {
    font-size: 14px;
    padding: 11px;
  }

  .ap-mega__panel {
    gap: 12px;
  }

  .ap-mega__card-image {
    margin-bottom: 10px;
  }

  .ap-mega__card-title {
    font-size: 14px;
    margin-bottom: 3px;
  }

  .ap-mega__card-desc {
    font-size: 12.5px;
  }

  .ap-mega__footer {
    margin: 14px -16px -16px;
    padding: 12px 16px;
  }
}

.ap-nav__actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
  margin-left: auto;
}

.ap-nav__actions .btn {
  height: 42px;
  padding: 0 22px;
  font-size: 14.5px;
  border-radius: 999px;
}

/* Hairline between the CTA and the sign-in link. */
.ap-nav__actions-divider {
  width: 1px;
  height: 24px;
  background: var(--ap-border);
  flex-shrink: 0;
}

.ap-nav__loginlink {
  font-size: 14px;
  font-weight: 500;
  color: var(--ap-text);
  padding: 8px 2px;
  transition: color var(--ap-fast);
}

.ap-nav__loginlink:hover {
  color: var(--ap-ink-dark);
}

/* Scoped exception (--ap-nav-accent, the original site's red) - see
   the :root comment above the variable itself. It now points at the
   same ink family as the rest of the page, so this is no longer a
   break from the palette, only a separately named hook for the nav. */
.ai-platform .ap-nav__cta {
  height: 38px;
  padding: 0 18px;
  font-size: 13.5px;
  font-weight: 500;
  border-radius: 999px;
  background: var(--ap-ink-dark);
  color: var(--ap-white);
}

.ai-platform .ap-nav__cta:hover {
  background: var(--ap-ink-deepest);
}

.ap-nav__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--ap-radius-sm);
  color: var(--ap-text);
  flex-shrink: 0;
  margin-left: auto;
}

.ap-nav__burger:hover {
  background: var(--ap-light-gray);
}

.ap-nav__burger-icon-close {
  display: none;
}

.ap-nav__burger.is-open .ap-nav__burger-icon-open {
  display: none;
}

.ap-nav__burger.is-open .ap-nav__burger-icon-close {
  display: block;
}

.ap-mobile-drawer {
  display: none;
  max-height: 0;
  overflow: hidden;
  background: var(--ap-surface);
  border-bottom: 1px solid var(--ap-border);
  transition: max-height var(--ap-fast-2);
}

.ap-mobile-drawer.is-open {
  max-height: 80vh;
  overflow-y: auto;
}

.ap-mobile-drawer__nav {
  padding: 16px var(--ap-gutter) 28px;
  display: flex;
  flex-direction: column;
}

.ap-mobile-drawer__label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  padding: 10px 4px 6px;
}

.ap-mobile-drawer__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 15.5px;
  font-weight: 500;
  padding: 13px 4px;
  border-bottom: 1px solid var(--ap-border);
}

.ap-mobile-drawer__link--sub {
  padding-left: 10px;
  font-weight: 400;
  color: var(--ap-text-secondary);
}

.ap-mobile-drawer__count {
  font-size: 12.5px;
  color: var(--ap-text-secondary);
}

.ap-mobile-drawer__divider {
  height: 1px;
  background: var(--ap-border);
  margin: 8px 0;
}

.ap-mobile-drawer__actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 20px;
}

/* Below 1080px the five nav links + both action buttons stop fitting
   on one row, so the whole set collapses into the burger drawer. The
   primary CTA stays in the bar down to 560px - it's the one action
   worth keeping permanently visible. */
@media (max-width: 1080px) {
  .ap-nav__links {
    display: none;
  }
  .ap-nav__actions {
    margin-left: auto;
    margin-right: 8px;
  }
  .ap-nav__actions .ap-nav__loginlink,
  .ap-nav__actions-divider {
    display: none;
  }
  .ap-nav__burger {
    display: flex;
    margin-left: 0;
  }
  .ap-mobile-drawer {
    display: block;
  }
}

/* Only once the logo + CTA + burger genuinely stop fitting on one row
   does the last button fold into the drawer. */
@media (max-width: 420px) {
  .ap-nav__actions {
    display: none;
  }
  /* With the actions gone, the burger itself has to hold the right edge. */
  .ap-nav__burger {
    margin-left: auto;
  }
}

/* ------------------------------------------------------------------------
   HERO - centered composition:
   badge / headline / description / search / popular pills / CTAs / trust
   ------------------------------------------------------------------------ */
.ap-hero {
  position: relative;
  padding: 104px 0 92px;
  background: var(--ap-hero-bg);
  overflow: hidden;
}

/* The ambient glow below is a 1040px circle inside an overflow:hidden
   section. On the shorter .cat-hero variants (use-cases, support,
   about, the category pages) the section's bottom edge cuts that
   circle while it is still at meaningful opacity, and the cut reads
   as a hard horizontal seam against the white section that follows.
   This fades the backdrop into the surface color over the last
   140px, so the hero always dissolves into whatever comes next
   regardless of how tall it ends up. Paints above the backdrop
   layers (all z-index auto) but below .ap-hero__inner, which
   carries z-index: 1. */
.ap-hero::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 140px;
  background: linear-gradient(to bottom, transparent 0%, var(--ap-hero-bg) 100%);
  pointer-events: none;
  z-index: 0;
}

/* Fine grid backdrop: a handful of large, very faint checker cells
   (--ap-checker - same technique as style.css's .page-bg elsewhere on
   this site) plus near-invisible 1px lines, masked so the whole thing
   fades out toward the section's outer edge only - #000 is the
   *reveal* color here, not a paint color: opaque through the middle,
   fading to transparent right at the ellipse's boundary. Layered
   BELOW .ap-hero__glow and .ap-hero__vignette (later in the DOM =
   painted on top), same back-to-front order as hero-v3.css's grid +
   glow stack. */
.ap-hero__grid-bg {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--ap-checker), var(--ap-checker)),
    linear-gradient(var(--ap-checker), var(--ap-checker)),
    linear-gradient(var(--ap-checker), var(--ap-checker)),
    linear-gradient(var(--ap-checker), var(--ap-checker)),
    linear-gradient(to right, rgba(25, 24, 23, 0.04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(25, 24, 23, 0.04) 1px, transparent 1px);
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat;
  background-size: 88px 88px, 88px 88px, 88px 88px, 88px 88px, 88px 88px, 88px 88px;
  /* The checker cells must land on the exact same raster as the grid
     lines below (which repeat from "center top" every 88px) or a
     cell straddles two line cells instead of sitting inside one -
     percentages don't guarantee that alignment since they're a
     fraction of container size, not a multiple of the 88px tile.
     calc(50% + Npx) anchors each cell to the same horizontal center
     the lines use, offset by an exact multiple of 88px; the vertical
     offsets are multiples of 88px from the top for the same reason. */
  background-position:
    calc(50% - 264px) 176px,
    calc(50% + 352px) 88px,
    calc(50% - 440px) 528px,
    calc(50% + 176px) 440px,
    center top, center top;
  /* Three stops, not two: a single #000 -> transparent pair puts the
     entire falloff in the last 40% of the ellipse, which lands as a
     visible edge where the texture stops. Adding a mid stop spreads
     the fade across the whole radius so the grid dissolves instead
     of ending. */
  -webkit-mask-image: radial-gradient(ellipse 88% 78% at 50% 32%, #000 20%, rgba(0, 0, 0, 0.5) 62%, transparent 100%);
  mask-image: radial-gradient(ellipse 88% 78% at 50% 32%, #000 20%, rgba(0, 0, 0, 0.5) 62%, transparent 100%);
  pointer-events: none;
}

/* Two restrained ambient lights, not one loud one - same "controlled
   ambient light around the centre" idea as hero-v3.css's
   .hero-v3-glow / .hero-v3-glow-core, recolored to this page's ink
   at a much lower opacity since it's sitting on white, not a dark
   panel. */
.ap-hero__glow {
  position: absolute;
  left: 50%;
  border-radius: 50%;
  pointer-events: none;
}

/* Tinted with --ap-hero-glow-rgb (the theme's accent) rather than
   neutral gray - at these opacities it reads as warmth in the light,
   not as color, and it ties the backdrop to the brand instead of
   leaving it a flat gray wash. */
.ap-hero__glow--a {
  top: -16%;
  width: 1040px;
  height: 1040px;
  transform: translateX(-50%);
  background: radial-gradient(circle, rgba(var(--ap-hero-glow-rgb), 0.08) 0%, transparent 68%);
}

.ap-hero__glow--b {
  top: 12%;
  width: 520px;
  height: 520px;
  transform: translateX(-50%);
  background: radial-gradient(circle, rgba(var(--ap-hero-glow-rgb), 0.07) 0%, transparent 70%);
}

/* The "content sits on a lighter patch" effect from style.css's page
   sections (they paint a flat --clr-bg over .page-bg's checker
   pattern wherever real content sits, so the pattern only shows in
   the gaps around it). Same idea here: a soft white glow centered on
   the content column, fading out before the hero's outer margins so
   the grid/checker/glow stack above still reads at the edges. */
.ap-hero__vignette {
  position: absolute;
  inset: 0;
  /* Sized/centered to cover the full content column top-to-bottom
     (badge through the trust line), not just its upper half - a
     smaller, higher-centered ellipse here left the CTAs and trust
     line completely outside the lightened area. */
  /* Five stops rather than three. The old 0.85 / 0.4 / 0 ramp changed
     slope sharply at the middle stop, which read as a bright ellipse
     with a discernible rim sitting on top of the grid; easing it
     across more stops makes the same wash read as depth. Widened to
     58% so the pills and CTA row sit inside the clean area too. */
  background: radial-gradient(
    ellipse 58% 84% at 50% 48%,
    rgba(var(--ap-hero-wash-rgb), 0.94) 0%,
    rgba(var(--ap-hero-wash-rgb), 0.86) 30%,
    rgba(var(--ap-hero-wash-rgb), 0.62) 54%,
    rgba(var(--ap-hero-wash-rgb), 0.28) 76%,
    rgba(var(--ap-hero-wash-rgb), 0) 100%
  );
  pointer-events: none;
}

.ap-hero__inner {
  position: relative;
  z-index: 1;
  max-width: var(--ap-shell);
  padding: 0 var(--ap-gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* --- Badge --- */
/* Frosted pill: hairline border + a two-stop shadow (tight contact
   shadow over a wide, very soft ambient one) rather than the single
   flat --ap-shadow-sm, so it reads as a lifted object on the grid
   backdrop instead of a stroked outline. */
.ap-hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 38px;
  padding: 0 16px 0 5px;
  border-radius: var(--ap-radius-pill);
  background: rgba(var(--ap-hero-wash-rgb), 0.82);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--ap-border);
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.05),
    0 8px 24px rgba(25, 24, 23, 0.05);
  transition: border-color var(--ap-fast), box-shadow var(--ap-fast), transform var(--ap-fast);
}

.ap-hero__badge:hover {
  border-color: var(--ap-border-strong);
  transform: translateY(-1px);
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.05),
    0 12px 30px rgba(25, 24, 23, 0.09);
}

.ap-hero__badge-tag {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-ink);
  color: var(--ap-white);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.005em;
  white-space: nowrap;
}

.ap-hero__badge-text {
  font-size: 14px;
  font-weight: 600;
  color: var(--ap-text);
  white-space: nowrap;
}

.ap-hero__badge-arrow {
  display: inline-flex;
  color: var(--ap-text-secondary);
  transition: transform var(--ap-fast);
}

.ap-hero__badge-arrow .ai-icon {
  width: 14px;
  height: 14px;
}

.ap-hero__badge:hover .ap-hero__badge-arrow {
  transform: translateX(3px);
}

/* --- Headline --- */
/* Sized so the two lines each stay unbroken at desktop widths - the
   longer line measures ~972px at the 56px cap, inside the 1080px box. */
.ap-hero__heading {
  margin-top: 40px;
  max-width: 1080px;
  font-size: clamp(30px, 4.2vw, 56px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.042em;
  color: #191817;
}

/* Brand-tinted rule that fades out to the right instead of a flat
   black bar - the same "hairline, not hard edge" language the header
   divider uses, so the accent reads as considered rather than
   underscored.

   Drawn as the span's own background rather than an absolutely
   positioned ::after. The ::after was sized to the span's *bounding
   box*, so the moment the phrase wrapped (it does below 768px, where
   the nowrap below is lifted) the bar stretched the full block width
   and struck through the following line. A background with
   box-decoration-break: clone is painted per line fragment instead,
   so each wrapped line gets its own correctly sized rule. The
   padding-bottom only positions the rule - padding on an inline box
   doesn't affect line layout, so the headline's leading is
   untouched. */
.ap-hero__heading-underline {
  font-weight: 400;
  white-space: nowrap;
  padding-bottom: 0.1em;
  background-image: linear-gradient(
    to right,
    var(--ap-ink) 0%,
    var(--ap-ink) 55%,
    rgba(var(--ap-hero-glow-rgb), 0.25) 100%
  );
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: 0 100%;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* --- Description --- */
.ap-hero__subtext {
  margin-top: 28px;
  max-width: 640px;
  font-size: 17.5px;
  font-weight: 400;
  line-height: 1.68;
  letter-spacing: -0.005em;
  color: var(--ap-text-secondary);
}

/* --- AI demo bar ---
   A single <a> to #ecosystem, skinned as a live "AI is matching your
   need to an agent" preview: a phrase types itself out, resolves into
   a matched-agent result chip, then erases and repeats. Functions as
   a real, large CTA rather than a decorative, non-functional input -
   see the hero.php comment for why this replaced a plain search bar. */
/* Pill, not a rounded rectangle - the same full-round geometry the
   header CTA uses, so the hero's primary object and the bar above it
   speak one shape language. Elevation is a three-stop stack (contact
   shadow / mid lift / wide ambient) instead of the old two flat
   values; that gradation is what separates a floating surface from a
   bordered box. */
.ap-hero__demo {
  margin-top: 40px;
  width: 100%;
  max-width: 620px;
  height: 66px;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 8px 8px 8px 18px;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-pill);
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.04),
    0 4px 12px rgba(25, 24, 23, 0.04),
    0 18px 44px rgba(25, 24, 23, 0.07);
  transition: border-color var(--ap-fast), box-shadow var(--ap-fast), transform var(--ap-fast);
}

.ap-hero__demo:hover,
.ap-hero__demo:focus-visible {
  border-color: var(--ap-border-strong);
  transform: translateY(-2px);
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.04),
    0 6px 16px rgba(25, 24, 23, 0.05),
    0 26px 56px rgba(25, 24, 23, 0.11);
}

.ap-hero__demo-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
}

.ap-hero__demo-icon .ai-icon {
  width: 17px;
  height: 17px;
}

.ap-hero__demo-icon-pulse {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ap-ink-dark);
  border: 2px solid var(--ap-surface);
}

.ap-hero__demo-icon-pulse::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid var(--ap-ink-dark);
  animation: ap-pulse-ring 2s ease-out infinite;
}

@keyframes ap-pulse-ring {
  0%   { transform: scale(0.7); opacity: 0.9; }
  100% { transform: scale(2.1); opacity: 0; }
}

.ap-hero__demo-text {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  overflow: hidden;
}

.ap-hero__demo-typed {
  font-size: 15.5px;
  font-weight: 500;
  color: var(--ap-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ap-hero__demo-cursor {
  width: 1.5px;
  height: 17px;
  flex-shrink: 0;
  background: var(--ap-text-secondary);
  animation: ap-cursor-blink 1s step-end infinite;
}

@keyframes ap-cursor-blink {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.ap-hero__demo-result {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 5px 12px 5px 8px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.ap-hero__demo-result.is-visible {
  opacity: 1;
  transform: translateX(0);
}

.ap-hero__demo-result-arrow {
  display: inline-flex;
}

.ap-hero__demo-result-arrow .ai-icon {
  width: 13px;
  height: 13px;
}

.ap-hero__demo-result-icon {
  display: inline-flex;
}

.ap-hero__demo-result-icon .ai-icon {
  width: 14px;
  height: 14px;
}

/* Scoped with .ai-platform so it outranks the `.ai-platform a` reset
   above, which would otherwise strip this tile's white icon color. */
.ai-platform .ap-hero__demo-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--ap-ink);
  color: var(--ap-white);
  transition: background var(--ap-fast), transform var(--ap-fast);
}

.ap-hero__demo:hover .ap-hero__demo-cta {
  background: var(--ap-ink-dark);
  transform: translateX(2px);
}

.ap-hero__demo-cta .ai-icon {
  width: 18px;
  height: 18px;
}

/* --- Popular pills --- */
.ap-hero__popular {
  margin-top: 22px;
  max-width: 660px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
}

.ap-hero__popular-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ap-text-secondary);
}

/* display:contents so the label and every pill share one wrapping flex
   row - as its own flex item the list would grow full-width and push
   the label onto a line by itself. */
.ap-hero__popular-list {
  display: contents;
}

.ap-hero__pill {
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 16px;
  border-radius: var(--ap-radius-pill);
  background: rgba(var(--ap-hero-wash-rgb), 0.72);
  border: 1px solid var(--ap-border);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ap-text);
  white-space: nowrap;
  transition: border-color var(--ap-fast), color var(--ap-fast), background var(--ap-fast), transform var(--ap-fast), box-shadow var(--ap-fast);
}

.ap-hero__pill:hover {
  border-color: var(--ap-border-strong);
  color: var(--ap-ink-dark);
  background: var(--ap-surface);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(25, 24, 23, 0.07);
}

/* --- CTA pair --- */
.ap-hero__ctas {
  margin-top: 34px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Pill geometry + a taller box, scoped to the hero so the shared
   .btn--lg used by the other sections' CTAs keeps its own shape.
   Matches the header's pill CTA, which is the shape the page now
   opens with. */
.ap-hero__ctas .btn--lg {
  height: 52px;
  padding: 0 30px;
  font-size: 15.5px;
  font-weight: 700;
  border-radius: var(--ap-radius-pill);
}

.ai-platform .ap-hero__ctas .btn--primary {
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.06),
    0 10px 24px rgba(25, 24, 23, 0.18);
}

.ai-platform .ap-hero__ctas .btn--primary:hover {
  box-shadow:
    0 1px 2px rgba(25, 24, 23, 0.06),
    0 16px 34px rgba(25, 24, 23, 0.24);
}

.ap-hero__ctas .btn--outline {
  border-color: var(--ap-border);
  background: rgba(var(--ap-hero-wash-rgb), 0.72);
}

.ap-hero__ctas .btn--outline:hover {
  border-color: var(--ap-border-strong);
  background: var(--ap-surface);
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(25, 24, 23, 0.08);
}

.ap-hero__cta-arrow {
  display: inline-flex;
  transition: transform var(--ap-fast);
}

.ap-hero__cta-arrow .ai-icon {
  width: 16px;
  height: 16px;
}

.btn--primary:hover .ap-hero__cta-arrow {
  transform: translateX(3px);
}

/* --- Trust line --- */
/* Tracked-out, uppercase caption rather than sentence-case body copy -
   it's a category list, not a sentence, and the wide tracking reads
   as a considered footnote instead of a fourth line of prose
   competing with the subtext above it. */
.ap-hero__trust {
  margin-top: 38px;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--ap-text-secondary);
  opacity: 0.85;
}

/* --- Hero responsive --- */
@media (max-width: 768px) {
  .ap-hero {
    padding: 72px 0 64px;
  }

  .ap-hero__grid-bg {
    background-size: 64px 64px;
    /* Re-anchored to multiples of the new 64px tile (was 88px) - the
       desktop offsets above are multiples of 88, so on their own they
       would drift off this smaller grid's line raster. */
    background-position:
      calc(50% - 192px) 128px,
      calc(50% + 256px) 64px,
      calc(50% - 320px) 384px,
      calc(50% + 128px) 320px,
      center top, center top;
  }

  .ap-hero__glow--a {
    width: 620px;
    height: 620px;
  }

  .ap-hero__glow--b {
    width: 340px;
    height: 340px;
  }

  .ap-hero__heading {
    margin-top: 28px;
    letter-spacing: -0.03em;
  }

  /* The nowrap that keeps the underlined phrase on one line at desktop
     would force horizontal overflow on a narrow screen. */
  .ap-hero__heading-underline {
    white-space: normal;
  }

  .ap-hero__subtext {
    margin-top: 18px;
    font-size: 15.5px;
    line-height: 1.65;
  }

  .ap-hero__demo {
    margin-top: 28px;
    height: 58px;
    padding-left: 14px;
  }

  .ap-hero__demo-cta {
    width: 44px;
    height: 44px;
  }

  .ap-hero__ctas {
    margin-top: 28px;
  }

  .ap-hero__ctas .btn--lg {
    height: 48px;
    padding: 0 24px;
    font-size: 15px;
  }

  .ap-hero__trust {
    margin-top: 28px;
    font-size: 11px;
    letter-spacing: 0.11em;
  }
}

@media (max-width: 560px) {
  /* The matched-agent result chip is the first thing to go - below
     this width there isn't room for both the typed phrase and the
     chip on one line, and the chip is the less essential of the two. */
  .ap-hero__demo-result {
    display: none;
  }

  .ap-hero__ctas {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }

  .ap-hero__ctas .btn {
    width: 100%;
  }
}

/* The pill demo bar's left padding has to shrink faster than a
   rounded-rect one's would - the full-round corner eats horizontal
   room the typed phrase needs. */
@media (max-width: 480px) {
  .ap-hero__demo {
    padding-left: 12px;
  }
}

@media (max-width: 420px) {
  .ap-hero__demo {
    padding-left: 10px;
    gap: 8px;
  }

  .ap-hero__demo-icon {
    width: 32px;
    height: 32px;
  }
}

@media (max-width: 400px) {
  .ap-hero__badge {
    height: auto;
    padding: 5px 12px 5px 5px;
    flex-wrap: wrap;
    justify-content: center;
  }
}



/* ------------------------------------------------------------------------
   HERO - IMMERSIVE / FULL-BLEED PHOTO VARIANT (.ap-hero--immersive)
   Used by index.php only. Everything below is additive: the light
   .ap-hero above still drives about-us.php, support.php,
   use-cases.php and the four category pages, which must not change.

   Anatomy, per the supplied reference: photo behind the whole hero
   (header transparent on top of it), left-aligned badge / headline /
   subtext, a row of category tabs, then a frosted card holding a
   short list, an input-shaped element, and a footer row.
   ------------------------------------------------------------------------ */
.ap-hero--immersive {
  /* The nav is fixed on these pages (see the has-immersive-hero rules
     further down), so it takes no flow space and the photo starts at
     y=0 and runs behind it. The top padding has to clear the nav
     itself before the content column begins. */
  /* Kept deliberately tight. The backdrop photo is ~2.08:1 and
     object-fit: cover scales to fill the shorter axis, so every extra
     px of hero height is horizontal crop - at 917px tall the hero was
     showing only the middle half of the image and the composition
     (open sky left, skyline right) was cropped away entirely. ~800px
     at desktop keeps the hero near the photo's own ratio. */
  padding: calc(var(--ap-nav-h) + 76px) 0 60px;
  min-height: 660px;
  display: flex;
  align-items: center;
  background: #1A1918;
  isolation: isolate;
}

/* The light hero's texture layers have no role here - a photograph is
   doing that job - and .ap-hero::after's fade-to-surface would paint
   a light band over the bottom of the image. */
.ap-hero--immersive .ap-hero__grid-bg,
.ap-hero--immersive .ap-hero__glow,
.ap-hero--immersive .ap-hero__vignette,
.ap-hero--immersive::after {
  display: none;
}

.ap-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* Stacked slides, all in the same box, crossfaded by toggling
   .is-active (ai-platform.js:initHeroSlideshow). object-position is
   set per slide inline from $hero_slides, since each frame's aspect
   and subject placement differ. */
.ap-hero__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  /* Long and eased, not a linear dissolve. 1.5s with a slow-out curve
     is what separates a crossfade that reads as intentional from one
     that reads as a slideshow widget; the two adjacent slides are
     both partially visible for most of it, which is why every slide
     is toned and composed alike. */
  transition: opacity 1500ms cubic-bezier(0.4, 0, 0.2, 1);
}

.ap-hero__slide.is-active {
  opacity: 1;
  /* A slow push in on whichever slide is showing. Runs 8s against a
     6.5s hold, so it is still moving when the next crossfade starts
     and never visibly parks at its end state. Re-triggered by the
     class being removed and re-added. */
  animation: ap-hero-drift 8s ease-out both;
}

@keyframes ap-hero-drift {
  from { transform: scale(1); }
  to   { transform: scale(1.045); }
}

/* Two gradients in one layer: a left-weighted horizontal wash that
   guarantees text contrast over whatever the photo is doing, plus a
   vertical one that darkens the top (so the transparent header's
   white text holds) and the bottom (so the section below does not
   meet a bright edge). Kept as one element rather than two stacked
   scrims so the blend stays predictable. */
.ap-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Alphas are deliberately modest: the two gradients multiply where
     they overlap, so the darkest point (bottom-left) already lands
     near 0.85 effective from these values. Pushing either layer
     higher flattens the photograph to black.

     The left end has to be heavy regardless, because that is where
     the copy sits and the sky behind it is a bright golden - white
     type needs roughly this much wash over it to clear contrast. The
     right end stays nearly clear so the skyline reads. */
  background:
    linear-gradient(
      to right,
      rgba(18, 17, 16, 0.80) 0%,
      rgba(18, 17, 16, 0.66) 36%,
      rgba(18, 17, 16, 0.28) 68%,
      rgba(18, 17, 16, 0.08) 100%
    ),
    linear-gradient(
      to bottom,
      rgba(18, 17, 16, 0.30) 0%,
      rgba(18, 17, 16, 0.03) 32%,
      rgba(18, 17, 16, 0.03) 60%,
      rgba(18, 17, 16, 0.52) 100%
    );
  pointer-events: none;
}

/* Left-aligned column, not the light hero's centred stack. Shares
   --ap-shell/--ap-gutter with the header, so the badge's left edge
   lines up with the logo above it. */
.ap-hero--immersive .ap-hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--ap-shell);
  margin: 0 auto;
  padding: 0 var(--ap-gutter);
  display: block;
  text-align: left;
}

/* --- Badge --- */
.ap-hero--immersive .ap-hero__badge {
  height: 32px;
  padding: 0 14px 0 4px;
  gap: 9px;
  background: rgba(255, 255, 255, 0.10);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-color: rgba(255, 255, 255, 0.18);
  box-shadow: none;
}

.ap-hero--immersive .ap-hero__badge:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.30);
  box-shadow: none;
}

.ap-hero--immersive .ap-hero__badge-tag {
  height: 24px;
  padding: 0 10px;
  font-size: 11.5px;
  background: rgba(255, 255, 255, 0.92);
  color: #1A1918;
}

.ap-hero--immersive .ap-hero__badge-text {
  font-size: 13px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.92);
}

.ap-hero--immersive .ap-hero__badge-arrow {
  color: rgba(255, 255, 255, 0.66);
}

/* --- Headline --- */
.ap-hero--immersive .ap-hero__heading {
  margin-top: 22px;
  /* A px measure, not ch (15.5ch of a 64px face is only ~500px, which
     once broke this headline over four lines). At 39 characters it
     holds two lines inside 760px even at the 64px cap - the copy got
     shorter, so the type could get bigger without the block growing. */
  max-width: 760px;
  font-size: clamp(34px, 5vw, 64px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: #FFFFFF;
  /* Deliberately not a full text-shadow (which muddies large type) -
     just enough spread to hold the descenders against the brighter
     parts of the photo on narrow screens, where the scrim's
     left-weighted wash is compressed. */
  text-shadow: 0 1px 24px rgba(14, 13, 12, 0.45);
}

/* The lighter-weight half of the headline, replacing the light hero's
   underlined span. No rule under it here: on a photograph an
   underline reads as clutter, and the weight contrast alone carries
   the emphasis. */
.ap-hero__heading-soft {
  font-weight: 300;
  color: rgba(255, 255, 255, 0.94);
}

/* Own line, rather than letting the two sentences reflow into each
   other. Left to wrap naturally the break landed mid-phrase ("One
   intelligent / platform."), orphaning a word; one sentence per line
   is the deliberate reading and it also lets the type run larger. */
.ap-hero--immersive .ap-hero__heading-soft {
  display: block;
}

/* --- Subtext --- */
.ap-hero--immersive .ap-hero__subtext {
  margin-top: 22px;
  /* One line now, so the old 560px measure is moot - this just stops
     it stretching if the copy is ever lengthened again. */
  max-width: 520px;
  font-size: 16px;
  /* 300, against the base rule's 400 - pairs with the headline's
     own light half rather than competing with it. */
  font-weight: 300;
  line-height: 1.55;
  letter-spacing: -0.005em;
  color: rgba(255, 255, 255, 0.7);
}

/* --- Category tabs --- */
.ap-hero__tabs {
  margin-top: 44px;
  display: flex;
  align-items: center;
  gap: 7px;
  /* Scrolls rather than wraps: four chips at their natural width
     overflow below ~900px, and a wrapped second row would push the
     card down and unbalance the composition. */
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 2px;
}

.ap-hero__tabs::-webkit-scrollbar {
  display: none;
}

.ap-hero__tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  height: 32px;
  padding: 0 13px;
  border-radius: var(--ap-radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: rgba(255, 255, 255, 0.74);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--ap-fast), color var(--ap-fast), border-color var(--ap-fast);
}

.ap-hero__tab:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
}

.ap-hero__tab.is-active {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: #1A1918;
}

.ap-hero__tab-icon {
  display: inline-flex;
  color: currentColor;
}

.ap-hero__tab-icon .ai-icon {
  width: 13px;
  height: 13px;
}

/* --- Frosted card --- */
.ap-hero__card {
  margin-top: 12px;
  width: 100%;
  max-width: 700px;
  padding: 16px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(115, 115, 119, 0.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.1);
  backdrop-filter: blur(18px) saturate(1.1);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 24px 60px rgba(6, 5, 9, 0.42);
}

.ap-hero__panels {
  /* One row. All four category descriptions are within a character of
     each other in length, so they wrap identically and the card holds
     the same height across every tab. */
  min-height: 22px;
}

.ap-hero__panel {
  display: none;
}

.ap-hero__panel.is-active {
  display: block;
}

/* JS toggles the class and the attribute together; this keeps the
   attribute authoritative if the two ever disagree. */
.ap-hero__panel[hidden] {
  display: none;
}

.ap-hero__agents {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.ap-hero__agent {
  display: flex;
  /* Centre, not baseline - the leading element is an icon tile now,
     not a text numeral. */
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  line-height: 1.4;
}

/* Replaced a "1." / "2." numeral, which implied a ranking these
   agents do not have. The tile also picks up the same icon language
   as the category chips above the card. */
.ap-hero__agent-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.10);
  color: rgba(255, 255, 255, 0.88);
}

.ap-hero__agent-icon .ai-icon {
  width: 11px;
  height: 11px;
}

.ap-hero__agent-name {
  flex-shrink: 0;
  font-weight: 600;
  color: #FFFFFF;
  /* Hairline separator between the chip's title and its description,
     drawn as a border so it disappears automatically when the two
     stack onto separate lines below 620px. */
  padding-right: 9px;
  border-right: 1px solid rgba(255, 255, 255, 0.18);
}

/* No nowrap/ellipsis any more. This used to be a trailing blurb next
   to one of several agent names, where truncating was the lesser
   evil; it is now the row's substance, so it wraps rather than being
   cut off. */
.ap-hero__agent-desc {
  color: rgba(255, 255, 255, 0.6);
}

/* --- Demo bar, restyled for the dark card ---
   The reference's copyable URL field: a recessed rounded rect inside
   the card with a round light button on its right end. Not the pill
   the light hero uses - inside a card the softer rectangle reads as
   a field, which is what the typing animation is imitating. */
.ap-hero--immersive .ap-hero__demo {
  /* 12px, not the 4px this had while a trailing "All N agents"
     link sat between the list and the field. With that link moved
     to the footer the two blocks were ~8px apart and read as one
     mass - the field needs to look like a separate affordance. */
  margin-top: 12px;
  max-width: none;
  height: 46px;
  gap: 10px;
  padding: 6px 6px 6px 12px;
  border-radius: 11px;
  border-color: rgba(255, 255, 255, 0.10);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: none;
}

.ap-hero--immersive .ap-hero__demo:hover,
.ap-hero--immersive .ap-hero__demo:focus-visible {
  transform: none;
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.09);
  box-shadow: none;
}

.ap-hero--immersive .ap-hero__demo-icon {
  width: 30px;
  height: 30px;
  background: rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.86);
}

.ap-hero--immersive .ap-hero__demo-icon .ai-icon {
  width: 15px;
  height: 15px;
}

.ap-hero--immersive .ap-hero__demo-icon-pulse {
  background: #FFFFFF;
  border-color: rgba(20, 19, 26, 0.9);
}

.ap-hero--immersive .ap-hero__demo-icon-pulse::after {
  border-color: rgba(255, 255, 255, 0.8);
}

.ap-hero--immersive .ap-hero__demo-typed {
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.92);
}

.ap-hero--immersive .ap-hero__demo-cursor {
  background: rgba(255, 255, 255, 0.7);
  height: 16px;
}

.ap-hero--immersive .ap-hero__demo-result {
  background: rgba(255, 255, 255, 0.14);
  color: #FFFFFF;
}

/* White circle with a dark glyph, as in the reference. This is the
   field's affordance rather than a CTA, so it does not take the
   brand accent - the accent stays on the "Get Started" button in the
   footer row below and in the header. */
.ai-platform .ap-hero--immersive .ap-hero__demo-cta {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: #FFFFFF;
  color: #1A1918;
}

.ap-hero--immersive .ap-hero__demo:hover .ap-hero__demo-cta {
  background: #FFFFFF;
  transform: translateX(2px);
}

.ap-hero--immersive .ap-hero__demo-cta .ai-icon {
  width: 17px;
  height: 17px;
}

/* --- Card footer --- */
.ap-hero__card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}

/* Scoped with .ai-platform so the light color outranks the
   `.ai-platform a { color: inherit }` reset near the top of this
   file - without it this anchor renders in --ap-text on a dark
   card, i.e. invisible. Same guard .ap-hero__demo-cta carries. */
.ai-platform .ap-hero__card-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.82);
  transition: color var(--ap-fast);
}

.ai-platform .ap-hero__card-link:hover {
  color: #FFFFFF;
}

.ap-hero__card-link .ai-icon {
  width: 13px;
  height: 13px;
}

/* On the dark card, so white like the header's - and scoped tightly
   enough that .ai-platform's plum default still wins everywhere the
   background is light. */
.ai-platform .ap-hero__card-foot .ap-nav__cta {
  height: 34px;
  padding: 0 16px;
  font-size: 13px;
  font-weight: 500;
  background: #FFFFFF;
  color: #1A1918;
}

.ai-platform .ap-hero__card-foot .ap-nav__cta:hover {
  background: rgba(255, 255, 255, 0.88);
  color: #1A1918;
}

/* --- Transparent header over the photo ---
   index.php sets $body_class = 'has-immersive-hero' before head.php.
   A body class rather than :has(.ap-hero--immersive) so the rules do
   not depend on selector support, and so the intent is greppable
   from the page that opts in.

   The nav goes fixed (not sticky) purely so it stops taking flow
   space - that is what lets the photo start at y=0 and run behind
   it. .is-scrolled is already applied by ai-platform.js past 8px, so
   the bar hands itself back to the default solid treatment as soon
   as the hero starts leaving. */
body.has-immersive-hero .ap-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background: transparent;
  border-bottom-color: transparent;
}

body.has-immersive-hero .ap-nav.is-scrolled {
  background: var(--ap-surface);
  border-bottom-color: var(--ap-line);
}

body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__wordmark,
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__link,
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__loginlink,
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__burger {
  color: #FFFFFF;
}

body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__chevron {
  color: rgba(255, 255, 255, 0.66);
}

/* White CTA over the photo. Deliberately scoped to :not(.is-scrolled):
   past 8px of scroll the bar becomes solid --ap-surface (white) and a
   white button on it would be invisible, so it reverts to the plum
   defined further up. The mobile drawer and every non-immersive page
   are untouched for the same reason - both sit on white. */
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__cta {
  background: #FFFFFF;
  color: #1A1918;
}

body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__cta:hover {
  background: rgba(255, 255, 255, 0.88);
  color: #1A1918;
}

body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__link:hover,
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__burger:hover {
  background: rgba(255, 255, 255, 0.12);
}

body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__actions-divider {
  background: rgba(255, 255, 255, 0.24);
}

/* The logo mark is a filled accent tile on white; over the photo it
   needs its own edge instead of relying on the page background. */
body.has-immersive-hero .ap-nav:not(.is-scrolled) .ap-nav__mark {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22);
}

/* --- Immersive hero responsive --- */
@media (max-width: 1080px) {
  .ap-hero--immersive .ap-hero__heading {
    max-width: 620px;
  }
}

@media (max-width: 860px) {
  .ap-hero--immersive {
    padding: calc(var(--ap-nav-h) + 80px) 0 72px;
    min-height: 0;
  }

  .ap-hero--immersive .ap-hero__heading {
    max-width: none;
    letter-spacing: -0.03em;
  }

  .ap-hero--immersive .ap-hero__subtext {
    margin-top: 18px;
    font-size: 15.5px;
  }

  .ap-hero__tabs {
    margin-top: 34px;
    /* Bleed the scrolling row to both screen edges so it reads as
       scrollable rather than clipped mid-chip at the gutter. */
    margin-left: calc(var(--ap-gutter) * -1);
    margin-right: calc(var(--ap-gutter) * -1);
    padding-left: var(--ap-gutter);
    padding-right: var(--ap-gutter);
  }

  .ap-hero__card {
    padding: 16px;
  }


  .ap-hero__panels {
    min-height: 22px;
  }
}

@media (max-width: 620px) {
  /* The horizontal wash is what buys text contrast at desktop, but
     there is no width left here for it to fall off across, so it goes
     near-flat and the vertical gradient does the work. Kept lighter
     than a first pass at 0.90/0.82, which multiplied out to ~0.94 and
     erased the photograph entirely - these values land near 0.72 in
     the copy band, still ~9:1 against white type. */
  .ap-hero__scrim {
    background:
      linear-gradient(
        to right,
        rgba(18, 17, 16, 0.74) 0%,
        rgba(18, 17, 16, 0.66) 100%
      ),
      linear-gradient(
        to bottom,
        rgba(18, 17, 16, 0.42) 0%,
        rgba(18, 17, 16, 0.06) 32%,
        rgba(18, 17, 16, 0.06) 60%,
        rgba(18, 17, 16, 0.64) 100%
      );
  }

  /* Title and description stop fitting on one line - stack them, with
     the description indented to the title's left edge (icon 20px +
     its 9px gap) instead of hanging under the icon. The title's
     separator border is dropped since it would now point at nothing. */
  .ap-hero__agent {
    flex-wrap: wrap;
  }

  .ap-hero__agent-name {
    padding-right: 0;
    border-right: 0;
  }

  .ap-hero__agent-desc {
    flex-basis: 100%;
    padding-left: 29px;
    margin-top: 2px;
  }

  .ap-hero__card-foot {
    flex-direction: column;
    align-items: stretch;
  }

  .ap-hero__card-foot .ap-nav__cta {
    width: 100%;
  }
}

@media (max-width: 420px) {
  .ap-hero--immersive .ap-hero__demo {
    padding-left: 10px;
    gap: 8px;
  }

  .ap-hero--immersive .ap-hero__demo-cta {
    width: 38px;
    height: 38px;
  }
}

/* ------------------------------------------------------------------------
   STATS - deliberately plain: a light section with a large light-weight
   heading and one row of figures split by full-height hairlines. No
   panel, no card, no icons.

   This replaced a dark rounded panel (gradient, grid texture, warm
   bleed, elevation). The panel version competed with the photographic
   hero directly above it for attention; sitting the figures straight
   on the page background lets the hero stay the loudest thing on the
   screen, which is what a stats band should do.

   Colours come from --ap-text / --ap-text-secondary / --ap-border, so
   index-warm.php and index-black.php pick up their own palettes with
   no override needed - on the black theme these tokens are already a
   warm off-white on near-black.
   ------------------------------------------------------------------------ */
.ap-stats {
  padding: 96px 0;
}

.ai-platform .ap-stats__heading {
  max-width: 900px;
  font-size: clamp(27px, 3.4vw, 44px);
  /* 300 - the figures below are 300 too, so the whole band reads as
     one light voice rather than as headline-plus-data. */
  font-weight: 300;
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--ap-text);
  margin-bottom: 60px;
}

.ap-stats__numbers {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Hairline on the left of every cell, including the first, as in the
   reference. A border rather than an absolutely-positioned bar so it
   spans the row's full height for free and stays put however the
   labels wrap. */
.stat-item {
  padding: 2px 0 2px 26px;
  /* --ap-border-strong (0.16), not --ap-border (0.09): at 9% alpha on
     white these rules were all but invisible, and they are the only
     structure this band has. */
  border-left: 1px solid var(--ap-border-strong);
}

.stat-item__value {
  font-size: clamp(38px, 4.4vw, 58px);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ap-text);
  margin-bottom: 10px;
}

/* The infinity glyph only. At the 300 the digits use it reads visibly
   thinner than they do - a symbol carries less stroke mass than a
   numeral at the same weight - so it takes one step up to sit at
   matching strength. Applied via a class from render_stat_card(),
   keyed off the value being non-numeric. */
.stat-item__value--glyph {
  font-weight: 400;
}

.stat-item__label {
  font-size: 16px;
  font-weight: 400;
  /* Sentence case, not the tracked-out uppercase this used to be -
     the reference's captions read as plain prose. */
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  /* Full-strength text, matching .stat-item__value above it, rather
     than the muted secondary - the label and its figure read as one
     unit. --ap-text, not the literal #191817, because index-black
     also renders this section and repoints the token to a light
     value; a literal would put near-black type on its near-black
     ground. Same reason for the two ecosystem rules below. */
  color: var(--ap-text);
}

@media (max-width: 900px) {
  .ap-stats {
    padding: 72px 0;
  }

  .ai-platform .ap-stats__heading {
    margin-bottom: 44px;
  }

  .stat-item {
    padding-left: 20px;
  }
}

/* Two up. The cells are grid tracks rather than flex items so
   minmax(0, 1fr) holds them to an even split - as flex items with a
   50% basis, `min-width: auto` let a long caption push a cell past
   its basis and bump the next one onto a row of its own. */
@media (max-width: 620px) {
  .ap-stats__numbers {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 34px;
  }
}

@media (max-width: 380px) {
  .ap-stats__numbers {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 26px;
  }
}


/* ------------------------------------------------------------------------
   BUILT FOR REAL LIFE - tab rail + agent grid inside one white card,
   per the supplied reference: near-black active pill, hairline item
   cards. The section itself takes no background, so the board sits on
   the page ground and is defined by its own hairline border.
   ------------------------------------------------------------------------ */
/* Left-aligned, not the shared centred .section-header. Used to sit
   as its own full-width strip above the board; now it is the first
   block inside .uc-board__rail, stacked above the tablist in the same
   340px column - see the markup and .uc-board__rail below. Its own
   spacing to the tablist comes from the rail's gap, not a margin
   here, since both are now flex siblings in the same column. */
.uc-head {
  width: 100%;
}

/* 800, matching the ecosystem panel's heading, so the two big
   sections read as siblings - at 600 this one went soft next to it.
   The weight is also what separates it from .uc-pane__title inside
   the board: those two were 38/600 against 29/600, close enough that
   a pane heading competed with the section heading for the same rank.

   Still a vw-based clamp even though the heading now lives in a fixed
   340px column, not the full container - the phrase is short enough
   ("Built for real life") to stay on one line at the same sizes that
   worked full-width, so there was no need to re-tune it against the
   narrower track. */
.ai-platform .uc-head__title {
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 600;
  letter-spacing: -0.032em;
  line-height: 1.12;
  color: var(--ap-text);
  margin-bottom: 14px;
}

/* Full strength at 18px, as the ecosystem panel sets its own
   supporting line - one short sentence carrying the whole section, so
   it holds up better as body copy than as muted caption text.
   No max-width now - the 340px column below is already narrower than
   the 620px this used to cap it at, from when it spanned the full
   section width. */
.uc-head__sub {
  font-size: 18px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ap-text);
}

.uc-board {
  display: grid;
  /* Fixed rail, fluid panes. minmax(0,1fr) so the pane's own grid can
     shrink rather than forcing the board wider than its column.
     340px, widened from 240px, because the rail column now carries
     the section heading above the tablist as well as the tabs
     themselves - 240px was sized for "Marketplace & Social AI" alone
     and had no heading to fit. */
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 30px;
  /*background: #f4f3ef;*/
  background: var(--ap-surface);
  /*border: 1px solid var(--ap-border);*/
  /*border-radius: 22px;*/
  /* The site's smallest shadow token - a soft lift off the page, not
     a hover-style "raised card" shadow. The board already has a
     hairline border defining its edge, so this only needs to add a
     little depth underneath it, not a second outline. */
  /*box-shadow: var(--ap-shadow-md);*/
  padding: 40px 0;
}

/* --- Left column: heading, then the tablist --- */
.uc-board__rail {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Between the heading block and the tablist below it - wider than
     the 17px between individual tabs (now .uc-board__tablist's own
     gap), so the two groups still read as separate even though both
     are flex children of this same column. */
  gap: 40px;
  /* Hairline down the channel, so the two halves of the board read as
     a deliberate split rather than two things that happen to sit side
     by side. Now runs the full height of the column, heading
     included, since the heading moved in here too. Removed at the
     780px breakpoint, where the tablist (not this whole column) turns
     into a horizontal row. */
  padding-right: 24px;
  border-right: 1px solid var(--ap-border);
}

/* --- Tablist: the tab buttons only - role="tablist" is scoped to
   this element in the markup, not the whole rail, since a tablist's
   children are expected to be tabs and the heading above is not
   one. */
.uc-board__tablist {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* 17px against a 33px item gives the reference's ~50px step. */
  gap: 17px;
  width: 100%;
}

.uc-tab {
  /* Icon + label on one line. Hugs its content - the reference's pill
     wraps the word rather than spanning the column. Both states carry
     the same horizontal padding so an inactive label lines up with
     the active pill's label, not with the pill's outer edge. */
  display: inline-flex;
  align-items: center;
  /* 7px, not 9px: the glyphs are drawn inset inside their own box
     (see the padding note below), which adds ~2.7px of air on this
     side too, so a 7px gap reads as about 9px. */
  gap: 7px;
  width: auto;
  max-width: 100%;
  /* Asymmetric on purpose. Every icon in the set is drawn inset
     within its 24-unit viewBox (layers spans x=4..20, so 3px each
     side once rendered at 18px), so a symmetrical left padding put
     the glyph ~19px off the pill edge against a flat 16px of space
     after the label. 13px on the left lands the drawn glyph 16px in.
     The 20px right is a deliberate wider trailing margin, not an
     optical correction. */
  padding: 9px 20px 9px 13px;
  border-radius: var(--ap-radius-pill);
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.15;
  text-align: left;
  /* Near-black, not secondary grey: in the reference the unselected
     labels are as dark as body copy, and only the pill distinguishes
     the active one. */
  color: var(--ap-text);
  cursor: pointer;
  transition: background var(--ap-fast), color var(--ap-fast),
              transform var(--ap-fast), box-shadow var(--ap-fast);
}

/* Nudges along the rail's own axis on hover - the rail is vertical,
   so a horizontal shift is the movement that fits it. */
.uc-tab:hover:not(.is-active) {
  background: var(--ap-soft);
  transform: translateX(3px);
}

/* Near-black pill for the selected one, as in the reference - not the
   brand plum, which would fight the plum CTAs elsewhere on the page.
   The shadow lifts it off the white board so the selection reads at a
   glance instead of only by its fill. */
.uc-tab.is-active {
  background: #191817;
  color: #FFFFFF;
  font-weight: 600;
  box-shadow: 0 2px 10px rgba(25, 24, 23, 0.18);
}

/* The glyph inherits currentColor, so it darkens with the label and
   turns white inside the active pill without a rule of its own. Each
   category uses the same mark here as in the ecosystem section. */
.uc-tab__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.uc-tab__icon .ai-icon {
  width: 18px;
  height: 18px;
}

/* Keeps a long label on one line rather than wrapping under its own
   icon - the rail track is sized for the longest of them. */
.uc-tab__label {
  white-space: nowrap;
}

/* --- Panes --- */
.uc-pane {
  display: none;
}

.uc-pane.is-active {
  display: block;
  /* Switching tabs used to swap one block for another with nothing in
     between. Going from display:none to block restarts the animation,
     so this replays on every switch without any JS. */
  animation: uc-pane-in 320ms cubic-bezier(0.22, 0.61, 0.24, 1) both;
}

@keyframes uc-pane-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.uc-pane[hidden] {
  display: none;
}

/* Down from 29px and up to 700: a pane heading is subordinate to the
   section heading above the board, and at 29/600 against 38/600 it
   did not read that way. Smaller but heavier keeps it confident. */
.ai-platform .uc-pane__title {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.2;
  color: var(--ap-text);
  margin-bottom: 10px;
}

.uc-pane__desc {
  font-size: 15.5px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ap-text-secondary);
  margin-bottom: 28px;
}

.uc-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* A touch wider than the cards' own 19px inner padding, so the row
     groups as a row instead of reading as one flat mesh. */
  gap: 22px;
  /* No min-height. Reserving two rows kept the board a fixed height
     across tabs, but Career AI holds only two agents - so that tab
     showed one row of cards above ~240px of empty white, with the
     "view all" link stranded at the bottom. A board that resizes when
     you switch tabs is the lesser problem, and is what tabbed panels
     normally do. */
  align-content: start;
}

/* --- Agent cards --- */
.uc-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 20px 20px 19px;
  /* Floor, so the box keeps some presence on the panes whose agent
     descriptions run short and would otherwise collapse it. */
  min-height: 186px;
  border: 1px solid var(--ap-border-strong);
  border-radius: 12px;
  background: var(--ap-surface);
  transition: border-color var(--ap-fast), box-shadow var(--ap-fast), transform var(--ap-fast);
}

.uc-card:hover {
  /*border-color: var(--ap-text);*/
  /*transform: translateY(-3px);*/
  box-shadow: 0 10px 26px rgba(25, 24, 23, 0.05);
}

.uc-card:focus-visible {
  outline: 2px solid var(--ap-ink);
  outline-offset: 2px;
}

/* The reference's small corner dot. Brand accent rather than its
   blue, which would be the only blue on the site. Held at a quarter
   strength at rest and brought up on hover: at full ink on all nine
   cards it competed with the icon chips for attention. */
.uc-card__dot {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(25, 24, 23, 0.25);
  transition: background var(--ap-fast), transform var(--ap-fast);
}

.uc-card:hover .uc-card__dot {
  background: var(--ap-ink);
  transform: scale(1.25);
}

.uc-card__head {
  display: flex;
  /*align-items: center;*/
  gap: 12px;
  /* Clear of the corner dot. */
  padding-right: 16px;
  margin-bottom: 15px;
}

/* Bare glyph beside the name - no chip, no fixed box, so it sizes
   to the SVG itself. The hover invert that came with the chip went
   with it: without a filled background behind it, going to white on
   hover would have dropped the icon out against the white card. */
/* Bare glyph, no chip - per earlier request. Color only, via
   --icon-color (an "R G B" triplet set on this element by
   ai_icon_style_attr() in PHP - see icons.php); falls back to the
   same flat ink this was before if a key has no mapped color. */
/* No background, box-shadow, or backdrop-filter - this card is being
   migrated to a real downloaded photo per agent (see
   $ai_platform_icon_images in icons.php / ai_agent_icon_html()), and
   those photos already carry their own full color; the glass tile
   this used to sit on was tuned for the single-hue SVG glyph it
   replaced and just fought the photo's own colors once one was
   placed. Removed rather than kept for the ones without a photo yet
   too, since ai_agent_icon_html() renders nothing for those - an
   empty 46x46 box with no chrome around it is a plain, honest blank
   space, not a tinted swatch with nothing inside it.
   .uc-card:hover .uc-card__icon below keeps a small lift on hover;
   there is no glow left to deepen with it. */
.uc-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /*width: 46px;
  height: 46px;*/
  transition: transform var(--ap-fast);
}

/* A small lift on hover - no glow left to deepen with it. */
.uc-card:hover .uc-card__icon {
  transform: translateY(-1px);
}

.uc-card__icon .ai-icon {
  width: 28px;
  height: 28px;
}

.ai-platform .uc-card__name {
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.25;
  color: var(--ap-text);
}

/* Clamped to two lines, as in the reference, so a long agent
   description cannot make one card taller than its row-mates. */
.uc-card__desc {
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.5;
  color: #505050;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* "Try" on its own line, under a hairline rule, right-aligned - the
   rule is what separates the card's content from its action. Only
   child, so flex-end does the aligning rather than a margin on the
   Try itself. */
/*.uc-card__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-top: 13px;
  padding-top: 11px;
  border-top: 1px solid var(--ap-border);
  display: none;  
}*/

.uc-card__foot {
  position: absolute;
  bottom: 10px;
  right: 15px;
  opacity: 0;
  pointer-events: none;
  transition: all ease-in-out 0.2s;
}

a.uc-card:hover .uc-card__foot {
  opacity: 0.9;
  pointer-events:auto;
}

/* Category name on each card. Pushed to the bottom with an auto
   margin so it sits on one line across a row even when the two
   descriptions above it differ in length. A micro-label rather than
   body text - it is metadata, clearly subordinate to the agent
   name. */
.uc-card__cat {
  margin-top: auto;
  padding-top: 13px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  /* Was 0.8 opacity on top of the secondary grey, which put this
     micro-label under 4.5:1. Full secondary at 600 keeps it clearly
     subordinate by size and case without dropping it below AA. */
  color: var(--ap-text-secondary);
}

/* "Try" affordance, right-aligned inside its own bordered row above
   (see .uc-card__foot). */
.uc-card__try {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: -0.005em;
  /* Full-strength ink at rest, same as the glyph beside it. Ink and
     not the reference's red, because nothing else in this palette is
     red. Kept as a colour rather than an element opacity: an opacity
     here would fade the glyph with it, and that stays fully dark. */
  color: var(--ap-ink);
  transition: color var(--ap-fast);
}

.uc-card:hover .uc-card__try,
.uc-card:focus-visible .uc-card__try {
  color: var(--ap-ink);
}

/* Full-strength ink at rest, not inherited from the muted label - the
   glyph is the thing that should read first in this row. */
.uc-card__try-icon {
  display: inline-flex;
  align-items: center;
  color: var(--ap-ink-dark);
}

/* The icon set renders fill="none" with a rounded 1.6 stroke, which
   softened the triangle's three corners into blobs at this size.
   Filling it and dropping the stroke gives the path's true corners -
   sharper, and a touch larger at 13px so it holds its own. */
.uc-card__try-icon .ai-icon {
  width: 18px;
  height: 18px;
  fill: currentColor;
  stroke: none;
}

.ai-platform .uc-pane__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 28px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ap-text);
  transition: color var(--ap-fast);
}

.ai-platform .uc-pane__more:hover {
  color: var(--ap-ink);
}

.uc-pane__more .ai-icon {
  width: 13px;
  height: 13px;
}

.uc-pane__more .link-arrow {
  display: inline-flex;
  transition: transform var(--ap-fast);
}

.uc-pane__more:hover .link-arrow {
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .uc-card,
  .uc-card__dot,
  .uc-card__icon,
  .uc-card__try,
  .uc-tab,
  .uc-pane__more .link-arrow {
    transition: none;
  }
  .uc-card:hover,
  .uc-card:hover .uc-card__dot,
  .uc-tab:hover:not(.is-active) {
    transform: none;
  }
  .uc-pane.is-active {
    animation: none;
  }
}

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

/* The tablist turns into a horizontal scrolling row below the
   heading - a 210px column plus a two-up grid does not fit below
   this. The rail itself just stacks the heading above that row now;
   the row's own layout (and the divider that moves from the rail's
   right edge to its bottom edge) lives on .uc-board__tablist. */
@media (max-width: 780px) {
  .uc-board {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
    padding: 22px;
    border-radius: 20px;
  }

  .uc-board__rail {
    /* The vertical divider belongs to the desktop side-by-side split
       only - there is nothing to its right once the board is one
       column. */
    padding-right: 0;
    border-right: 0;
    gap: 20px;
  }

  .uc-board__tablist {
    flex-direction: row;
    gap: 6px;
    border-bottom: 1px solid var(--ap-border);
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding-bottom: 2px;
    /* Bleed to the card's edges so it reads as scrollable rather than
       clipped mid-tab. */
    margin: 0 -22px;
    padding-left: 22px;
    padding-right: 22px;
    /* width stays the 100% the base rule sets - overriding it here
       would let this shrink-to-fit its tabs instead of staying
       pinned to the card's width, and overflow-x needs that fixed
       width to have anything to scroll within. */
  }

  .uc-board__tablist::-webkit-scrollbar {
    display: none;
  }

  .uc-tab {
    width: auto;
    flex-shrink: 0;
    /* Same optical trim as the desktop rule above, scaled down. */
    padding: 9px 14px 9px 11px;
    font-size: 13px;
    white-space: nowrap;
  }
}

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

  .ai-platform .uc-pane__title {
    font-size: 21px;
  }
}


/* ------------------------------------------------------------------------
   BUILT FOR THE TOUCHPOINTS THAT MATTER MOST - rebuilt to match a
   supplied reference screenshot as closely as possible rather than
   the site's own visual language: a roughly even left/right split
   header (headline, then a supporting line), then a left column of
   accordion items (title, and for the active one only, a paragraph)
   over a right column holding a light-gray rounded panel with a
   white "chat" card inside it, plus a floating "Voice chat" badge
   overlapping the panel's corner. See
   includes/ai-platform/sections/agent-touchpoints.php for the copy
   and why it is what it is.

   Departs from this file's usual conventions in a few places because
   the reference does: the two-tone gray/white card nesting has no
   equivalent elsewhere on the site (every other card here is a
   single layer), and the header/board columns are near-equal rather
   than a narrow fixed rail beside a fluid column like .uc-board
   above it.
   ------------------------------------------------------------------------ */
.tp-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 64px;
  align-items: start;
  margin-bottom: 48px;
}

/* Standard tracking, not the -0.032em every other big heading in this
   file uses - the reference's headline sits noticeably looser than
   this site's own type. Wraps at two words per the reference's own
   line break, forced with a <br> rather than a max-width, since the
   break point ("touchpoints" / "that matter most") does not fall
   naturally at any width this column is likely to be. */
.ai-platform .tp-top__title {
  font-size: clamp(30px, 3.4vw, 40px);
  font-weight: 500;
  letter-spacing: normal;
  line-height: 1.18;
  color: var(--ap-text);
}

/* Dark, not muted - the reference's supporting line reads at close to
   full text strength, distinctly darker than .tp-item__desc below,
   even though both are "supporting copy" in the site's own voice. */
.tp-top__sub {
  font-size: 17px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ap-text);
  max-width: 34em;
  /* Lines up with the headline's cap-height, not its full block. */
  padding-top: 4px;
}

.tp-board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 64px;
  align-items: start;
}

/* --- Left: accordion list ---
   No dividers between items, no chevron on the button - the
   reference tells collapsed from active by color alone, nothing
   else. */
.tp-list {
  display: flex;
  flex-direction: column;
  gap: 38px;
}

.tp-item__toggle {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font-family: inherit;
  cursor: pointer;
  font-size: 25px;
  font-weight: 400;
  letter-spacing: normal;
  line-height: 1.3;
  /* Collapsed title color, as specified. */
  color: #A59F97;
  transition: color var(--ap-fast);
}

/* Active title color, as specified - dark, the site's standard text
   ink, same token .uc-head__title and every other heading in this
   system uses for "this is the important one". */
.tp-item.is-active .tp-item__toggle {
  color: var(--ap-text);
}

/* A hover cue only on the collapsed ones - the active title is
   already at full strength, so hovering it has nothing useful to
   move toward. */
.tp-item:not(.is-active) .tp-item__toggle:hover {
  color: var(--ap-ink);
}

.tp-item__toggle:focus-visible {
  outline: 2px solid var(--ap-ink);
  outline-offset: 3px;
  border-radius: 2px;
}

.tp-item__panel {
  margin-top: 14px;
}

.tp-item__desc {
  font-size: 16px;
  line-height: 1.65;
  /* Paragraph color, as specified. */
  color: #777169;
  max-width: 30em;
}

/* Mobile-only copy of the active item's chat - see .tp-stage below
   for why this exists as a second copy rather than the same element
   moved around. Hidden above the board's breakpoint, where the stage
   column does this job instead. */
.tp-item__chat-inline {
  display: none;
}

/* --- Right: the chat stage ---
   Holds one .tp-chat per item, but only the active one is ever not
   [hidden] - the browser's default "[hidden] { display: none }" rule
   is what keeps the inactive ones from taking any space or ever
   being seen, the same mechanism .uc-pane already relies on. No
   positioning trick needed to "stack" them: at most one is ever
   actually in flow. */
.tp-stage {
  display: flex;
  justify-content: center;
}

.tp-chat {
  display: flex;
  justify-content: center;
  width: 100%;
}

/* Setting any display above beats the UA sheet's own
   "[hidden] { display: none }" on specificity, which is what was
   keeping the four inactive copies out of the layout - without this
   they all render at once, side by side. */
.tp-chat[hidden] {
  display: none;
}

/* The soft panel the card sits on, measured off the reference
   (rgb(245,243,241), 24px radius, no border). Roughly square there,
   with the card centred in it and a generous margin all round - the
   panel is sized by the column, not by the card. */
.tp-stage-outer {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 520px;
  aspect-ratio: 1 / 1;
  max-height: 480px;
  background: rgb(245, 243, 241);
  border-radius: 24px;
  border: 1px solid #E5E5E5;
}

/* Tall and narrow (2:3, like a phone screen) rather than the wide
   landscape shape most chat mockups use - the reference's own
   proportion, carried over rather than adapted. */
.tp-chat__card {
  display: flex;
  flex-direction: column;
  width: 272px;
  max-width: calc(100% - 48px);
  aspect-ratio: 2 / 3;
  max-height: 408px;
  background: #FFFFFF;
  border-radius: 28.8px;
  padding: 14px;
  box-shadow:
    0 0 0.9px rgba(0, 0, 0, 0.4),
    0 1.8px 1.8px rgba(0, 0, 0, 0.04);
}

.tp-chat__header {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 11px;
  padding-bottom: 6px;
}

/* Holds the speaking agent's own icon. This was a dark gradient
   sphere while the card carried the reference's generic bot, which
   had a photographic avatar there and no equivalent asset here; now
   that each situation names a real agent, its real icon belongs in
   the circle. Neutral tint rather than the agent's accent colour -
   the icons are already full-colour illustrations and a tinted
   ground behind them muddied both. */
.tp-chat__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  flex-shrink: 0;
  background: #F3F2EF;
}

.tp-chat__avatar .ai-icon-img {
  width: 26px;
  height: 26px;
}

.tp-chat__agent-name {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  color: #000000;
}

/* The clipped window the conversation scrolls inside. */
.tp-chat__log {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* White-to-transparent wash across the top of the log, so a message
   pushed up out of view dissolves into the card instead of being
   sliced off at a hard edge. Sits above the messages, below nothing
   else - it is purely decorative and must never take a click. */
.tp-chat__fade {
  position: absolute;
  inset: 0 0 auto 0;
  height: 56px;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg,
    #FFFFFF 0%,
    rgba(255, 255, 255, 0.98) 16%,
    rgba(255, 255, 255, 0) 100%);
}

/* Bottom-anchored, so the newest message sits at the bottom and the
   stack grows upward - the reference's own behaviour, and what makes
   older messages ride up under the fade as new ones arrive. */
.tp-chat__messages {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  min-height: 100%;
}

.tp-chat__bubble {
  margin: 0;
  font-size: 13px;
  /* 18px flat, not a ratio - the reference computes to exactly
     13px/18px and a 1.4 multiplier lands on 18.2px. */
  line-height: 18px;
  padding: 14px;
}

/* The visitor's message - the only one of the two bubble types that
   gets a visible fill. The radius is asymmetric on purpose: the
   small corner is the "tail," pointing toward the side this bubble
   sits on (top-right, since this one is right-aligned). */
.tp-chat__bubble--user {
  align-self: flex-end;
  /* The reference caps this bubble at 15rem inside a row that is
     itself capped at 90% of the card's inner width. */
  max-width: min(240px, 90%);
  width: fit-content;
  background: rgba(235, 232, 228, 0.8);
  border: 1px solid rgba(0, 0, 0, 0.07);
  border-radius: 21px 7.2px 21px 21px;
  color: rgb(119, 113, 105);
}

/* The agent's reply - no bubble at all in the reference, just black
   text at the same size as the visitor's message. Only the tool-
   status pills carry a visible container on the agent's side. */
.tp-chat__bubble--agent {
  align-self: flex-start;
  max-width: 90%;
  color: #000000;
}

/* Small "tool used" chip either side of the reply.
   display: flex (not inline-flex) + width: fit-content, not
   inline-flex alone - without a block-level display this sits in
   normal inline flow next to whatever follows it instead of
   stacking under it. */
.tp-chat__pill {
  display: flex;
  align-self: flex-start;
  width: fit-content;
  align-items: center;
  gap: 8px;
  padding: 4px 14px 4px 4px;
  border-radius: 999px;
  background: #FFFFFF;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.08),
    0 1.7px 3.4px rgba(0, 0, 0, 0.04);
  font-size: 12.5px;
  font-weight: 400;
  color: #000000;
}

.tp-chat__pill-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  flex-shrink: 0;
  background: #E5E5E5;
  color: #000000;
}

.tp-chat__pill-icon svg {
  width: 8px;
  height: 8px;
}

/* Same pill treatment as .tp-chat__pill - the reference draws its
   typing indicator as one more small white chip, not bare dots
   floating in the card. Unlike the pills it is transient: it shows
   while the agent is "thinking" and the reply replaces it. */
.tp-chat__typing {
  display: flex;
  align-self: flex-start;
  width: fit-content;
  align-items: center;
  gap: 4px;
  padding: 10px 14px;
  border-radius: 999px;
  background: #FFFFFF;
  box-shadow:
    0 0 0 0.5px rgba(0, 0, 0, 0.08),
    0 1.7px 3.4px rgba(0, 0, 0, 0.04);
}

/* Warm grey rather than the reference's black: at this size solid
   black dots read as three hard specks and pull more attention than
   a "still thinking" cue should. This sits between the body copy
   (#777169) and the collapsed item titles (#A59F97) in the section's
   own palette, so it recedes without disappearing.

   5px with a 4px gap, up slightly from 4/3 - the tighter setting
   merged into a dash at a glance instead of reading as three
   separate dots. */
.tp-chat__typing span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  color: #8A847B;
  animation: tp-typing-bounce 1.4s infinite ease-in-out;
}

.tp-chat__typing span:nth-child(2) {
  animation-delay: 0.18s;
}

.tp-chat__typing span:nth-child(3) {
  animation-delay: 0.36s;
}

/* A shallower lift and a wider opacity swing than before: most of
   the movement now reads as the dots brightening in sequence rather
   than hopping, which is the calmer, more considered version of the
   same idea. The long tail from 55% to 100% is the rest between
   waves - without it the three dots never settle and the whole chip
   fidgets. */
@keyframes tp-typing-bounce {
  0%, 55%, 100% {
    transform: translateY(0);
    opacity: 0.32;
  }
  28% {
    transform: translateY(-2.5px);
    opacity: 1;
  }
}

/* --- The looping conversation ---
   initTouchpoints() drives this: .is-playing means JS has taken
   over, and every step starts hidden and is added back one at a
   time, then the whole thing clears and replays. Without JS
   .is-playing is never set and the full conversation is simply
   there, which is also what the card rests on between loops. */
.tp-chat.is-playing [data-tp-chat-step],
.tp-chat.is-playing [data-tp-chat-typing] {
  display: none;
}

/* The pop scales out of the corner the message actually arrives
   from, not its middle. Vertically that is always the bottom edge -
   messages land at the bottom of the wall and the stack grows
   upward - so the only thing that varies is the horizontal half,
   which follows each message's own alignment: left-aligned ones
   (the agent's reply, both tool pills, the typing chip) grow from
   their bottom-left, and the one right-aligned message overrides to
   bottom-right below. A centred origin made every message inflate
   outward from its own middle, which reads as a zoom rather than as
   something emerging from where it entered. */
.tp-chat.is-playing [data-tp-chat-step].is-in,
.tp-chat.is-playing [data-tp-chat-typing].is-in {
  display: flex;
  transform-origin: 0% 100%;
  animation: tp-msg-in 440ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* The visitor's message is the only one sitting on the right, so it
   is the only one that grows out of its bottom-right corner. */
.tp-chat.is-playing .tp-chat__bubble--user.is-in {
  transform-origin: 100% 100%;
}

.tp-chat.is-playing p[data-tp-chat-step].is-in {
  display: block;
}

/* The pop-in, taken from the reference's own starting values: it
   stages each message at scale(0.3), rotate(1deg), opacity ~0 and
   springs it to rest. The 1deg tilt is what stops the scale reading
   as a purely mechanical zoom, and the overshoot in the timing
   function above is the bounce - it carries slightly past full size
   before settling, rather than easing flatly into it.

   Opacity is done by 45% so the message is fully solid while the
   scale is still settling; fading for the whole 440ms would read as
   sluggish against the bounce. */
@keyframes tp-msg-in {
  0% {
    opacity: 0;
    transform: scale(0.3) rotate(1deg);
  }
  45% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

/* Whatever is already on the wall slides up to make room, rather
   than snapping to its new spot. initTouchpoints() measures each
   message before and after the new one is added and hands the
   difference to this transition (a FLIP) - see showStep() there. */
.tp-chat.is-playing .tp-chat__messages > .is-in.is-shifting {
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Clearing the wall at the end of a loop. Without this the whole
   conversation blinks out in one frame, which is the one moment the
   card looked mechanical - everything else about it eases. The exit
   is quicker and flatter than the entrance on purpose: arriving
   should draw the eye, leaving should not. Higher specificity than
   the pop-in rule above so it takes over the animation slot rather
   than fighting it. */
.tp-chat.is-playing [data-tp-chat-step].is-in.is-out,
.tp-chat.is-playing [data-tp-chat-typing].is-in.is-out {
  animation: tp-msg-out 260ms cubic-bezier(0.4, 0, 1, 1) both;
}

@keyframes tp-msg-out {
  from {
    opacity: 1;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(0.96);
  }
}

/* Switching items on the left swaps the whole card underneath. That
   was a hard cut; this gives the incoming one a short settle so the
   two reads as one card changing rather than two cards blinking.

   A keyframe rather than a transition, deliberately: going from
   display:none to visible restarts a CSS animation on its own, so
   this needs no class toggling and, more to the point, no JS
   cleanup. The first version drove it from a class removed on the
   next animation frame, which left the card stuck invisible
   whenever requestAnimationFrame was throttled - backgrounded tab,
   reduced-power mode - because the frame that cleared it never
   came. */
.tp-chat__card {
  animation: tp-card-in 280ms ease-out both;
}

@keyframes tp-card-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* The typing chip is never part of the resting state - it only ever
   shows mid-loop, so it stays hidden when JS is not running. */
.tp-chat:not(.is-playing) [data-tp-chat-typing] {
  display: none;
}

/* initTouchpoints() already declines to run the loop at all under
   this setting, so the card just shows the finished conversation.
   These are the belt-and-braces half: every piece of motion the
   card can produce is neutralised here, so nothing animates even if
   a class is left behind by a run that was in flight when the
   setting changed. */
@media (prefers-reduced-motion: reduce) {
  .tp-item__toggle {
    transition: none;
  }
  .tp-chat__typing span {
    animation: none;
  }
  .tp-chat.is-playing [data-tp-chat-step].is-in,
  .tp-chat.is-playing [data-tp-chat-typing].is-in,
  .tp-chat.is-playing [data-tp-chat-step].is-in.is-out,
  .tp-chat.is-playing [data-tp-chat-typing].is-in.is-out {
    animation: none;
  }
  .tp-chat.is-playing .tp-chat__messages > .is-in.is-shifting {
    transition: none;
  }
  .tp-chat__card {
    animation: none;
  }
}

/* Same 780px several other two-column sections on this page collapse
   at. */
@media (max-width: 780px) {
  .tp-top {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
    margin-bottom: 36px;
  }

  .tp-top__sub {
    padding-top: 0;
    max-width: none;
  }

  .tp-board {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  /* The stage column's job - showing the active item's chat - moves
     to the inline copy inside each panel, since there is no side
     column left to put it in. */
  .tp-stage {
    display: none;
  }

  .tp-item__chat-inline {
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }
}


/* ------------------------------------------------------------------------
   INDUSTRIES WE SERVE - the ten industries three to a row, styled
   after the supplied reference (Perplexity's "On demand sessions"
   list): a hairline over each cell, the name as the heading, a small
   icon + count line, an overlapping avatar stack with names beside
   it, and a dark pill on the last line. Replaced how-it-works-v2.php
   in this slot. See sections/industries.php for what each part of the
   reference maps onto here.
   ------------------------------------------------------------------------ */
.ind-head {
  margin-bottom: 44px;
}

.ai-platform .ind-head__title {
  font-size: clamp(28px, 3.2vw, 38px);
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.15;
  color: var(--ap-text);
  margin-bottom: 12px;
}

.ind-head__sub {
  font-size: 17px;
  font-weight: 400;
  line-height: 1.55;
  color: #777169;
  max-width: 46ch;
}

/* A fixed three-up, per request, rather than the auto-fit the earlier
   tile version used: the hairline over each cell only reads as the
   reference's ruled list if the rules line up into continuous rows,
   which an auto-fit track count cannot guarantee. Ten cells over
   three columns leaves a single cell on the last row - that is what
   the reference does too, and it is why the row gap is large enough
   for the rules to read as separators rather than as a table. */
.ind-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 34px;
  row-gap: 40px;
}

/* Cells stretch to the tallest in their row, so pushing the avatar
   block down with margin-top:auto lines the avatars and the pills up
   across a row even when one title wraps to two lines. */
.ind-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding-top: 22px;
  border-top: 1px solid var(--ap-border-strong);
}

.ai-platform .ind-card__title {
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.3;
  color: var(--ap-text);
  margin: 0;
}

.ind-card__meta {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 10px 0 0;
  font-size: 13.5px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--ap-text-secondary);
}

.ind-card__meta-icon {
  display: inline-flex;
  color: var(--ap-text-secondary);
}

.ind-card__meta-icon .ai-icon {
  width: 15px;
  height: 15px;
}

.ind-card__agents {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: auto;
  padding-top: 30px;
}

.ind-card__avatars {
  display: inline-flex;
  flex-shrink: 0;
}

/* The white ring is what separates one avatar from the next where
   they overlap, so it is a border on the circle rather than an
   outline - an outline sits outside the element and would be painted
   over by the neighbour stacked on top of it. */
.ind-card__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid #e9e9e9;
  background: #F4F2F0;
  box-sizing: border-box;
}

.ind-card__avatar + .ind-card__avatar {
  margin-left: -11px;
}

.ind-card__names {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--ap-text-secondary);
}

/* Scoped under .ai-platform so it outranks the sitewide
   '.ai-platform a { color: inherit }', which is one class more
   specific than a bare .ind-card__cta and would otherwise leave the
   label the same near-black as the pill behind it. */
.ai-platform .ind-card__cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 18px;
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--ap-ink-dark);
  color: var(--ap-white);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  transition: background-color var(--ap-fast);
  display: none;
}

.ai-platform .ind-card__cta:hover {
  background: var(--ap-ink-deepest);
}

.ind-card__cta-arrow {
  display: inline-block;
  transition: transform var(--ap-fast);
}

.ai-platform .ind-card__cta:hover .ind-card__cta-arrow {
  transform: translateX(2px);
}

@media (max-width: 1000px) {
  .ind-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 28px;
    row-gap: 34px;
  }
}

@media (max-width: 640px) {
  .ind-head {
    margin-bottom: 30px;
  }

  /* One per row below this: at two-up the card is narrow enough that
     the agent names wrap past the avatars and the pill is left alone
     on a third line. */
  .ind-grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 26px;
  }

  .ind-card {
    padding-top: 18px;
  }

  .ai-platform .ind-card__title {
    font-size: 18.5px;
  }

  .ind-card__agents {
    padding-top: 20px;
  }

  .ai-platform .ind-card__cta {
    margin-top: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ai-platform .ind-card__cta,
  .ind-card__cta-arrow {
    transition: none;
  }

  .ai-platform .ind-card__cta:hover .ind-card__cta-arrow {
    transform: none;
  }
}

/* ------------------------------------------------------------------------
   MARKET SEGMENTS - dark, two-column and editorial, per the supplied
   reference: a light heading over a large list of industries on the
   left, a stack of three captioned photo cards on the right. Selecting
   an industry rolls the stack (see ai-platform.js:initSegments).
   Replaced a grid of bordered icon+label tiles.
   ------------------------------------------------------------------------ */
.ap-segments {
  background: #0F0F0E;
  padding-top: 104px;
  padding-bottom: 104px;
}

.ap-segments__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.7fr);
  gap: 72px;
  align-items: start;
}

.ai-platform .ap-segments__heading {
  max-width: 18ch;
  font-size: clamp(36px, 4.4vw, 58px);
  font-weight: 300;
  line-height: 1.14;
  letter-spacing: -0.03em;
  color: #FFFFFF;
  margin-bottom: 68px;
}

/* Caps the list at ~5-6 items tall (tuned to the item font-size
   above); the rest scroll into view rather than stretching the
   section to fit all ten industries. */
.ap-segments__list {
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  max-height: 400px;
  overflow-y: auto;
  padding-right: 16px;
  margin-right: -16px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
}

.ap-segments__list::-webkit-scrollbar {
  width: 5px;
}

.ap-segments__list::-webkit-scrollbar-track {
  background: transparent;
}

.ap-segments__list::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.28);
  border-radius: 999px;
}

.ap-segments__list::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.5);
}

/* Serif, against this site's Inter everywhere else. The reference sets
   this list in a serif and it is the most distinctive part of the
   look; a system stack keeps it free (no webfont request) since the
   project self-hosts only Inter. Swap the stack for `inherit` to put
   it back on Inter.

   Scoped with .ai-platform to outrank `.ai-platform button {
   font-family: inherit }` near the top of this file - at a bare
   class the reset won and this list rendered in Inter. */
.ai-platform .ap-segments__item {
  display: block;
  padding: 4px 0;
  border: 0;
  background: transparent;
  font-family: Georgia, 'Times New Roman', Times, serif;
  font-size: clamp(28px, 3.4vw, 42px);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: -0.01em;
  text-align: left;
  /* Muted warm grey, so the selected one reads as lit by contrast
     rather than the rest reading as disabled. */
  color: rgba(255, 255, 255, 0.42);
  cursor: pointer;
  transition: color var(--ap-fast);
}

.ap-segments__item:hover {
  color: rgba(255, 255, 255, 0.72);
}

.ap-segments__item.is-active {
  color: #FFFFFF;
  /* Underline via a border, not text-decoration, so the rule sits
     clear of the descenders in "Hospitality" and "Legal". */
  border-bottom: 1px solid rgba(255, 255, 255, 0.9);
}

.ap-segments__item:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 4px;
}

/* --- Photo stack ---
   .ap-segments__stack is the masked viewport: a fixed-height window,
   clipped, with a fade at the top and bottom edge so cards look like
   they are scrolling through a frame rather than just stacked.
   .ap-segments__track is the thing that actually moves - it holds
   the segment list twice back to back (see the PHP), so animating
   it from translateY(0) to translateY(-50%) loops with no seam: the
   second copy lines up exactly where the first one started. */
.ap-segments__stack {
  position: relative;
  width: 100%;
  max-width: 360px;
  margin-left: auto;
  height: 752px;
  overflow: hidden;
  border-radius: 14px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
}

.ap-segments__stack:hover .ap-segments__track {
  animation-play-state: paused;
}

.ap-segments__track {
  display: flex;
  flex-direction: column;
  gap: 16px;
  animation: ap-segments-scroll 34s linear infinite;
}

.ap-segments__track.is-jumping {
  animation-play-state: paused;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes ap-segments-scroll {
  from {
    transform: translateY(0);
  }
  to {
    /* Exactly one copy of the (doubled) list tall. */
    transform: translateY(-50%);
  }
}

.ap-segments__card {
  position: relative;
  flex: 0 0 auto;
  margin: 0;
  overflow: hidden;
  border-radius: 14px;
  background: #1D1C1B;
  aspect-ratio: 3 / 2;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.42);
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.45s ease;
}

.ap-segments__card:hover {
  transform: scale(1.08);
  z-index: 2;
  box-shadow: 0 28px 64px rgba(0, 0, 0, 0.58);
}

.ap-segments__card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Caption sits on the photo, so it needs its own scrim rather than
   relying on whatever happens to be behind it. */
.ap-segments__card::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(14, 13, 12, 0.82) 0%, rgba(14, 13, 12, 0) 100%);
  pointer-events: none;
}

.ap-segments__caption {
  position: absolute;
  left: 16px;
  bottom: 13px;
  z-index: 1;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: #FFFFFF;
}

@media (prefers-reduced-motion: reduce) {
  .ap-segments__item {
    transition: none;
  }

  .ap-segments__track {
    animation: none;
  }
}

@media (max-width: 1000px) {
  .ap-segments__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 44px;
  }

  .ai-platform .ap-segments__heading {
    max-width: none;
    margin-bottom: 40px;
  }

  .ap-segments__list {
    max-height: 320px;
  }

  /* Side by side once the column is full width - three stacked 3:2
     cards would run past 900px tall on their own. The marquee is a
     desktop flourish; here the (single, non-duplicated) cards just
     sit in a static row. */
  .ap-segments__stack {
    max-width: none;
    height: auto;
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .ap-segments__track {
    flex-direction: row;
    gap: 14px;
    animation: none;
    transform: none;
  }

  .ap-segments__card.is-duplicate {
    display: none;
  }

  .ap-segments__card {
    flex: 1 1 0;
    min-width: 0;
  }
}

@media (max-width: 620px) {
  .ap-segments {
    padding-top: 72px;
    padding-bottom: 72px;
  }

  .ap-segments__track {
    /* Back to a column, but the cards go landscape so three of them
       still fit a phone screen without endless scrolling. */
    flex-direction: column;
  }

  .ap-segments__card {
    /* Undo the `flex: 1 1 0` set for the side-by-side row above.
       Back in a column that basis of 0 gave every card zero
       height - the whole stack collapsed to 28px - because there
       is no fixed container height for flex-grow to divide up.
       auto lets the aspect-ratio determine the height again. */
    flex: 0 0 auto;
    aspect-ratio: 16 / 9;
  }
}

/* ------------------------------------------------------------------------
   SEGMENT GROUPS (Ecosystem section - "segments across sectors")
   ------------------------------------------------------------------------ */
/* 2 columns, not a full-width stack: at full width, a category with
   only 2-4 pills (Career AI, Marketplace & Social AI) left a huge
   stretch of empty space next to its short pill row. The category
   order (2, 4, 11, 16 agents) also happens to pair up nicely here -
   the two small categories share a row, the two large ones share
   the row below, so paired cards stay reasonably close in height. */
.segment-groups {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
  align-items: start;
}

.segment-group {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 28px;
  box-shadow: var(--ap-shadow-sm);
}

.segment-group__head {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-bottom: 20px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--ap-border);
}

/* Per-category color via --icon-color - see the comment on
   .agent-card__icon above, the same treatment. */
.segment-group__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  border-radius: 15px;
  background:
    linear-gradient(140deg,
      rgb(var(--icon-color-2, 90 88 86) / 0.3) 0%,
      rgb(var(--icon-color, 25 24 23) / 0.15) 100%);
  color: rgb(var(--icon-color, 25 24 23));
  box-shadow:
    inset 0 0 0 1px rgb(var(--icon-color, 25 24 23) / 0.16),
    inset 0 1px 0 rgb(255 255 255 / 0.55),
    0 6px 16px -8px rgb(var(--icon-color, 25 24 23) / 0.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  flex-shrink: 0;
}

.segment-group__icon .ai-icon {
  width: 27px;
  height: 27px;
}

.segment-group__heading {
  flex: 1;
  min-width: 0;
}

.segment-group__name {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin-bottom: 3px;
}

.segment-group__desc {
  font-size: 13.5px;
  color: var(--ap-text-secondary);
}

.segment-group__count {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 12px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-soft);
  border: 1px solid var(--ap-border);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  white-space: nowrap;
}

.segment-group__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.segment-pill {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-soft);
  border: 1px solid var(--ap-border);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ap-text);
  transition: background var(--ap-fast), border-color var(--ap-fast), color var(--ap-fast);
}

.segment-pill:hover {
  background: var(--ap-ink-tint-10);
  border-color: var(--ap-ink-dark);
  color: var(--ap-ink-dark);
}

/* Distinguishes the "+N more" link from an actual agent-name pill -
   solid ink-dark fill instead of the neutral soft-gray the name
   pills use. Scoped with .ai-platform so this outranks the
   `.ai-platform a { color: inherit }` reset (a single class alone
   loses to class+element on specificity) - without it, this anchor's
   white text would resolve to the inherited dark text color instead. */
.ai-platform .segment-pill--more {
  background: var(--ap-ink-tint-10);
  border-color: var(--ap-border);
  color: var(--ap-ink-dark);
}

.ai-platform .segment-pill--more:hover {
  background: rgba(23, 30, 38, 0.16);
  border-color: var(--ap-ink-dark);
  color: var(--ap-ink-dark);
}

/* Scoped with .ai-platform for the same reason as .segment-pill--more
   above - here the color difference is negligible (--ap-ink-dark vs
   the inherited --ap-text are nearly identical), but scoping correctly
   from the start avoids relying on that coincidence. */
.ai-platform .segment-group__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  height: 35px;
  padding: 0 15px;
  border-radius: 8px;
  background: var(--ap-ink-dark);
  font-size: 12px;
  font-weight: 700;
  color: var(--ap-white);
  transition: background var(--ap-fast), transform var(--ap-fast);
}

.ai-platform .segment-group__link:hover {
  background: var(--ap-ink-deepest);
  transform: translateY(-1px);
}

@media (max-width: 768px) {
  .segment-groups {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   ECOSYSTEM CARDS - editorial photo cards (used by
   ecosystem-cards.php / index.php; ecosystem.php / index-warm.php keep
   the .segment-group pill layout untouched). One card per category:
   a rounded photograph with the title and description below it on the
   section's own background - no box, border, shadow or scrim.
   Replaced a dark tile that laid the copy over the photo on a
   gradient; the copy is easier to read off the page than off an
   image, and the photograph reads as a photograph.
   ------------------------------------------------------------------------ */
/* The section reads as one large rounded panel on the page rather
   than an unbounded band - the radius is what separates it from the
   white sections above and below it. No overflow:hidden: the cards
   inside cast hover shadows that would get clipped, and the radius
   does not need it since the fill is on the section itself. */
.ap-ecosystem {
  /*background: var(--ap-eco-bg);*/
  background:#F4F3EF;
  border-radius: 50px 50px 0 0;
  /* More than the shared --ap-section-pad-y (72px). Because this
     section carries a fill and a 50px radius it reads as a panel,
     and a panel needs more inset than a plain band - at 72px the
     content sat close to the rounded corners. Scoped here so the
     other .ap-section bands keep the shared value. */
  padding-top: 108px;
  padding-bottom: 108px;
}

@media (max-width: 768px) {
  /* --ap-section-pad-y drops to 48px here; keep this panel
     proportionally roomier than that without going to 108px. */
  .ap-ecosystem {
    padding-top: 72px;
    padding-bottom: 72px;
  }
}

/* Left-aligned (the section passes align="left"), and narrower than
   the shared 700px measure: the reference stacks a bold two-line
   heading over a two-line subtitle hard left above the cards, which
   needs a tighter measure than a centred header to break that way.
   Scoped here because the ~20 other headers sharing this component
   are centred and different lengths.

   Measures are set on the heading and body individually below - the
   reference runs the subtitle wider than the heading, so a single
   max-width on the block cannot produce both breaks. */
.ap-ecosystem .section-header {
  max-width: none;
  /* Reference: ~68px between the subtitle's last line and the top of
     the photos, against the shared component's 36px. This margin is
     the space under the description - the description is the header
     block's last child. */
  margin-bottom: 66px;
}

/* 37px/800 at desktop, tracking pulled in - in the reference this
   heading is the loudest thing in the section and noticeably heavier
   than the site's other section headings. The measure is what breaks
   it after "sectors.", matching the reference's two lines. */
.ai-platform .ap-ecosystem .section-heading {
  max-width: 520px;
  font-size: clamp(36px, 3.4vw, 48px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.022em;
  color: #422f2f;
  margin-bottom: 18px;
}

.ap-ecosystem .section-body {
  max-width: 600px;
  font-size: 18px;
  line-height: 1.7;
  color: var(--ap-text);
}

/* Three cards visible at a time, sliding horizontally - there are
   four categories, so the row auto-advances one card at a time (see
   ai-platform.js:initEcoCarousel). The viewport clips; the track
   inside it is what moves.

   --eco-gap is the channel between cards. It is a custom property
   because both the card's flex-basis and the JS step distance are
   derived from it, and the breakpoints below change it. */
.eco-carousel {
  --eco-gap: 38px;
  overflow: hidden;
}

.eco-carousel__track {
  display: flex;
  gap: var(--eco-gap);
  /* Set by the JS on each advance. The easing is a long, soft
     decelerate so the set glides to rest rather than snapping. */
  transform: translate3d(0, 0, 0);
  transition: transform 900ms cubic-bezier(0.22, 0.61, 0.24, 1);
  will-change: transform;
}

/* No transition while the loop wraps - the JS adds this class, jumps
   the track back a full set (where the clones sit in exactly the
   slots the originals started in, so nothing moves on screen), then
   removes it. */
.eco-carousel__track.is-resetting {
  transition: none;
}

/* Exactly three per view: the three cards plus the two channels
   between them fill the viewport's width. */
.eco-carousel .eco-card {
  flex: 0 0 calc((100% - 2 * var(--eco-gap)) / 3);
  min-width: 0;
}

/* Not a tile: a photo with copy under it. No background, border,
   radius or shadow on the card itself - only .eco-card__media is
   drawn. */
.eco-card {
  display: block;
}

.eco-card__media {
  display: block;
  position: relative;
  overflow: hidden;
  /* Reference: a small radius on the photo, ~8px at a 380px-wide
     card - not the 14-16px the site's other cards use. */
  border-radius: 8px;
  /* Slightly deeper than the reference's 16/9 (380x211). */
  aspect-ratio: 16 / 10;
  background: var(--ap-light-gray);
  /* Own stacking context, so the scaling photo inside can never paint
     over a neighbouring card. */
  isolation: isolate;
}

.eco-card__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Knocked back, so the photos sit behind the copy rather than
     competing with it. */
  filter: brightness(0.7);
  /* Slow push-in on hover, same easing family as the hero slideshow's
     drift so the two read as one motion language. */
  transition: transform 620ms cubic-bezier(0.2, 0, 0.2, 1);
}

.eco-card:hover .eco-card__photo {
  transform: scale(1.05);
}

/* Scoped with .ai-platform to outrank the generic
   `.ai-platform h1, h2, h3, h4 { color: var(--ap-text) }` rule.
   22px/800 with a ~1.3 leading and ~22px above the photo - heavier
   than the reference's own card titles. */
.ai-platform .eco-card__title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.3;
  color: #422f2f;
  /*color: var(--ap-text);*/
  margin: 22px 0 12px;
  transition: color var(--ap-fast);
}

/* The card carries no "Explore ->" line, so the title lighting up is
   the affordance that says the whole card is a link. */
.ai-platform .eco-card:hover .eco-card__title {
  color: var(--ap-ink);
}

.eco-card__desc {
  font-size: 17px;
  line-height: 1.5;
  color: #4c4c4c;
  /* Exactly two lines, whatever the copy does. Three of the four
     descriptions fit on one line at desktop and the fourth wrapped
     to two, so the block under the photos sat at two different
     depths across the row. min-height reserves the second line for
     the short ones; the clamp stops a longer one (or a narrower
     card) running to three. Keep the 1.5 here in step with the
     line-height above, and in em so both follow the font-size the
     620px breakpoint sets. */
  min-height: calc(2 * 1.5em);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Keyboard focus has to be visible on a card whose only affordance is
   the card itself. Offset clears the photo's rounded corner. */
.eco-card:focus-visible {
  outline: 2px solid var(--ap-ink);
  outline-offset: 4px;
  border-radius: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .eco-card__photo,
  .ai-platform .eco-card__title,
  .eco-carousel__track {
    transition: none;
  }

  .eco-card:hover .eco-card__photo {
    transform: none;
  }
}

/* Two up. Three cards stop working before the band does - below
   ~1080px the photos are too small to read and the titles start
   breaking every other word. The JS reads the visible count off the
   card's own measured width, so it follows this on its own. */
@media (max-width: 1080px) {
  .eco-carousel {
    --eco-gap: 32px;
  }

  .eco-carousel .eco-card {
    flex-basis: calc((100% - var(--eco-gap)) / 2);
  }
}

/* One up, full width. */
@media (max-width: 620px) {
  .eco-carousel {
    --eco-gap: 24px;
  }

  .eco-carousel .eco-card {
    flex-basis: 100%;
  }

  .ai-platform .eco-card__title {
    font-size: 19px;
    margin-top: 18px;
  }

  .eco-card__desc {
    font-size: 15.5px;
  }
}

/* ------------------------------------------------------------------------
   MARKET SEGMENTS (replaced the Connected Ecosystem chain section)
   Compact, dense icon+name cards - deliberately no description/link,
   so 10 of them read as a single "we cover every industry" grid
   rather than a repeat of the fuller card language used elsewhere.
   ------------------------------------------------------------------------ */
/* No box, no border, no shadow, no icon chip - a plain icon + label
   row instead of a boxed card. 5 columns so 10 items land in exactly
   2 rows; a hairline bottom rule is the only structure, standing in
   for the card outline that used to separate each item. */
.segment-card-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 40px 24px;
}

.segment-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--ap-border);
}

.segment-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--ap-ink-dark);
  transition: color var(--ap-fast);
}

.segment-card:hover .segment-card__icon {
  color: var(--ap-ink-deepest);
}

.segment-card__icon .ai-icon {
  width: 26px;
  height: 26px;
}

.segment-card__name {
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ap-text);
  line-height: 2;
  transition: color var(--ap-fast);
}

.segment-card:hover .segment-card__name {
  color: var(--ap-ink-dark);
}

@media (max-width: 1024px) {
  .segment-card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 560px) {
  .segment-card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ------------------------------------------------------------------------
   MARKET SEGMENTS v2 (index.php only) - each segment as a bordered,
   hoverable card instead of .segment-card's plain icon+label row with
   only a bottom rule.
   ------------------------------------------------------------------------ */
.segment-tile-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
}

.segment-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 24px 14px;
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.segment-tile:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-ink);
}

.segment-tile__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink);
  transition: transform var(--ap-fast);
}

.segment-tile:hover .segment-tile__icon {
  transform: scale(1.08);
}

.segment-tile__icon .ai-icon {
  width: 21px;
  height: 21px;
}

.segment-tile__name {
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ap-text);
}

@media (max-width: 1024px) {
  .segment-tile-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 560px) {
  .segment-tile-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ------------------------------------------------------------------------
   CATEGORY GRID (kept on disk, not currently used by any section -
   the Ecosystem section above uses .segment-groups instead)
   ------------------------------------------------------------------------ */
.category-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.category-tile {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 32px 28px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
  display: flex;
  flex-direction: column;
}

.category-tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.category-tile__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

/* Per-agent/category color via --icon-color - see the comment on
   .agent-card__icon above, the same treatment. */
.category-tile__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 58px;
  height: 58px;
  border-radius: 17px;
  background:
    linear-gradient(140deg,
      rgb(var(--icon-color-2, 90 88 86) / 0.3) 0%,
      rgb(var(--icon-color, 25 24 23) / 0.15) 100%);
  color: rgb(var(--icon-color, 25 24 23));
  box-shadow:
    inset 0 0 0 1px rgb(var(--icon-color, 25 24 23) / 0.16),
    inset 0 1px 0 rgb(255 255 255 / 0.55),
    0 6px 16px -8px rgb(var(--icon-color, 25 24 23) / 0.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background var(--ap-fast), box-shadow var(--ap-fast);
}

.category-tile__icon .ai-icon {
  width: 31px;
  height: 31px;
}

/* Was rgba(23, 30, 38, 0.14) - a leftover blue-slate value from
   before every navy/blue-adjacent hue on the site was retired. Now
   just a stronger version of the icon's own tint. */
.category-tile:hover .category-tile__icon {
  background: linear-gradient(140deg,
      rgb(var(--icon-color-2, 90 88 86) / 0.42) 0%,
      rgb(var(--icon-color, 25 24 23) / 0.24) 100%);
}

.category-tile__count {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 12px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-soft);
  border: 1px solid var(--ap-border);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
}

.category-tile__name {
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin-bottom: 10px;
}

.category-tile__desc {
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  margin-bottom: 20px;
  line-height: 1.6;
  flex: 1;
}

.category-tile__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ap-ink-dark);
}

.link-arrow {
  display: inline-flex;
  transition: transform var(--ap-fast);
}

.link-arrow .ai-icon {
  width: 16px;
  height: 16px;
}

.category-tile__link:hover .link-arrow,
.agent-card__link:hover .link-arrow,
.usecase-card__answer:hover .link-arrow,
.segment-group__link:hover .link-arrow {
  transform: translateX(3px);
}

@media (max-width: 1024px) {
  .category-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  .category-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   AGENT CARDS (shared by dual-column, personal, business sections)
   ------------------------------------------------------------------------ */
.agent-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
  display: flex;
  flex-direction: column;
}

.agent-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

/* Per-agent color, set as --icon-color (an "R G B" triplet) on this
   element by ai_icon_style_attr() in PHP - see icons.php. Falls back
   to the same flat ink chip this was before if a key has no mapped
   color. The ring is a 1px outline in the icon's own color rather
   than a heavier shadow, so the chip reads as "tinted glass with a
   crisp edge" instead of a drop shadow floating off the card. */
.agent-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background:
    linear-gradient(140deg,
      rgb(var(--icon-color-2, 90 88 86) / 0.3) 0%,
      rgb(var(--icon-color, 25 24 23) / 0.15) 100%);
  color: rgb(var(--icon-color, 25 24 23));
  box-shadow:
    inset 0 0 0 1px rgb(var(--icon-color, 25 24 23) / 0.16),
    inset 0 1px 0 rgb(255 255 255 / 0.55),
    0 6px 16px -8px rgb(var(--icon-color, 25 24 23) / 0.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  margin-bottom: 16px;
}

.agent-card__icon .ai-icon {
  width: 26px;
  height: 26px;
}

.agent-card__name {
  font-size: 16.5px;
  margin-bottom: 8px;
}

.agent-card__desc {
  font-size: 14px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
  margin-bottom: 16px;
  flex: 1;
}

.agent-card__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ap-ink-dark);
}

.agent-card-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.agent-grid {
  display: grid;
  gap: 20px;
}

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

.agent-grid--business {
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

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

@media (max-width: 640px) {
  .agent-grid--2 {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 1024px) {
  .agent-grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .agent-grid--3,
  .agent-grid--business {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   DUAL COLUMN (Career + Marketplace & Social)
   ------------------------------------------------------------------------ */
.ap-dual__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
}

.ap-dual__col-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 24px;
}

.ap-dual__col-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  color: var(--ap-ink-dark);
}

.ap-dual__col-title {
  font-size: 20px;
}

@media (max-width: 900px) {
  .ap-dual__grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
}

/* ------------------------------------------------------------------------
   BUSINESS AI GROUPS
   ------------------------------------------------------------------------ */
.business-groups {
  display: flex;
  flex-direction: column;
  gap: 44px;
}

.business-group__label {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  margin-bottom: 18px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--ap-border);
}

/* ------------------------------------------------------------------------
   HOW IT WORKS
   Flexbox, not grid: the row has 7 DOM children (4 cards + 3
   connectors interleaved), and a `repeat(4, 1fr)` grid was placing
   those 7 items across 4 columns as auto-placement saw fit - wrapping
   the 4 steps into two misaligned rows with the connectors stretched
   to full card-width instead of sitting as a slim gap between them.
   Flex with cards at flex:1 and connectors at a small fixed width
   keeps everything on one row regardless of item count.
   ------------------------------------------------------------------------ */
.steps-row {
  display: flex;
  align-items: stretch;
}

.step-card {
  flex: 1 1 0;
  min-width: 0;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 26px 22px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast);
  display: flex;
  flex-direction: column;
}

.step-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
}

.step-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

.step-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
}

.step-card__icon .ai-icon {
  width: 19px;
  height: 19px;
}

/* A large, receding "ghost" numeral rather than a filled badge circle
   - reads as an editorial workflow annotation instead of the generic
   numbered-circle look the design brief calls out to avoid. */
.step-card__num {
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ap-border-strong);
}

.step-card__title {
  font-size: 16.5px;
  margin-bottom: 8px;
}

.step-card__desc {
  font-size: 14px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
  flex: 1;
}

.step-connector {
  flex: 0 0 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.step-connector__circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #e7e8e9;
  border: 1px solid var(--ap-border);
  color: var(--ap-ink-dark);
}

.step-connector__circle .ai-icon {
  width: 14px;
  height: 14px;
}

@media (max-width: 900px) {
  .steps-row {
    flex-direction: column;
    gap: 16px;
  }
  .step-connector {
    display: none;
  }
}

/* ------------------------------------------------------------------------
   HOW IT WORKS v2 (index.php only) - step markers sitting on one
   continuous connecting line instead of cards + small arrow
   connectors. The line sits at z-index 0 behind the markers; each
   marker's border is painted in the section's own surface color so it
   reads as a gap cut into the line, not a circle sitting on top of it.
   ------------------------------------------------------------------------ */
/* Four columns split by full-height hairlines, each with a large
   light-weight step numeral - the same language the stats band uses,
   so the two quiet light sections on this page read as one system.

   Replaced a horizontal timeline rule with a 56px filled numeral
   circle AND a 38px tinted icon tile per step. Two markers of
   competing weight for one step is one too many, and the rule ran
   edge-to-edge so it visibly overshot the first and last markers.

   $step['icon'] is no longer rendered: the numeral is the marker now,
   and a second glyph beside it was the redundancy being removed. The
   field stays in data.php because how-it-works.php (index-warm /
   index-black) still draws it. */
.how-timeline {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
}

.how-step {
  padding: 2px 26px;
  /* Hairline on every column including the first, matching .stat-item.
     A border rather than a positioned bar, so it spans the row's full
     height for free however the copy wraps. */
  border-left: 1px solid var(--ap-border-strong);
}

.how-step__num {
  display: block;
  font-size: clamp(30px, 3.2vw, 40px);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ap-text);
  /* Muted well down: it marks position, it is not the headline. At
     full strength a 40px numeral out-shouted the step title next to
     it. */
  opacity: 0.26;
  margin-bottom: 20px;
}

.ai-platform .how-step__title {
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: var(--ap-text);
  margin-bottom: 9px;
}

.how-step__desc {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ap-text-secondary);
}

@media (max-width: 900px) {
  /* Two up. The hairlines stay vertical, so the grid still reads as
     columns rather than becoming a stacked list. */
  .how-timeline {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 36px;
  }

  .how-step {
    padding: 2px 20px;
  }

  .how-step__num {
    margin-bottom: 14px;
  }
}

@media (max-width: 520px) {
  .how-timeline {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 28px;
  }
}
/* ------------------------------------------------------------------------
   CONNECTED ECOSYSTEM CHAINS
   ------------------------------------------------------------------------ */
.chain-list {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* Was var(--ap-soft) - identical to this section's own background,
   so the card had zero fill contrast and only its 1px border hinted
   it was a card at all. White + a shadow gives it real elevation,
   consistent with every other card on the page. */
.chain {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 28px;
  box-shadow: var(--ap-shadow-sm);
}

.chain__label {
  font-size: 14px;
  font-weight: 600;
  color: var(--ap-text-secondary);
  margin-bottom: 18px;
}

.chain__row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Now that .chain itself is white, these needed their own fill
   (--ap-soft, matching the section behind the card) so they still
   read as distinct chips instead of blending into the card. */
.chain-node {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--ap-soft);
  border: 1px solid var(--ap-border-strong);
  border-radius: var(--ap-radius-pill);
  padding: 7px 16px 7px 7px;
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
}

.chain-node__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  flex-shrink: 0;
}

.chain-node__icon .ai-icon {
  width: 13px;
  height: 13px;
}

.chain-arrow {
  display: inline-flex;
  color: var(--ap-ink-dark);
  flex-shrink: 0;
}

.chain-arrow .ai-icon {
  width: 16px;
  height: 16px;
}

@media (max-width: 640px) {
  .chain__row {
    flex-direction: column;
    align-items: flex-start;
  }
  .chain-arrow {
    transform: rotate(90deg);
  }
}

/* ------------------------------------------------------------------------
   USE CASES
   ------------------------------------------------------------------------ */
.usecase-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}

.usecase-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 26px 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.usecase-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

/* No background, box-shadow, or backdrop-filter - see the comment on
   .uc-card__icon, the same reasoning: this card is being migrated to
   a real downloaded photo per agent, which brings its own full color,
   and ai_agent_icon_html() renders nothing at all for an agent that
   doesn't have one yet, so the empty 48x48 box is a plain blank
   space rather than a tinted swatch with nothing inside it. */
.usecase-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-bottom: 18px;
}

.usecase-card__icon .ai-icon {
  width: 26px;
  height: 26px;
}

/* Left accent rule marks this as the "asked" line, distinct from the
   resolved-answer pill below it - was plain bold text with nothing to
   visually separate the question from the answer. */
.usecase-card__question {
  font-size: 15px;
  font-weight: 700;
  color: var(--ap-text);
  line-height: 1.45;
  padding-left: 12px;
  border-left: 2px solid var(--ap-border-strong);
  margin-bottom: 22px;
  flex: 1;
}

/* Scoped with .ai-platform so the white label/icon outrank the
   `.ai-platform a { color: inherit }` reset - this is an anchor, and
   without this it would inherit dark text on its own dark fill. */
.ai-platform .usecase-card__answer {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-ink-dark);
  border: 1px solid var(--ap-ink-dark);
  transition: background var(--ap-fast), border-color var(--ap-fast);
}

.ai-platform .usecase-card__answer:hover {
  background: var(--ap-ink-deepest);
  border-color: var(--ap-ink-deepest);
}

.usecase-card__answer-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
}

.usecase-card__agent {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ap-white);
}

.usecase-card__answer .ai-icon {
  width: 12px;
  height: 12px;
  color: var(--ap-white);
}

@media (max-width: 1024px) {
  .usecase-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  .usecase-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   USE CASES v2 (index.php only) - each use case as a two-bubble chat
   mockup (the question as a user bubble, the agent's answer as a
   reply bubble) instead of an icon+question+pill card - visualizes
   the "ask AI, get the right agent" pitch directly instead of
   describing it.
   ------------------------------------------------------------------------ */
.usecase-chat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}

.usecase-chat {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 20px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.usecase-chat:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-ink);
}

.usecase-chat__bubble {
  font-size: 13.5px;
  line-height: 1.4;
  padding: 10px 14px;
  border-radius: 14px;
}

.usecase-chat__bubble--q {
  align-self: flex-end;
  max-width: 94%;
  background: var(--ap-soft);
  color: var(--ap-text);
  font-weight: 600;
  border-radius: 14px 14px 4px 14px;
}

.ai-platform .usecase-chat__bubble--a {
  align-self: flex-start;
  max-width: 94%;
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--ap-ink);
  color: var(--ap-white);
  font-weight: 700;
  border-radius: 14px 14px 14px 4px;
}

.usecase-chat__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  flex-shrink: 0;
}

.usecase-chat__icon .ai-icon {
  width: 11px;
  height: 11px;
  color: var(--ap-white);
}

.ai-platform .usecase-chat__bubble--a .link-arrow .ai-icon {
  width: 12px;
  height: 12px;
  color: var(--ap-white);
  margin-left: 2px;
}

@media (max-width: 1024px) {
  .usecase-chat-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  .usecase-chat-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   WHO IT'S FOR
   ------------------------------------------------------------------------ */
.who-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.who-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 28px 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.who-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.who-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 11px;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  margin-bottom: 18px;
}

.who-card__title {
  font-size: 18px;
  margin-bottom: 10px;
}

.who-card__desc {
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  line-height: 1.6;
}

@media (max-width: 1024px) {
  .who-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  .who-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   WHY THIS PLATFORM
   ------------------------------------------------------------------------ */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.feature-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 26px 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.feature-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.feature-card__num {
  font-size: 13px;
  font-weight: 700;
  color: var(--ap-text-secondary);
  margin-bottom: 14px;
}

.feature-card__title {
  font-size: 17px;
  margin-bottom: 8px;
}

.feature-card__desc {
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
}

@media (max-width: 900px) {
  .feature-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  .feature-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   FINAL CTA
   ------------------------------------------------------------------------ */
/* The section itself is light (white); the dark ink panel is an
   inset, rounded card inside it, not a full-bleed dark section. */
/* padding-bottom was 96px - sized for the rounded inset card this
   section used to hold, which needed room to breathe before the page
   edge. The panel is full-bleed now and closes itself out with its
   own 76px bottom padding (below), and .ap-footer already opens with
   56px of its own top padding plus a hairline border-top marking the
   seam - so this section stacking another 96px on top of both left
   ~230px of flat, unexplained dark space between the buttons and the
   footer's first link. 24px is just a sliver of breathing room, not
   a second buffer doing the same job the panel and the footer are
   already doing. */
.ap-final-cta {
  background-color: #1A1918;
  padding: 24px 0;
}

/* Full-bleed - edge to edge with the browser window, per the
   supplied reference - not an inset rounded card. It needs no
   breakout margin trick to get there: .ap-container moved inside it
   (see final-cta.php), so nothing above the panel constrains its
   width and a plain block-level 100% already reaches both edges.
   Square corners follow from that - a border-radius would cut a
   visible notch out of the browser's own edge instead of rounding a
   card floating inside a gutter, which is why it is gone along with
   the horizontal padding that used to hold the card in from its own
   edges (the text still gets a gutter, from .ap-container inside).

   Symmetric padding again - the panel briefly carried a dot-pattern
   background image (cta-bg.png) closed off by a dedicated banded
   element with its own bottom padding; both are gone per request; a
   flat panel closes itself out the same way top and bottom. */
.ap-final-cta__panel {
  position: relative;
  overflow: hidden;
  padding: 76px 0;
}

.ap-final-cta__inner {
  position: relative;
  text-align: center;
  max-width: 640px;
  margin: 0 auto;
}

/* Scoped with .ai-platform so this outranks the generic
   `.ai-platform h1, h2, h3, h4 { color: var(--ap-text) }` rule (a
   class+element selector beats a single class on specificity) -
   without it this <h2> rendered in dark text on the dark panel,
   nearly invisible. */
.ai-platform .ap-final-cta__heading {
  color: var(--ap-white);
  font-size: clamp(27px, 3.4vw, 38px);
  /* 300, like the reference's - and like the stats heading and the
     segments heading, the page's other two light-on-dark headings. */
  font-weight: 300;
  line-height: 1.2;
  letter-spacing: -0.025em;
  margin-bottom: 18px;
}

.ap-final-cta__subtext {
  color: rgba(255, 255, 255, 0.72);
  font-size: 16.5px;
  margin-bottom: 30px;
}

/* No longer used by final-cta.php (the homepage's checklist was
   removed per request) - still rendered by
   sections/support/final-cta.php, so these four rules stay. */
.ap-final-cta__checklist {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin-top: 28px;
}

.ap-final-cta__checklist li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  color: rgba(255, 255, 255, 0.75);
  white-space: nowrap;
}

/* White, not the reference's green - every other color on this page
   is strictly ink/white (navy and blue were both fully retired per
   request), so this stays in that same palette rather than
   introducing a one-off accent color for just this icon. */
.ap-final-cta__check-icon {
  display: inline-flex;
  color: var(--ap-white);
}

.ap-final-cta__check-icon .ai-icon {
  width: 15px;
  height: 15px;
  stroke-width: 2.4;
}

@media (max-width: 640px) {
  /* .ap-final-cta's own padding isn't set here - the later, wider
     @media (max-width: 768px) block below always matches whenever
     this one does and would win regardless (same specificity, later
     in source), so a value here would be dead. See that block for
     the real one. */
  .ap-final-cta__panel {
    /* Symmetric again, scaled down for this width - still full-bleed;
       the horizontal gutter for the text comes from .ap-container
       inside, which drops to --ap-gutter at this width on its own.
       No border-radius here either, for the same reason the desktop
       rule has none: the panel still reaches both edges of the
       screen. */
    padding: 48px 0;
  }

  /* Still used by sections/support/final-cta.php. */
  .ap-final-cta__checklist {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .ap-final-cta__checklist li {
    white-space: normal;
  }
}

/* ------------------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------------------ */
.ap-footer {
  background: var(--ap-surface);
  border-top: 1px solid var(--ap-border);
  padding: 56px 0 0;
}

.ap-footer__top {
  display: grid;
  grid-template-columns: 1.2fr 2fr;
  gap: 56px;
  padding-bottom: 56px;
}

.ap-footer__brand {
  max-width: 300px;
}

.ap-footer__tagline {
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  margin: 16px 0 22px;
  line-height: 1.6;
}

.ap-footer__social {
  display: flex;
  gap: 10px;
}

.ap-footer__social-link,
.ap-footer__social-link:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--ap-border);
  color: var(--ap-text-secondary);
  transition: border-color var(--ap-fast), color var(--ap-fast), transform var(--ap-fast);
}

.ap-footer__social-link .ai-icon {
  width: 16px;
  height: 16px;
}

.ap-footer__social-link:hover {
  border-color: var(--ap-ink-dark);
  color: var(--ap-ink-dark);
  transform: translateY(-2px);
}

.ap-footer__columns {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}

.footer-col__title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ap-text);
  margin-bottom: 18px;
}

.footer-col__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* :visited is listed alongside the base state (same selector, same
   specificity) rather than relying on inheritance or a separate
   reset rule - real footer links (career-ai.php, about-us.php, etc.)
   would otherwise pick up the browser's default visited-link color
   once a visitor has actually clicked them, making some links look
   like a different color from others for no visible reason. Browsers
   also block getComputedStyle from ever revealing this (a privacy
   protection), so it has to be verified by eye, not by script. */
.footer-col__list a,
.footer-col__list a:visited {
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  transition: color var(--ap-fast);
}

.footer-col__list a:hover {
  color: var(--ap-ink-dark);
}

.ap-footer__bottom {
  border-top: 1px solid var(--ap-border);
  padding: 22px 0;
  text-align: center;
}

.ap-footer__bottom p {
  font-size: 13.5px;
  color: var(--ap-text-secondary);
}

@media (max-width: 900px) {
  .ap-footer__top {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .ap-footer__columns {
    grid-template-columns: repeat(2, 1fr);
    gap: 32px 20px;
  }
}

@media (max-width: 480px) {
  .ap-footer__columns {
    grid-template-columns: 1fr 1fr;
  }
}

/* ------------------------------------------------------------------------
   SCROLL REVEAL (fade-up)
   ------------------------------------------------------------------------ */
.reveal-group > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 500ms ease, transform 500ms ease;
}

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

.reveal-group.is-visible > *:nth-child(1) { transition-delay: 0ms; }
.reveal-group.is-visible > *:nth-child(2) { transition-delay: 60ms; }
.reveal-group.is-visible > *:nth-child(3) { transition-delay: 120ms; }
.reveal-group.is-visible > *:nth-child(4) { transition-delay: 180ms; }
.reveal-group.is-visible > *:nth-child(5) { transition-delay: 240ms; }
.reveal-group.is-visible > *:nth-child(6) { transition-delay: 300ms; }
.reveal-group.is-visible > *:nth-child(7) { transition-delay: 360ms; }
.reveal-group.is-visible > *:nth-child(8) { transition-delay: 420ms; }

@media (prefers-reduced-motion: reduce) {
  .reveal-group > * {
    opacity: 1;
    transform: none;
    transition: none;
  }

  /* The demo bar itself renders one static phrase + result with no
     typing/erasing loop when this is set - see initHeroDemo() in
     ai-platform.js - but the icon's pulse ring and the text cursor
     are pure CSS and need to be switched off here independently. */
  .ap-hero__demo-icon-pulse::after,
  .ap-hero__demo-cursor {
    animation: none;
  }

  .ap-hero__demo-cursor {
    display: none;
  }

  /* The slideshow itself stops in JS (it also skips downloading the
     deferred slides), but this drift is pure CSS. */
  .ap-hero__slide.is-active {
    animation: none;
  }
}

/* ------------------------------------------------------------------------
   RESPONSIVE section padding + hero at small widths
   ------------------------------------------------------------------------ */
@media (max-width: 768px) {
  .ap-hero {
    padding-top: 32px;
    padding-bottom: 16px;
  }
  /* The 32px above assumes the light hero's sticky nav, which takes
     its own flow space above the section. The immersive hero's nav is
     fixed and overlays the photo, so that value put the badge
     underneath the logo - this restores the nav clearance. Declared
     here rather than in the immersive block further up the file
     because this rule is later in source order at equal specificity
     and would otherwise win. */
  .ap-hero--immersive {
    padding-top: calc(var(--ap-nav-h) + 56px);
    padding-bottom: 56px;
  }
  /* Matches the desktop value (was its own separate 48px) - the
     panel's own bottom padding plus this plus the footer's own top
     padding were stacking three buffers doing the same job. This is
     the rule that actually governs .ap-final-cta's padding at every
     width from 768px down to 0 - it wins over any narrower @media
     block below by source order at equal specificity, so the value
     belongs here, not in those. */
  .ap-final-cta {
    padding: 24px 0;
  }
  .ap-footer {
    padding-top: 40px;
  }
}

/* ------------------------------------------------------------------------
   CATEGORY PAGES (career-ai.php etc.) - shared template components
   ------------------------------------------------------------------------ */
.cat-hero {
  padding-bottom: 56px;
}

.cat-hero__stats {
  display: flex;
  justify-content: center;
  gap: 36px;
  margin-top: 44px;
}

.cat-hero__stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0 20px;
  position: relative;
}

.cat-hero__stat:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -18px;
  transform: translateY(-50%);
  width: 1px;
  height: 30px;
  background: var(--ap-border);
}

.cat-hero__stat strong {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ap-ink-dark);
}

.cat-hero__stat span {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
}

/* Featured agent cards - like .agent-card, but roomier and can host
   either an ai-platform stroke icon or an inline currentColor SVG
   from includes/data/category-pages.php (both sized the same here,
   independent of the .ai-icon class the platform's own icons use). */
.cat-agent-card {
  padding: 32px;
}

.cat-agent-card .agent-card__icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
}

.cat-agent-card .agent-card__icon svg {
  width: 22px;
  height: 22px;
}

.cat-agent-card__eyebrow {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  margin-bottom: 6px;
}

.cat-agent-card .agent-card__name {
  font-size: 19px;
}

.cat-agent-card .agent-card__desc {
  font-size: 14.5px;
}

/* Benefit / feature cards ("Why" section) */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.feature-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.feature-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.feature-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  margin-bottom: 16px;
}

.feature-card__icon svg {
  width: 19px;
  height: 19px;
}

.feature-card__title {
  font-size: 15.5px;
  margin-bottom: 8px;
}

.feature-card__desc {
  font-size: 13.5px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
}

/* Scenario cards ("A Conversation, Not a Form") - prompt styled like
   .usecase-card__question, response styled like a resolved answer
   pill but roomier since it carries a full sentence, not a label. */
.scenario-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.scenario-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 26px 24px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.scenario-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.scenario-card__prompt {
  font-size: 15px;
  font-weight: 700;
  color: var(--ap-text);
  line-height: 1.45;
  padding-left: 12px;
  border-left: 2px solid var(--ap-border-strong);
  margin-bottom: 18px;
}

.scenario-card__response {
  background: var(--ap-soft);
  border-radius: 10px;
  padding: 14px 16px;
}

.ai-platform .scenario-card__agent {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ap-ink-dark);
  margin-bottom: 8px;
}

.scenario-card__agent .ai-icon {
  width: 13px;
  height: 13px;
}

.scenario-card__response p {
  font-size: 14px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
}

/* FAQ accordion - one item open at a time, toggled by
   initFaqAccordions() in ai-platform.js. The answer wrapper collapses
   via grid-template-rows (0fr -> 1fr) so it animates without any JS
   height calculation. */
.faq-list {
  max-width: 760px;
  margin: 0 auto;
}

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

.faq-item:first-child {
  border-top: 1px solid var(--ap-border);
}

.ai-platform .faq-item__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  text-align: left;
  padding: 22px 4px;
  font-size: 16px;
  font-weight: 600;
  color: var(--ap-text);
  background: transparent;
}

.faq-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--ap-border-strong);
  color: var(--ap-ink-dark);
  flex-shrink: 0;
  transition: transform var(--ap-fast), background var(--ap-fast), color var(--ap-fast), border-color var(--ap-fast);
}

.faq-item__icon .ai-icon {
  width: 15px;
  height: 15px;
}

.faq-item.is-open .faq-item__icon {
  background: var(--ap-ink-dark);
  border-color: var(--ap-ink-dark);
  color: var(--ap-white);
  transform: rotate(180deg);
}

.faq-item__a-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--ap-fast);
}

.faq-item__a {
  overflow: hidden;
  min-height: 0;
  font-size: 14.5px;
  color: var(--ap-text-secondary);
  line-height: 1.6;
  padding: 0 4px;
}

.faq-item.is-open .faq-item__a-wrap {
  grid-template-rows: 1fr;
}

.faq-item.is-open .faq-item__a {
  padding-bottom: 22px;
}

@media (prefers-reduced-motion: reduce) {
  .faq-item__a-wrap,
  .faq-item__icon {
    transition: none;
  }
}

/* Final CTA panel with two buttons (category pages) instead of the
   homepage's single button + checklist. */
.ap-final-cta__ctas {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
}

.ai-platform .ap-final-cta .btn--outline {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.3);
  color: var(--ap-white);
}

.ai-platform .ap-final-cta .btn--outline:hover {
  border-color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.08);
}

@media (max-width: 1024px) {
  .feature-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .scenario-grid {
    grid-template-columns: 1fr;
  }
  .cat-hero__stats {
    gap: 24px;
  }
}

@media (max-width: 640px) {
  .feature-grid {
    grid-template-columns: 1fr;
  }
  .cat-agent-card {
    padding: 24px;
  }
}

/* ------------------------------------------------------------------------
   ABOUT PAGE - split copy/photo section ("Why We Exist")
   ------------------------------------------------------------------------ */
.ap-story__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
}

.ap-story__copy .section-heading {
  text-align: left;
  margin: 10px 0 20px;
}

.ap-story__copy .eyebrow {
  text-align: left;
}

.ap-story__text {
  font-size: 15.5px;
  color: var(--ap-text-secondary);
  line-height: 1.7;
  margin-bottom: 16px;
}

.ap-story__visual {
  border-radius: var(--ap-radius-card);
  overflow: hidden;
  box-shadow: var(--ap-shadow-md);
}

.ap-story__visual img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 900px) {
  .ap-story__grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .ap-story__visual {
    order: -1;
  }
}

/* ------------------------------------------------------------------------
   SUPPORT PAGE - contact channel cards
   ------------------------------------------------------------------------ */
.channel-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.channel-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 28px;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.channel-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.channel-card__note {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ap-ink-dark);
  background: var(--ap-ink-tint-10);
  padding: 3px 10px;
  border-radius: var(--ap-radius-pill);
  margin-bottom: 12px;
}

.channel-card .feature-card__desc {
  margin-bottom: 18px;
}

@media (max-width: 1024px) {
  .channel-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   USE CASES PAGE - situation cards (real photo + icon badge overlay)
   ------------------------------------------------------------------------ */
.situation-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}

.situation-card {
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  overflow: hidden;
  box-shadow: var(--ap-shadow-sm);
  transition: transform var(--ap-fast), box-shadow var(--ap-fast), border-color var(--ap-fast);
}

.situation-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--ap-shadow-md);
  border-color: var(--ap-border-strong);
}

.situation-card__media {
  position: relative;
  height: 180px;
}

.situation-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.situation-card__icon {
  position: absolute;
  left: 16px;
  bottom: -18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--ap-ink-dark);
  color: var(--ap-white);
  box-shadow: var(--ap-shadow-md);
}

.situation-card__icon svg {
  width: 20px;
  height: 20px;
}

.situation-card__body {
  padding: 32px 24px 24px;
}

.situation-card__count {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ap-ink-dark);
  margin-bottom: 10px;
}

.situation-card__title {
  font-size: 18px;
  line-height: 1.35;
  margin-bottom: 10px;
}

.situation-card__desc {
  font-size: 14px;
  color: var(--ap-text-secondary);
  line-height: 1.6;
  margin-bottom: 16px;
}

.situation-card__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}

.situation-card__chip {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 11px;
  border-radius: var(--ap-radius-pill);
  background: var(--ap-ink-tint-10);
  color: var(--ap-ink-dark);
  font-size: 12px;
  font-weight: 600;
}

.situation-card__example {
  background: var(--ap-soft);
  border-radius: 10px;
  padding: 14px 16px;
  font-size: 13.5px;
  color: var(--ap-text-secondary);
  line-height: 1.55;
}

.situation-card__example strong {
  color: var(--ap-text);
}

@media (max-width: 900px) {
  .situation-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------------------
   USE CASES PAGE - "A Day With IndiaConnect AI" timeline
   ------------------------------------------------------------------------ */
.timeline {
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  padding: 20px 0;
}

.timeline__line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  background: var(--ap-border-strong);
  transform: translateX(-50%);
}

.timeline__item {
  position: relative;
  width: 50%;
  padding: 0 40px 40px 0;
}

.timeline__item--flip {
  margin-left: 50%;
  padding: 0 0 40px 40px;
  text-align: left;
}

.timeline__item:not(.timeline__item--flip) {
  text-align: right;
}

.timeline__card {
  display: inline-block;
  background: var(--ap-surface);
  border: 1px solid var(--ap-border);
  border-radius: var(--ap-radius-card);
  padding: 20px 22px;
  box-shadow: var(--ap-shadow-sm);
  text-align: left;
}

.timeline__time {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ap-text-secondary);
  margin-bottom: 6px;
}

.timeline__agent {
  display: inline-block;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ap-ink-dark);
  background: var(--ap-ink-tint-10);
  padding: 3px 10px;
  border-radius: var(--ap-radius-pill);
  margin-bottom: 10px;
}

.timeline__text {
  font-size: 14px;
  color: var(--ap-text-secondary);
  line-height: 1.6;
}

.timeline__node {
  position: absolute;
  top: 6px;
  right: -6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ap-ink-dark);
  border: 3px solid var(--ap-surface);
  box-shadow: 0 0 0 2px var(--ap-border-strong);
}

.timeline__item--flip .timeline__node {
  right: auto;
  left: -6px;
}

@media (max-width: 768px) {
  .timeline__line {
    left: 6px;
  }
  .timeline__item,
  .timeline__item--flip {
    width: 100%;
    margin-left: 0;
    padding: 0 0 32px 32px;
    text-align: left;
  }
  .timeline__item .timeline__node,
  .timeline__item--flip .timeline__node {
    left: 0;
    right: auto;
  }
}

/* --- CTA button pair: one solid white, one white outline, both pills,
   per the reference. Scoped with .ai-platform so the label colours
   outrank the `.ai-platform a { color: inherit }` reset. --- */
.ap-final-cta__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

.ai-platform .ap-final-cta__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  height: 48px;
  padding: 0 26px;
  border-radius: var(--ap-radius-pill);
  border: 1px solid transparent;
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: background var(--ap-fast), color var(--ap-fast), border-color var(--ap-fast);
}

.ai-platform .ap-final-cta__btn--solid {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: #1A1918;
}

.ai-platform .ap-final-cta__btn--solid:hover {
  background: rgba(255, 255, 255, 0.88);
  border-color: rgba(255, 255, 255, 0.88);
}

.ai-platform .ap-final-cta__btn--ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.55);
  color: #FFFFFF;
}

.ai-platform .ap-final-cta__btn--ghost:hover {
  border-color: #FFFFFF;
  background: rgba(255, 255, 255, 0.08);
}

.ap-final-cta__btn .ai-icon {
  width: 16px;
  height: 16px;
}

.ap-final-cta__btn .link-arrow {
  display: inline-flex;
  transition: transform var(--ap-fast);
}

.ap-final-cta__btn:hover .link-arrow {
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .ai-platform .ap-final-cta__btn,
  .ap-final-cta__btn .link-arrow {
    transition: none;
  }
  .ap-final-cta__btn:hover .link-arrow {
    transform: none;
  }
}

@media (max-width: 480px) {
  .ap-final-cta__actions {
    flex-direction: column;
    align-items: stretch;
  }
  .ai-platform .ap-final-cta__btn {
    width: 100%;
  }
}

/* --- Dark footer, continuous with the CTA section above it. The
   base rules below were written for a light footer, so every colour
   they set is re-pointed here rather than edited in place - keeping
   the light versions intact for any page that wants them. --- */
.ap-footer {
  background: #0F0F0E;
  border-top-color: rgba(255, 255, 255, 0.10);
}

/* .ap-nav__wordmark is shared with the header, where it is plum on
   white. The icon tile beside it is a filled plum square and reads
   fine on black, but the wordmark itself needs inverting. */
.ap-footer .ap-nav__wordmark {
  color: #FFFFFF;
}

.ap-footer__tagline {
  color: rgba(255, 255, 255, 0.56);
}

.ap-footer .ap-footer__social-link,
.ap-footer .ap-footer__social-link:visited {
  border-color: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.7);
}

.ap-footer .ap-footer__social-link:hover {
  border-color: rgba(255, 255, 255, 0.6);
  color: #FFFFFF;
}

.ap-footer .footer-col__title {
  color: #FFFFFF;
  /* 600, not the 700 the light footer used - matches the page's
     heavier weight everywhere else. */
  font-weight: 600;
  text-transform: none;
  letter-spacing: -0.01em;
  font-size: 14px;
}

/* :visited kept alongside the base state for the same reason the
   light rule does it - without it, links a visitor has actually
   clicked pick up the browser default and look like a different
   colour from their neighbours. Not verifiable via
   getComputedStyle (browsers block it), so this one is by eye. */
.ap-footer .footer-col__list a,
.ap-footer .footer-col__list a:visited {
  color: rgba(255, 255, 255, 0.64);
}

.ap-footer .footer-col__list a:hover {
  color: #FFFFFF;
}

.ap-footer__bottom {
  border-top-color: rgba(255, 255, 255, 0.10);
}

.ap-footer__bottom p {
  color: rgba(255, 255, 255, 0.44);
}
