/* =========================================================================
   StepWISE — Shared site stylesheet (V1)
   Used by every page, including the homepage. Homepage-only hero and
   waypoint behaviour lives separately in home.css so it can never leak
   into internal pages. Design tokens, typography, header/nav, buttons,
   cards and footer are all derived directly from the approved
   StepWISE_Homepage_v4.html baseline — values are reused verbatim
   wherever the same element exists there.
   ========================================================================= */

:root{
  --navy:#0B0161;
  --paper:#F7F4EE;
  --paper-2:#EFEAE0;
  --waypoint-blue:#00A2FF;
  --amber:#DB6B01;
  /* Deepened, more saturated variant of --amber — same orange family, used
     where amber needs to read more strongly (Attendee Tracking Zone B). */
  --amber-strong:#E8600C;
  --grad-start:#0100FE;
  --grad-end:#DB6B01;
  --warm-gray:#8C877E;
  --white:#FFFFFF;
  --rule:#DEDACE;
  /* Figtree is the site's one sans-serif (400/500/600 only). Source Serif 4
     is reserved for exactly the three approved signature statements and is
     applied directly by .signature-line — nothing here ever swaps it. */
  --sans: 'Figtree',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --content-w: 700px;
  --wide-w: 980px;
  --dur: 260ms;
  /* Fixed display size for the Environments page's per-subsection SVG
     icons. */
  --env-icon-size: 140px;
}

*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
  margin:0; background:var(--paper); color:var(--navy); font-family:var(--sans);
  font-size:17px; line-height:1.65; -webkit-font-smoothing:antialiased;
}
body.reduced-motion, body.reduced-motion *{
  scroll-behavior:auto !important; transition-duration:1ms !important; animation-duration:1ms !important;
}
img,svg{display:block;max-width:100%;}
a{color:inherit;}
.sr-only{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; }

/* Prevent horizontal overflow at narrow widths regardless of page content. */
html,body{ overflow-x:hidden; }

/* ---------- Skip link ---------- */
.skip-link{
  position:absolute; left:12px; top:-52px; z-index:100; background:var(--navy); color:var(--paper);
  padding:10px 16px; border-radius:8px; font-size:14px; font-weight:600; text-decoration:none;
  transition:top var(--dur);
}
.skip-link:focus{ top:12px; }

/* ---------- Visible keyboard focus, consistent across the site ---------- */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible{
  outline:2px solid var(--waypoint-blue); outline-offset:2px; border-radius:4px;
}

/* ---------- Heading system: Level 1 (brand statements) ----------
   Source Serif 4 is reserved for exactly three signature statements
   (homepage hero headline, homepage positioning headline, homepage
   philosophy quote). Every other typographic element on the site uses
   Figtree (var(--sans)) — including every internal-page headline. */
.signature-line{ font-family:var(--serif); font-weight:600; letter-spacing:-0.01em; line-height:1.24; }

/* ---------- Heading system: Level 2 (section headings) ---------- */
h1,h2,h3,h4{ margin:0; font-weight:600; letter-spacing:-0.01em; }
.section-head{ font-size:29px; color:var(--navy); margin-bottom:16px; line-height:1.28; }

/* ---------- Layout shell ---------- */
.site-frame{ position:relative; max-width:100%; margin:0 auto; background:var(--paper); overflow:clip; }
.wrap{ max-width:var(--content-w); margin:0 auto; padding:0 28px; }
.wrap-wide{ max-width:var(--wide-w); margin:0 auto; padding:0 28px; }
section{ padding:96px 0; position:relative; }
section.tight{ padding:64px 0; }
.rule-top{ border-top:1px solid var(--rule); }

/* ---------- Header ----------
   Sticky positioning lives on the wrapper, not the header itself. On the
   homepage the wrapper also contains the mobile waypoint bar so the two
   stick as one contiguous unit; on internal pages the wrapper contains
   only the header, so this is simply a normal sticky header. */
.header-stack{ position:sticky; top:0; z-index:40; }
header.site-header{
  background:rgba(247,244,238,.92);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border-bottom:1px solid var(--rule);
}
.header-inner{ display:flex; align-items:center; padding-top:14px; padding-bottom:14px; }
.logo-mark{ display:flex; align-items:center; gap:10px; flex:0 0 auto; }
.logo-mark img{ height:37px; width:auto; }
.site-nav{ display:flex; align-items:center; gap:24px; margin-left:36px; flex:1; }
.site-nav a{ font-size:14.5px; color:var(--navy); text-decoration:none; padding:4px 2px; border-bottom:2px solid transparent; }
.site-nav a:hover{ border-bottom-color:var(--rule); }
/* Current-page indication: an understated bottom rule, not a heavy pill or
   background fill, keeping the nav visually calm. */
.site-nav a[aria-current="page"], .mobile-nav a[aria-current="page"]{
  border-bottom-color:var(--navy); font-weight:600;
}

