/* ==========================================================================
   Taq Ventures — shared stylesheet
   Used by: index.html, case-studies.html
   Brand colors sampled directly from the client-supplied logo files
   (assets/taq-icon.png / assets/taq-logo.png), background RGB(66,90,125).
   ========================================================================== */

/* ==========================================================================
   Webfonts — self-hosted, from this origin.
   ==========================================================================

   These used to be a <link> to fonts.googleapis.com on every page. That cost
   every visitor two extra connections before any text could paint: one DNS
   lookup + TLS handshake to googleapis.com for a stylesheet, then a second one
   to gstatic.com for the woff2 files that stylesheet names. On a slow mobile
   connection those two handshakes are the slowest part of the page — and they
   are serialised, because the browser cannot know which font file it needs
   until the first request comes back.

   Serving them from /assets/fonts/ removes both. The files arrive on the
   connection already open for the HTML, and the browser learns about them from
   this stylesheet, which it was fetching anyway. The `preload` hints in each
   page's <head> start the two above-the-fold files even earlier.

   The rules below are generated — run `node scripts/fetch-fonts.mjs --css` and
   paste the result rather than hand-editing, and see that script for how the
   binaries got here and how to refresh them. The version in each filename
   (v13, v20) is Google's family version, which is what makes it safe for
   _headers to serve these as immutable: a new version is a new filename.

   `font-display: swap` and the `unicode-range` gating are carried over exactly
   as Google served them, so text still paints immediately in the fallback and
   a page only downloads the subsets it actually uses. Only latin and latin-ext
   are here; the cyrillic, greek and vietnamese subsets were never downloaded
   by an en-CA page and are not in the repository.
   ========================================================================== */

/* Body text. One variable file per subset covering 400-600 — Google serves the
   same woff2 for all three weights and lets the browser interpolate, so this is
   one rule with a weight range rather than three identical ones. CSS asking for
   700 clamps to 600, exactly as it did before this change. */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/inter-v20-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/inter-v20-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Headings. Three static instances per subset: unlike Inter, Barlow Condensed
   is served as one file per weight. */
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-500.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-600.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-700.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-ext-500.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-ext-600.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/barlow-condensed-v13-latin-ext-700.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root{
  /* Surface */
  --bg: #FFFFFF;
  --panel: #F6F6F4;
  /* Same tint as --panel, but let through: the full-bleed tinted bands used to
     be opaque, so the ambient wash stopped dead at each band edge and left a
     hard horizontal line across the page — usually right beside a heading.
     Boxed callouts and form panels stay opaque; only the full-width bands use
     this. */
  --panel-veil: rgba(246, 246, 244, 0.82);
  --line: #E6E6E3;
  --line-strong: #C7C7C2;

  /* Type */
  --text: #16181B;
  /* Was #6B7178, which measured 4.49:1 on white — a hair under AA, and the
     ambient wash behind the page pushes anything borderline over the edge.
     This reads as the same grey and holds 5.9:1 on white, 4.7:1 on the
     densest part of the wash. */
  --muted: #5F656C;

  /* Brand accent — sampled from client logo, RGB(66,90,125). Two blues, and
     they are not interchangeable: the navy pair below owns every filled button
     and every primary action, and --accent-bright is the lighter, more
     saturated blue used for accents only — the dash markers above section
     labels, the stat values in a case study's fact row, and link hover states.
     Before it existed the whole site was white, grey, black and one navy, which
     left nothing at all to mark a section or a number with.

     Same hue family as the brand blue (around 210°), taken up in saturation and
     lightness rather than sideways in hue, so it reads as the brand's own blue
     rather than a second brand. It holds 5.2:1 on white and 4.8:1 on --panel,
     so it clears AA as small text everywhere it is used — which the obvious
     brighter candidates around #2E7BC4 do not. Do not put it on a filled
     button: white on it is 4.0:1, and the navy is there for that. */
  --accent: #425A7D;        /* exact brand blue — high-contrast on white, used for text/links/small UI */
  --accent-solid: #33465F;  /* deeper blue — used for primary CTA emphasis */
  --accent-bright: #1D6FB8; /* lighter accent blue — section markers, stat values, link hovers */
}

