/* ============================================================
   PB Security — brand skin
   Colours + type derived from the pb-security-brand skill.
   ============================================================ */

/* ---- Fonts (self-hosted Aptos, woff2) ---- */
/* url() is resolved relative to THIS stylesheet (/assets/css/), so ../fonts/…
   stays correct whether the site is at the domain root or a subdir. */
@font-face {
  font-family: "Aptos";
  src: url("../fonts/aptos/Aptos.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Aptos";
  src: url("../fonts/aptos/Aptos-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Aptos";
  src: url("../fonts/aptos/Aptos-ExtraBold.woff2") format("woff2");
  font-weight: 800; font-style: normal; font-display: swap;
}

/* ---- Brand tokens ---- */
:root {
  --burgundy: #800020;
  --burgundy-dark: #5e0018;
  --lapis: #15317E;
  --lapis-dark: #0f2560;
  --green: #2D6A4F;
  --gold: #B8860B;

  --cream: #F2F2F0;
  --cream-2: #E6E5E1;
  --cream-3: #E5E1DD;

  /* Lapis washed out to a surface. There was no light blue in the palette, and
     a panel needed one: cream reads as the page's own background, so a panel in
     it does not look like it belongs to what opened it. Both are tints of
     --lapis rather than a new hue. */
  --lapis-wash: #E8EBF4;
  --lapis-wash-line: #D3D9EB;

  --ink: #1a1a1a;
  --body: #3a3a3a;
  --muted: #6a6a6a;
  --line: #d9d6d0;

  /* Two values taken straight from PB's Word brand, for the code block and the
     data table in an article body. They are NOT the same as --line and --cream
     above, and that is the point of keeping them separate: --line is this site's
     warm grey, LINE_GREY is the master's cooler one, and reusing ours would
     quietly redraw a brand element.

     Source: claude-skills/tools/pb_brand_spec.py — LINE_GREY, and the row grey
     documented in brand/references/word.md § tables. Checked by
     `npm run check-brand-tokens`, which fails when the master moves. */
  --brand-line: #DCDEE3;
  --row-grey: #F2F2F2;
  --line-soft: #e8e5df;
  --white: #ffffff;

  --wrap: 1180px;
  --font: "Aptos", "Segoe UI", Calibri, Arial, sans-serif;
}

/* ---- Reset / base ---- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  color: var(--body);
  background: var(--white);
  line-height: 1.6;
  font-size: 16px;
}
h1, h2, h3, h4 { color: var(--lapis); line-height: 1.2; margin: 0; }
a { color: var(--lapis); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }

/* ---- Accessibility ---- */
/* Visible, consistent keyboard focus ring (mouse clicks stay clean via
   :focus-visible). Lapis on light surfaces; white on the lapis footer. */
:focus-visible { outline: 2px solid var(--lapis); outline-offset: 2px; border-radius: 2px; }
.btn:focus-visible { outline-offset: 3px; }
.site-footer a:focus-visible, .site-footer summary:focus-visible { outline-color: #fff; }
/* Skip-to-content: off-screen until focused, then slides in at the top-left. */
.skip-link { position: absolute; left: 8px; top: -48px; z-index: 1000; background: var(--burgundy); color: var(--white); padding: 10px 16px; border-radius: 6px; font-size: 14px; font-weight: 700; transition: top .15s; }
.skip-link:focus { top: 8px; text-decoration: none; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 32px; }
.eyebrow {
  font-size: 12px; font-weight: 700; letter-spacing: 1px;
  text-transform: uppercase; color: var(--burgundy); margin-bottom: 12px;
}
/* page-name eyebrow (the label above a page's H1) is dark grey */
.page-head .eyebrow, .hero .eyebrow { color: var(--body); }

/* ---- Buttons ---- */
.btn {
  display: inline-block; font-size: 13px; font-weight: 700;
  letter-spacing: .4px; padding: 12px 22px; border-radius: 6px;
  border: 1.5px solid var(--burgundy); cursor: pointer; white-space: nowrap;
  transition: background .15s, color .15s;
}
.btn:hover { text-decoration: none; }
.btn-solid { background: var(--burgundy); color: var(--white); }
.btn-solid:hover { background: var(--burgundy-dark); border-color: var(--burgundy-dark); }
.btn-outline { background: transparent; color: var(--burgundy); }
.btn-outline:hover { background: var(--burgundy); color: var(--white); }
.btn.full { display: block; text-align: center; width: 100%; }

/* ---- Nav ---- */
.site-nav {
  background: var(--white);
  position: sticky; top: 0; z-index: 50;
}
.nav-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 6px 32px;
  display: flex; align-items: center; gap: 28px;
}
/* Line the header wordmark up with the footer logo, which sits on the footer's
   content line (114px, inside the panel padding). logo.png carries ~8.2%
   transparent side margin, so the box is offset to land the visible mark there. */
/* The wordmark does not shrink. It is a flex item next to a row that can get
   long, and without this it was being squeezed to 24px of its 128px on a narrow
   window instead of the row wrapping or collapsing. */
.logo { flex: none; }
.logo img { height: 104px; width: auto; margin-left: 24px; }
.navlinks { display: flex; gap: 8px; margin-left: auto; }
.navlinks a {
  font-size: 14px; font-weight: 600; color: var(--ink);
  padding: 8px 14px; border-radius: 6px;
}
.navlinks a:hover { background: var(--cream); text-decoration: none; }
.navlinks a.active { color: var(--burgundy); }
/* News lives inside Stories and has no entry of its own, so this is the only
   sign that one has arrived. It sits IN the line rather than floating above it,
   and it is a word: the first version was a 6px dot in the corner, and it read
   as dirt on the screen rather than as a signal. Added by freshness.js against
   the reader's clock, so it goes away by itself. */
/* A framed link with the word sitting on its top-right corner, per Allan's
   sketch. The frame is drawn on the link; the tag is positioned over it and
   covers the corner, which is what leaves the frame open there. */
/* The word sits up and to the right of the label, clear of it. No frame: one
   was tried and dropped after four attempts at chasing a sketch. */
.navlinks a.is-fresh { position: relative; }
.nav-fresh {
  position: absolute; bottom: 74%; left: 52%;
  padding: 2px 7px 3px; background: var(--gold); color: var(--ink);
  font-size: 12px; font-weight: 700; line-height: 1.1; letter-spacing: .2px;
  white-space: nowrap;
}
/* The drawer's rows are full width, so "up and to the right" would put the word
   at the far edge of the screen, a long way from the label it belongs to. There
   it sits beside it. */
.nav-drawer .nav-fresh {
  position: static; display: inline-block; margin-left: 8px; vertical-align: 2px;
}
.navlinks a.stub { color: var(--muted); }
.site-nav .btn { padding: 10px 18px; }
/* Line the header "Talk to us" up with the "If you need help" CTA button, which
   sits inset from the content edge by the CTA card's padding (32px) + border (1px). */
/* THE HEIGHT IS DECLARED, NOT INHERITED, so this matches the search field it
   stands beside. Left to the padding it came out at 42.8px against the field's
   40: 13px of type times the inherited 1.6 line-height, plus 20px of padding and
   2px of border, which is a result rather than a decision and agrees with
   nothing. `inline-flex` keeps the label centred once the box no longer measures
   itself from its own text.
   ON `.nav-cta` RATHER THAN `.site-nav .btn`: the drawer's "Talk to us" is also
   a .btn inside .site-nav, and it is a full-width row on a phone. An inline-flex
   box there would shrink to its own text. Only the two boxes standing side by
   side in the bar are matched, and only in height: the radius stays at the
   site's 6px, which belongs to every button rather than to this one. */
.nav-cta {
  margin-right: 33px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
}
.nav-toggle { display: none; }

/* The line a Danish page carries when its text is English. Quiet: it is an
   explanation, not a warning, and the reader is about to read the article anyway.
   Without it the page reads as an oversight rather than as the choice it is. */
.lang-note {
  margin: 0 0 22px; padding: 10px 14px;
  background: var(--cream); border-left: 3px solid var(--line);
  font-size: 14px; color: var(--muted);
}

/* ---- Language toggle ---- */
/* Above and to the right of "Talk to us", on its corner. Same idiom as the gold
   news word over the Stories link, and chosen the same way: a small marker
   belonging to something, rather than a sixth item competing in the row.
   `.nav-cta-wrap` is what it is positioned against, which is why the button's own
   right margin moved onto the wrapper. */
.nav-cta-wrap { position: relative; flex: none; margin-right: 33px; }
.nav-cta-wrap .nav-cta { margin-right: 0; }
/* `bottom: 100%` is the button's TOP edge, so the flags clear it completely. An
   earlier version used 76%, which put them on the button rather than above it. */
.langtoggle {
  position: absolute; bottom: calc(100% + 5px); left: 62%;
  display: flex; align-items: center; gap: 5px;
}
.langtoggle a, .langtoggle .lang-on {
  display: block; line-height: 0; padding: 2px; border-radius: 4px;
  border: 1px solid transparent;
}
.langtoggle .flag { width: 21px; height: 14px; display: block; border-radius: 2px; }
/* The one you are on is STATED, the other is OFFERED, and both are always drawn.
   The current one keeps its frame and full colour; the other sits back until the
   pointer finds it. Dimming rather than hiding, because a toggle that shows one
   flag is the control everybody reads backwards. */
.langtoggle .lang-on { border-color: var(--line); }
.langtoggle a .flag { opacity: .5; transition: opacity .15s; }
.langtoggle a:hover .flag { opacity: 1; }

/* ---- Site search — the header field and the panel it opens ---- */
/* Hidden until search.js wires it (`is-ready`), the same rule the archive view
   toggle follows: a field that swallows what you type is worse than no field. */
.navsearch { display: none; }
.navsearch.is-ready {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
  width: 216px; height: 40px; padding: 0 12px;
  background: var(--cream); border: 1px solid var(--line-soft); border-radius: 8px;
  transition: background .15s, border-color .15s;
}
/* The width does NOT grow on focus. It was tried: the nav links sit on an auto
   margin, so every character typed slid the whole menu sideways. */
.navsearch.is-ready:focus-within { background: var(--white); border-color: var(--burgundy); }
.navsearch-ic {
  width: 18px; height: 18px; flex: none;
  fill: none; stroke: var(--muted); stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.navsearch.is-ready:focus-within .navsearch-ic { stroke: var(--burgundy); }
.navsearch-input {
  flex: 1; min-width: 0; padding: 0; border: 0; outline: none;
  background: transparent; font-family: var(--font); font-size: 14px;
  color: var(--ink);
}
.navsearch-input::placeholder { color: var(--muted); }

.search-panel {
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--white);
  border-top: 1px solid var(--line-soft); border-bottom: 1px solid var(--line-soft);
  box-shadow: 0 14px 30px rgba(0,0,0,.10);
  max-height: calc(100vh - 130px); overflow-y: auto;
}
.sr-cols {
  max-width: var(--wrap); margin: 0 auto; padding: 24px 32px 28px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px;
}
/* Each column carries its own footer link, so it has to be able to push it down:
   without this the three "All N ..." links land at three different heights. */
.sr-col { display: flex; flex-direction: column; min-width: 0; }
.sr-col-head { margin-bottom: 10px; }
.sr-bars { display: flex; flex-direction: column; gap: 8px; }
.sr-bar {
  display: block; padding: 10px 14px; color: var(--body);
  border: 1px solid var(--line-soft); border-radius: 10px;
  transition: background .15s, border-color .15s;
}
.sr-bar:hover { background: var(--cream); border-color: var(--line); text-decoration: none; }
.sr-bar-title { display: block; font-size: 16px; font-weight: 700; color: var(--lapis); line-height: 1.3; }
.sr-bar:hover .sr-bar-title { color: var(--burgundy); }
/* Two lines, then an ellipsis. A hero question runs to about 60 characters and a
   news teaser further, and a bar that grows to fit its longest neighbour stops
   being a bar. */
.sr-bar-line {
  margin-top: 3px; font-size: 13px; color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.sr-empty { margin-top: 2px; }
/* How many matched, when more matched than fit. Cutting a list at six silently
   would say "there are six", which is the wrong answer to the question asked. */
.sr-more { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.sr-all { display: inline-block; align-self: flex-start; margin-top: auto; padding-top: 14px; }
.sr-note { max-width: var(--wrap); margin: 0 auto; padding: 22px 32px; font-size: 15px; color: var(--muted); }
.sr-none { max-width: var(--wrap); margin: 0 auto; padding: 22px 32px 26px; }
.sr-none .sr-note { max-width: none; margin: 0; padding: 0; }
.sr-none-lead { margin: 10px 0 12px; font-size: 15px; color: var(--body); }
.sr-none-bars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }

/* ---- Hero ---- */
/* Boxed like the CTA card: a centred, rounded band inset to the content width
   (matching the CTA box's edges), not a full-bleed edge-to-edge bar. */
.hero {
  width: calc(100% - 64px);
  max-width: calc(var(--wrap) - 64px);
  margin: 20px auto 0;
  background: var(--cream);
  border: 1px solid var(--cream-2);
  border-radius: 12px;
  padding: 44px 0;
  position: relative;
  overflow: hidden;
}
/* Hard right boundary so the copy ends BEFORE the photo becomes visible, never
   running under it. The home media is 60% wide (opaque from ~56% of the box), so
   this reserves more than the 52%-wide page-head heads. Removed on mobile. */
.hero .wrap { position: relative; z-index: 1; padding-right: calc(47% + 8px); }
/* Photo sits in the empty right half of the grey box; a diagonal mask fades it
   out toward the text on the left, so it dissolves into the cream. Box size is
   unchanged — the media is absolutely positioned. */
.hero-media {
  position: absolute; top: 0; bottom: 0;
  /* Right edge = the boxed band's right edge (the band is already inset to the
     content width), clipped by the card's rounded corners. */
  right: 0;
  width: 60%;
  /* Artwork at full brightness/saturation, fading to transparent toward the
     left via an OPACITY gradient (transparency only — no dimming, no grey/white
     overlay). The fade edge is angled ~15deg from vertical (105deg) so the
     visible artwork is a touch narrower at the top; the ramp is gradual so the
     artwork's brightness carries further toward the left. Left stays clean for
     the copy. */
  -webkit-mask-image: linear-gradient(105deg, transparent 0%, transparent 27%, #000 63%);
          mask-image: linear-gradient(105deg, transparent 0%, transparent 27%, #000 63%);
  pointer-events: none;
}
/* Slideshow: 5 stacked slides, each shown ~5s, cross-fading on a 25s loop. */
.hero-slide {
  position: absolute; inset: 0;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  opacity: 0;
  animation: heroFade 25s infinite;
}
.hero-slide-1 { animation-delay: 0s;  background-image: url(../img/hero-1.jpg); }
.hero-slide-2 { animation-delay: 5s;  background-image: url(../img/hero-2.jpg); }
.hero-slide-3 { animation-delay: 10s; background-image: url(../img/hero-3.jpg); }
.hero-slide-4 { animation-delay: 15s; background-image: url(../img/hero-4.jpg); }
.hero-slide-5 { animation-delay: 20s; background-image: url(../img/hero-5.jpg); }
/* Static topbar image (non-home page-head bars). */
.hero-static img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
@keyframes heroFade {
  0%   { opacity: 0; }
  3%   { opacity: 1; }
  20%  { opacity: 1; }
  23%  { opacity: 0; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-slide { animation: none; }
  .hero-slide-1 { opacity: 1; }
}
/* Same slideshow on the grey page-head topbars — a touch smaller than the home
   hero, since those bars are shorter. */
.page-head.has-media { position: relative; overflow: hidden; }
/* Reserve the full image column so the copy ends BEFORE the artwork becomes
   visible (the media is 52% wide, right-aligned, opaque from ~62% of the box).
   A hard right boundary = the copy never glides into the image, matching the
   two-column heads on About/Customers. */
.page-head.has-media .wrap { position: relative; z-index: 1; padding-right: calc(41% + 8px); }
.page-head.has-media .hero-media { width: 52%; }
.hero h1 {
  font-size: 34px; font-weight: 800; letter-spacing: -1px;
  max-width: 720px; margin-bottom: 18px;
}
.hero-body { font-size: 16px; color: var(--muted); line-height: 1.65; max-width: 560px; margin: 0 0 30px; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }

/* ---- Journey (homepage steps) ---- */
/* Spacing evened out 2026-08-09: it was 72px above the section and 16px down to
   the cards, so the section floated away from the hero while its own halves were
   pressed together. */
/* ---- The newest announcement, above the journey ---------------------------
   Only on the home page, and only while freshness.js says the item is under a
   week old. It is rendered with `hidden`, so `[hidden]` doing its job is the
   whole no-JavaScript story and there is no `display: none` here to fight it.

   IT IS DELIBERATELY QUIETER THAN THE JOURNEY BELOW IT. The journey is what the
   page is for; this is one thing that happened. So: the cream panel the site uses
   for a note, a gold eyebrow rather than a burgundy one, and no shadow. Making it
   compete would mean the front page changes its subject every time we publish. */
.justin { padding: 20px 0 0; }
/* WHITE, NOT CREAM, and that is not a preference. The hero panel directly above is
   cream, so a cream band under it read as one block with a seam rather than as its
   own thing — measured on the first build. White against white needs the border and
   the gold eyebrow to be a panel at all, which is the right weight for it anyway. */
.justin-card {
  display: block; text-align: left;
  background: var(--white); border: 1px solid var(--line); border-radius: 12px;
  padding: 20px 24px; color: inherit;
}
.justin-card:hover { border-color: var(--burgundy); text-decoration: none; }
.justin-eyebrow {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 6px;
}
.justin-title { font-size: 20px; font-weight: 800; margin: 0 0 4px; color: var(--lapis); }
.justin-teaser { font-size: 15px; color: var(--muted); margin: 0; line-height: 1.55; }
.justin-more {
  display: inline-block; margin-top: 10px;
  font-size: 14px; font-weight: 700; color: var(--burgundy);
}
.justin-card:hover .justin-more { text-decoration: underline; }
@media (max-width: 640px) {
  .justin-card { padding: 16px 18px; }
  .justin-title { font-size: 18px; }
}

.journey { padding: 40px 0 64px; text-align: center; }
.journey h2 { font-size: 24px; font-weight: 800; margin-bottom: 8px; }
.journey-sub { font-size: 16px; color: var(--muted); margin: 0 auto 40px; max-width: 520px; }
/* A stage is a container holding two links: the stage, and the newest article
   written for it. It used to be one <a>; the article could not live inside that. */
/* Pulled out by the same 18px each stage pads itself with, so the OUTER cards
   land on the content line (82/1198 at 1280px) that the hero panel above, this
   section's own h2, the testimonials, the CTA strip and the footer all sit on.
   The padding is from the scaffold and drew nothing for five weeks: a stage held
   a centred icon and a centred heading, and symmetric padding around centred
   content is invisible. On 2026-08-09 the stage's article became `.step-card`
   with a border and a white surface, and the padding acquired an edge you could
   see — 18px inside everything else on the page (Allan, 2026-08-13).
   Negative margin rather than moving the gutter to `.steps { gap }`: the
   connector between the icons is positioned `left: calc(50% + 44px);
   right: calc(-50% + 44px)`, which has this 8px gap baked into it and would go
   asymmetric if the gap changed. This way the connector geometry is untouched. */
.steps { display: flex; gap: 8px; align-items: stretch; margin: 0 -18px; }
.step {
  flex: 1 1 0; padding: 0 18px; position: relative; text-align: center;
  color: var(--body); display: flex; flex-direction: column;
}
/* `flex: 1` rather than pushing the article down with margin-top:auto. The
   stages are equal height, so an equal-height top half puts every "Latest"
   label on the same line. Bottom-aligning instead would line up the last line
   of the titles, and a one-line title next to a two-line one then lifts its
   own label out of the row (Design.md § Cards: line up the repeated element). */
.step-main { color: inherit; display: block; flex: 0 0 auto; }
.step-main:hover { text-decoration: none; }
/* The card under a stage. Same language as every other card on the site: white
   surface, soft border, 12px radius, cream on hover, a burgundy "more" cue. Left
   aligned inside its own edges, because three lines of reading text centred
   under a centred icon is not reading text (Design.md § Alignment law). */
/* `flex: 1` so the card stretches to whatever height the tallest stage needs,
   rather than to its own content. The stages are equal height already, and the
   half above the card is a fixed size, so the four cards end up identical even
   when one title runs to three lines. */
/* THE FIVE CARDS ARE STACKED IN ONE GRID CELL, ALL OF THEM LAID OUT, AND THAT IS
   WHAT KEEPS THE ROW STILL. `hidden` (display:none) would take the four inactive
   ones out of sizing, so the box would resize to whatever card happened to be
   showing and the whole section below it would jump every thirty seconds.
   `visibility` leaves them measured, so the cell is the height of the tallest of
   the five and never changes. It also takes them out of the tab order and the
   accessibility tree, which display:none would do but opacity alone would not. */
.step-cards { margin-top: 36px; flex: 1 1 auto; display: grid; }
.step-card {
  grid-area: 1 / 1; display: flex; flex-direction: column;
  background: var(--white); border: 1px solid var(--line-soft); border-radius: 12px;
  padding: 16px 18px; text-align: left; color: var(--body);
  visibility: hidden; opacity: 0;
  transition: border-color .15s, box-shadow .15s, color .15s, opacity .6s;
}
.step-card.is-on { visibility: visible; opacity: 1; }
/* The first pick of a visit is a cut. The page arrives with card one marked, the
   script picks another a moment later, and a crossfade would make an invisible
   correction into a visible flicker. */
.step-cards.no-fade .step-card { transition: none; }
/* The type tag. Label role: 12/700 uppercase, letter-spaced. Colour carries the
   type so the four cards can be told apart at a glance without reading. */
.step-card-tag {
  align-self: flex-start; margin-bottom: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  padding: 3px 8px; border-radius: 5px;
}
/* Four distinct tags. News is lapis: burgundy would vanish into the stage icons,
   the CTA and every "read more" on this page, and gold would collide with the
   news flag in the navigation, which is gold and means something else. Two gold
   things saying different things on one screen beat any gain from matching.
   Case study takes burgundy so it does not become a second blue tag. */
.tag-blog { background: var(--cream-2); color: var(--lapis); }
.tag-news { background: var(--lapis); color: var(--white); }
.tag-case { background: var(--burgundy); color: var(--white); }
.tag-voice { background: var(--cream-2); color: var(--burgundy); }
/* Service takes --green, the one colour in the brand palette that was declared
   and never used. Not burgundy: the paragraph above rules it out on this page
   for the same reason it ruled it out for news, and it already means case study.
   Not gold: that is the news flag in the navigation and means something else.
   Since the four stages now turn together, this colour marks WHEN rather than
   WHICH: the whole row is showing services, or articles, or news. */
.tag-service { background: var(--green); color: var(--white); }

/* Heading role: 16/700/lapis. Two lines RESERVED so a short title does not make
   its card shorter than its neighbours, but three ALLOWED: between 861 and about
   1150px the four columns are under 200px wide, and a two-line cap cut real
   titles there. A clipped title loses the one thing the card is about, and one
   uneven line is only cosmetic. */
.step-card-title {
  font-size: 16px; font-weight: 700; color: var(--lapis); line-height: 1.3;
  margin-bottom: 8px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; min-height: calc(2 * 1.3em);
}
/* Body role: 15/400/--body. Do not add flex-grow here, clamp plus grow leaks text
   past the ellipsis. */
/* The cue used to hold the card's bottom edge with margin-top:auto. With it
   gone the teaser is the last element, so it takes the remaining space itself.
   No flex-grow on a clamped element (Design.md § Cards): clamp plus grow leaks
   text past the ellipsis. margin-bottom:auto pushes from above instead. */
/* FIVE lines, matching .post-card-excerpt, and that is not a coincidence: this box
   shows `latest.teaser`, which IS the blog or news cardTeaser (see the
   latestInStage filter). One text, two boxes, so they get the same number of lines
   and the cap follows whichever is narrower.
   This one is the narrower. At three lines it held 99 characters at 1280px, fewer
   than on a phone, because the card sits in a four-column grid on a wide screen and
   full width on a narrow one. Four of the home page's cards were clipped there.
   Measured with scripts/measure-text-capacity.js. */
.step-card-teaser {
  font-size: 15px; font-weight: 400; color: var(--body); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;
  overflow: hidden; margin-bottom: auto;
}
.step-icon {
  width: 64px; height: 64px; border: 1.5px solid var(--burgundy); border-radius: 14px;
  background: var(--burgundy); display: flex; align-items: center; justify-content: center;
  margin: 0 auto 16px; position: relative; z-index: 2;
  transition: border-color .15s, box-shadow .15s, color .15s;
}
.step-icon svg { width: 28px; height: 28px; fill: none; stroke: var(--white); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.step-main:hover .step-icon { background: var(--burgundy-dark); border-color: var(--burgundy-dark); }
.step:not(:last-child)::after {
  content: ""; position: absolute; top: 32px; left: calc(50% + 44px);
  right: calc(-50% + 44px); height: 2px; background: var(--line); z-index: 1;
}
.step h3 { font-size: 16px; font-weight: 800; margin-bottom: 0; }
.step-main:hover h3 { color: var(--burgundy); }

/* ---- Testimonials ---- */
.t-section { padding: 8px 0 72px; }
.t-section h2 { font-size: 24px; font-weight: 800; margin-bottom: 8px; }
.t-lede { font-size: 16px; color: var(--muted); max-width: 520px; margin: 0 0 36px; }
.t-card {
  flex: 1 1 0; margin: 0; background: var(--white);
  border: 1px solid var(--line-soft); border-radius: 12px;
  padding: 26px 24px; display: flex; flex-direction: column;
  position: relative;
  transition: border-color .15s, box-shadow .15s, color .15s;
}
/* The whole card links to the service, via an overlay rather than by wrapping
   the card in an <a>. Wrapping would put a blockquote and a figcaption inside a
   link, and it would swallow the drag the slider needs; the overlay sits behind
   the content, so text stays selectable and a drag is still a drag. */
.t-cover { position: absolute; inset: 0; z-index: 0; border-radius: 12px; }
.t-card.is-link > *:not(.t-cover) { position: relative; z-index: 1; pointer-events: none; }
.t-cover:focus-visible { outline: 2px solid var(--lapis); outline-offset: 2px; }
.stars { color: var(--gold); font-size: 15px; letter-spacing: 2px; margin-bottom: 14px; }
.t-value { font-size: 15px; font-weight: 800; color: var(--burgundy); line-height: 1.35; margin: 0 0 16px; padding-left: 14px; border-left: 3px solid var(--lapis); }
.t-card blockquote { margin: 0 0 20px; font-size: 15px; color: var(--body); line-height: 1.6; display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; }
.t-card figcaption { margin-top: auto; }
.t-card figcaption { display: flex; align-items: center; gap: 12px; }
/* The attribution tile: lapis square, white mark. It held a person's initials, and since
   2026-08-10 it holds the client's INDUSTRY as an icon — the quote is attributed to a job
   role and a sector rather than to a name, because PB has no approved quote from a named
   client. The tile's size and weight are unchanged, so the card reads the same. */
.t-avatar {
  width: 38px; height: 38px; border-radius: 8px; flex-shrink: 0;
  background: var(--lapis); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700;
}
/* Same treatment as every other icon on the site: stroke only, no fill, colour inherited
   so the icon set carries no colour of its own. 1.6 at 22px is the site's weight. */
.t-avatar svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.t-who { display: flex; flex-direction: column; line-height: 1.3; }
.t-who strong { color: var(--lapis); font-size: 14px; }
.t-who em { color: var(--muted); font-size: 13px; font-style: normal; }
.t-tag {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft);
  font-size: 12px; font-weight: 600; color: var(--burgundy);
}

/* ---- CTA strip ---- */
.cta-strip { padding: 0 0 72px; }
.trust-section + .cta-strip { padding-top: 48px; }
.cta-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  background: var(--cream); border: 1px solid var(--cream-2);
  border-radius: 12px; padding: 28px 32px;
}
.cta-inner h3 { font-size: 16px; font-weight: 800; margin-bottom: 4px; }
.cta-inner p { margin: 0; color: var(--muted); font-size: 15px; }

/* ---- Footer ---- */
/* Boxed like the CTA card — a centred, rounded lapis panel inset to the content
   width, not an edge-to-edge bar. */
.site-footer {
  background: var(--lapis); color: #c7cfe6;
  width: calc(100% - 64px);
  max-width: calc(var(--wrap) - 64px);
  margin: 24px auto;
  border-radius: 12px;
  overflow: hidden;
}
.footer-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 24px 32px 20px;
  display: flex; gap: 48px; flex-wrap: wrap; justify-content: space-between;
  align-items: flex-start;
}
.footer-cols { display: flex; flex-wrap: wrap; gap: 28px 40px; }
.footer-col h4 { color: var(--white); font-size: 12px; text-transform: uppercase; letter-spacing: .5px; margin: 0 0 8px; }
.footer-col p { margin: 0 0 3px; font-size: 13px; line-height: 1.45; color: #aab4d6; }
.footer-col a { color: #c7cfe6; }
.footer-col a:hover { color: var(--white); }
/* Icons align to the column heading's left edge; the label sits to the right of
   the icon (icon + gap indent). */
.footer-link { display: inline-flex; align-items: center; gap: 8px; }
/* Address block: pin aligns with the heading, address text to its right, icon
   pinned to the first line. */
.footer-addr { display: flex; align-items: flex-start; gap: 8px; }
.footer-addr .footer-ic { margin-top: 3px; }
.footer-addr p { margin: 0 0 3px; }
.footer-ic { width: 15px; height: 15px; flex-shrink: 0; color: #8b96bb; }
.site-footer a:hover .footer-ic { color: currentColor; }
.footer-ic.stroke { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.footer-ic.fill { fill: currentColor; }
.footer-logo-left { padding-right: 24px; align-self: flex-start; }
.footer-logo-left img { height: 62px; width: auto; display: block; }
.footer-legal { max-width: var(--wrap); margin: 0 auto; padding: 0 32px; }
.footer-legal-inner {
  border-top: 1px solid rgba(255,255,255,.14); padding: 11px 0;
  display: flex; flex-wrap: wrap; gap: 8px 24px;
  align-items: center; justify-content: space-between;
}
.footer-legal p { margin: 0; font-size: 12px; color: #8b96bb; }
.footer-legal-nav { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.footer-legal-nav a { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: #aab4d6; }
.footer-legal-nav .footer-ic { width: 13px; height: 13px; }
.footer-legal-nav a:hover { color: var(--white); }

/* ---- Generic page head (services landing, future pages) ---- */
/* Same boxed treatment as the hero — centred, rounded, inset to content width. */
.page-head {
  width: calc(100% - 64px);
  max-width: calc(var(--wrap) - 64px);
  margin: 20px auto 0;
  background: var(--cream);
  border: 1px solid var(--cream-2);
  border-radius: 12px;
  padding: 34px 0;
  position: relative;
  overflow: hidden;
}
/* Align the grey-box copy with the card text below it (cards inset 26px; the
   default .wrap padding is 32px, which left the head 6px further in). */
.page-head > .wrap { padding-left: 26px; }
.page-head h1 { font-size: 34px; font-weight: 800; letter-spacing: -.5px; max-width: 720px; }
.page-head .lede { font-size: 16px; color: var(--muted); max-width: 620px; margin: 16px 0 0; }

/* ---- Services landing ---- */
.stage-block { padding: 48px 0; border-bottom: 1px solid var(--line-soft); }
.stage-head { display: flex; align-items: center; gap: 18px; margin-bottom: 28px; }
.stage-num {
  width: 46px; height: 46px; border-radius: 10px; flex-shrink: 0;
  background: var(--burgundy); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 800;
}
.stage-num svg { width: 24px; height: 24px; fill: none; stroke: var(--white); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.stage-head h2 { font-size: 24px; font-weight: 800; }
.stage-q { margin: 2px 0 0; color: var(--muted); font-size: 15px; }
.svc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 18px; }
.svc-card {
  border: 1px solid var(--line-soft); border-radius: 12px; padding: 22px 22px;
  color: var(--body); display: flex; flex-direction: column; gap: 8px;
  transition: border-color .15s, box-shadow .15s, color .15s;
}
.svc-card h3 { font-size: 18px; font-weight: 800; }
/* Three lines, not two. At two this box held 80 characters at 390px while the lint
   allowed 120, and two of the real teasers were clipped. Three holds 121, which is
   what makes the 70-120 cap true rather than aspirational. */
.svc-card p { margin: 0; font-size: 14px; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.svc-card .svc-more { margin-top: auto; }
.stage-empty { color: var(--muted); font-style: italic; font-size: 15px; margin: 0; }

/* ---- Services journey accordion ---- */
.journey-accordion { padding: 40px 0 56px; }
.journey-item { border: 1px solid var(--line-soft); border-radius: 14px; margin-bottom: 16px; background: var(--white); scroll-margin-top: 90px; overflow: hidden; }
.journey-item > summary { list-style: none; cursor: pointer; display: flex; align-items: flex-start; gap: 20px; padding: 22px 26px; transition: background .15s; }
.journey-item > summary:hover { background: var(--cream); }
.journey-item > summary::-webkit-details-marker { display: none; }
.ji-icon { width: 52px; height: 52px; border-radius: 12px; background: var(--burgundy); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ji-icon svg { width: 26px; height: 26px; fill: none; stroke: var(--white); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ji-copy { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ji-question { font-size: 16px; font-weight: 700; color: var(--lapis); }
.ji-title { font-size: 14px; font-weight: 400; color: var(--burgundy); }
.ji-intro { font-size: 15px; color: var(--body); line-height: 1.5; }
.journey-item > summary::after { content: "+"; font-size: 24px; font-weight: 400; color: var(--burgundy); line-height: 1; flex-shrink: 0; }
.journey-item[open] > summary::after { content: "\2212"; }
/* The left indent puts the panel under the summary's own heading rather than
   under the icon — the line the eye is already following. It is the summary's
   26px padding + the 52px icon + the 20px flex gap, so it is derived from those
   three and has to move with them. It was 74px, which is 4px INSIDE the icon's
   right edge and under nothing at all; measured 2026-08-13 the panel started at
   157 where the icon ends at 161 and the heading starts at 181.
   The right stays at 26px: that is the summary's own padding, so the panel ends
   where the bar's content ends. It looks 27px short of the content line and is
   not — the bar is a card ON that line, and this is its inside. */
.ji-panel { padding: 4px 26px 26px 98px; }

/* ---- FAQ bar (fifth journey item) ----
   Deliberately set apart from the four journey bars: blue (lapis) icon instead
   of burgundy, and the summary heading order/colours inverted — red bold "FAQs"
   on top, blue normal strap below. Each question is its own expand/collapse
   (+/−); a 2×2 stage grid keeps each stage in a fixed cell so opening a question
   grows its own cell rather than reflowing across columns. The panel indent
   lines the questions up under the summary heading, not the icon. */
.faq-item .ji-icon { background: var(--lapis); }
.faq-item .ji-question { color: var(--burgundy); }
.faq-item .ji-title { color: var(--lapis); }
.faq-panel { padding-left: 98px; }
.faq-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 48px; align-items: start; }
.faq-group { margin-bottom: 20px; }
.faq-stage { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin: 0 0 6px; }
.faq-qa { border-bottom: 1px solid var(--line-soft); }
.faq-q { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding: 12px 0; font-size: 15px; font-weight: 400; color: var(--body); line-height: 1.4; transition: color .15s; }
.faq-q:hover { color: var(--burgundy); }
.faq-q::-webkit-details-marker { display: none; }
.faq-q::after { content: "+"; font-size: 20px; font-weight: 400; color: var(--burgundy); line-height: 1.2; flex-shrink: 0; }
.faq-qa[open] .faq-q::after { content: "\2212"; }
.faq-a { font-size: 15px; font-weight: 400; color: var(--body); line-height: 1.6; margin: 0; padding: 0 28px 14px 0; }

/* ---- Service detail page ---- */
.breadcrumb {
  background: var(--cream); border-bottom: 1px solid var(--line-soft);
  padding: 12px 0; font-size: 13px; color: var(--muted);
}
/* The arrow is what makes the parent link read as a way BACK rather than as a
   label saying where you are. It sits on the link itself, so the whole thing —
   arrow and word — is one target, and so every detail page gets it from one
   rule. Not history.back(): most arrivals here come from a LinkedIn comment,
   where there is no back to go to, and the archive is the honest destination. */
.breadcrumb .bc-link {
  color: var(--muted); font-weight: 600;
  display: inline-flex; align-items: baseline; gap: 8px;
}
.breadcrumb .bc-link::before { content: "\2190"; font-size: 15px; line-height: 1; }
.breadcrumb .bc-link:hover { color: var(--brand); }
.breadcrumb .bc-sep { margin: 0 8px; color: var(--line); }
.breadcrumb strong { color: var(--ink); }

.jtrack { background: var(--cream); border-bottom: 1px solid var(--line-soft); padding: 14px 0; overflow-x: auto; }
.jtrack-inner { max-width: var(--wrap); margin: 0 auto; padding: 0 32px; display: flex; align-items: center; justify-content: flex-start; min-width: max-content; }
.jt { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--muted); }
/* Understated wayfinding: grey square + white icon; hover turns it burgundy. */
.jt .badge { width: 28px; height: 28px; border-radius: 7px; flex-shrink: 0; background: var(--muted); color: var(--white); display: flex; align-items: center; justify-content: center; }
.jt .badge svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
/* "You are here" — the current stage is marked burgundy (label + badge). */
.jt.active { font-weight: 700; color: var(--burgundy); }
.jt.active .badge { background: var(--burgundy); color: var(--white); }
.jt-arr { color: var(--line); margin: 0 12px; }

.cat-banner { background: var(--lapis); color: var(--white); padding: 34px 0; }
.cat-inner { max-width: var(--wrap); margin: 0 auto; padding: 0 32px; display: flex; gap: 48px; align-items: flex-start; }
.cat-label { font-size: 11px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; color: #9fb0d8; margin-bottom: 8px; }
.cat-head { flex: 0 0 300px; }
.cat-q { font-size: 22px; font-weight: 800; color: var(--white); line-height: 1.25; margin: 0; }
.cat-intro { font-size: 15px; color: #d5dcee; line-height: 1.6; margin: 0; flex: 1; border-left: 1px solid #33478a; padding-left: 32px; }

.svc-head { padding: 48px 0 8px; }
.svc-label { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--burgundy); margin-bottom: 12px; }
.svc-head h1 { font-size: 34px; font-weight: 800; letter-spacing: -.4px; max-width: 780px; margin-bottom: 26px; }
.why-title { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin-bottom: 16px; }
.why-text { font-size: 16px; color: var(--body); line-height: 1.7; max-width: 720px; margin: 0; }

.svc-help { padding: 40px 0 0; }
.svc-help .sec { margin-bottom: 0; }
.svc-help .sec p { max-width: 760px; }
.content { display: flex; gap: 52px; padding: 44px 32px 64px; align-items: flex-start; }
.content .main { flex: 1 1 0; min-width: 0; }
/* Pull the sidebar up by the box's top padding (22px) so the Related Services
   heading lines up with the Deliverables heading in the main column. */
.content .side { flex: 0 0 280px; margin-top: -22px; }
.sec { margin-bottom: 40px; }
.sec-lbl { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin-bottom: 16px; }
.sec p { font-size: 16px; color: var(--body); line-height: 1.7; margin: 0; }

.dlv { list-style: none; margin: 0; padding: 0; }
.dlv li { display: flex; align-items: center; gap: 12px; font-size: 15px; font-weight: 600; color: var(--lapis); padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
.dlv li:last-child { border-bottom: none; }
.dlv li::before { content: ""; width: 8px; height: 8px; border-radius: 1px; background: var(--burgundy); flex-shrink: 0; }

.box { border: 1px solid var(--line-soft); border-radius: 12px; padding: 22px; margin-bottom: 18px; }
.box.soft { background: var(--cream); border-color: var(--cream-2); }
.box h4 { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin-bottom: 16px; }
.cta-box p { font-size: 14px; color: var(--body); margin: 0 0 16px; }
.jlist { list-style: none; margin: 0; padding: 0; }
.jlist li { padding: 0; }
.jlist li a { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--muted); padding: 7px 0; }
.jlist li a:hover { color: var(--burgundy); text-decoration: none; }
/* Blue exception: the service-page sidebar journey recap uses lapis squares. */
.jlist li span { width: 26px; height: 26px; border-radius: 6px; background: var(--lapis); color: var(--white); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.jlist li span svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.jlist li.on a { color: var(--lapis); font-weight: 700; }
.jlist li.on span { background: var(--lapis); color: var(--white); }
.related { list-style: none; margin: 0 0 14px; padding: 0; }
.related li { padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.related a { font-size: 14px; font-weight: 600; color: var(--muted); display: flex; justify-content: space-between; }
.related a:hover { color: var(--burgundy); text-decoration: none; }
.related a span { color: inherit; }
.related li.no-link { font-size: 14px; font-weight: 600; color: var(--muted); }
.explore-all { display: block; width: -moz-fit-content; width: fit-content; margin: 10px auto 0; font-size: 13px; font-weight: 700; color: var(--burgundy); border: 1.5px solid var(--burgundy); border-radius: 0; padding: 9px 16px; transition: background .15s, color .15s; }
.explore-all:hover { background: var(--burgundy); color: var(--white); text-decoration: none; }

/* ---- Journey strip as links (About / Customers) ---- */
.jtrack a.jt:hover { text-decoration: none; color: var(--burgundy); }
.jtrack a.jt:hover .badge { background: var(--burgundy); color: var(--white); }

/* ---- Page head with stat blocks (About / Customers) ---- */
.about-head { display: flex; gap: 56px; align-items: center; justify-content: space-between; }
.about-head-copy { max-width: 620px; }
/* Stat: a fixed-size burgundy figure with the % / + symbol at half size, then
   the unit and description at one shared (small) size. No rules. */
.stat-blocks { display: flex; gap: 34px; flex-shrink: 0; }
.stat { display: flex; flex-direction: column; align-items: center; text-align: center; width: 150px; }
.stat-fig { font-size: 52px; font-weight: 800; color: var(--burgundy); line-height: 1; }
.stat-suf { font-size: 0.5em; }
.stat-desc { font-size: 15px; font-weight: 400; color: var(--burgundy); line-height: 1.4; margin-top: 8px; max-width: 150px; }

/* ---- Team ---- */
.team-section { padding: 56px 0; }
.team-section h2 { font-size: 24px; font-weight: 800; margin-bottom: 8px; }
/* "Join the team" invite under the team slider — links to Careers. */
.join-team { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px 24px; margin-top: 32px; padding: 22px 28px; border: 1px solid var(--line-soft); border-radius: 14px; background: var(--cream); }
.join-team:hover { text-decoration: none; }
.join-team-copy { display: flex; flex-direction: column; gap: 3px; }
.join-team-title { font-size: 18px; font-weight: 800; color: var(--lapis); }
.join-team-sub { font-size: 15px; color: var(--body); }
.join-team-cta { font-size: 14px; font-weight: 700; color: var(--burgundy); white-space: nowrap; flex-shrink: 0; }
.card-slider {
  display: flex; gap: 22px;
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: none; -ms-overflow-style: none;
  user-select: none; -webkit-user-select: none;
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='10.5' fill='%23800020' fill-opacity='.14' stroke='%23800020' stroke-width='1.5'/%3E%3Cpath d='M10.5 16h11M13 12.5 9.5 16l3.5 3.5M19 12.5l3.5 3.5-3.5 3.5' fill='none' stroke='%23800020' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 16 16, grab;
}
.card-slider::-webkit-scrollbar { display: none; }
.card-slider img { -webkit-user-drag: none; user-drag: none; }
.card-slider.grabbing {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='10.5' fill='%23800020' stroke='%23800020' stroke-width='1.5'/%3E%3Cpath d='M10.5 16h11M13 12.5 9.5 16l3.5 3.5M19 12.5l3.5 3.5-3.5 3.5' fill='none' stroke='%23ffffff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 16 16, grabbing;
  user-select: none; -webkit-user-select: none;
}
.team-slider { margin-top: 32px; }
.member { flex: 0 0 340px; scroll-snap-align: start; scroll-margin-top: 90px; border: 1px solid var(--line-soft); border-radius: 12px; padding: 24px; display: flex; flex-direction: column; transition: border-color .15s, box-shadow .15s, color .15s; }
.slider-dots { display: flex; justify-content: center; gap: 10px; margin-top: 20px; }
.slider-dot { width: 11px; height: 11px; border-radius: 3px; background: var(--cream-2); border: 1px solid var(--line); transition: border-color .15s, box-shadow .15s, color .15s; }
.slider-dot:hover { background: var(--burgundy); border-color: var(--burgundy); }
.slider-viewport { position: relative; }
.slider-arrows { position: absolute; inset: 0; pointer-events: none; }
.slider-arrow { position: absolute; top: 50%; transform: translateY(-50%); pointer-events: auto; width: 42px; height: 42px; border-radius: 8px; border: 1px solid var(--line); background: var(--white); color: var(--burgundy); font-size: 22px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px rgba(21, 49, 126, .12); transition: background .15s, color .15s, border-color .15s; }
.slider-arrow.prev { left: -21px; }
.slider-arrow.next { right: -21px; }
.slider-arrow:hover { background: var(--burgundy); color: var(--white); border-color: var(--burgundy); }
.member-head { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
.member-photo { flex-shrink: 0; line-height: 0; }
.member-avatar { width: 72px; height: 72px; border-radius: 12px; flex-shrink: 0; background: var(--lapis); color: var(--white); display: flex; align-items: center; justify-content: center; font-size: 22px; font-weight: 800; }
.member-photo-note { font-size: 12px; color: var(--line); font-style: italic; }
.member-avatar-img { width: 72px; height: 72px; border-radius: 12px; object-fit: cover; flex-shrink: 0; }
.member h3 { font-size: 18px; font-weight: 800; }
.member-role { color: var(--burgundy); font-weight: 700; font-size: 14px; margin: 4px 0 0; }
.member-bio { font-size: 14px; color: var(--body); line-height: 1.6; margin: 0 0 12px; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.member-skills { font-size: 13px; font-weight: 600; color: var(--muted); margin: 0 0 14px; word-spacing: 3px; }
.member-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.tag { font-size: 12px; font-weight: 600; color: var(--lapis); background: var(--cream); border: 1px solid var(--cream-2); border-radius: 20px; padding: 4px 12px; }
.member-linkedin { font-size: 13px; font-weight: 700; color: var(--lapis); }
/* Member popup body: full bio, no clamp */
.member-modal-bio { font-size: 15px; color: var(--body); line-height: 1.7; margin: 4px 0 12px; }
#member-modal .member-head { margin-bottom: 18px; }
#member-modal .member-skills { margin-bottom: 16px; }
#member-modal h2 { font-size: 22px; font-weight: 800; }

/* ---- Trust band ---- */
.trust-section { padding: 20px 0; }
/* Contained, rounded grey box aligned to the content line (not wall-to-wall). */
.trust-box { background: var(--cream); border: 1px solid var(--line-soft); border-radius: 16px; padding: 40px; }
.trust-section h2 { font-size: 24px; font-weight: 800; margin-bottom: 28px; }
.trust-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 24px; }
.trust-item h4 { font-size: 15px; font-weight: 800; color: var(--lapis); margin-bottom: 8px; padding-left: 14px; border-left: 3px solid var(--burgundy); }
.trust-item p { font-size: 14px; color: var(--muted); margin: 0; padding-left: 14px; }

/* ---- Logo wall ---- */
.logo-wall { padding: 44px 0 8px; }
.logo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(210px, 100%), 1fr)); gap: 14px 20px; margin-top: 24px; }
/* Auto-scrolling single-row logo ticker (JS drives the motion + seamless loop).
   Edges fade so logos ease in and out rather than hard-cut. */
.logo-ticker { position: relative; overflow: hidden; margin-top: 24px; }
/* Edge fade via overlays (not mask-image, which broke the animation on Safari). */
.logo-ticker::before, .logo-ticker::after { content: ""; position: absolute; top: 0; bottom: 0; width: 64px; z-index: 2; pointer-events: none; }
.logo-ticker::before { left: 0; background: linear-gradient(to right, var(--white), transparent); }
.logo-ticker::after { right: 0; background: linear-gradient(to left, var(--white), transparent); }
.logo-track { display: flex; width: max-content; will-change: transform; animation: logo-scroll 48s linear infinite; }
.logo-ticker:hover .logo-track { animation-play-state: paused; }
.logo-track .logo-cell { flex: 0 0 auto; margin-right: 12px; min-width: 220px; min-height: 132px; padding: 18px 24px; }
/* Bound both dimensions so logos read at roughly the same size (matches wall). */
.logo-track .logo-cell img { max-height: 84px; max-width: 176px; }
@keyframes logo-scroll { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }
.logo-all { text-align: center; margin: 18px 0 0; }
.link-btn { background: none; border: none; cursor: pointer; font: inherit; font-size: 13px; font-weight: 700; color: var(--burgundy); }
.link-btn:hover { text-decoration: underline; }
.contact-dialog.logos-dialog { max-width: 680px; max-height: 85vh; overflow-y: auto; }
.logos-modal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(185px, 100%), 1fr)); gap: 12px; margin-top: 6px; }
.logos-modal-grid .logo-cell { min-height: 128px; padding: 18px 20px; border: 1px solid var(--line-soft); border-radius: 10px; }
.logos-modal-grid .logo-cell img { max-height: 84px; max-width: 100%; }
.logo-cell { display: flex; align-items: center; justify-content: center; padding: 28px 26px; border-radius: 10px; min-height: 132px; }
.logo-cell img { max-height: 76px; max-width: 100%; width: auto; object-fit: contain; }

/* ---- Customers ---- */
.cust-testimonials { padding: 44px 0 8px; }
/* gap 18 (not the shared 22) so 3 cards fit the content column exactly:
   3*360 + 2*18 = 1116 = column width — the 3rd card lands on the right anchor
   instead of spilling past it. */
.t-slider { margin-top: 20px; gap: 18px; }
.t-slider .t-card { flex: 0 0 360px; scroll-snap-align: start; }
.case-studies { padding: 48px 0 64px; }
.case-studies .lede { margin-bottom: 28px; }
.cs-slider { margin-top: 4px; }
.cs-slider .cs-card { flex: 0 0 300px; scroll-snap-align: start; }
.cs-card { border: 1px solid var(--line-soft); border-radius: 12px; padding: 26px 24px; background: var(--white); display: flex; flex-direction: column; gap: 10px; transition: border-color .15s, box-shadow .15s, color .15s; }
.cs-stage { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--burgundy); }
.cs-card h3 { font-size: 18px; font-weight: 800; line-height: 1.3; min-height: 2.6em; }
.cs-summary { font-size: 15px; color: var(--body); line-height: 1.6; margin: 0; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
/* Reserve two lines for the result so the divider line sits at the same height
   on every card, whatever the result length. */
.cs-result { font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--lapis); padding-top: 12px; border-top: 1px solid var(--line-soft); min-height: calc(2.8em + 13px); margin-top: auto; }
/* Case-study popup body */
.case-summary { font-size: 15px; color: var(--body); line-height: 1.7; margin: 0 0 6px; }
#case-modal .cs-stage { margin-bottom: 8px; }
#case-modal h2 { font-size: 22px; font-weight: 800; line-height: 1.3; margin-bottom: 12px; }
#case-modal .cs-result { min-height: 0; }

/* ---- Blog index ---- */
.blog-list { padding: 48px 0 64px; }
.post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); grid-auto-rows: 1fr; gap: 24px; }
.post-card { background: var(--white); border: 1px solid var(--line-soft); border-radius: 12px; padding: 28px 26px; color: var(--body); display: flex; flex-direction: column; gap: 10px; transition: border-color .15s, box-shadow .15s, color .15s; }
/* ONE hover for EVERY card on the site — stories, news, case studies, services,
   the journey steps, team members, testimonials, the find-us rows. It carries the
   whole affordance now that the "Read more" line is gone, so it has to be
   readable rather than tasteful: the border takes the brand colour and the
   heading follows it.
   Before this there were five different hovers. Some cards went grey, some
   changed a border nobody could see, some did both — and a reader cannot learn a
   rule that has five versions. Nothing goes grey any more: a filled background
   says "selected", and hovering is not selecting. */
.post-card:hover,
.news-card:hover,
.cs-card:hover,
.svc-card:hover,
.step-card:hover,
.member:hover,
.t-card.is-link:hover,
.findus-card:hover {
  text-decoration: none;
  border-color: var(--burgundy);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .08);
}
/* Each card's own heading element — the one line a reader looks at first. */
.post-card:hover h2,
.news-card:hover h3,
.cs-card:hover h3,
.svc-card:hover h3,
.member:hover h3,
.step-card:hover .step-card-title,
.t-card.is-link:hover .t-value,
.findus-card:hover strong { color: var(--burgundy); }
.post-card-stage, .post-stage { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--burgundy); }
/* Always reserve two lines for the card heading so the date/meta row starts at
   the same height across cards, whatever the title length. */
.post-card h2 { font-size: 18px; font-weight: 800; line-height: 1.3; min-height: 2.6em; }
.post-card-meta, .post-meta { font-size: 13px; color: var(--muted); margin: 0; }
.post-card-meta span, .post-meta span { margin: 0 4px; }
/* Five lines, not three. Measured 2026-08-10: at three lines this box holds 114
   characters at 390px while the lint required a minimum of 120, so EVERY valid
   teaser was clipped on a phone and four of them were. The same text also appears
   in .step-card-teaser on the home page, which is the narrower of the two, so both
   carry five lines and the cap follows the narrower one. See scripts/
   measure-text-capacity.js — the numbers there are measured, not chosen. */
.post-card-excerpt { font-size: 15px; color: var(--body); margin: 0; display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; }
/* No "Read more" line. The whole card is the link, so the label was telling the
   reader something the card already says, and it said it in three different
   wordings across three card types. The teaser takes the bottom slack instead. */
.post-card-excerpt { margin-bottom: auto; }

/* `wrap` on both rows is the belt to the template's braces: the window keeps the
   number count constant, and wrapping means that even an unforeseen count drops
   to a second line instead of pushing the whole page sideways. */
.pagination { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 44px; flex-wrap: wrap; }
.pg-step { font-size: 13px; font-weight: 700; color: var(--burgundy); padding: 8px 14px; border: 1px solid var(--line); border-radius: 8px; }
.pg-step:hover { background: var(--burgundy); color: var(--white); border-color: var(--burgundy); text-decoration: none; }
.pg-step.disabled { color: var(--line); border-color: var(--line-soft); pointer-events: none; }
.pg-nums { display: flex; gap: 6px; margin: 0 6px; flex-wrap: wrap; justify-content: center; }
.pg-gap { height: 34px; display: flex; align-items: center; padding: 0 2px; font-size: 13px; color: var(--muted); }
.pg-num { min-width: 34px; height: 34px; padding: 0 6px; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; color: var(--lapis); border: 1px solid var(--line); border-radius: 8px; }
.pg-num:hover { background: var(--cream); text-decoration: none; }
.pg-num.active { background: var(--burgundy); color: var(--white); border-color: var(--burgundy); }

/* ---- News (blog-page CTA + /news/ archive) ---- */
.news-cta { padding: 40px 0 8px; }
/* Shared feed panel — used by both the News box and the Blog (Stories) box. */
.feed-panel { background: var(--cream); border: 1px solid var(--cream-2); border-radius: 14px; padding: 26px 28px 30px; }
.feed-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; margin-bottom: 20px; }
.feed-head h2 { font-size: 22px; font-weight: 800; letter-spacing: -.3px; margin: 2px 0 0; }
/* Pagination lives inside the Blog box; #blog is the scroll target so paging
   lands on the box (offset for the sticky header) instead of the page top. */
#blog { scroll-margin-top: 132px; }
.feed-panel .pagination { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--cream-2); }
.news-archive-link { font-size: 14px; font-weight: 700; color: var(--burgundy); white-space: nowrap; }
.news-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 16px; }
.news-cards-grid { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 20px; }
/* News box is inverted vs the Blog box: white panel, grey (cream) cards. */
.news-cta .feed-panel { background: var(--white); }
.news-card { display: flex; flex-direction: column; gap: 8px; text-align: left; background: var(--cream); border: 1px solid var(--line); border-radius: 12px; padding: 20px 20px 18px; cursor: pointer; transition: border-color .15s, box-shadow .15s, color .15s; }
.news-card:focus-visible { outline: 2px solid var(--lapis); outline-offset: 2px; }
.news-date { font-size: 12px; font-weight: 700; letter-spacing: .3px; color: var(--burgundy); }
.news-card h3 { font-size: 16px; font-weight: 800; line-height: 1.3; color: var(--lapis); margin: 0; }
.news-text { font-size: 14px; color: var(--body); line-height: 1.55; margin: 0; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.news-text { margin-bottom: auto; }   /* took over the slack the "Read →" line held */
/* Compact fallback on the blog page when no item is within 4 months. */
.news-cta-slim { display: flex; align-items: center; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; background: var(--cream); border: 1px solid var(--cream-2); border-radius: 14px; padding: 20px 28px; color: var(--body); font-size: 15px; }
.news-cta-slim:hover { text-decoration: none; border-color: var(--burgundy); }
.news-cta-slim .eyebrow { display: inline; margin-right: 6px; }
.news-archive { padding: 40px 0 64px; }
.news-modal-date { display: block; font-size: 12px; font-weight: 700; letter-spacing: .3px; color: var(--burgundy); margin-bottom: 6px; }
.news-modal-text { font-size: 15px; color: var(--body); line-height: 1.6; margin: 8px 0 0; white-space: pre-line; }

/* ---- Contact modal ---- */
.contact-modal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; padding: 24px; }
.contact-modal[hidden] { display: none; }
.contact-backdrop { position: absolute; inset: 0; background: rgba(21, 49, 126, .45); }
.contact-dialog { position: relative; z-index: 1; width: 100%; max-width: 420px; background: var(--white); border-radius: 14px; padding: 32px 30px; box-shadow: 0 24px 64px rgba(0, 0, 0, .28); }
.contact-close { position: absolute; top: 12px; right: 14px; width: 34px; height: 34px; background: none; border: none; font-size: 26px; line-height: 1; color: var(--muted); cursor: pointer; border-radius: 8px; }
.contact-close:hover { color: var(--burgundy); background: var(--cream); }
.contact-dialog h2 { font-size: 22px; font-weight: 800; margin-bottom: 4px; }
.contact-sub { font-size: 15px; color: var(--muted); margin: 0 0 22px; }
.contact-field { margin-bottom: 18px; }
.contact-flabel { display: block; font-size: 12px; font-weight: 700; color: var(--lapis); margin-bottom: 6px; }
.contact-flabel span { color: var(--muted); font-weight: 600; }
.contact-textarea { width: 100%; font-family: inherit; font-size: 14px; color: var(--ink); background: var(--white); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; resize: vertical; min-height: 70px; line-height: 1.5; }
.contact-textarea:focus { outline: none; border-color: var(--lapis); box-shadow: 0 0 0 3px rgba(21, 49, 126, .12); }
.contact-fhelp { font-size: 12px; color: var(--muted); line-height: 1.4; margin: 7px 0 0; }
.contact-methods { display: flex; flex-direction: column; gap: 10px; }
.contact-method { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: 10px; color: var(--body); }
.contact-method:hover { text-decoration: none; background: var(--cream); border-color: var(--cream-2); }
.contact-ic { width: 40px; height: 40px; border-radius: 10px; background: var(--lapis); color: var(--white); display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background .15s, color .15s; }
.contact-method:hover .contact-ic { background: var(--burgundy); color: var(--white); }
.contact-ic svg { width: 20px; height: 20px; }
.contact-ic .ic-stroke { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.contact-ic .ic-fill { fill: currentColor; }
.contact-method-txt { display: flex; flex-direction: column; line-height: 1.3; }
.contact-method-txt strong { font-size: 15px; color: var(--lapis); }
.contact-method-txt em { font-size: 13px; color: var(--muted); font-style: normal; }
.contact-copy-block { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line-soft); }
.contact-copy-note { font-size: 13px; color: var(--muted); line-height: 1.5; margin: 0 0 10px; }
.contact-email { display: flex; align-items: center; gap: 10px; border: 1px solid var(--line-soft); border-radius: 8px; padding: 7px 7px 7px 14px; }
.contact-email-addr { flex: 1; font-size: 15px; font-weight: 600; color: var(--lapis); overflow-wrap: anywhere; }
.contact-copy { flex-shrink: 0; font-size: 13px; font-weight: 700; color: var(--burgundy); background: var(--cream); border: 1px solid var(--line); border-radius: 6px; padding: 7px 14px; cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.contact-copy:hover { background: var(--burgundy); color: var(--white); border-color: var(--burgundy); }
.contact-copy.copied { background: var(--lapis); color: var(--white); border-color: var(--lapis); }
.contact-confidential { margin: 18px 0 0; font-size: 12px; color: var(--muted); text-align: center; }

/* ---- Find us (footer popup + /find-us/ subpage) ---- */
.findus-section { padding: 44px 0 12px; }
.findus-addr { font-size: 16px; font-weight: 700; color: var(--lapis); line-height: 1.5; margin: 0 0 10px; }
.findus-note { font-size: 15px; color: var(--muted); line-height: 1.65; max-width: 560px; margin: 0 0 22px; }
.findus-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 12px; max-width: 620px; }
.findus-card { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border: 1px solid var(--line-soft); border-radius: 10px; color: var(--body); transition: border-color .15s, box-shadow .15s, color .15s; }
.findus-ic { width: 42px; height: 42px; border-radius: 10px; background: var(--lapis); color: var(--white); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.findus-ic svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.findus-txt { display: flex; flex-direction: column; line-height: 1.3; flex: 1; }
.findus-txt strong { font-size: 15px; color: var(--lapis); }
.findus-txt em { font-size: 13px; color: var(--muted); font-style: normal; }
.findus-go { color: var(--burgundy); font-weight: 700; flex-shrink: 0; }

/* ---- Blog post ---- */
.post-head { background: var(--cream); border-bottom: 1px solid var(--line-soft); padding: 48px 0; }
.post-head h1 { font-size: 34px; font-weight: 800; letter-spacing: -.5px; max-width: 780px; margin: 8px 0 14px; }
/* THE ARTICLE COLUMN, and the reason it is not the page width. Allan asked why an article
   does not use the whole page when there is a page to use (2026-08-10). Measured: the body
   text already runs at 83 characters per line, up to 106, where the comfortable band is
   45-75 and 66 is the classic target. At the full 1116px it would reach about 120, which is
   where the eye starts losing the line on the way back. So the TEXT stays at 696px.
   Nothing about that applies to a photograph, a table or a code block, and those were the
   real answer to his question: his article's image is 1573px wide and was being shown at
   696, and Slavi's table of eight command names per cell is the page that scrolls sideways
   most.

   THREE COLUMNS, NOT NEGATIVE MARGINS. The obvious alternative is `margin-left: -210px` on
   the wide elements, sized from `100vw`. But `100vw` includes the scrollbar on Windows and
   most desktop Linux, so every wide element would sit a few pixels past the edge and the
   page would gain a horizontal scroll — the exact thing check-widths exists to catch. A
   grid takes its measurements from the container, which has no scrollbar in it. */
.post-body {
  padding: 48px 32px 8px;
  display: grid;
  grid-template-columns: 1fr min(696px, 100%) 1fr;
}
/* EVERYTHING stays in the text column, pictures and tables included.
   They broke out to the full 1116px for about an hour on 2026-08-10, on the reasoning that
   a photograph and a table have no line-length problem and Allan had asked why an article
   does not use the page width. The reasoning was sound and the result was not: seeing it,
   his verdict was that an image wider than the text it sits in does not look good, and he
   is right — the column edge is what tells the eye where the article is, and an element
   crossing it reads as a mistake rather than as generosity.
   The grid stays because it is how the column is centred; only the breakout rule is gone.
   THE PRICE, so it is not discovered later: a table wide enough to need it scrolls inside
   its own frame again, and Slavi's eight-command cells are the case. That was the strongest
   argument for the breakout and it did not survive looking at it. */
.post-body > * { grid-column: 2; }
.post-body p { font-size: 16px; line-height: 1.75; color: var(--body); }
.post-body h2 { font-size: 24px; font-weight: 800; margin: 40px 0 14px; }
.post-body h3 { font-size: 18px; font-weight: 800; margin: 32px 0 12px; }
.post-body ol { padding-left: 22px; margin: 18px 0; }
/* TIGHTER THAN A PARAGRAPH, on purpose. A list item used to inherit the paragraph's 1.75
   and carry 8px below it, which put 36px between two one-line items — Allan showed a
   reference at roughly 30px and said the lists had too much air (2026-08-10). 1.6 with 4px
   below gets there, and it also brings article lists into line with `.job-list`, which was
   already 1.6.
   THE TRADE-OFF IS REAL AND IT WAS THE CLOSER CALL. Slavi's items run to seven lines each,
   and there the gap BETWEEN items is the only thing separating them from the lines inside
   them. Four variants were rendered side by side against both a one-line list and his; at
   2px the long items merged into one block. This is the tightest setting that still reads
   as separate items, and the burgundy squares carry the rest. If a long list ever stops
   being readable, the honest fix is shorter items — an item of seven lines is a paragraph
   in disguise — not more air. */
.post-body li { font-size: 16px; line-height: 1.6; color: var(--body); margin-bottom: 4px; }
.post-body ol li::marker { color: var(--burgundy); }
/* The brand's filled square, not a coloured dot. Design.md § Shapes says list
   bullets are the burgundy ■, and the deliverables list already renders it that
   way; article bodies were still using the browser's disc. Numbered lists keep
   their numerals. */
.post-body ul { list-style: none; padding-left: 0; margin: 18px 0; }
.post-body ul li { position: relative; padding-left: 22px; }
.post-body ul li::before {
  /* .53em, not .62em. The old value was tuned against line-height 1.75; at 1.6 the line
     box is 2.4px shorter and the square measured 1.4px low against the first line's optical
     centre. Measured rather than eyeballed — 1.4px is invisible on its own and reads as a
     list that is subtly not quite aligned. */
  content: ""; position: absolute; left: 0; top: .53em;
  width: 7px; height: 7px; background: var(--burgundy);
}
.post-body a { color: var(--lapis); text-decoration: underline; }
/* A callout, and it is `CalloutCritical` from the Word master — NOT Intense Quote,
   which docs/Content.md claimed until 2026-08-10 (caught by Allan). The two have
   nothing in common: IntenseQuote is a pull-quote, bordered top AND bottom in lapis,
   centred, italic, indented both sides. This is a note in a panel.
   Read from word/styles.xml, not from the guide's prose:

     shading fill F2F2F0   -> var(--cream), which is already that value
     left border sz=18     -> 2.25pt, so 3px
     indent left 340tw     -> ~0.6cm, so the 22px of left padding
     spacing 120tw         -> 6pt before/after

   THE BRAND HAS FIVE OF THESE and markdown has one `>`. Info and Effect are lapis,
   Decision gold, Critical burgundy, Recommendation green — identical otherwise. A
   syntax to pick between them (`> [!info]`) would be a convention we invented, which
   breaks the file for every other markdown tool; the same reason table width hints
   were rejected. So `>` is the burgundy one, and the other four do not exist here.

   NO BOLD AND NO LARGER SIZE, deliberately reverted. Both were mine, and neither is
   in the style: CalloutCritical is based on Normal and adds only the panel, the rule,
   the indent and the spacing. The panel is what carries the weight — that is what it
   is for, and setting bold on top of it says the same thing twice. */
.post-body blockquote {
  margin: 24px 0;
  padding: 14px 20px 14px 22px;
  background: var(--cream);
  border-left: 3px solid var(--burgundy);
  color: var(--body);
}
.post-body blockquote p { margin: 0; }
.post-body blockquote p + p { margin-top: 10px; }

/* A PULL QUOTE — `IntenseQuote` from the Word master, written as a NESTED blockquote:
   `>>` or `> >`. The site had no form for this until 2026-08-10, and Allan's AI article
   is the first text that uses it. Note that the fix earlier the same day went the other
   way: it took `>` AWAY from Intense Quote and gave it CalloutCritical. The two are
   complementary, not the same edit — `>` is a note in a panel, this is a sentence lifted
   out and displayed.

   Values from word/styles.xml, not from prose:
     borders top AND bottom, sz=4 (0.5pt), colour 15317E  -> 1px, var(--lapis)
     alignment centre  ·  italic  ·  text 15317E
     indent left AND right 864tw (1.5cm)                  -> the 56px margin

   WHY NESTING RATHER THAN A NEW MARKER. `> [!quote]` and friends are conventions we would
   have invented, and they break the file for every other markdown tool — the same reason
   table width hints were rejected. Nested blockquote is markdown's own, renders everywhere,
   and the only thing that distinguishes the two forms is depth.

   The outer blockquote has to be undone, or the callout's panel wraps the pull quote. */
.post-body blockquote:has(> blockquote) {
  margin: 0;
  padding: 0;
  background: none;
  border-left: none;
}
.post-body blockquote blockquote {
  margin: 32px 56px;
  /* 9px, down from 18px, and the paragraphs drop from the body's 1.75 to 1.35. Allan showed
     two renderings and said the second was closer: "formatteringen fylder for meget, der
     skal være mindre luft før og efter teksten, linjeafstanden skal være mindre"
     (2026-08-10). Both numbers had been inherited rather than chosen — the padding from the
     master's 1.5cm indent read as if it applied vertically too, and the line-height from
     `.post-body p`, which is set for reading a long paragraph. A pull quote is two lines
     that belong tightly together, not a paragraph. */
  padding: 9px 0;
  background: none;
  border-left: none;
  border-top: 1px solid var(--lapis);
  border-bottom: 1px solid var(--lapis);
  text-align: center;
  font-style: italic;
  color: var(--lapis);
}
.post-body blockquote blockquote p { line-height: 1.35; }
/* Two lines of a pull quote are one thought, so they sit closer than two body paragraphs.
   Written as separate paragraphs rather than with a markdown hard break, because a hard
   break is two trailing spaces — invisible, and stripped by most editors. */
.post-body blockquote blockquote p + p { margin-top: 2px; }

/* `ItalicsCentered` — a whole paragraph in italics, written as `*one sentence.*` alone on
   a line, and given its class by the transform in eleventy.config.js.

   WHY IT EXISTS (Allan, 2026-08-10). His LinkedIn posts use a standalone italic line for
   the author's own aside: "The attackers know it." The site had exactly one italic form,
   IntenseQuote, and that one is a QUOTE — rules top and bottom, indented, lifted out.
   Setting an aside in it says the sentence came from somewhere else, which is the opposite
   of what an aside is.

   GREY, and `--muted` rather than `--body`, because Allan asked for grey and `--body` IS
   grey. A line meant to read as set apart has to be the lighter one, which puts it beside
   captions and meta in the grey law rather than inventing a third grey.

   NO WORD PENDANT. Every other body element maps to a style in the brand master; this one
   is the first that does not — 110 styles, and the only italic-and-centred one is
   IntenseQuote. Adding it belongs in claude-skills, not here. */
.post-body p.italics-centered {
  margin: 28px 0;
  text-align: center;
  color: var(--muted);
}
@media (max-width: 620px) {
  /* 56px each side leaves too little for the line to breathe on a phone. */
  .post-body blockquote blockquote { margin-left: 20px; margin-right: 20px; }
}
.post-body strong { color: var(--ink); }

/* Screenshots in an article body need an edge of their own. Most of what we
   illustrate with is a portal or a console, and those are white to the edge — so
   on this site's white page the image simply dissolves into it and the reader
   cannot tell where the screen stops (Allan, 2026-08-10).

   The line is the site's own card treatment (--line-soft + 12px, same as
   .post-card, .cs-card, .member). The shadow is deliberately weaker than any
   other on the site: 7% against the 8% used for card HOVER and 28% for the
   dialog. Here it does not mean "you can act on this" — it means the image is a
   window from somewhere else, lying on top of the page, which is what a
   screenshot actually is.

   SCOPED TO .post-body ON PURPOSE. A bare `img` rule would frame the footer
   logo, the customer logos, the team avatars and the hero, none of which are
   windows onto anything. */
.post-body img {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .07);
}

/* ---- Code and data tables in an article body -----------------------------
   Taken from PB's WORD brand rather than invented, so the same artefact quoted
   in a report and on a page reads the same way (Allan, 2026-08-10). Sources, so
   the next person can check rather than trust:

     claude-skills/brand/references/word.md § "Code and terminal output"
     claude-skills/brand/references/word.md § tables (Table2Cols)
     claude-skills/tools/pb_brand_spec.py    (LINE_GREY, INK, the grey scale)

   THE BLOCK IS `PBCodeBlock`, NOT `PBTerminalBlock`. The brand's distinction is
   about what the text IS: a terminal block depicts a screen that is not PB's and
   is black on purpose, outside the palette, because branding it would claim the
   screen was ours. A code block quotes an artefact INTO our surface and stays on
   brand tokens. A KQL query is the second kind.

   Courier New is the brand's choice and it carries over for the brand's own
   reason: whitespace means something in a command, columns have to line up, and
   `I` must not read as `l`. On the web it needs a fallback chain, since Courier
   New is not on every machine the way it is on every Office install. */
.post-body pre {
  margin: 24px 0;                       /* brand: 6pt before and after */
  padding: 14px 16px;
  background: var(--cream);             /* brand panel F2F2F0 = --cream */
  border-left: 3px solid var(--brand-line);
  color: var(--ink);
  font-family: "Courier New", Courier, monospace;
  font-size: 14px;
  line-height: 1.55;
  /* Scrolls inside its own frame instead of breaking the page. A query is one
     long line with nothing to wrap on, and a command split across two lines is
     worse to read than one you have to scroll (Allan, 2026-08-10). */
  overflow-x: auto;
}
/* `white-space: pre` is not redundant. The inline `code` rule below sets nowrap so a
   long command is never broken across two lines, and that selector also matches the
   <code> inside a <pre>, which collapsed the query's line breaks into one line. The
   HTML was right and the CSS undid it; caught by looking at the rendered page. */
.post-body pre code { font: inherit; background: none; padding: 0; white-space: pre; }

/* ---- The BLACK block: the brand's `PBTerminalBlock` ----------------------
   Written as ```terminal. Two block styles exist in the brand and the format could
   only reach one of them, so a writer could not choose the black one when the content
   actually IS a foreign screen. Bottega raised it 2026-08-10 after Allan opened the
   editor, saw a grey block and missed the black.

   Values read out of the master's own styles.xml, not from the guide's prose:
     fill  000000   pure black, and the guide is explicit that this is OUTSIDE the
                    palette on purpose. The block depicts a screen that is not PB's,
                    and branding it would claim the screen was ours.
     color CCCCCC   the brand's "output" grey
     Courier New at 10pt, 6pt before and after, 8.5pt side indents

   NOT carried over: the four ANSI prompt colours (FF5555 user@host, 5F87FF path,
   white command, CCCCCC output). In Word they are direct run formatting, because a
   style holds one colour and a prompt line has four. On the web that needs syntax
   highlighting, which needs JavaScript, which the CSP forbids. So the whole block is
   the output grey, and a prompt line is not coloured. That is a simplification of the
   brand rather than a match, and it is deliberate: the alternative is a script tag.

   `:has()` because markdown-it puts the language class on <code>, not on <pre>, and
   the background belongs to the block. Supported everywhere since 2023. */
.post-body pre:has(code.language-terminal) {
  background: #000;
  border-left: none;
  color: #CCC;
  padding: 14px 16px;
}
.post-body pre:has(code.language-terminal) code { color: #CCC; }

/* Inline: the brand's `Code` character style, and that style is ONLY Courier New.
   Read out of the master's styles.xml, not from memory: no shading, no colour, no
   border. An earlier version here gave it a cream background and a bit of padding,
   which is the web convention and is not what the brand says, so it is gone. The
   font change alone is enough to tell a command from prose, because the body face is
   proportional and this one is not.
   `nowrap` stays: it is not decoration, it stops a browser breaking
   `New-HostedOutboundSpamFilterPolicy` across two lines at an arbitrary width. */
.post-body code {
  font-family: "Courier New", Courier, monospace;
  font-size: 0.92em;
  white-space: nowrap;
}

/* `Table2Cols`: brand blue header with white bold text, zebra rows, thin borders
   on every cell. The name is not a column limit — the brand is explicit that it
   bands by ROW and applies to any column count. */
.post-body table {
  /* `display: block` is what makes overflow-x work on a table element, so a wide
     table scrolls in place. Without it the table forces the page wider and
     check-widths fails the build. */
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 24px 0;
  font-size: 15px;
  max-width: 100%;
}
.post-body thead th {
  background: var(--lapis);             /* brand blue 15317E = --lapis */
  color: #fff;
  font-weight: 700;
  text-align: left;
}
.post-body th, .post-body td {
  border: 1px solid var(--line);
  padding: 8px 12px;                    /* brand: compact, never cramped */
  vertical-align: top;
  color: var(--body);
}
/* Zebra by row. The brand's row grey is F2F2F2, a hair off --cream (F2F2F0);
   kept as its own token rather than reusing cream, because they are two
   different values in the master. */
.post-body tbody tr:nth-child(even) td { background: var(--row-grey); }
/* Alignment written as `|:---|:---:|---:|` in the source. The classes are put here by
   the `tableAlignment` transform in eleventy.config.js, which replaces the inline
   `style="text-align:…"` markdown-it emits — the CSP refuses inline styles, so the
   alignment did nothing at all until 2026-08-12.

   Two classes deep on purpose. `.post-body thead th` above sets `text-align: left` for
   every header cell, and a single-class selector would lose to it, leaving a centred
   header row silently left-aligned — the same failure this whole thing exists to fix. */
.post-body th.align-left,   .post-body td.align-left   { text-align: left; }
.post-body th.align-center, .post-body td.align-center { text-align: center; }
.post-body th.align-right,  .post-body td.align-right  { text-align: right; }
/* Text for a screen reader only. It was removed along with the freshness dot
   and taken back out of use, which put the words "Cards" and "List" visibly
   inside two icon buttons. An icon-only control still needs a name. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Card / list toggle (news archive) ----
   Sits above the cards, right aligned, burgundy. Hidden until viewtoggle.js has
   wired it, so a control that cannot do anything is never on the page. */
.view-toggle { display: none; justify-content: flex-end; gap: 4px; margin-bottom: 18px; }
.view-toggle.is-ready { display: flex; }
.vt-btn {
  width: 34px; height: 34px; padding: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--white); color: var(--burgundy);
  border: 1px solid var(--line); border-radius: 8px;
  transition: background .15s, color .15s, border-color .15s;
}
.vt-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.vt-btn svg rect { fill: currentColor; stroke: none; }
.vt-btn svg circle { fill: currentColor; stroke: none; }
.vt-btn:hover { background: var(--cream); }
.vt-btn.is-on { background: var(--burgundy); color: var(--white); border-color: var(--burgundy); }

/* A hidden panel must actually be hidden. `.news-cards { display: grid }` is a
   class selector and beats the browser's built-in `[hidden] { display: none }`,
   so the attribute was set, the DOM said hidden, and the grid stayed on screen.
   Any rule that sets display on a panel has to be answered here. */
[data-view-panel][hidden] { display: none !important; }

/* ---- News archive, list view ---- */
.news-list { list-style: none; margin: 0; padding: 0; }
.news-list li { border-bottom: 1px solid var(--line-soft); }
.news-list a {
  display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 4px 20px;
  padding: 14px 6px; color: var(--body);
}
.news-list a:hover { background: var(--cream); text-decoration: none; }
.nl-date { grid-row: 1 / span 2; font-size: 13px; color: var(--muted); padding-top: 2px; }
.nl-title { font-size: 15px; font-weight: 700; color: var(--lapis); }
.nl-teaser {
  font-size: 14px; color: var(--muted); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
@media (max-width: 620px) {
  /* The date column costs more than it gives at this width: it takes a fifth of
     the line and the teaser is what people scan by. */
  .news-list a { grid-template-columns: 1fr; gap: 2px; }
  .nl-date { grid-row: auto; }
}

/* ---- Team profile panel: one, under the slider, empty until a card is chosen ---- */
.member-panel {
  position: relative; max-width: 760px; margin: 28px auto 0;
  background: var(--lapis-wash); border: 1px solid var(--lapis-wash-line); border-radius: 12px;
  padding: 26px 30px 24px;
}
.member-panel[hidden] { display: none; }
.mp-close {
  position: absolute; top: 10px; right: 14px;
  background: none; border: 0; cursor: pointer;
  font-size: 26px; line-height: 1; color: var(--muted); padding: 4px 8px;
}
.mp-close:hover { color: var(--burgundy); }
.mp-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.mp-name { font-size: 16px; font-weight: 700; color: var(--lapis); }
.mp-role { font-size: 13px; color: var(--muted); }
/* The bio is rendered markdown, so it arrives as paragraphs. The gap between them
   is the same 14px the block itself sits on, and the last one carries none, so a
   one-paragraph bio measures exactly as it did before this became possible. */
.mp-bio { font-size: 15px; line-height: 1.7; color: var(--body); margin: 0 0 14px; }
.mp-bio p { margin: 0 0 14px; }
.mp-bio p:last-child { margin-bottom: 0; }
.mp-linkedin { font-size: 13px; font-weight: 700; color: var(--burgundy); }
.mp-linkedin[hidden] { display: none; }

/* Images in an article body. Centred, and never wider than the image itself is,
   so a small diagram is not stretched to the column width and softened.
   The caption sits centred under the picture and is as wide as the picture
   rather than as wide as the column: it belongs to the image, and a caption
   running past its edges reads as body text that happens to be grey. */
/* `display: table` rather than fit-content, so the figure is exactly as wide as
   the IMAGE. With fit-content the widest child wins, and a caption longer than
   the picture stretched the figure to fit the text, which put the caption's
   edges outside the image it belongs to. A table takes its width from its
   content and a table-caption is forced to that width without affecting it. */
.post-body figure {
  display: table; margin: 32px auto; max-width: 100%;
}
.post-body img {
  max-width: 100%; height: auto; border-radius: 12px; display: block;
}
.post-body figcaption {
  display: table-caption; caption-side: bottom;
  padding-top: 10px; font-size: 13px; color: var(--muted); line-height: 1.5;
  text-align: center;
}
/* No max-width: it sits in the article grid's centre column, which is already 696px, so
   the 760px this used to carry could never apply. */
.post-foot { padding: 16px 0 56px; }
.back-link { font-size: 14px; font-weight: 700; color: var(--burgundy); }
.legal-note { font-size: 13px; color: var(--muted); font-style: italic; margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--line-soft); }

/* ---- Legal pages (privacy, cookies) — same expression as the rest ---- */
/* Left-align the legal prose to the same boxed column as the page-head heading
   (so heading and body share a left edge). Paragraphs keep their own reading
   measure via .legal-body p { max-width }. */
.legal-body { padding: 44px 32px 12px; width: calc(100% - 64px); max-width: calc(var(--wrap) - 64px); }
.legal-body h2 { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin: 36px 0 14px; }
.legal-body > p:first-child + h2, .legal-body > h2:first-child { margin-top: 8px; }
.legal-body p { font-size: 16px; line-height: 1.7; color: var(--body); margin: 0 0 14px; max-width: 720px; }
.legal-body a { color: var(--lapis); text-decoration: underline; }
.legal-body strong { color: var(--ink); }

/* ---- Careers page — postings reuse the services journey-item bar ---- */
.job-panel { padding-top: 4px; }
.job-intro { font-size: 15px; line-height: 1.65; color: var(--body); margin: 0 0 20px; max-width: 720px; }
.job-sub { font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--lapis); border-bottom: 2px solid var(--burgundy); padding-bottom: 8px; display: inline-block; margin: 0 0 14px; }
.job-list { list-style: none; margin: 0 0 24px; padding: 0; max-width: 720px; }
.job-list li { position: relative; padding: 0 0 10px 22px; font-size: 15px; line-height: 1.6; color: var(--body); }
.job-list li::before { content: ""; position: absolute; left: 0; top: 9px; width: 8px; height: 8px; border-radius: 1px; background: var(--burgundy); }
.job-apply { margin: 4px 0 0; display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px; }
.job-apply-note { font-size: 14px; color: var(--muted); }

/* An open position, marked once. The row is otherwise identical to a standing profile,
   and the difference between "we would like to meet someone like you" and "this job is
   vacant" is the only thing a visitor scanning the page has to be able to see.

   Burgundy on a wash rather than a solid fill: it sits inside a heading that is already
   lapis, and a second solid block beside the button below would compete with it. Reuses
   the pill shape of `.tag`, so the page gains no new vocabulary. */
.job-flag { display: inline-block; vertical-align: 2px; margin-left: 10px; font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--burgundy); background: var(--cream); border: 1px solid var(--cream-2); border-radius: 20px; padding: 3px 10px; }
.job-open > summary .ji-title { color: var(--body); }

.job-empty { max-width: 760px; }
.job-empty p { font-size: 15px; line-height: 1.65; color: var(--body); margin: 0; }
.job-empty a { color: var(--lapis); text-decoration: underline; }

/* ---- Footer links column ---- */

/* ---- Responsive ---- */
/* The stages stack at 1100, not 860. Four columns below that are under 200px
   wide, which was survivable when a stage was an icon and two short lines and
   is not now that each carries a card: the headings wrap differently, the
   stages end up different heights, and the cards inherit it. Measured at 1024:
   225px next to 203px. Above 1100 the columns are 237px and everything is
   equal. The rest of the 860 breakpoint is unrelated and stays where it is. */
@media (max-width: 1100px) {
  .steps { flex-direction: column; gap: 28px; }
  .step:not(:last-child)::after { display: none; }
  .navsearch.is-ready { width: 170px; }
}

/* THE NAV COLLAPSES INTO THE DRAWER HERE, NOT AT 560px, AND THE SECOND REASON IS
   NOT THIS FEATURE'S. Measured on the built page: the five links are a fixed
   418px and the CTA 99px, which leaves 33px of slack at 768px and 135px at
   900px, so a usable field simply does not fit beside them. The measurement also
   turned up a fault that was already there: between 561px and about 660px the
   header overflowed on its own, the logo squeezed from 128px to 24px and the
   page scrolled sideways, because the desktop nav was being asked to hold a
   width it never fits in. Collapsing at 1000px is what makes room, and it closes
   that at the same time. */
@media (max-width: 1000px) {
  .navlinks, .nav-cta { display: none; }
  /* The button it hangs off is in the drawer now, so the flags come back into the
     row on their own rather than floating over nothing. */
  .nav-cta-wrap { margin-right: 0; }
  .langtoggle { position: static; padding: 0; background: none; }
  .logo img { height: 64px; margin-left: 0; }
  /* The field takes the room the links left, up to a width where a search box
     stops looking like one. */
  .navsearch.is-ready,
  .navsearch.is-ready:focus-within { width: auto; flex: 1 1 auto; min-width: 0; max-width: 420px; }
  .nav-toggle { display: block; margin-left: auto; }
  .nav-toggle summary { list-style: none; cursor: pointer; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; }
  .nav-toggle summary::-webkit-details-marker { display: none; }
  .burger { position: relative; display: block; width: 24px; height: 2px; background: var(--ink); border-radius: 2px; }
  .burger::before, .burger::after { content: ""; position: absolute; left: 0; width: 24px; height: 2px; background: var(--ink); border-radius: 2px; }
  .burger::before { top: -7px; }
  .burger::after { top: 7px; }
  .nav-drawer { position: absolute; left: 0; right: 0; top: 100%; background: var(--white); border-bottom: 1px solid var(--line-soft); box-shadow: 0 10px 24px rgba(0,0,0,.10); display: flex; flex-direction: column; padding: 6px 20px 16px; }
  .nav-drawer a { padding: 13px 2px; font-size: 16px; font-weight: 600; color: var(--ink); border-bottom: 1px solid var(--line-soft); }
  .nav-drawer a.btn { margin-top: 12px; border-bottom: none; text-align: center; color: var(--white); }
}

@media (max-width: 860px) {
  .sr-cols { grid-template-columns: 1fr 1fr; gap: 22px; }
  .sr-none-bars { grid-template-columns: 1fr 1fr; }
  .content { flex-direction: column; }
  .content .side { flex: 1 1 auto; width: 100%; margin-top: 0; }
  .cat-inner { flex-direction: column; gap: 20px; }
  .cat-head { flex-basis: auto; }
  .cat-intro { border-left: none; padding-left: 0; border-top: 1px solid #33478a; padding-top: 20px; }
  .cta-inner { flex-direction: column; align-items: flex-start; }
  .about-head { flex-direction: column; align-items: flex-start; gap: 28px; }
  .stat-blocks { flex-wrap: wrap; gap: 20px 28px; }
  .faq-cols { grid-template-columns: 1fr; }
  .ji-panel { padding-left: 26px; }
}
@media (max-width: 560px) {
  .wrap, .nav-inner { padding-left: 20px; padding-right: 20px; }
  .hero .wrap, .page-head.has-media .wrap { padding-right: 20px; }
  .hero, .page-head, .site-footer { width: calc(100% - 40px); }
  .hero-media { display: none; }
  /* Everything that collapses the nav is in the 1000px block above. What is left
     here is the phone: a smaller wordmark and a tighter row. */
  .logo img { height: 46px; margin-left: -4px; }
  .nav-inner { gap: 10px; }
  .sr-cols { grid-template-columns: 1fr; gap: 20px; padding: 20px 20px 24px; }
  .sr-none-bars { grid-template-columns: 1fr; }
  .sr-note, .sr-none { padding-left: 20px; padding-right: 20px; }
}