/* ---------- Capabilities dropdown ----------
   A single unified control: "Capabilities" and its chevron are one button
   that only ever opens/closes the submenu of real links beneath it — it
   never navigates anywhere itself. Styled to match the plain nav-link
   typography around it (same font-size/colour/underline-on-hover as
   .site-nav a) so it reads as part of the same navigation, not a separate
   control glued on. */
.nav-item{ position:relative; display:flex; align-items:center; }
.dropdown-toggle{
  /* Buttons don't inherit typography the way links do — browsers give
     them their own native control font regardless of declared
     font-family/size, which is why this previously rendered smaller than
     "Environments"/"How We Work"/"About" despite matching declarations.
     font:inherit resets every font-related sub-property (size, weight,
     line-height, family) to match the surrounding nav before the shared
     nav-link typography below is reapplied on top. */
  font: inherit;
  -webkit-appearance: none; appearance: none;
  margin: 0; vertical-align: middle;
  display:inline-flex; align-items:center; gap:5px; background:none; border:none; cursor:pointer;
  font-family:var(--sans); font-size:14.5px; font-weight:400; color:var(--navy); padding:4px 2px; border-bottom:2px solid transparent;
}
.dropdown-toggle:hover{ border-bottom-color:var(--rule); }
.dropdown-toggle svg{ width:9px; height:9px; flex:0 0 auto; transition:transform var(--dur); }
.dropdown-toggle[aria-expanded="true"] svg{ transform:rotate(180deg); }
/* Understated indicator that the visitor is somewhere within the
   Capabilities section (overview or a solution page) — same visual
   language as the current-page underline used elsewhere in the nav, but
   applied via a plain class since this control has no href of its own
   for aria-current to describe. */
.nav-item.in-section .dropdown-toggle{ border-bottom-color:var(--navy); font-weight:600; }
.dropdown-menu{
  display:none; position:absolute; top:100%; left:0; margin-top:10px; min-width:220px;
  background:var(--paper); border:1px solid var(--rule); border-radius:12px; padding:8px;
  box-shadow:0 18px 40px rgba(11,1,97,0.14); z-index:50;
}
.dropdown-menu.open{ display:block; }
.dropdown-menu a{
  display:block; padding:9px 12px; border-radius:8px; font-size:14.5px; color:var(--navy);
  text-decoration:none; border-bottom:none;
}
/* Hover: the same restrained grey underline used on hover by the primary
   nav links (site-nav a:hover), not a ring or fill. text-decoration draws
   under the text itself, not the full block-level row, so it never spans
   the item's full width, never changes its size and never shifts or
   overlaps neighbouring items. */
.dropdown-menu a:hover{
  text-decoration:underline; text-decoration-color:var(--rule); text-decoration-thickness:2px;
  text-underline-offset:5px; text-decoration-skip-ink:none;
}
/* Keyboard focus: a contained treatment, not the site-wide outset blue
   outline (a:focus-visible near the top of this file) — that outline sits
   outside the element's box and would collide with the item above/below
   it here. Still clearly visible, just held inside the item's own shape,
   and kept distinct from the hover underline above. */
.dropdown-menu a:focus-visible{
  outline:none; text-decoration:none; box-shadow:inset 0 0 0 2px var(--waypoint-blue);
}
/* Current page: filled like the primary CTA buttons, so it reads as
   "you are here" rather than "this is hovered/focused" — kept visually
   distinct from both of those states at every size, since it's a solid
   fill rather than an outline or underline. */