*{ box-sizing: border-box; margin:0; padding:0; }
html{ scroll-behavior: smooth; }
body{
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, .display{
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: 0.002em;
  /* Even out the rag on every heading in the site, not just the handful that
     asked for it locally. Headings here sit in grid columns of 1fr and 1.2fr,
     which is exactly the width where the last word drops onto a line of its
     own and the heading reads as broken. The spec caps `balance` at ~6 lines,
     so it can never reach body copy, and browsers without it just wrap
     normally. */
  text-wrap: balance;
}
/* Body copy gets `pretty` instead: it leaves the line breaking alone except
   for the last line, so a paragraph never ends on a single stranded word.
   Applied here rather than per-page — every stylesheet was setting this on its
   own paragraph classes or, mostly, not at all. */
p, li, dd, figcaption, label{ text-wrap: pretty; }
a{ color: inherit; }

/* Accessibility: visible focus ring for keyboard navigation.
   Do not remove — this is the only focus indicator on the page. */
a:focus-visible,
button:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.wrap{
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 32px;
}
@media (max-width: 640px){
  .wrap{ padding: 0 20px; }
  /* Guard against sideways page scroll on small screens. A single
     overflowing child used to drag the whole layout off its gutters, which
     read as everything being misaligned and clipped at the left edge. */
  body{ overflow-x: clip; }
}

/* Reusable two-column split: heading/eyebrow in a narrower left column,
   short supporting content (subhead, CTA) in a wider right column.
   Used for section headers site-wide instead of stacking everything in
   one narrow centered column. Not used for long-form body paragraphs —
   those stay narrower for readability. */
.split{
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 48px;
  align-items: center;
}
@media (max-width: 800px){
  .split{ grid-template-columns: 1fr; gap: 20px; }
}

/* ---- skip link ---- */
/* The first focusable element on every page, and invisible until it is
   focused. Clipped rather than display:none or visibility:hidden: those remove
   an element from the tab order entirely, so the link could never be reached
   to be shown. It goes `fixed` on focus so it appears at the top of the
   viewport wherever the page happens to be scrolled.

   :focus, not :focus-visible — this link exists for keyboard and screen-reader
   users and should appear whenever focus reaches it, including the cases the
   heuristic behind :focus-visible decides not to draw a ring for. */
.skip-link{
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.skip-link:focus{
  position: fixed;
  top: 12px;
  left: 12px;
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
  /* Above the case-study lightbox (z-index 100), which is the highest thing
     the site puts on screen. */
  z-index: 200;
  padding: 12px 18px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 4px;
  font-size: 14px;
  text-decoration: none;
}

/* ---- header / nav ---- */
header{ border-bottom: 1px solid var(--line); }
.header-inner{
  display:flex;
  align-items:center;
  justify-content:space-between;
  /* Vertical only. .header-inner is also a .wrap, and a shorthand `padding`
     here would zero out the gutter .wrap sets, dropping the wordmark and the
     hamburger hard against the screen edges. */
  padding-top: 26px;
  padding-bottom: 26px;
  flex-wrap: wrap;
  position: relative;
}
.logo-link{ display:block; line-height:0; }
/* Wordmark sizes live here rather than only in the img height attribute, so
   they can scale down at small widths without editing every page. Header and
   footer now carry the same single-line "taq×" mark — the header used to carry
   the taller stacked lockup, which is why these two heights differ by only
   2px rather than by the 10px they once did. The stacked lockup is still the
   JSON-LD logo and image, where a squarer crop suits a knowledge panel.

   32px is the mark's own aspect ratio (900x416, about 2.16:1) at the height
   the nav is set in: it matches the 69x32 width/height on the img in every
   page, so the box is reserved before the image loads and nothing shifts. */
.logo-link img{
  display:block;
  height: 32px;
  width: auto;
}
.footer-logo img{ height: 30px; }

.site-nav{
  display:flex;
  align-items:center;
  gap: 22px;
}
.nav-link{
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease;
}
.nav-link:hover{ color: var(--accent-bright); }
.nav-link.active{
  color: var(--accent-solid);
  font-weight: 600;
  text-shadow: 0 0 10px rgba(66, 90, 125, 0.45);
}
.nav-link-highlight{
  color: var(--accent);
  font-weight: 600;
}
.nav-link-highlight:hover{ color: var(--accent-solid); }
.nav-link-highlight.active{ color: var(--accent-solid); }

/* The free presence grader. It used to be the last row of the Solutions
   submenu, where a visitor had to open a menu and read past seven services to
   find the one thing on the site that gives them something before we ask for
   anything. It is the lead-generation entry point, so it gets its own outlined
   slot in the nav — the only bordered item, which reads as a tool rather than
   another page. */
.nav-link-tool{
  color: var(--accent-solid);
  font-weight: 600;
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 7px 13px;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-link-tool:hover{ background: var(--panel); color: var(--accent-solid); }
.nav-link-tool.active{
  background: var(--accent-solid);
  border-color: var(--accent-solid);
  color: #FFFFFF;
  /* The shared .nav-link.active glow is a text-shadow, which is unreadable
     against the filled background this one gets instead. */
  text-shadow: none;
}

/* ---- Solutions dropdown ---- */
.nav-dropdown{ position: relative; }
.nav-dropdown-toggle{
  display:flex;
  align-items:center;
  gap: 4px;
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  color: var(--muted);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color 0.15s ease;
}
.nav-dropdown-toggle:hover{ color: var(--accent-bright); }
.nav-dropdown-toggle.active{
  color: var(--accent-solid);
  font-weight: 600;
  text-shadow: 0 0 10px rgba(66, 90, 125, 0.45);
}
.nav-dropdown-toggle::after{
  content: '▾';
  font-size: 10px;
  transform: translateY(1px);
  transition: transform 0.18s ease;
}
.nav-dropdown-toggle[aria-expanded="true"]::after{ transform: translateY(1px) rotate(180deg); }
.nav-dropdown-menu{
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 100%;
  /* Anchored to the toggle's left edge, NOT centred on it. The menu is 270px
     wide and the "Solutions" toggle is about 70px, so centring hangs ~100px of
     menu to the left of the toggle. That is invisible on a wide screen where
     the nav sits on the right, but in the stacked menu below 960px the toggle
     sits at the left gutter and the overhang runs straight off the left edge
     of the screen, where nothing can scroll it back into view. Left-anchoring
     keeps the menu inside the page at every width, and there is always room to
     its right because "Solutions" is the second of seven nav items. */
  left: 0;
  transform: translateY(-6px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 14px 32px rgba(22, 24, 27, 0.1);
  padding: 18px 10px 10px;
  min-width: 270px;
  /* Last-resort guard so a narrow viewport or a future longer label can never
     push the panel past the right edge either. */
  max-width: calc(100vw - 24px);
  z-index: 30;
}
.nav-dropdown-menu.open{
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
@media (min-width: 961px){
  .nav-dropdown:hover .nav-dropdown-menu{
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
    transition: opacity 0.18s ease, transform 0.18s ease;
  }
}
.nav-dropdown-link{
  display: block;
  padding: 9px 12px;
  border-radius: 5px;
  font-size: 14px;
  color: var(--text);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-dropdown-link:hover{ background: rgba(66, 90, 125, 0.08); color: var(--accent-solid); }
/* The row for the page you are on. The menu used to give no sign of where you
   already were, so seven near-identical rows all read the same. A tint plus a
   left bar marks the current service without turning it into a button. */
.nav-dropdown-link.active{
  background: rgba(66, 90, 125, 0.1);
  box-shadow: inset 2px 0 0 var(--accent-solid);
  color: var(--accent-solid);
  font-weight: 600;
}
.nav-dropdown-link.nav-dropdown-all{
  color: var(--accent-solid);
  font-weight: 600;
  border-radius: 0;
  border-bottom: 1px solid var(--line-strong);
  margin-bottom: 6px;
  padding: 9px 12px 14px;
}
/* This row already reads as the emphasised one, so on solutions.html it only
   needs the bar — the tint on a square-cornered full-width row looks like a
   rendering error against the border under it. */
.nav-dropdown-link.nav-dropdown-all.active{ background: none; }
/* Category headings inside the Solutions menu. Seven flat rows read as a wall
   of similar-length labels; three headed groups let the eye land on the
   category first. Each label is also a link to that pillar's own page, so the
   category is reachable from the menu and not only through the homepage — but
   it stays styled as a heading rather than an eighth row, or the three pillars
   would be buried in the list of services.
   Small, uppercase and tracked out, in brand blue with a short accent rule
   trailing the text — the same eyebrow idiom the page sections use. Muted grey
   left the categories weaker than the rows they head, which is what made the
   whole panel read as one flat, faded list with no entry point. The rule
   trails rather than leads so the heading text keeps sharing a left edge with
   the service rows under it. */
.nav-dropdown-group-label{
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 4px;
  padding: 0 12px;
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.nav-dropdown-group-label::after{
  content: '';
  flex: none;
  width: 18px;
  height: 2px;
  background: var(--accent);
  transition: width 0.15s ease, background 0.15s ease;
}
a.nav-dropdown-group-label{
  text-decoration: none;
  border-radius: 5px;
  transition: color 0.15s ease;
}
a.nav-dropdown-group-label:hover{ color: var(--accent-solid); }
a.nav-dropdown-group-label:hover::after{ width: 26px; background: var(--accent-solid); }
/* The category the current page belongs to, whether that is the category page
   itself or one of the services under it. */
.nav-dropdown-group.is-current .nav-dropdown-group-label{ color: var(--accent-solid); }
.nav-dropdown-group.is-current .nav-dropdown-group-label::after{
  width: 26px;
  background: var(--accent-solid);
}
/* Rule between groups only, never above the first one — the "All solutions"
   row already carries a bottom border, and two rules stacked 6px apart looks
   like a mistake. */
.nav-dropdown-group + .nav-dropdown-group{
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line-strong);
}
@media (max-width: 960px){
  /* In the stacked mobile nav the dropdown has to span the full menu width.
     Left at its default it collapses to the width of the "Solutions" label,
     which forces the longer link labels to wrap a word per line. */
  .nav-dropdown{ width: 100%; }
  .nav-dropdown-toggle{
    width: 100%;
    justify-content: space-between;
    padding: 11px 0;
  }
  .nav-dropdown-menu{
    display: none;
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    background: none;
    box-shadow: none;
    border: none;
    /* A left rule ties the sub-items to the parent item instead of leaving
       them floating at an arbitrary indent. */
    border-left: 2px solid var(--line-strong);
    border-radius: 0;
    min-width: 0;
    margin: 2px 0 6px;
    padding: 2px 0 2px 14px;
    transition: none;
  }
  .nav-dropdown-menu.open{ display: flex; }
  /* Roomier rows — these are the primary touch targets on mobile. */
  .nav-dropdown-link{ padding: 11px 8px; }
  .nav-dropdown-link.nav-dropdown-all{
    margin-bottom: 4px;
    padding: 4px 8px 12px;
  }
  /* Align the headings with the roomier mobile rows (8px, not 12px) and give
     each group a little more air now that the rows are taller. */
  .nav-dropdown-group-label{ padding: 0 8px; margin-bottom: 2px; }
  .nav-dropdown-group + .nav-dropdown-group{ margin-top: 12px; padding-top: 12px; }
  /* The tint alone is thin against the plain page background the mobile menu
     sits on, so the current row also carries the bar at the row's own left
     edge rather than the panel's. */
  .nav-dropdown-link.active{ box-shadow: inset 3px 0 0 var(--accent-solid); }
}

/* Hamburger toggle — hidden on desktop, shown only when the nav can't
   fit on one line at small widths. Bars morph into an X when open. */
.nav-toggle{
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  /* 44px min box keeps the tap target at the accessible minimum while the
     bars themselves stay 22px wide. */
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  cursor: pointer;
}
.nav-toggle span{
  width: 22px;
  height: 2px;
  background: var(--text);
  display: block;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle.open span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.nav-toggle.open span:nth-child(2){ opacity: 0; }
.nav-toggle.open span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }

/* 960px, not 640px. The seven top-level items plus the Solutions toggle need
   roughly 620px of the header to themselves, and the wordmark takes the rest of
   a narrow viewport — so anywhere between about 620px and 850px the nav had
   already wrapped onto its own line below the logo and then jammed all seven
   labels together with almost no gap between them, while the hamburger that
   would have fixed it was still waiting for 640px. Collapsing at 960px means
   the row only ever renders where it genuinely fits beside the wordmark, and
   every width below that gets the stacked menu instead. Raising it further
   would start taking the menu away from laptops that have room for it. */
@media (max-width: 960px){
  .nav-toggle{
    display: flex;
    /* The bars are centred in a 44px box, leaving 11px either side. Pulling
       that back lines the bars up with the .wrap gutter, so they share an
       edge with the wordmark opposite them. */
    margin-right: -11px;
  }
  .site-nav{
    display: none;
    flex-direction: column;
    /* stretch (not flex-start) makes every row full width, so a tap lands
       anywhere on the line and all labels share the logo's left edge. */
    align-items: stretch;
    gap: 2px;
    width: 100%;
    margin-top: 16px;
    padding: 10px 0 14px;
    border-top: 1px solid var(--line);
  }
  .site-nav.open{ display: flex; }
  .nav-link{ padding: 11px 0; }
  /* Full-strength text on mobile. Muted grey is right in the desktop header,
     where the nav is a quiet strip beside the wordmark and colour is reserved
     for the item you are on — but the mobile menu IS the screen while it is
     open, and seven grey rows over a white sheet read as disabled. Contact and
     the grader keep their own colours, hence the exclusions. */
  .nav-link:not(.nav-link-highlight):not(.nav-link-tool),
  .nav-dropdown-toggle{ color: var(--text); }
  .nav-link.active:not(.nav-link-highlight):not(.nav-link-tool),
  .nav-dropdown-toggle.active{ color: var(--accent-solid); }
  /* The stacked nav makes every row full width, which would stretch the
     grader's outline across the menu and stop it reading as a tool. Sized to
     its label instead, with room either side of the rows above and below. */
  .nav-link-tool{
    align-self: flex-start;
    padding: 10px 14px;
    margin: 6px 0;
  }
}

/* Phone-only header sizing. This used to live in the block above, but that
   block now starts at 960px and neither rule belongs at tablet width: a 34px
   wordmark and a 12px header are sized for a viewport where the mark is the
   only branding above the fold. */
@media (max-width: 640px){
  /* Tighter than desktop so the larger wordmark doesn't inflate the bar.
     Vertical only — see the note on .header-inner above. */
  .header-inner{
    padding-top: 12px;
    padding-bottom: 12px;
  }
  /* Still slightly bigger than desktop: the mark is the only branding visible
     above the fold on a phone, so it carries more weight there. It no longer
     needs the extra height it did as a stacked lockup, whose second line read
     as fine print below 34px — a single line has no small type to protect, so
     this is now a 2px nudge rather than a 6px one. */
  .logo-link img{ height: 34px; }
  .footer-logo img{ height: 30px; }
}

/* Buttons/CTAs: filled blue background — the brand button style. */
.btn{
  display:inline-block;
  font-family:'Inter', sans-serif;
  font-weight:600;
  font-size: 14px;
  color: #FFFFFF;
  text-decoration:none;
  white-space: nowrap;
  padding: 12px 22px;
  background: var(--accent);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.15s ease;
}
.btn:hover{ background: var(--accent-solid); color: #FFFFFF; }
.btn-solid{
  background: var(--accent-solid);
  font-weight: 700;
}
.btn-solid:hover{ background: var(--accent); }
/* Neutral variant, for a real action that is not the page's primary one — the
   about band's link to the full story sits under prose that leads nowhere else,
   so it needs a button's affordance without claiming the blue that the grader
   and the pillar CTAs use. Grey fill on a hairline border rather than an
   outlined blue button, so it stays inside the line-based language and does not
   read as a second-tier version of the same choice. */
.btn-grey{
  background: var(--panel);
  border: 1px solid var(--line-strong);
  color: var(--text);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.btn-grey:hover{
  background: #EAEAE6;
  border-color: var(--muted);
  color: var(--text);
}

/* Utility: consistent spacing above a button that follows a block of content.
   For a pair of real actions the visitor is choosing between (about.html,
   404.html). The "and here is the whole list" panel that closes a section is
   .next-step below, not this. */
.btn-row{ margin-top: 24px; }

/* ---- Onward row: the button that closes a column of prose.
   All that is left of this is the row itself, used once — the about band on
   the homepage, whose row holds a real `.btn` rather than a lateral link. The
   "and here is the whole list" links that used to sit in it are now
   `.next-step` panels below. ---- */
.onward{
  display: flex;
  justify-content: flex-end;
  margin-top: 30px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
/* Opt back into the page's left rag. The right-aligned default exists to clear
   left-aligned card buttons in the list sections; where an onward row closes a
   column of prose instead, there is nothing beneath it to clear, and the link
   reads as detached from the paragraph it follows. */
.onward-left{ justify-content: flex-start; }
@media (max-width: 640px){
  .onward{ justify-content: flex-start; margin-top: 24px; }
}

/* ---- Next step: the panel that closes a list section ("View all solutions",
   "View case studies", "See the whole board").

   Two earlier passes at this are worth knowing about, because both failed in
   opposite directions. It began as a plain `.btn`, which put a fourth filled
   blue rectangle under three pillar cards that each already had one — four
   identical buttons reading as four peer choices when only three of them are.
   The fix was to demote it to a small underlined link on a hairline, set to
   the right of the section, which cleared the jam but left the single most
   useful link in the band looking like a footnote: 15px of text under a
   full-width list, easy to miss entirely on a phone.

   So it is neither now. It is a full-width panel — the width is what gives it
   presence, rather than colour or weight — carrying three lines: what is
   through there, the destination, and one sentence on what it is worth. It
   cannot be confused with the card buttons above it because it shares nothing
   with them: no fill, a different shape, and the page's own type at a heading
   size. The only accent is a blue spine on the left edge, short at rest and
   running the full height on hover, and the arrow, which slides. Both are
   transforms, so the hover costs no layout. ---- */
.next-step-row{ margin-top: 26px; }
.next-step{
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 24px;
  /* Sized against the lists these close rather than in isolation. At
     22px/26px of padding around a 26px title the panel stood ~150px tall,
     twice the height of a ticket row and taller than a pillar card's whole
     header — the section's own content read as preamble to it. The box still
     spans the full width, which is where its presence comes from; it just no
     longer outweighs everything above it. */
  padding: 18px 24px 18px 26px;
  background: #FFFFFF;
  border: 1px solid var(--line);
  border-radius: 4px;
  /* Keeps the spine inside the rounded corners. An outline is drawn outside
     the box, so the focus ring is unaffected. */
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: background 0.18s ease, border-color 0.18s ease;
}
/* The spine. transform-origin at the top so it grows downward rather than out
   from the middle, which reads as the row filling in. */
.next-step::before{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 3px;
  background: var(--accent);
  transform: scaleY(0.32);
  transform-origin: 50% 0;
  transition: transform 0.22s ease;
}
.next-step-text{
  display: grid;
  gap: 6px;
  min-width: 0;
}
.next-step-label{
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}
.next-step-title{
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  /* Two passes down from clamp(24px, 2.6vw, 30px), which put it within 2px of
     the 32px section h2 above it: three of these panels run down the homepage,
     so at that size the page read as six headings of near-equal weight and no
     clear order. The pillar-title size (26px) that replaced it still made the
     panel the largest thing in a section like "Proven on the job", where
     nothing else exceeds the 19px client name. Pitched just above that
     instead — clearly the strongest link in the band, clearly not a heading
     competing with the one at the top of it. */
  font-size: clamp(20px, 1.7vw, 22px);
  line-height: 1.05;
  letter-spacing: 0.002em;
  color: var(--text);
  transition: color 0.18s ease;
}
.next-step-meta{
  font-size: 15px;
  line-height: 1.5;
  color: var(--muted);
  /* 62ch here is a prose measure applied to a one-sentence caption, and it
     wrapped the longest of these (the case-studies panel) onto a second line
     while a third of the panel sat empty to the left of the arrow — so that
     one panel ran taller than its siblings for no reason a reader can see.
     Wide enough now that each caption holds one line at full width, and still
     short of the ~104ch the grid column actually offers. */
  max-width: 88ch;
  text-wrap: pretty;
}
.next-step-arrow{
  flex-shrink: 0;
  color: var(--line-strong);
  transition: transform 0.18s ease, color 0.18s ease;
}
.next-step:hover{
  background: var(--panel);
  border-color: var(--line-strong);
}
.next-step:hover::before{ transform: scaleY(1); }
.next-step:hover .next-step-title{ color: var(--accent-bright); }
.next-step:hover .next-step-arrow{
  transform: translateX(6px);
  color: var(--accent);
}
@media (max-width: 640px){
  .next-step-row{ margin-top: 20px; }
  .next-step{
    gap: 16px;
    padding: 16px 16px 16px 20px;
  }
  .next-step-title{ font-size: 21px; }
  .next-step-meta{ font-size: 14px; }
}
@media (prefers-reduced-motion: reduce){
  .next-step,
  .next-step::before,
  .next-step-title,
  .next-step-arrow{ transition: none; }
  .next-step::before{ transform: none; }
  .next-step:hover .next-step-arrow{ transform: none; }
}

/* ---- FAQ: plain accordion, no boxes. Shared across any page. ---- */
.faq-list{ margin-top: 4px; }
.faq-item{ border-top: 1px solid var(--line); }
.faq-item:last-child{ border-bottom: 1px solid var(--line); }
.faq-question{
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 20px 0;
  background: none;
  border: none;
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 18px;
  font-weight: 500;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.faq-toggle{
  font-family: 'Inter', sans-serif;
  font-size: 20px;
  font-weight: 400;
  color: var(--accent);
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.faq-item.open .faq-toggle{ transform: rotate(45deg); }
.faq-answer{
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
}
.faq-answer p{
  color: var(--muted);
  font-size: 15px;
  max-width: 62ch;
  padding-bottom: 20px;
}

/* ---- promoted grader band: shared by index.html and solutions.html ----
   The free grader is the one thing on the site that gives a visitor something
   before we ask anything of them, so it gets a band of its own high on both
   pages rather than a link in a submenu. The address typed here is handed to
   presence-grade.html?url=..., which grades on arrival — see
   assets/grader-promo.js. Styling stays inside the line-based language: a
   tinted band closed by a rule, no card and no shadow. */
.grader-promo{
  background: var(--panel-veil);
  /* No top rule: both pages that carry the band place it under a section that
     already ends in one, and two adjacent 1px rules read as a 2px line. Same
     shape as .pg-download, the tinted band on the grader page itself. */
  border-bottom: 1px solid var(--line);
  padding: 56px 0;
}
/* Two halves rather than the 1.2fr / 1fr the rest of the page uses. The band
   used to be a paragraph in the wide column and the form in the narrow one,
   which meant the offer arrived as five lines of prose listing what the grader
   checks — the one part of it a visitor would rather scan than read. So the
   audit (the ask and its single field) takes one half, the points take the
   other, and the two are peers: equal columns, no dominant one. The footer
   line closes the band across both. */
.grader-promo-inner{
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* No row gap: the footer line spans both columns on the second row and sets
     its own space with a margin, so a row gap here would stack on top of it. */
  gap: 0 56px;
  align-items: start;
}
.grader-promo-lead,
.grader-promo-points-col{ min-width: 0; }
.grader-promo-eyebrow{
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: 14px;
  margin-bottom: 18px;
}
.grader-promo-eyebrow .rule{
  width: 28px;
  height: 2px;
  background: var(--accent-bright);
}
.grader-promo h2{
  font-size: 32px;
  margin-bottom: 16px;
}
.grader-promo-body{
  color: var(--muted);
  max-width: 46ch;
}

/* ---- the points, in the band's other half ----
   A divided list of short claims, each with one line saying what it means.
   Same spec-sheet idiom as the service rows and the ticket list, so the column
   reads as information about the tool rather than a second pitch: the first
   rule is the strong one, which gives the list a top edge on the tint, and the
   rest are hairlines between rows. Content is graderPromo.points. */
.grader-promo-points-label{
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}
.grader-promo-points{ list-style: none; }
.grader-promo-points li{
  display: grid;
  gap: 3px;
  padding: 13px 0;
  border-top: 1px solid var(--line);
}
.grader-promo-points li:first-child{ border-top-color: var(--line-strong); }
.grader-promo-points li:last-child{ padding-bottom: 0; }
.grader-promo-point-title{
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}
.grader-promo-point-body{
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
}

/* The line that closes the band, under both columns rather than tucked below
   the paragraph in one of them. It is the only place on the page that says
   what an email is for, so it reads across the full width: the report is free
   and complete on screen, and the PDF is the one thing we ask for an address
   to send. */
.grader-promo-note{
  grid-column: 1 / -1;
  margin-top: 34px;
  padding-top: 18px;
  border-top: 1px solid var(--line-strong);
  font-size: 14px;
  color: var(--muted);
  /* The rule has to reach the far edge of the points column — a line that
     closes the band cannot stop halfway across it. So the element stays full
     width and the reading measure comes from padding instead of max-width,
     which would have shortened the border along with the text. */
  padding-right: 45%;
}
/* White box on the tinted band, and square-edged fields — the same treatment
   the grader page gives its own forms, so the band looks like the front door to
   that tool rather than a different component. */
.grader-promo-form{
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Directly under the heading it belongs to now, in the same half of the band,
     so it fills its column rather than being capped at a width that used to
     stop it colliding with the prose beside it. */
  margin-top: 24px;
  background: var(--bg);
  border: 1px solid var(--line);
  padding: 26px;
}
.grader-promo-form input{
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 0;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 17px;
  padding: 14px 16px;
  transition: border-color 0.15s ease;
}
.grader-promo-form input:hover{ border-color: var(--muted); }
.grader-promo-form input:focus{
  outline: none;
  border-color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.grader-promo-form input::placeholder{ color: var(--muted); }
.grader-promo-form button{
  align-self: flex-start;
  border: none;
  cursor: pointer;
}
.grader-promo-label{
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 16px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: -6px;
}
.grader-promo-link{
  font-size: 14px;
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
}
.grader-promo-link:hover{ color: var(--accent-bright); }
/* Stacks a step earlier than .split does: two halves of a 1056px wrap are
   ~500px each, and by 860px the points column is narrow enough that its
   one-line bodies wrap to three. */
@media (max-width: 860px){
  .grader-promo-inner{ grid-template-columns: 1fr; gap: 30px; }
  .grader-promo-body{ max-width: 62ch; }
  /* The stacked grid's 30px row gap already sits above the footer rule, and
     there is no second column left to clear, so the text runs full width. */
  .grader-promo-note{ margin-top: 0; padding-right: 0; }
}
@media (max-width: 640px){
  .grader-promo{ padding: 36px 0; }
  .grader-promo h2{ font-size: 26px; }
  .grader-promo-eyebrow{ margin-bottom: 14px; }
  .grader-promo-form{ padding: 20px; }
  .grader-promo-form button{ align-self: stretch; text-align: center; }
}

/* ---- footer ---- */
footer{
  border-top: 1px solid var(--line);
  padding: 32px 0;
}
.footer-inner{
  display:flex;
  justify-content:space-between;
  align-items:center;
  flex-wrap: wrap;
  gap: 14px;
}
@media (max-width: 640px){
  footer{ padding: 26px 0; }
  /* space-between strands the wrapped meta line mid-row; stacking puts the
     mark and the contact line on one shared left edge. */
  .footer-inner{
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  footer .meta{ line-height: 1.7; }
}

/* ---- mobile vertical rhythm ----
   Section padding is tuned for a desktop viewport. Carried over unchanged to a
   phone it costs a third of the screen per gap, so the page reads as a slideshow
   of one element at a time. These pull the vertical spacing in across every
   page; horizontal gutters are untouched. */
@media (max-width: 640px){
  .btn-row{ margin-top: 20px; }
  .faq-question{ padding: 16px 0; }
  .faq-answer p{ padding-bottom: 16px; }
}

/* ---- ambient background: a fixed blue wash behind all content --------------
   Fixed rather than scrolled, so it behaves like the air the page sits in
   instead of a decoration attached to one section: two gradients pushed off the
   top and bottom edges, showing through the full-bleed bands that let it
   through (--panel-veil).

   Density is deliberately kept to the edges. The content column is 1120px
   inside a wrap that leaves only ~80px of gutter on a laptop, so anything dense
   in the middle of the viewport lands under body copy — the wash tops out
   around a fifth of the accent's strength anywhere text sits, which is what
   keeps --muted paragraphs above AA on top of it.

   There used to be four blurred cores drifting slowly over this wash. They are
   gone, and the four <span class="fog-blob"> elements went out of the 21 pages
   with them. Each was a 580-820px layer with blur(120px) and `will-change` on a
   30-48s infinite animation: a compositing job the GPU repeats for as long as
   the tab is open, on a page that is otherwise completely static. They also
   made the contrast under body copy time-varying, since the drift keyframes
   swung opacity between 0.36 and 0.56 — so the figure in the paragraph above
   was a range rather than a number. The wash is the part that reads as depth.
   The drift was the part that cost battery to notice. */
.bg-fog{
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(135% 90% at 50% -18%, rgba(66, 90, 125, 0.14), transparent 62%),
    radial-gradient(115% 80% at 50% 118%, rgba(51, 70, 95, 0.12), transparent 60%);
}
/* Thinner on a phone, where the same wash covers a much narrower column and
   sits closer to the text. */
@media (max-width: 640px){
  .bg-fog{
    background:
      radial-gradient(140% 70% at 50% -12%, rgba(66, 90, 125, 0.11), transparent 60%),
      radial-gradient(120% 60% at 50% 115%, rgba(51, 70, 95, 0.09), transparent 60%);
  }
}
footer .meta{ color: var(--muted); font-size: 14px; }
footer .meta a{ text-decoration: underline; text-decoration-color: var(--line-strong); }

/* ---- footer bottom row: copyright, legal links, profile icons ----
   Its own row under a rule, so the legal line and the profiles sit apart from
   the contact details rather than being appended to an already-long line. */
.footer-bottom{
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 24px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
}
.footer-legal{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 18px;
}
.footer-legal p{ margin: 0; }
.footer-legal a{
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease;
}
.footer-legal a:hover{ color: var(--accent-bright); }

footer .footer-social{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
}
footer .footer-social a{
  color: var(--text);
  text-decoration: none;
  transition: color 0.15s ease;
}
footer .footer-social a:hover{ color: var(--accent-bright); }

/* A profile on a network with an icon shows as the icon. Keyed on the host
   rather than a class because replaceSocialLinks, the renderSocial copies in
   the render scripts and the static HTML all emit a plain labelled link — so
   nothing about the markup changes, and a network with no icon here just keeps
   its label. The label stays inside the link, pushed out of view, as its
   accessible name. The icon is a mask filled with currentColor so it follows
   the hover colour, and it is on ::before rather than the link itself so the
   mask does not also clip the keyboard focus ring. */
footer .footer-social a:is([href*="instagram.com"], [href*="facebook.com"], [href*="linkedin.com"]){
  position: relative;
  display: inline-block;
  width: 24px;
  height: 24px;
  overflow: hidden;
  white-space: nowrap;
  text-indent: 100%;
}
footer .footer-social a:is([href*="instagram.com"], [href*="facebook.com"], [href*="linkedin.com"])::before{
  content: "";
  position: absolute;
  inset: 0;
  background-color: currentColor;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
footer .footer-social a[href*="instagram.com"]::before{
  -webkit-mask-image: url(icons/instagram.svg);
  mask-image: url(icons/instagram.svg);
}
footer .footer-social a[href*="facebook.com"]::before{
  -webkit-mask-image: url(icons/facebook.svg);
  mask-image: url(icons/facebook.svg);
}
footer .footer-social a[href*="linkedin.com"]::before{
  -webkit-mask-image: url(icons/linkedin.svg);
  mask-image: url(icons/linkedin.svg);
}

@media (max-width: 640px){
  /* Same reasoning as .footer-inner above: stacked, on one left edge. */
  .footer-bottom{
    flex-direction: column;
    align-items: flex-start;
    margin-top: 20px;
    padding-top: 18px;
  }
}

/* Sits under a submit button whose action continues in the user's mail app,
   so nobody reads "Open this in my email app" and wonders what just happened. */
.form-note{
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 46ch;
}

/* ==========================================================================
   Page band — the top section of every page.
   The homepage refresh introduced a near-black "ink" hero; this is the same
   structure (a faint engineering grid faded to the edges, a soft blue glow,
   bold condensed headings, lifting buttons) softened onto the logo's own slate
   blue, and shared so every page opens the same way.

   Each page's first section is the skip-link target, `section#content`, which
   is what the selector keys on — no per-page markup. The legal pages put
   #content on <main>, so their `.intro` is named directly. Wrapping them in
   :is() gives every rule below id-level specificity, so it wins over the
   per-page stylesheets' eyebrow/paragraph colours without !important.
   ========================================================================== */
:root{
  --band: #425A7D;                      /* exact brand blue, from the logo */
  --band-deep: #354A68;
  --band-line: rgba(255, 255, 255, 0.16);
  --band-body: #E6ECF3;                 /* 6:1 on --band */
  --band-soft: #D3DDE9;                 /* eyebrows, secondary lines */
  --band-rule: #A9CDEF;
}

:is(section#content, main#content > .intro){
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: #FFFFFF;
  border-bottom: none;
  background:
    radial-gradient(110% 90% at 82% 0%, rgba(140, 195, 245, 0.28), transparent 55%),
    radial-gradient(90% 80% at 10% 100%, rgba(38, 54, 78, 0.45), transparent 60%),
    linear-gradient(180deg, #4A6387, var(--band) 60%, var(--band-deep));
}
/* The grid texture, faded out towards the edges so it reads as a surface and
   not as a pattern. Decorative, so a pseudo-element. */
:is(section#content, main#content > .intro)::before{
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(85% 75% at 50% 40%, #000, transparent 82%);
  mask-image: radial-gradient(85% 75% at 50% 40%, #000, transparent 82%);
}
:is(section#content, main#content > .intro) h1{
  color: #FFFFFF;
  font-weight: 700;
  letter-spacing: -0.01em;
}
:is(section#content, main#content > .intro) p{ color: var(--band-body); }
:is(section#content, main#content > .intro) :is(.eyebrow, .hero-tag, .about-eyebrow, .contact-eyebrow, .va-eyebrow, .pg-eyebrow){
  color: var(--band-soft);
  font-weight: 600;
  letter-spacing: 0.08em;
}
:is(section#content, main#content > .intro) .rule{ background: var(--band-rule); }
:is(section#content, main#content > .intro) :is(.va-subhead, .pg-intro, .hero-accent){ color: #FFFFFF; }
:is(section#content, main#content > .intro) :is(.pg-nowall, .legal-updated){ color: var(--band-soft); }
:is(section#content, main#content > .intro) a:not(.btn){ color: #FFFFFF; }
:is(section#content, main#content > .intro) a:focus-visible{ outline-color: #FFFFFF; }
/* Primary action inverts to white, so it still leads on a blue ground. */
:is(section#content, main#content > .intro) .btn,
:is(section#content, main#content > .intro) .btn-solid{
  background: #FFFFFF;
  color: var(--accent-solid);
  box-shadow: 0 10px 24px -12px rgba(20, 30, 46, 0.6);
}
:is(section#content, main#content > .intro) .btn:hover,
:is(section#content, main#content > .intro) .btn-solid:hover{
  background: #EAF1F9;
  color: var(--accent-solid);
}
/* Secondary action as a ghost button. */
:is(section#content, main#content > .intro) .btn-grey{
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.55);
  color: #FFFFFF;
  box-shadow: none;
}
:is(section#content, main#content > .intro) .btn-grey:hover{
  background: rgba(255, 255, 255, 0.16);
  border-color: #FFFFFF;
  color: #FFFFFF;
}

/* ---- buttons: lift and a tinted shadow on the primary ---- */
.btn{
  border-radius: 6px;
  transition: background 0.18s ease, transform 0.18s cubic-bezier(.2, .7, .3, 1), box-shadow 0.18s ease, border-color 0.18s ease;
}
.btn-solid{ box-shadow: 0 8px 22px -12px rgba(51, 70, 95, 0.6); }
.btn:hover{ transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce){
  .btn, .btn:hover{ transition: none; transform: none; }
}

/* ---- headings: heavier, like the homepage hero ---- */
h1, h2{ font-weight: 700; }