.dropdown-menu a[aria-current="page"]{
  background:var(--navy); color:var(--paper); font-weight:600; box-shadow:none;
}
.dropdown-menu a[aria-current="page"]:hover{ text-decoration:none; }
.dropdown-menu a[aria-current="page"]:focus-visible{
  outline:none; box-shadow:inset 0 0 0 2px var(--paper);
}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex; align-items:center; gap:8px; border:none; cursor:pointer;
  font-family:var(--sans); font-weight:600; font-size:15px; letter-spacing:.01em;
  border-radius:9px; padding:11px 20px; transition:background var(--dur), color var(--dur), border-color var(--dur);
  text-decoration:none;
}
.btn-primary{ background:var(--navy); color:var(--paper); border:1.5px solid var(--navy); }
.btn-primary:hover{ background:#241a6e; }
.btn-outline{ background:transparent; color:var(--navy); border:1.5px solid var(--navy); }
.btn-outline:hover{ background:var(--navy); color:var(--paper); }
.btn-quiet{ background:transparent; color:var(--navy); padding:11px 6px; text-decoration:underline; text-underline-offset:4px; text-decoration-color:var(--rule); border:none; }
.btn-quiet:hover{ text-decoration-color:var(--navy); }
.header-cta{ font-size:14px; padding:8px 15px; flex:0 0 auto; }
/* Submit-in-progress feedback (contact form) — same fill, just visibly inert. */
.btn:disabled{ opacity:.6; cursor:not-allowed; }
.btn-primary:disabled:hover{ background:var(--navy); }

/* ---------- Mobile nav ---------- */
.nav-toggle{ display:none; background:none; border:none; cursor:pointer; padding:8px; flex-direction:column; gap:4px; flex:0 0 auto; }
.nav-toggle span{ width:20px; height:2px; background:var(--navy); display:block; border-radius:1px; }
.mobile-nav{ display:none; flex-direction:column; padding:6px 20px 16px 20px; background:var(--paper); border-bottom:1px solid var(--rule); }
.mobile-nav.open{ display:flex; }
.mobile-nav a{ padding:11px 0; font-size:15.5px; color:var(--navy); text-decoration:none; border-bottom:1px solid var(--rule); }
.mobile-nav .btn{ margin-top:14px; align-self:flex-start; }

/* Inline expandable Capabilities group inside the mobile menu — the same
   single-button toggle mechanism as desktop, styled to match the other
   full-width mobile-nav link rows (same padding/font-size/border-bottom
   rhythm as .mobile-nav a) so it reads as one of the list, not a second
   distinct control. */
.mobile-nav .nav-item{ flex-direction:column; align-items:stretch; }
.mobile-nav .dropdown-toggle{
  display:flex; align-items:center; justify-content:space-between; width:100%; text-align:left;
  padding:11px 0; font-size:15.5px; border:none; border-bottom:1px solid var(--rule); border-radius:0;
}
.mobile-nav .dropdown-toggle svg{ width:10px; height:10px; }
.mobile-nav .nav-item.in-section .dropdown-toggle{ border-bottom-color:var(--navy); font-weight:600; }
.mobile-nav .dropdown-menu{
  display:none; position:static; margin:0 0 6px 0; padding:0 0 0 14px; border:none; box-shadow:none; background:none;
}
.mobile-nav .dropdown-menu.open{ display:block; }
.mobile-nav .dropdown-menu a{ padding:9px 0; font-size:14.5px; border-bottom:1px solid var(--rule); border-radius:0; }
.mobile-nav .dropdown-menu a:last-child{ border-bottom:none; }

/* ---------- Internal-page hero (compact, static) ---------- */
.page-hero{ padding-top:72px; padding-bottom:64px; text-align:center; }
.page-hero .eyebrow{
  display:block; font-size:14px; letter-spacing:.04em; text-transform:uppercase; color:var(--warm-gray);
  margin-bottom:14px; font-weight:600;
}
.page-hero h1{ font-size:36px; line-height:1.28; margin:0 auto; max-width:22ch; }
/* Headings with an explicit, approved <br> break: the default max-width
   exists to wrap ordinary single-line headlines gracefully, but here it
   would fight the intended two-line break by wrapping each half again.
   Only headings carrying this class are exempt. */
.page-hero h1.headline-break{ max-width:none; }
.page-hero .lead{ margin:20px auto 0 auto; max-width:62ch; font-size:18px; color:#2c245f; text-align:left; }
.page-hero .cta-row{ margin-top:30px; display:flex; align-items:center; justify-content:center; gap:20px; }

/* ---------- Breadcrumb ---------- */
.breadcrumb{ font-size:13.5px; color:var(--warm-gray); margin-bottom:18px; }
.breadcrumb a{ color:var(--warm-gray); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--rule); }
.breadcrumb a:hover{ color:var(--navy); text-decoration-color:var(--navy); }
.breadcrumb .sep{ margin:0 6px; }
.breadcrumb [aria-current="page"]{ color:var(--navy); }

/* ---------- Section intro paragraphs (shared across pages) ---------- */
.section-intro{ max-width:64ch; font-size:18px; color:#2c245f; margin-bottom:26px; }
/* Plain body paragraphs directly inside a content wrapper (not part of a
   card/list component, which set their own colour) read in the same
   softened navy used throughout the approved homepage copy. */
.wrap > p, .wrap-wide > p{ max-width:64ch; font-size:17px; color:#2c245f; margin:0 0 18px 0; }
.wrap > p:last-child, .wrap-wide > p:last-child{ margin-bottom:0; }

/* ---------- Plain dash list (shared) ---------- */
.dash-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:15px; }
.dash-list li{ position:relative; padding-left:22px; font-size:17px; color:#2c245f; max-width:58ch; }
.dash-list li::before{ content:""; position:absolute; left:0; top:11px; width:9px; height:2px; background:var(--warm-gray); }

/* ---------- Legal content (Privacy Policy and similar reference pages) ----------
   A single flowing document rather than discrete bordered/carded sections.
   Reuses .wrap's existing 700px reading width — comfortably narrow rather
   than a new width system — and adds only what a long, heading-heavy
   policy needs on top of that: a clear two-level heading hierarchy,
   calmer paragraph/list rhythm than the site's marketing copy, and
   underlined links matching the rest of the site's accessible link style. */
.legal-content .updated-line{ font-size:14.5px; color:var(--warm-gray); margin:0 0 40px 0; }
.legal-content h2{ font-size:23px; color:var(--navy); margin:44px 0 14px 0; line-height:1.3; }
.legal-content h2:first-of-type{ margin-top:0; }
.legal-content h3{ font-size:17px; color:var(--navy); margin:26px 0 10px 0; }
.legal-content p{ margin:0 0 16px 0; max-width:64ch; font-size:16px; line-height:1.65; color:#2c245f; }
.legal-content p:last-child{ margin-bottom:0; }
.legal-content ul{ list-style:none; margin:0 0 16px 0; padding:0; display:flex; flex-direction:column; gap:10px; max-width:64ch; }
.legal-content li{ position:relative; padding-left:20px; font-size:16px; line-height:1.6; color:#2c245f; }
.legal-content li::before{ content:""; position:absolute; left:0; top:9px; width:8px; height:2px; background:var(--warm-gray); }
.legal-content a{ color:var(--navy); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--rule); }
.legal-content a:hover{ text-decoration-color:var(--navy); }

/* ---------- Differentiator-style cards (2-up, left rule) ---------- */
.diff-grid{ display:grid; grid-template-columns:1fr 1fr; gap:26px 40px; margin-top:38px; }
.diff-item{ border-left:2px solid var(--rule); padding-left:16px; }
.diff-item h4, .diff-item h3{ font-size:15.5px; color:var(--navy); margin-bottom:6px; }
.diff-item p{ margin:0; font-size:15px; color:#453e77; }

/* ---------- Flexible info cards (variable item counts, left rule) ----------
   Same visual language as .diff-item but auto-fits any number of items
   (4, 5, 6 …) without per-page column tuning, collapsing to a single
   column at the narrow breakpoint below. */
.info-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:26px 32px; margin-top:38px; }
.info-card{ border-left:2px solid var(--rule); padding-left:16px; }
.info-card h3, .info-card h4{ font-size:15.5px; color:var(--navy); margin-bottom:6px; }
.info-card p{ margin:0; font-size:15px; color:#453e77; }
.info-card p.role{ font-weight:600; color:var(--warm-gray); font-size:13px; text-transform:uppercase; letter-spacing:.04em; margin:-2px 0 8px 0; }

/* ---------- Simple subsection stack ----------
   For a small number of sub-headed passages that carry more content (a
   nested list, a longer paragraph) than comfortably fits a card grid. */
.stack{ display:flex; flex-direction:column; gap:28px; margin-top:28px; }
.stack h3{ font-size:17px; color:var(--navy); margin-bottom:8px; }
.stack p{ margin:0 0 12px 0; font-size:15.5px; color:#453e77; }
.stack p:last-child{ margin-bottom:0; }
.stack .dash-list{ margin-top:10px; }

/* ---------- Related-group subsections (e.g. named environments) ----------
   A set of <article> subsections that belong to one parent section and
   should read as a single related group rather than a run of separate
   pages: restrained spacing and a thin top rule between items instead of
   full section padding + a section-level horizontal rule for every one. */
.subsection-group{ display:flex; flex-direction:column; margin-top:8px; }
.subsection-item{ padding-top:30px; margin-top:30px; border-top:1px solid var(--rule); }
.subsection-item:first-child{ padding-top:0; margin-top:0; border-top:none; }
.subsection-item h3{ font-size:19px; color:var(--navy); margin-bottom:10px; }
.subsection-item p{ margin:0 0 14px 0; max-width:64ch; font-size:17px; color:#2c245f; }
.subsection-item p:last-child{ margin-bottom:0; }
.subsection-item .dash-list{ margin:2px 0 14px 0; }

/* ---------- Environment icons (Environments page) ----------
   One 140x140 SVG icon per environment subsection, referenced with <img>
   — final approved artwork, never reproduced inline. Two treatments share
   the same base .env-graphic-flow/.env-graphic-icon:

   1. Default (currently just Exhibitions and conferences): the icon
      floats at the left edge of its subsection's content column,
      immediately beneath the heading, with body copy flowing to its
      right and wrapping beneath it once the copy runs longer than the
      icon's height — a restrained editorial float, not a fixed grid
      column. display:flow-root on the wrapper contains the float
      cleanly so it can't escape into the next subsection. This floated
      treatment is kept at every viewport width — the icon never stacks
      above the copy.

   2. .env-graphic-flow--fixed (the other six entries): a fixed icon +
      copy row (flex) rather than a float, so the copy column never lets
      its final lines drop beneath the icon regardless of how short or
      long that entry's copy is. The icon is taken out of flow (float:
      none) and given a fixed flex-basis of --env-icon-size; the copy
      sits in its own .env-graphic-copy column (flex:1 1 auto;
      min-width:0) so it keeps wrapping normally within that column at
      every viewport width instead of ever reflowing beneath the icon.

   Both are at the page's existing standard content width (no wrap-wide
   breakout). The outer .subsection-item and its <h3> are untouched by
   any of this, so the shared divider/spacing rhythm between all seven
   entries is unaffected. */
.env-graphic-flow{ display:flow-root; }
.env-graphic-icon{
  float:left;
  width:var(--env-icon-size);
  height:var(--env-icon-size);
  margin:0 24px 14px 0;
}

.env-graphic-flow--fixed{
  display:flex;
  align-items:flex-start;
  gap:24px;
}
.env-graphic-flow--fixed .env-graphic-icon{
  float:none;
  flex:0 0 var(--env-icon-size);
  margin:0;
}
.env-graphic-flow--fixed .env-graphic-copy{
  flex:1 1 auto;
  min-width:0;
}

/* ---------- Solution previews (larger sub-headed blocks with a tagline) ----------
   Used for the three solution summaries on the Capabilities overview page:
   heading, short bold tagline, supporting copy and a quiet "Explore" link. */
.solution-list{ display:flex; flex-direction:column; gap:44px; margin-top:38px; }
.solution-preview{ padding-top:32px; border-top:1px solid var(--rule); }
.solution-preview:first-child{ padding-top:0; border-top:none; }
.solution-preview h3{ font-size:23px; margin-bottom:10px; }
.solution-preview .tagline{ font-weight:600; color:var(--navy); margin:0 0 10px 0; font-size:16.5px; }
.solution-preview p{ margin:0 0 12px 0; max-width:62ch; font-size:15.5px; color:#453e77; }
.solution-preview p:last-of-type{ margin-bottom:16px; }

/* ---------- Capability-style cards (icon, heading, copy) ---------- */
.cap-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:32px; }
.cap-card{
  background:transparent; border:none; border-top:2px solid var(--rule); padding:24px 0 0 0;
  display:flex; flex-direction:column; gap:14px; text-decoration:none; color:inherit;
  transition:border-color var(--dur);
}
a.cap-card:hover, a.cap-card:focus-visible{ border-top-color:var(--waypoint-blue); }
.cap-card svg{ width:32px; height:32px; }
.cap-card h3{ font-size:19px; display:flex; align-items:center; gap:8px; }
.cap-card p{ margin:0; font-size:15.5px; color:#453e77; }
.cap-card .card-arrow{ font-size:15px; color:var(--waypoint-blue); }

/* ---------- Process steps (numbered/dotted, static on internal pages) ---------- */
.method-row{ display:grid; grid-template-columns:repeat(4,1fr); gap:24px; }
.method-step{ position:relative; }
.method-dot{
  width:11px; height:11px; border-radius:50%; background:var(--waypoint-blue); border:2px solid var(--waypoint-blue);
  margin-bottom:16px;
}
.method-step h3{ font-size:14px; letter-spacing:.04em; text-transform:uppercase; color:var(--warm-gray); margin-bottom:8px; }
.method-step p{ margin:0; font-size:16px; color:#2c245f; }

/* ---------- Pills ---------- */
.env-pills{ display:flex; flex-wrap:wrap; gap:10px; margin-top:28px; }
.pill{ font-size:14px; padding:8px 16px; border-radius:100px; border:1px solid var(--rule); background:var(--paper-2); color:var(--navy); }
.env-accent{ margin-top:24px; height:2px; width:130px; background:linear-gradient(90deg,var(--grad-start),var(--grad-end)); border-radius:2px; }

/* ---------- Final CTA (shared page-ending pattern) ---------- */
.page-cta{ text-align:center; }
.page-cta p{ max-width:54ch; margin:0 auto 30px auto; font-size:19px; color:#2c245f; }

/* ---------- Footer ---------- */
.site-footer{ padding:52px 0 40px 0; border-top:1px solid var(--rule); }
.footer-inner{ display:flex; flex-direction:column; align-items:center; gap:18px; text-align:center; }
.footer-nav{ display:flex; flex-wrap:wrap; justify-content:center; gap:20px; }
.footer-nav a{ font-size:14px; color:var(--navy); text-decoration:none; border-bottom:1px solid transparent; }
.footer-nav a:hover{ border-bottom-color:var(--rule); }
.footer-contact{ display:flex; align-items:center; justify-content:center; gap:8px; }
.footer-contact a{ font-size:14px; color:var(--navy); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--rule); }
.footer-contact a:hover{ text-decoration-color:var(--navy); }
/* LinkedIn icon beside the email link — subtle by default, full navy on
   hover/focus. Keyboard focus is handled entirely by the site-wide
   a:focus-visible rule near the top of this file; no separate rule needed. */
.footer-contact .footer-social{ display:inline-flex; color:var(--navy); opacity:.7; text-decoration:none; transition:opacity var(--dur); }
.footer-contact .footer-social:hover{ opacity:1; }
.footer-social svg{ width:19px; height:19px; display:block; }
.footer-locations{ display:flex; flex-wrap:wrap; justify-content:center; gap:24px; font-size:13px; color:var(--warm-gray); }
.footer-line{ margin:6px 0 0 0; font-size:13px; color:var(--warm-gray); }
.footer-copyright{ margin:2px 0 0 0; font-size:12px; color:var(--warm-gray); }

/* ---------- Contact form ---------- */
.form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:22px; margin-top:8px; }
.form-field{ display:flex; flex-direction:column; gap:7px; }
.form-field.full{ grid-column:1 / -1; }
.form-field label{ font-size:14.5px; font-weight:600; color:var(--navy); }
.form-field .req{ font-weight:400; color:var(--warm-gray); font-size:13px; }
.form-field input, .form-field select, .form-field textarea{
  font-family:var(--sans); font-size:15.5px; color:var(--navy); background:var(--white);
  border:1.5px solid var(--rule); border-radius:9px; padding:11px 14px; width:100%;
}
.form-field textarea{ min-height:140px; resize:vertical; }
.form-field input:focus-visible, .form-field select:focus-visible, .form-field textarea:focus-visible{
  outline:2px solid var(--waypoint-blue); outline-offset:1px; border-color:var(--waypoint-blue);
}
.form-help{ font-size:13.5px; color:var(--warm-gray); margin:0; }
.form-actions{ margin-top:8px; }
/* Shown after a submit attempt, reporting the success or failure returned
   by api/contact.php. role="status"/aria-live="polite" on the element (set
   in markup) means assistive technology announces it as soon as its
   content changes; JavaScript also moves keyboard focus to it once a
   response arrives (see .form-status:focus below), so the result reaches
   keyboard and screen-reader users reliably either way. */
.form-status{ margin-top:16px; padding:14px 16px; border-radius:9px; background:var(--paper-2); border:1px solid var(--rule); color:var(--navy); font-size:14.5px; line-height:1.55; max-width:60ch; }
.form-status a{ color:var(--navy); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--rule); }
.form-status a:hover{ text-decoration-color:var(--navy); }
.form-note{ margin-top:16px; font-size:13.5px; color:var(--warm-gray); max-width:60ch; }
/* Honeypot: off-screen (not display:none, which some bots specifically
   detect and skip) rather than visually restyled — real visitors never
   see or reach it; see contact/index.html for the tabindex/aria-hidden
   pairing that also keeps it out of keyboard and screen-reader use. */
.hp-field{ position:absolute; left:-9999px; top:-9999px; width:1px; height:1px; overflow:hidden; }
/* The status region is given tabindex="-1" in markup so JS can move
   keyboard focus to it after a submission; this keeps that focus visible
   even where :focus-visible's heuristics might not treat a script-driven
   focus() call as keyboard-triggered. */
.form-status:focus{ outline:2px solid var(--waypoint-blue); outline-offset:2px; }

/* ---------- Locations ---------- */
.locations-grid{ display:grid; grid-template-columns:1fr 1fr; gap:32px; margin-top:12px; }
.location h3{ font-size:15.5px; margin-bottom:6px; }
.location p{ margin:0; font-size:15.5px; color:#453e77; }

/* ---------- Explanatory graphics (Waypoints & routes) ----------
   One shared presentation frame reused by the four capability-page
   graphics selected from the visual-direction comparison. Static only —
   no animation, no controls. Each graphic ships two hand-authored SVG
   variants (desktop/tablet and mobile) swapped by the same 760px
   breakpoint used everywhere else on the site, so mobile gets a taller,
   simplified layout with legible text rather than the wide desktop
   graphic shrunk into a shallow strip. Only one variant is ever in the
   document flow at a time. */
.explain-graphic{ margin:36px auto 8px auto; max-width:600px; }
/* Page-specific modifier: extra clearance beneath the graphic on the two
   pages where the following content sat too close to it. Deliberately not
   a change to the shared .explain-graphic default, which stays correct
   for Attendee Tracking. */
.explain-graphic--spacious{ margin-bottom:44px; }
.explain-frame{
  width:100%; aspect-ratio:2/1; background:var(--paper-2);
  border:1px solid var(--rule); border-radius:14px; overflow:hidden;
}
.explain-frame svg{ width:100%; height:100%; display:block; }
.explain-frame text{ font-family:var(--sans); }
.explain-frame .mobile-variant{ display:none; }

/* =========================================================================
   Solution-graphic animations (Indoor Navigation, RecapHub, Attendee
   Tracking only — Capabilities Overview no longer carries a graphic).

   Architecture:
   - Every rule in this block is scoped under .sg-playing, so with no JS
     (assets/js/solution-graphics.js, loaded only on these three pages) the
     graphics render exactly their static final frame — the approved
     default appearance — with zero behavioural change.
   - .sg-playing is added by the controller once a graphic's .explain-frame
     enters the viewport; .sg-paused toggles animation-play-state (offscreen
     or the browser tab is hidden) so playback truly pauses and resumes
     instead of restarting.
   - Every animated property is opacity/transform/fill or stroke-dashoffset
     (paired with stroke-dasharray) — no layout-affecting properties — kept
     deliberately modest for CPU and well supported across Safari/WebKit.
   - Longhand animation-* properties are used throughout (never the
     `animation` shorthand) so the .sg-paused rule's animation-play-state
     can never be silently reset by a later shorthand declaration.
   - prefers-reduced-motion is enforced twice: solution-graphics.js never
     attaches .sg-playing when the user prefers reduced motion, and the
     media query below forces animation:none regardless, so the complete
     final frame always shows immediately either way.
   ========================================================================= */

.explain-frame.sg-paused .gfx-anim{ animation-play-state:paused; }

@media (prefers-reduced-motion:reduce){
  .gfx-anim{ animation:none !important; }
}

/* ---------- Indoor Navigation ----------
   The Indoor Navigation route is no longer CSS-keyframe driven. It is a
   single continuous path (.nav-route) whose three intermediate waypoints
   (.nav-waypoint) are positioned via getPointAtLength() and whose forward
   draw / hold / retract cycle is driven by one authoritative progress
   value — all in assets/js/indoor-navigation-graphic.js, loaded only on
   capabilities/indoor-navigation/index.html. That file also owns this
   graphic's viewport/tab-visibility pause-resume and reduced-motion
   handling directly, so it needs no rules here and no .gfx-anim class:
   the route's default (no-JS) appearance is simply its natural solid
   stroke, and the waypoints default to visible at hand-placed fallback
   positions — both already the complete, correct final frame. */

/* ---------- RecapHub ----------
   The RecapHub route is no longer CSS-keyframe driven. A single
   authoritative progress value draws the main route (.recap-route) and
   reveals each numbered waypoint (.recap-node-1..4) at a threshold found
   by measuring the route's real length and locating each node's own
   (cx,cy) on it (node 1 and node 4 are the route's own start/end by
   construction) — then, once the route is fully drawn, a second progress
   value extends the four-way fork (.recap-fork-line, .recap-fork-reveal).
   All of this lives in assets/js/recaphub-graphic.js, loaded only on
   capabilities/recaphub/index.html, which also owns this graphic's
   viewport/tab-visibility pause-resume and reduced-motion handling
   directly — so it needs no rules here and no .gfx-anim class: the
   default (no-JS) appearance is simply every element's natural, fully
   visible rendering, already the complete final frame. */

/* ---------- Attendee Tracking (colour-differentiated zones + drift) ----------
   Each zone's dots take a distinct brand colour (kept from the existing
   palette, no new colours introduced — Zone B uses --amber-strong, a
   deepened variant of --amber for stronger visibility). Most dots drift
   gently within their own zone on one of four predetermined wander loops;
   two dots are designated travellers that make a single calm, slow round
   trip into the neighbouring zone and back within each 16s cycle,
   switching to the destination zone's colour as they arrive and switching
   back as they return home. All paths are fixed keyframes — nothing here
   is randomised at runtime.

   Every dot's resting position (set in the HTML) and every drift/travel
   delta below were chosen together so that, at every point in the
   animation, the dot stays comfortably clear of its zone's rect edges and
   its zone's label text — not just at rest. */
.zone-a-dot{ fill:var(--waypoint-blue); }
.zone-b-dot{ fill:var(--amber-strong); }
.zone-c-dot{ fill:var(--navy); }

@keyframes trackDrift1{ 0%,100%{ transform:translate(0,0); } 50%{ transform:translate(10px,-8px); } }
@keyframes trackDrift2{ 0%,100%{ transform:translate(0,0); } 50%{ transform:translate(-12px,7px); } }
@keyframes trackDrift3{ 0%,100%{ transform:translate(0,0); } 50%{ transform:translate(8px,11px); } }
@keyframes trackDrift4{ 0%,100%{ transform:translate(0,0); } 50%{ transform:translate(-9px,-10px); } }
.explain-frame.sg-playing .track-drift-1{ animation-name:trackDrift1; animation-duration:6.5s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }
.explain-frame.sg-playing .track-drift-2{ animation-name:trackDrift2; animation-duration:7.5s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }
.explain-frame.sg-playing .track-drift-3{ animation-name:trackDrift3; animation-duration:8.5s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }
.explain-frame.sg-playing .track-drift-4{ animation-name:trackDrift4; animation-duration:9.5s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }

/* Traveller 1: Zone A ⇄ Zone B. Traveller 2: Zone B ⇄ Zone C. The two
   travellers are deliberately NOT mirror images of each other — different
   route heights (desktop) / columns (mobile), different total durations
   (15s vs 20s) and a non-half-cycle phase offset (-7.5s), so they read as
   two unrelated attendees rather than one synchronised pair. The exact
   numbers were chosen by simulating both travellers' transit windows
   across a long shared timeline (their periods' LCM is 60s) and
   confirming no transit window of one ever overlaps a transit window of
   the other by less than ~1.1s, so they never begin, cross a boundary or
   arrive together at any point in the repeating pattern — not just within
   a single 15s/20s cycle taken in isolation.

   Traveller 1 crosses through the upper part of its available vertical
   space on desktop (a gentle diagonal from (165,108) to (248,142), chosen
   — along with its target — by simulating its position across a full
   600-second window against every resident dot's own drift motion and
   against traveller 2, to keep a comfortable ≥19px gap throughout rather
   than merely avoiding other dots' resting coordinates) and a left column
   on mobile (x≈100–120, unchanged — already collision-free by the same
   simulation). Traveller 2 crosses through the lower-middle on desktop
   (y≈178, clearly below traveller 1's band) and a right column on mobile
   (x≈240–250, a clear 130–150px over from traveller 1). Each traveller's
   home and target rest inside its zone's safe interior, clear of every
   rect edge and label. */
@keyframes trackTravel1{
  0%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  20%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  27%{ transform:translate(83px,34px); fill:var(--waypoint-blue); }
  27.3%{ transform:translate(83px,34px); fill:var(--amber-strong); }
  84%{ transform:translate(83px,34px); fill:var(--amber-strong); }
  91%{ transform:translate(0,0); fill:var(--amber-strong); }
  91.3%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  100%{ transform:translate(0,0); fill:var(--waypoint-blue); }
}
@keyframes trackTravel2{
  0%{ transform:translate(0,0); fill:var(--amber-strong); }
  39%{ transform:translate(0,0); fill:var(--amber-strong); }
  45%{ transform:translate(180px,0px); fill:var(--amber-strong); }
  45.3%{ transform:translate(180px,0px); fill:var(--navy); }
  89%{ transform:translate(180px,0px); fill:var(--navy); }
  95%{ transform:translate(0,0); fill:var(--navy); }
  95.3%{ transform:translate(0,0); fill:var(--amber-strong); }
  100%{ transform:translate(0,0); fill:var(--amber-strong); }
}
@keyframes trackTravel1M{
  0%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  20%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  27%{ transform:translate(-20px,95px); fill:var(--waypoint-blue); }
  27.3%{ transform:translate(-20px,95px); fill:var(--amber-strong); }
  84%{ transform:translate(-20px,95px); fill:var(--amber-strong); }
  91%{ transform:translate(0,0); fill:var(--amber-strong); }
  91.3%{ transform:translate(0,0); fill:var(--waypoint-blue); }
  100%{ transform:translate(0,0); fill:var(--waypoint-blue); }
}
@keyframes trackTravel2M{
  0%{ transform:translate(0,0); fill:var(--amber-strong); }
  39%{ transform:translate(0,0); fill:var(--amber-strong); }
  45%{ transform:translate(-10px,97px); fill:var(--amber-strong); }
  45.3%{ transform:translate(-10px,97px); fill:var(--navy); }
  89%{ transform:translate(-10px,97px); fill:var(--navy); }
  95%{ transform:translate(0,0); fill:var(--navy); }
  95.3%{ transform:translate(0,0); fill:var(--amber-strong); }
  100%{ transform:translate(0,0); fill:var(--amber-strong); }
}
.explain-frame.sg-playing .track-traveler-1{ animation-name:trackTravel1; animation-duration:15s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }
.explain-frame.sg-playing .track-traveler-2{ animation-name:trackTravel2; animation-duration:20s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; animation-delay:-7.5s; }
.explain-frame.sg-playing .track-traveler-1-m{ animation-name:trackTravel1M; animation-duration:15s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; }
.explain-frame.sg-playing .track-traveler-2-m{ animation-name:trackTravel2M; animation-duration:20s; animation-timing-function:ease-in-out; animation-iteration-count:infinite; animation-delay:-7.5s; }

/* ---------- Narrow viewports (shared) ---------- */
@media (max-width:760px){
  .logo-mark img{ height:32px; }
  .site-nav{ display:none; }
  .header-cta{ display:none; }
  .nav-toggle{ display:flex; }
  .diff-grid{ grid-template-columns:1fr; }
  .cap-grid{ grid-template-columns:1fr; }
  .method-row{ grid-template-columns:1fr; gap:22px; }
  .section-head{ font-size:23px; }
  section{ padding:56px 0; }
  section.tight{ padding:44px 0; }
  .page-hero{ padding-top:52px; padding-bottom:44px; }
  .page-hero h1{ font-size:27px; }
  .form-grid{ grid-template-columns:1fr; }
  .locations-grid{ grid-template-columns:1fr; }
  .legal-content h2{ font-size:20px; margin-top:34px; }
  .legal-content h3{ font-size:16px; }
  .explain-frame{ aspect-ratio:340/400; }
  .explain-frame .desktop-variant{ display:none; }
  .explain-frame .mobile-variant{ display:block; }
}
