/* ============================================================
   FirstOrg — "LONDON" — the primary site theme.
   Systems-London / wayfinding reading, self-contained (no imports of
   other variants). Loaded site-wide after spectrum.css, so it re-skins
   every page. Per docs/design-language.md, and following the swatch only:

     Surfaces   warm canvas #F4EFE6 · Portland cream #EDE6D6 · iron black #1C1C1E
     Brand      Johnston-blue indigo #2E2A6B (structural ink)
     Accent     pillar-box red #DA251D (CTAs only)
     The lines  coral #F26B5E · amber #F4A81D · teal #2FA39A · azure #00A1DE
     Type       Libre Franklin (plain) throughout

   Base elements carried over from the approved Ramp pass: flat tiles,
   near-rectangular 6px corners, line-art engine, compact type scale.
   ============================================================ */

:root {
  /* --- surfaces (near-white) --- */
  --canvas:   #FCFCFB;
  --tint:     #F3F3F0;
  --ink:      #1C1C1E;
  --ink-soft: #5A5750;
  --hairline: #DCD4C4;

  /* --- the four lines (engine stages) --- */
  --strategy: #F26B5E; /* coral  */
  --calendar: #F4A81D; /* amber  */
  --write:    #2FA39A; /* teal   */
  --publish:  #00A1DE; /* azure  */

  /* --- structural ink: Johnston-blue indigo --- */
  --brand:      #2E2A6B;
  --brand-deep: #211E50;
  --brand-rgb:  46 42 107;
  --success:    #1E8C57;

  /* --- the single accent: pillar-box red (CTAs only) --- */
  --accent:      #DA251D;
  --accent-deep: #B71E18;
  --accent-rgb:  218 37 29;

  /* --- near-rectangular corners site-wide --- */
  --radius:    6px;
  --radius-lg: 6px;

  /* --- type: plain Libre Franklin --- */
  --font-display: 'Libre Franklin', system-ui, sans-serif;
  --font-body:    'Libre Franklin', system-ui, sans-serif;
}

/* nav glass tuned to the near-white canvas */
.nav { background: rgba(252, 252, 251, .82); }

/* ------------------------------------------------------------
   BACKGROUND — a faint amber metro-line texture tucked into the top-right
   corner of the page, faded radially. (Anchored to the top of every page.)
   ------------------------------------------------------------ */
body { position: relative; }
.page-metro-bg {
  position: absolute;
  top: 0; right: 0;
  width: clamp(512px, 67vw, 1024px);
  height: clamp(512px, 67vw, 1024px);
  overflow: hidden;
  -webkit-mask-image: radial-gradient(circle at 100% 0%, #000 0%, #000 22%, transparent 68%);
          mask-image: radial-gradient(circle at 100% 0%, #000 0%, #000 22%, transparent 68%);
  pointer-events: none;
  z-index: -1;
}
.page-metro-bg svg { display: block; width: 100%; height: 100%; }
.page-metro-bg .gbox__deco-line { stroke: rgb(244 168 29 / .3); stroke-width: 1.4; }
.page-metro-bg .gbox__deco-station { stroke: rgb(244 168 29 / .3); stroke-width: 1.4; fill: var(--canvas); }

.hero__lead { max-width: 56ch; }

/* ------------------------------------------------------------
   GREY BOXES — width-limited content boxes on the swatch grey (--tint).
   Used by Big Features (2-col), Use cases (3-col).
   ------------------------------------------------------------ */
.bigfeatures,
.prod-sec,
.compare-sec,
.statement-sec,
.capabilities,
.problem-statement { padding-block: clamp(2.3rem, 5.3vw, 4rem); }
/* product sections: trim the top pad so the first one sits close to the hero */
.prod-sec--first { padding-top: clamp(2rem, 4vw, 3rem); }
.prod-sec--tint { background: var(--canvas); }
/* desktop only: .prod-demo (the video) is deliberately full-bleed with
   zero section padding there, so .bigfeatures right after it was only
   getting spacing from its own (smaller) top padding — that seam read
   tighter than every other section gap on the page. Extra top padding
   here, same padding-block shorthand as the shared rule above (not
   padding-top) to avoid a physical/logical property mismatch. Mobile
   already has its own fix (.prod-demo joins the shared rhythm group
   there instead, since the video isn't full-bleed on mobile). */
@media (min-width: 761px) {
  .bigfeatures { padding-block: clamp(4rem, 9vw, 6.5rem) clamp(2.3rem, 5.3vw, 4rem); }
}
/* mobile: the 5.3vw component barely registers at phone widths, so the
   2.3rem floor was doing all the work and sections ended up sitting
   right on top of each other — a taller floor + a vw component that
   actually contributes at these widths. .prod-demo (Product Demo/video)
   joins the group here only — on desktop that section is deliberately
   full-bleed with zero padding (.video__frame--viewport breaks out to
   100vw/100vh by design), but on mobile the video drops back to a
   normal inset card, so it needs the same rhythm as every other
   section for its gaps to match theirs. */
@media (max-width: 760px) {
  .bigfeatures,
  .prod-sec,
  .compare-sec,
  .prod-demo,
  .statement-sec,
  .capabilities,
  .problem-statement { padding-block: clamp(3.5rem, 12vw, 4.5rem); }
}
/* .statement-sec and .capabilities read as one continuous intro (a
   standalone statement, then straight into "Everything You Need") — at
   every viewport, after both rhythm rules above so these win the cascade
   at any width: trim .statement-sec's own trailing space (its
   .section-head has no content after it to space out) and .capabilities'
   leading space, instead of two full section gaps stacked back to back. */
.statement-sec { padding-bottom: clamp(1.5rem, 3vw, 2.4rem); }
.statement-sec .section-head { margin-bottom: 0; }
.capabilities { padding-top: clamp(1.5rem, 3vw, 2.4rem); }
/* desktop only: on mobile the headline is already wrapping naturally at
   full width, and a 70% cap there would force awkward extra line breaks
   in an already-large headline. */
@media (min-width: 761px) {
  .statement-sec .page-hero__h1 { max-width: 70%; }
}
/* HOMEPAGE STATEMENT — full-viewport spotlight, homepage only
   (.statement-sec--loose, the product-page variant, is untouched). Same
   100vh/100svh recipe as .hero so this reads as a second full-screen
   moment on the way down the page rather than a compact headline strip;
   flex-centered since — unlike the hero — there's no bottom-anchored
   graphic pulling the copy down. Compound selector (both classes) so
   this always wins over the trimmed rhythm rules above regardless of
   source order. The radial glow reuses .page-hero's own brand-glow
   formula so the "shine" stays in-system rather than inventing a new
   background treatment. */
.statement-sec.statement-sec--viewport {
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: clamp(3rem, 8vw, 5rem);
  background: radial-gradient(1200px 600px at 15% 10%, rgb(var(--brand-rgb) / .07), transparent 65%);
}
.statement-sec.statement-sec--viewport .section-head { margin-bottom: 0; }
.statement-sec.statement-sec--viewport .page-hero__h1 {
  font-size: clamp(3rem, 8vw, 6.5rem);
  max-width: 900px;
}
@media (max-width: 760px) {
  .statement-sec.statement-sec--viewport { padding-block: clamp(3rem, 12vw, 4.5rem); }
}
.prod-lead { max-width: 56ch; margin: .9rem 0 0; color: var(--ink-soft); font-size: clamp(1rem, 1.4vw, 1.1rem); line-height: 1.55; }

/* Problem Statement — growth chart variant. No photo; a full-width bar
   chart stands in its place, with the same three quotes — now in
   .gbox.swatch.swatch--duotone-indigo-amber cards, same treatment the
   hero's own background uses — captioning the third of the chart their
   "chapter" of the story lines up with. Single series, so one hue
   (brand) for every bar, no legend. Bars are capped at 24px and centered
   in their column rather than filling it, per the site's chart mark
   spec — the leftover width is deliberate air, not a layout bug. */
.growth-chart__cards { margin-bottom: clamp(1.6rem, 4vw, 2.6rem); }
.growth-chart__stage { position: relative; }
/* growth-chart uses the exact same shared padding-block as every other
   section (see .bigfeatures/.prod-sec/etc. above) — no special-cased extra
   bottom padding. That asymmetric approach made gaps inconsistent
   (this section's bottom + the next section's own top padding didn't
   add up to the same total other section-pairs did); giving every
   section, including Product Demo below, identical top/bottom padding
   is what actually makes every gap on the page read the same. */

/* Desktop only. Two changes from the plain stacked-then-chart layout:
   1) .growth-chart__pin centers .growth-chart__stage vertically in the
      pinned viewport instead of leaving the chart flush under the nav
      with all the leftover space dumped below it.
   2) the three cards stop being a row above the chart and become an
      absolutely-positioned overlay on it instead — .growth-chart__cards
      is inset:0 on .growth-chart__stage (which is sized by the chart
      alone, see its own rule above), each card is bottom-% positioned
      within that, low/mid/high to roughly track the revenue level its
      quote is about. Only one card is ever visible at a time (the
      data-show-from/-to ranges don't overlap), so they can share the
      same stack without colliding. */
@media (min-width: 761px) {
  .growth-chart__scroll--pinned .growth-chart__pin {
    min-height: calc(100vh - 72px);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  .growth-chart__cards {
    position: absolute;
    inset: 0;
    z-index: 2;
    margin-bottom: 0;
    pointer-events: none;
  }
  .growth-chart__cards .gbox {
    position: absolute;
    width: min(85%, 380px);
    min-height: auto;
    pointer-events: auto;
  }
  /* low/left → mid/centre → high/right — horizontal position tracks the
     same low-to-high story the bottom-% (vertical) position already does */
  .growth-chart__cards .gbox:nth-child(1) { bottom: 16%; left: 2%; }
  .growth-chart__cards .gbox:nth-child(2) { bottom: 50%; left: 50%; transform: translateX(-50%); }
  .growth-chart__cards .gbox:nth-child(3) { bottom: 72%; right: 2%; }
}

/* Scroll-scrub rig (initGrowthChart in app.js). Default here is plain,
   normal-flow layout — no pin, no extra scroll height — so a no-JS or
   prefers-reduced-motion visitor just gets the static section. JS adds
   .growth-chart__scroll--pinned only once it's confirmed it's running
   and motion is allowed; that's what turns on the tall track + sticky
   pin below. Bars fill in (.is-pending removed) and cards swap
   (.is-hidden toggled) as scroll position crosses each bar's index —
   JS only ever *adds* is-pending/is-hidden, never assumes them, so a
   slow/broken script leaves the section fully visible rather than stuck
   blank or grey. */
.growth-chart__scroll--pinned { height: 300vh; }
.growth-chart__scroll--pinned .growth-chart__pin {
  position: sticky;
  top: 72px;
}
@media (max-width: 760px) {
  .growth-chart__scroll--pinned { height: 260vh; }
}

.growth-chart__chart { position: relative; }
/* reading-direction hint at the end of the axis — not the value axis
   (that's a distraction near the bars/peak), the baseline/category one:
   → on desktop (periods run left to right), ↓ on mobile (periods run
   top to bottom). Sits right at/below the baseline rather than hovering
   over the bars, so top: 100% (just under the chart's own box, in the
   margin below the bars) with a small gap, not near the peak at all. */
.growth-chart__axis {
  position: absolute;
  top: 100%;
  margin-top: .5rem;
  right: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15rem;
}
.growth-chart__axis-arrow { font-size: 1rem; line-height: 1; color: var(--ink-soft); }
.growth-chart__axis-arrow::before { content: "→"; }
.growth-chart__axis-label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.growth-chart__track {
  display: grid;
  grid-template-columns: repeat(36, 1fr);
  column-gap: 2px;
  height: clamp(180px, 30vw, 320px);
}
.growth-chart__col {
  height: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
/* --v is each bar's value, in % — the single source of truth for the
   data, read as a height (magnitude axis vertical) on desktop and as a
   width (magnitude axis horizontal, category axis flipped vertical) on
   mobile, see the media query below. Set per-bar via the --N classes,
   not inline styles. */
.growth-chart__bar {
  width: 100%;
  max-width: 14px;
  height: var(--v);
  border-radius: 4px 4px 0 0;
  background: var(--brand);
  transition: background .18s var(--ease), transform .18s var(--ease);
  transform-origin: bottom;
}
.growth-chart__bar:hover,
.growth-chart__bar:focus-visible { background: var(--brand-deep); transform: scaleY(1.02); }
/* not-yet-reached during the scroll-scrub — see the rig comment above */
.growth-chart__bar.is-pending { background: #CDD0E3; }
.growth-chart__baseline { height: 1px; background: var(--hairline); }

/* cards fade/slide out when their bar range isn't the one in view during
   the scroll-scrub; see the rig comment above */
.growth-chart__cards .gbox { transition: opacity .4s var(--ease), transform .4s var(--ease); }
.growth-chart__cards .gbox.is-hidden {
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
}
/* box 2 (only) is also translateX(-50%)-centered on desktop (see the
   overlay rules above) — combine both instead of letting is-hidden's
   transform silently replace the centering and knock it sideways while
   hidden. Boxes 1/3 use left/right, not transform, for their horizontal
   position, so the shared translateY(12px) above is already correct for
   them. Same selector + specificity as the rule above, placed after it,
   so this wins on desktop without needing an extra class. */
@media (min-width: 761px) {
  .growth-chart__cards .gbox:nth-child(2).is-hidden { transform: translate(-50%, 12px); }
}

/* sample revenue per period, as a % of the chart's magnitude axis — 36
   periods. Very slow growth through the first several periods, a quick
   rise to a peak at 13-14 (middle quote — this is the "initial jump"),
   a quick fall into a stagnant plateau, a shaky recovery, then from 26
   on (later quote) a rising, still-erratic climb that pushes past that
   original 13/14 peak by the end — see the .growth-chart HTML comment.
   Rescaled (bars 1-25 keep their same values, just renormalised) since
   the new high at 35 is taller than the old scale's 100%. */
.growth-chart__bar--1  { --v: 3%; }
.growth-chart__bar--2  { --v: 2%; }
.growth-chart__bar--3  { --v: 2%; }
.growth-chart__bar--4  { --v: 3%; }
.growth-chart__bar--5  { --v: 4%; }
.growth-chart__bar--6  { --v: 4%; }
.growth-chart__bar--7  { --v: 5%; }
.growth-chart__bar--8  { --v: 11%; }
.growth-chart__bar--9  { --v: 17%; }
.growth-chart__bar--10 { --v: 28%; }
.growth-chart__bar--11 { --v: 41%; }
.growth-chart__bar--12 { --v: 54%; }
.growth-chart__bar--13 { --v: 66%; }
.growth-chart__bar--14 { --v: 68%; }
.growth-chart__bar--15 { --v: 63%; }
.growth-chart__bar--16 { --v: 49%; }
.growth-chart__bar--17 { --v: 36%; }
.growth-chart__bar--18 { --v: 26%; }
.growth-chart__bar--19 { --v: 25%; }
.growth-chart__bar--20 { --v: 25%; }
.growth-chart__bar--21 { --v: 26%; }
.growth-chart__bar--22 { --v: 25%; }
.growth-chart__bar--23 { --v: 25%; }
.growth-chart__bar--24 { --v: 28%; }
.growth-chart__bar--25 { --v: 33%; }
.growth-chart__bar--26 { --v: 34%; }
.growth-chart__bar--27 { --v: 42%; }
.growth-chart__bar--28 { --v: 38%; }
.growth-chart__bar--29 { --v: 53%; }
.growth-chart__bar--30 { --v: 47%; }
.growth-chart__bar--31 { --v: 63%; }
.growth-chart__bar--32 { --v: 58%; }
.growth-chart__bar--33 { --v: 76%; }
.growth-chart__bar--34 { --v: 68%; }
.growth-chart__bar--35 { --v: 90%; }
.growth-chart__bar--36 { --v: 82%; }

/* mobile: plain text directly over the (moving, colour-changing) bars
   turned out illegible — black/teal text over indigo bars with nothing
   behind it. Card comes back, and it's the exact same
   .gbox.swatch.swatch--duotone-indigo-amber card the Design Scheme
   documents — position changes below (absolute placement + the top-%
   stops), plus one readability override: full-width at this size, the
   135deg duotone's amber half ends up directly under the amber
   .swatch-accent text (desktop's narrower cards keep that text on the
   indigo side). The gradient below holds indigo through the text zone
   and pushes amber out to a right-edge glow — same two colours, same
   direction, no amber-on-amber. */
@media (max-width: 760px) {
  /* same scroll-triggered swap as desktop (no change needed to the JS —
     is-hidden is a universal rule) and the same overlay technique
     (.growth-chart__cards inset:0 on .growth-chart__stage, which is
     sized by .growth-chart__chart alone — see the desktop rule) so the
     text sits right on the chart instead of in its own flow block above
     it. No left/mid/right stagger (full-width, one column) but the
     vertical position IS contextual, same idea as desktop's low/mid/high:
     the chart here is a tall top-to-bottom list rather than a short
     left-to-right row, so "near this card's own bars" means top / middle
     / last-third of that list instead of a bottom-%. Gaps between the
     top-% stops (38% / 28% of the ~36-row track) comfortably clear the
     Design Scheme card's own min-height, so nothing here needs shrinking
     to fit. */
  .growth-chart__cards {
    position: absolute;
    inset: 0;
    z-index: 2;
    margin-bottom: 0;
    pointer-events: none;
  }
  .growth-chart__cards .gbox {
    position: absolute;
    left: 0;
    right: 0;
    pointer-events: auto;
    background: linear-gradient(135deg, var(--brand) 0%, var(--brand) 40%, var(--calendar) 115%);
  }
  .growth-chart__cards .gbox:nth-child(1) { top: 2%; }
  .growth-chart__cards .gbox:nth-child(2) { top: 40%; }
  .growth-chart__cards .gbox:nth-child(3) { top: 68%; }
}

/* mobile: rotate the chart 90° rather than cramming 36 thin columns into
   a narrow viewport. The category axis (periods) runs top to bottom —
   period 1 (value 0) is the first row, so it lands at the top — and
   each period's bar grows rightward from a left baseline instead of
   upward from a bottom one. Same --v values as desktop; only the axis
   they're read against (height → width) and the layout direction change. */
@media (max-width: 760px) {
  /* breathing room above the pinned chart instead of it sitting flush
     under the nav — a fixed offset, not desktop's full vertical centring,
     since the mobile chart's own height (36 stacked rows) can already run
     long and centring it could push more of it below the fold */
  .growth-chart__scroll--pinned .growth-chart__pin { padding-top: clamp(2rem, 10vw, 4rem); }
  .growth-chart__track {
    display: flex;
    flex-direction: column;
    height: auto;
    row-gap: 3px;
    padding-left: 10px;
    border-left: 1px solid var(--hairline);
  }
  .growth-chart__col {
    height: 14px;
    justify-content: flex-start;
    align-items: center;
  }
  .growth-chart__bar {
    width: var(--v);
    max-width: none;
    height: 8px;
    border-radius: 0 4px 4px 0;
    transform-origin: left;
  }
  .growth-chart__bar:hover,
  .growth-chart__bar:focus-visible { transform: scaleX(1.02); }
  .growth-chart__baseline { display: none; }
  /* same fix as desktop just applied — top: 100% puts the label's own
     top edge at the container's bottom edge, so it sits fully below
     the last row instead of bottom: 0, which anchored the label's
     bottom edge there and left it extending upward, above the last row. */
  .growth-chart__axis { right: auto; left: 0; }
  .growth-chart__axis-arrow::before { content: "↓"; }
}

.gbox-grid { display: grid; gap: clamp(1rem, 2vw, 1.4rem); }
/* a single grid cell holding two boxes stacked vertically instead of one —
   same gap as .gbox-grid so the vertical rhythm matches the grid's own */
.gbox-stack { display: flex; flex-direction: column; gap: clamp(1rem, 2vw, 1.4rem); }
/* stacking two .gbox-grid rows directly (no wrapper) — same gap as the
   grid's own, so vertical rhythm between rows matches within a row */
.gbox-grid + .gbox-grid { margin-top: clamp(1rem, 2vw, 1.4rem); }

.gbox-grid--1 { grid-template-columns: 1fr; }
.gbox-grid--2 { grid-template-columns: repeat(2, 1fr); }
.gbox-grid--3 { grid-template-columns: repeat(3, 1fr); }
.gbox-grid--4 { grid-template-columns: repeat(4, 1fr); }
/* a single .gbox--span2 sits across 2 columns of its grid row, as one wide
   box, instead of taking just one column like a plain box would */
.gbox--span2 { grid-column: span 2; }
@media (max-width: 900px) {
  .gbox-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 760px) {
  .gbox-grid--2,
  .gbox-grid--3,
  .gbox-grid--4 { grid-template-columns: 1fr; }
  /* outer grid is down to 1 column here — an explicit span: 2 would force
     an extra implicit column back in (the same bug fixed earlier for the
     usecases spanning box), so drop it and let it stack full-width too */
  .gbox--span2 { grid-column: auto; }
}

/* use cases: "How do I / [question]" cards with a link-out arrow. The 4
   text cards are .swatch--grey (default size), sized entirely by the
   Background Treatments system, matching the Design Scheme exactly — they
   fill columns 1–2 across 2 rows by normal grid auto-flow. Column 3 is a
   single .swatch--double card spanning both rows; default grid stretch
   (no align-items override needed) sizes each row to roughly half its
   height, which works out cleanly since .swatch--double's min-height
   (240–320px) is exactly double .swatch's default (120–160px). */
.usecases .swatch--double { grid-column: 3; grid-row: 1 / span 2; }
@media (max-width: 760px) {
  /* .gbox-grid--3 collapses to a single column here, but an explicit
     grid-column/row still forces the grid to keep 3 columns around to
     satisfy it — reset back to normal single-column flow */
  .usecases .swatch--double { grid-column: auto; grid-row: auto; }
}
/* more breathing room before the final CTA — .usecases is the last section
   above it on the homepage, so this only affects that transition */
.usecases { padding-bottom: clamp(5rem, 11vw, 8rem); }

/* Paddle Party case study — photo background, white logo overlaid */
.gbox.uc-case {
  display: flex;
  flex-direction: column;
  border-color: transparent;
  color: #FFFFFF;
  background-image:
    linear-gradient(180deg, rgb(12 20 38 / .5) 0%, rgb(12 20 38 / .68) 100%),
    url(/assets/paddle-party-court.jpg);
  background-size: cover;
  background-position: center;
}
.uc-case .gbox__deco { display: none; }  /* no metro texture on the photo box */
.uc-case__tag {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: rgb(255 255 255 / .85);
}
/* same .gbox__title--duo format as the other cards; line one already inherits
   white from .gbox.uc-case's own color, this recolours the accent line for
   the photo (teal from .swatch-accent--site wouldn't read here) */
.uc-case .swatch-accent { color: rgb(255 255 255 / .82); }
.uc-case__logo {
  margin-top: auto;                      /* spacer pushes it to the bottom-left */
  width: clamp(46px, 15%, 60px);
  height: auto;
  display: block;
  filter: brightness(0) invert(1);       /* recolour the navy logo to white */
}
/* line the arrow up with the logo's bottom edge; solid (not translucent)
   white so it reads crisply over the photo — same red arrow / red-fill
   hover as every other gbox__link, just opaque */
.uc-case .gbox__link { bottom: clamp(1.5rem, 3vw, 2.1rem); background: #FFFFFF; }
.uc-case .gbox__link:hover,
.uc-case .gbox__link:focus-visible { background: var(--accent); color: #FFFFFF; }

/* Trust Levels: a control showing the modes + #-bulleted points */
.trust-seg {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  margin-top: 1.3rem;
  padding-bottom: .8rem;
  border-bottom: 1px solid var(--hairline);
}
.trust-seg__opt {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .74rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
  white-space: nowrap;
}
.trust-list {
  list-style: none;
  margin: 1.2rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .55rem;
}
.trust-list li {
  position: relative;
  padding-left: 1.5rem;
  font-size: .95rem;
  color: var(--ink);
}
.trust-list li::before {
  content: "#";
  position: absolute;
  left: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 600;
  color: var(--brand);
}

/* link-out arrow, bottom-right; only the 36px circle itself is the hit area */
.gbox__link {
  position: absolute;
  right: clamp(1.1rem, 2vw, 1.5rem);
  bottom: clamp(1.1rem, 2vw, 1.5rem);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 0.5px solid var(--hairline);
  border-radius: 9px;
  background: rgb(255 255 255 / .55);
  color: var(--accent);
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.gbox__link svg { width: 18px; height: 18px; }
.gbox__link:hover,
.gbox__link:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
  color: #FFFFFF;
}

/* standalone version of the same square arrow chip — .gbox__link is always
   position: absolute to sit in a card's corner, so it can't be dropped into
   normal page flow as-is. Same shape/border/hover, just static-positioned
   and on a solid tint (translucent white would vanish outside a card). */
.arrow-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0.5px solid var(--hairline);
  border-radius: 9px;
  background: var(--tint);
  color: var(--accent);
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.arrow-cta svg { width: 18px; height: 18px; }
.arrow-cta:hover,
.arrow-cta:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
  color: #FFFFFF;
}
/* same chip, extended with a text label ahead of the arrow */
.arrow-cta--text {
  width: auto;
  height: auto;
  padding: .85em 1.2em .85em 1.35em;
  gap: .6em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .95rem;
  white-space: nowrap;
}

/* background-colour variants — same logic as .gbox__link's .swatch__link--*
   family (icon colour keyed to the card's own hue so it doesn't disappear,
   hover fills with a contrasting colour), rewritten self-contained so they
   don't depend on a .swatch ancestor and work wherever .arrow-cta is dropped.
   Default .arrow-cta above is for a plain light/tint surface (site default);
   these four cover every other surface the site already places this chip
   on: the three brand colour cards and a dark/photo background. */
.arrow-cta--on-indigo,
.arrow-cta--on-amber,
.arrow-cta--on-azure { background: rgb(255 255 255 / .85); }

.arrow-cta--on-indigo { color: var(--brand); }
.arrow-cta--on-indigo:hover,
.arrow-cta--on-indigo:focus-visible { background: var(--calendar); border-color: var(--calendar); color: var(--ink); }

.arrow-cta--on-amber { color: #C2790C; }
.arrow-cta--on-amber:hover,
.arrow-cta--on-amber:focus-visible { background: var(--brand); border-color: var(--brand); color: #FFFFFF; }

.arrow-cta--on-azure { color: #0577A0; }
.arrow-cta--on-azure:hover,
.arrow-cta--on-azure:focus-visible { background: var(--calendar); border-color: var(--calendar); color: var(--ink); }

/* solid (not translucent) white so it stays legible over a photo/dark
   image, same red arrow / red-fill hover as the plain default chip */
.arrow-cta--on-dark {
  background: #FFFFFF;
  color: var(--accent);
}
.arrow-cta--on-dark:hover,
.arrow-cta--on-dark:focus-visible { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.gbox {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 3vw, 2.1rem);
}
/* faint metro-line texture in the top-right corner, faded radially */
.gbox__deco {
  position: absolute;
  top: 0;
  right: 0;
  width: clamp(120px, 38%, 220px);
  aspect-ratio: 1 / 1;
  z-index: -1;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at 100% 0%, #000 0%, #000 26%, transparent 70%);
          mask-image: radial-gradient(circle at 100% 0%, #000 0%, #000 26%, transparent 70%);
}
.gbox__deco-svg { display: block; width: 100%; height: 100%; }

.gbox__deco-line {
  fill: none;
  stroke: rgb(244 168 29 / .3);
  stroke-width: 3.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.gbox__deco-station {
  fill: var(--tint);
  stroke: rgb(244 168 29 / .3);
  stroke-width: 3.2;
}
.gbox__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.3rem;
  line-height: 1.2;
  margin: 0 0 .85rem;
}
.gbox__body {
  color: var(--ink-soft);
  font-size: .95rem;
  line-height: 1.55;
  margin: 0;
}

/* ---- media card — same box sizes as .gbox/.swatch, but the box is now a
   pure image frame (no padding, no headline inside it) and the title sits
   as a caption underneath instead. Two variants: plain frame, or
   --deco (opt-in to the same JS-injected metro-line corner overlay
   .gbox gets — see addBoxDeco()'s querySelectorAll list in app.js). The
   caption reuses .gbox__title verbatim, unchanged, since it's a plain
   sibling here rather than nested in a .swatch — none of the .swatch
   .gbox__title overrides (white text, max-width 75%) apply. ---- */
.gbox-media { margin: 0; }
.gbox-media__frame {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--radius);
  border: 0.5px solid var(--hairline);
  background: var(--tint);
  min-height: clamp(120px, 14vw, 160px);
}
.gbox-media__frame--half   { min-height: clamp(70px, 8vw, 90px); }
.gbox-media__frame--double { min-height: clamp(240px, 28vw, 320px); }
.gbox-media__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gbox-media .gbox__title { margin-top: .85rem; margin-bottom: .4rem; }
.gbox-media .gbox__body { margin-bottom: 0; }
/* two rows of .gbox-media cards read as taller, busier units (image + title
   + body) than a plain text .gbox, so they need more air between rows than
   the sitewide default .gbox-grid + .gbox-grid gap. */
.capabilities .gbox-grid + .gbox-grid { margin-top: clamp(2.2rem, 4.5vw, 3.2rem); }
/* mobile: each 4-up row collapses to a single stacked column (see the
   shared .gbox-grid--4 rule), so the row-boundary gap above and the
   default sitewide .gbox-grid card gap (1rem) end up stacked back to
   back as 8 cards in one column — the plain 1rem gap reads cramped for
   image+title+body cards this size, and it stood out as the one bigger
   gap in an otherwise tight run. Match both to the same value so every
   gap in the stack, within a row or between rows, reads consistently. */
@media (max-width: 760px) {
  .capabilities .gbox-grid { gap: clamp(3rem, 9vw, 4rem); }
  .capabilities .gbox-grid + .gbox-grid { margin-top: clamp(3rem, 9vw, 4rem); }
}

/* status badge — a small pill for a card's state ("Live", "Coming Soon",
   or any other short label), always overlaying the image inside
   .gbox-media__frame (bottom-right corner) — see product.css for the
   same recipe reused on plain, image-less .gbox cards (Full B2B Stack,
   /product/). Color is a modifier, not a fixed value — pick any of the
   five swatch colors (indigo, coral, amber, teal, azure — the same
   palette .swatch-accent-- and .swatch--solid-- use) to match whatever
   the card needs to signal, or --grey for a muted/not-yet-live state;
   white text + a soft shadow (same trick as .swatch .gbox__title) keeps
   it legible on every one of them. */
.gbox-media__badge {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .62rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 4px rgb(0 0 0 / .2);
  background: var(--brand);
  padding: .35em .7em;
  border-radius: 999px;
}
.gbox-media__badge--indigo { background: var(--brand); }
.gbox-media__badge--coral  { background: var(--strategy); }
.gbox-media__badge--amber  { background: var(--calendar); }
.gbox-media__badge--teal   { background: var(--write); }
.gbox-media__badge--azure  { background: var(--publish); }
.gbox-media__badge--grey {
  background: var(--tint);
  color: var(--ink);
  text-shadow: none;
  border: 0.5px solid var(--hairline);
}
.gbox-media__frame .gbox-media__badge {
  position: absolute;
  bottom: .75rem;
  right: .75rem;
  z-index: 1;
}

/* ---- capability card art: platform-icon tile (Organic Social Content) —
   two app-icon badges (already rounded-square, colour-per-brand PNGs)
   centered on the frame's own tint background. Shadow is a per-icon
   filter (follows each icon's own rounded shape) rather than a box-shadow
   (which would draw a square shadow behind the rounded corners). ---- */
.gbox-media__icons {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 4vw, 2rem);
}
.gbox-media__icon {
  width: clamp(32px, 9vw, 44px);
  height: clamp(32px, 9vw, 44px);
  filter: drop-shadow(0 4px 8px rgb(0 0 0 / .2));
}

/* ---- capability card art: browser-mockup tile (Blog & Landing Pages) — a
   tiny site preview: chrome bar (traffic-light dots + url pill) over a
   dark page body with placeholder copy lines, a CTA block (--accent, same
   red as .btn--primary) and a colour block standing in for a photo. ---- */
.gbox-media__browser {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--brand-deep);
}
.gbox-media__browser-bar {
  display: flex;
  align-items: center;
  gap: .3rem;
  flex: none;
  padding: .5rem .6rem;
  background: var(--tint);
}
.gbox-media__browser-dot {
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--hairline);
}
.gbox-media__browser-url {
  margin-left: .4rem;
  flex: 1;
  height: .55rem;
  border-radius: 999px;
  background: #fff;
  border: 0.5px solid var(--hairline);
}
.gbox-media__browser-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: 0 .9rem;
}
.gbox-media__browser-copy {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.gbox-media__browser-line {
  width: 60%;
  height: .4rem;
  border-radius: 999px;
  background: rgb(255 255 255 / .35);
}
.gbox-media__browser-line--lg {
  width: 85%;
  height: .55rem;
  background: rgb(255 255 255 / .85);
}
.gbox-media__browser-cta {
  margin-top: .3rem;
  width: 40%;
  height: .8rem;
  border-radius: 999px;
  background: var(--accent);
}
.gbox-media__browser-media {
  flex: none;
  width: 26%;
  align-self: stretch;
  margin: .9rem .4rem 2.5rem 0;
  border-radius: calc(var(--radius) * .4);
  background: linear-gradient(150deg, var(--publish), var(--brand));
}

/* ---- capability card art: shared avatar chip — a plain initials-in-circle
   stand-in (no real headshots), reused across the DM/comment/review
   mockups below. --brand flips it to the FirstOrg-side voice in a
   two-party exchange (thread reply, DM reply). ---- */
.gbox-media__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--ink-soft);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .52rem;
}
.gbox-media__avatar--brand { background: var(--brand); }
.gbox-media__avatar--lg { width: 34px; height: 34px; font-size: .82rem; }

/* ---- capability card art: comment + reply thread (Social Engagement) ---- */
.gbox-media__thread {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .6rem;
  padding: 1rem 1.1rem;
}
.gbox-media__comment { display: flex; gap: .5rem; }
.gbox-media__comment--reply { margin-left: 1.4rem; }
.gbox-media__comment-body { min-width: 0; }
.gbox-media__comment-name {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .68rem;
  color: var(--ink);
}
.gbox-media__comment-text {
  margin: .1rem 0 0;
  font-size: .68rem;
  line-height: 1.35;
  color: var(--ink-soft);
}

/* ---- capability card art: stacked ad cards (Paid Ads) — a search-ad card
   over a social paid-promotion post, on the site's amber tone (same
   colour Paid Ads' badge/category uses elsewhere). Second card sits
   mostly below the frame edge, cropped by .gbox-media__frame's own
   overflow: hidden, so only its header + a sliver of media peeks out —
   same "stacked, cropped" read as the reference screenshot. ---- */
.gbox-media__ads {
  position: absolute;
  inset: 0;
  background: linear-gradient(165deg, var(--calendar), #C9820F);
}
.gbox-media__ad-card {
  position: absolute;
  left: .7rem;
  right: .7rem;
  top: .7rem;
  background: #fff;
  border-radius: calc(var(--radius) * .35);
  box-shadow: 0 8px 20px rgb(0 0 0 / .18);
  padding: .55rem .6rem;
}
.gbox-media__ad-card--post { top: 62%; }
.gbox-media__ad-head { display: flex; align-items: center; gap: .4rem; }
.gbox-media__ad-brand {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .62rem;
  color: var(--ink);
}
.gbox-media__ad-url { display: block; font-size: .56rem; color: var(--ink-soft); }
.gbox-media__ad-headline {
  margin: .35rem 0 0;
  font-size: .66rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--publish);
}
.gbox-media__ad-desc {
  margin: .25rem 0 0;
  font-size: .58rem;
  line-height: 1.3;
  color: var(--ink-soft);
}
.gbox-media__ad-card--post .gbox-media__ad-url { font-size: .56rem; }
.gbox-media__ad-media {
  margin-top: .5rem;
  height: 34px;
  border-radius: calc(var(--radius) * .3);
  background: linear-gradient(140deg, var(--ink), var(--brand-deep));
}

/* ---- capability card art: cold email (Email Outbound) ---- */
.gbox-media__email {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: .9rem 1.1rem;
}
.gbox-media__email-row {
  display: flex;
  gap: .4rem;
  padding: .3rem 0;
  border-bottom: 0.5px solid var(--hairline);
  font-size: .62rem;
}
.gbox-media__email-label { flex: none; color: var(--ink-soft); font-weight: 600; }
.gbox-media__email-value { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gbox-media__email-value--subject { font-weight: 700; }
.gbox-media__email-body {
  margin: .6rem 0 0;
  font-size: .66rem;
  line-height: 1.45;
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- capability card art: LinkedIn DM (LinkedIn Outbound) — outreach
   bubble on the left, prospect's reply on the right in --brand, showing
   the "opens doors" outcome rather than just the outbound message alone. ---- */
.gbox-media__dm {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .4rem;
  padding: 1rem 1.1rem 2.3rem;
}
.gbox-media__dm-head { display: flex; align-items: center; gap: .4rem; margin-bottom: .15rem; }
.gbox-media__dm-name { font-family: var(--font-display); font-weight: 700; font-size: .66rem; color: var(--ink); }
.gbox-media__dm-bubble {
  margin: 0;
  max-width: 82%;
  padding: .4rem .6rem;
  border-radius: 999px 999px 999px 4px;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  font-size: .62rem;
  line-height: 1.3;
  color: var(--ink);
}
.gbox-media__dm-bubble--out {
  align-self: flex-end;
  margin-right: 2.2rem;
  border-radius: 999px 999px 4px 999px;
  background: var(--brand);
  border-color: transparent;
  color: #fff;
}

/* ---- capability card art: qualifying email that ends in a booked meeting
   (AI SDR) — reuses the .gbox-media__email-row/-label/-value/-body pieces
   above, plus a calendar chip standing in for a scheduler confirmation. ---- */
.gbox-media__sdr {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: .9rem 1.1rem 2.3rem;
}
.gbox-media__sdr-meeting {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  align-self: flex-start;
  margin-top: .5rem;
  padding: .3em .65em;
  border-radius: 999px;
  background: rgb(47 163 154 / .14);
  color: var(--write);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .58rem;
  letter-spacing: .02em;
}
.gbox-media__sdr-meeting svg { width: 12px; height: 12px; flex: none; }

/* ---- capability card art: 5-star review (Reviews & Case Studies) ---- */
.gbox-media__review {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .4rem;
  padding: 1rem 1.1rem;
}
.gbox-media__stars {
  color: var(--calendar);
  font-size: .78rem;
  letter-spacing: .1em;
}
.gbox-media__review-quote {
  margin: 0;
  font-size: .68rem;
  line-height: 1.4;
  color: var(--ink);
  font-style: italic;
}
.gbox-media__review-who { display: flex; align-items: center; gap: .45rem; margin-top: .15rem; }
.gbox-media__review-name { display: block; font-family: var(--font-display); font-weight: 700; font-size: .62rem; color: var(--ink); }
.gbox-media__review-role { display: block; font-size: .56rem; color: var(--ink-soft); }

/* ---- capability card art: X/Twitter-style post (Quick Thoughts format,
   product/index.php) — a rounded, bordered, drop-shadowed card that reads
   as an embedded tweet widget sitting inside the frame (frame's own tint
   + deco shows as a mat around it), not a flat panel filling the frame
   edge-to-edge. .gbox-media__frame--embed centers/pads it. Chrome mirrors
   X's own: verified badge + handle + time on the name line, a "more" dots
   button at the far right, then post text, then the reply/repost/like/
   share icon row (heart filled red, matching X's own like state). Icons
   are stylised approximations, not literal platform glyphs — same as
   every other capability-card mockup on the site (.gbox-media__browser
   etc.), not a pixel clone of a real X card. ---- */
.gbox-media__frame--embed {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(1rem, 3vw, 1.5rem);
}
.gbox-media__tweet {
  width: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: .6rem;
  padding: 1rem 1.1rem;
  background: #fff;
  border-radius: 18px;
  border: 1px solid var(--hairline);
  box-shadow: 0 10px 26px rgb(20 20 30 / .1);
}
.gbox-media__tweet-head { display: flex; align-items: flex-start; gap: .5rem; }
.gbox-media__tweet-who { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 .35rem; min-width: 0; }
.gbox-media__tweet-name {
  display: inline-flex;
  align-items: center;
  gap: .2rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .7rem;
  color: var(--ink);
  white-space: nowrap;
}
.gbox-media__badge-check { width: 13px; height: 13px; flex: none; color: var(--publish); }
.gbox-media__tweet-handle {
  font-size: .62rem;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gbox-media__tweet-text {
  margin: 0;
  font-size: .74rem;
  line-height: 1.45;
  color: var(--ink);
}
.gbox-media__tweet-stats {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  color: var(--ink-soft);
  font-size: .6rem;
}
.gbox-media__tweet-stats span { display: inline-flex; align-items: center; gap: .3rem; }
.gbox-media__tweet-stats svg { width: 14px; height: 14px; flex: none; }
.gbox-media__tweet-stat--like { color: #E0245E; }
.gbox-media__tweet-stat--like svg { color: #E0245E; }

/* ---- capability card art: LinkedIn-style post (Every Day Content and
   Thought Leadership formats, product/index.php) — same "embedded widget"
   treatment as the tweet card above (rounded, bordered, shadowed, sitting
   on the frame's own tint mat via .gbox-media__frame--embed), but with
   LinkedIn's own tighter corner radius and flatter shadow instead of X's
   rounder/deeper one. Avatar + a 3-line header (name, headline/tagline
   truncated to one line, time), a "more" dots button, post copy as real
   paragraphs (not one clamped block — .gbox-media__frame--double's own
   overflow: hidden crops whatever doesn't fit, so a short post shows in
   full and a long multi-paragraph one trails off naturally, same as
   LinkedIn's own "…see more" preview), then the reaction-dot cluster +
   comment count and a Like/Comment/Share action row. ---- */
.gbox-media__li-post {
  width: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: .55rem;
  padding: 1rem 1.1rem;
  background: #fff;
  border-radius: 10px;
  border: 1px solid var(--hairline);
  box-shadow: 0 6px 20px rgb(20 20 30 / .08);
}
.gbox-media__li-head { display: flex; align-items: flex-start; gap: .5rem; }
.gbox-media__li-who { display: flex; flex-direction: column; min-width: 0; }
.gbox-media__li-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .7rem;
  color: var(--ink);
}
.gbox-media__li-headline {
  font-size: .6rem;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gbox-media__li-meta {
  font-size: .58rem;
  color: var(--ink-soft);
}
.gbox-media__li-text {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: .55rem;
}
.gbox-media__li-text p {
  margin: 0;
  font-size: .7rem;
  line-height: 1.45;
  color: var(--ink);
}
.gbox-media__li-reactions { display: flex; align-items: center; gap: .4rem; }
.gbox-media__li-reax { display: flex; }
.gbox-media__li-reax-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid #fff;
  margin-left: -4px;
}
.gbox-media__li-reax-dot:first-child { margin-left: 0; }
.gbox-media__li-reax-dot--like { background: var(--publish); }
.gbox-media__li-reax-dot--support { background: #7C5CE0; }
.gbox-media__li-reax-dot--insight { background: var(--calendar); }
.gbox-media__li-reax-count { font-size: .58rem; color: var(--ink-soft); }
.gbox-media__li-actions {
  display: flex;
  gap: 1.3rem;
  padding-top: .55rem;
  border-top: 0.5px solid var(--hairline);
  color: var(--ink-soft);
  font-size: .6rem;
  font-weight: 600;
}
.gbox-media__li-actions span { display: inline-flex; align-items: center; gap: .3rem; }
.gbox-media__li-actions svg { width: 14px; height: 14px; flex: none; }

/* ---- shared: "more options" dots + verified-badge check reused by both
   the tweet and LinkedIn mockups above ---- */
.gbox-media__more { display: flex; align-items: center; gap: 2px; margin-left: auto; padding-top: .15rem; }
.gbox-media__more span { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-soft); }

/* ---- channel messaging-pillar carousel (JS-driven; hidden until live) ---- */
.pillarstage {
  display: none;            /* JS reveals it; no-JS shows the fallback text */
  position: relative;
  overflow: hidden;
  height: 268px;
  min-height: 268px;        /* floor so it never collapses when flexed */
  margin-top: 2rem;
}
.pcard {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(248px, 90%);
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  gap: .85rem;
  padding: 1.25rem;
  transform: translateX(-135%);
  opacity: 0;
  transition: transform .56s var(--ease), opacity .56s var(--ease);
}
.pcard.enter { transform: translateX(0);     opacity: 1; z-index: 2; }
.pcard.leave { transform: translateX(135%);  opacity: 0; z-index: 1; }
.pcard__head { display: flex; align-items: center; gap: .5rem; flex: none; }
.pcard__logo { width: 22px; height: 22px; display: block; flex: none; }
.pcard__name { font-family: var(--font-display); font-weight: 600; font-size: .9rem; color: var(--ink); }
.pcard__pills {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  flex: 1;                    /* fill the rest of the square */
  align-content: flex-start;
}
.ppill {
  font-size: .7rem;
  line-height: 1.2;
  padding: .38rem .68rem;
  max-width: 100%;
  border-radius: 999px;
  background: rgb(var(--brand-rgb) / .09);
  color: var(--brand);
  opacity: 0;
  transform: translateY(6px) scale(.96);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.ppill.on { opacity: 1; transform: none; }

/* ---- Conversion schedule: spinning wireframe globe + regional callouts ---- */
.globestage { display: none; margin-top: 2rem; position: relative; }

.globe-wrap {
  position: relative;
  width: 104px;
  height: 104px;
  margin: 0 auto 1.3rem;
  perspective: 640px;
}
.globe__edge {                         /* always a perfect circle silhouette */
  position: absolute;
  inset: 0;
  border: 0.5px solid rgb(var(--brand-rgb) / .55);
  border-radius: 50%;
}
.globe {                               /* tilted polar axis */
  position: absolute;
  inset: 0;
  transform: rotateX(-16deg);
  transform-style: preserve-3d;
}
.globe__grid {                         /* the part that actually spins */
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  animation: globe-spin 20s linear infinite;
}
.globe__mer,
.globe__lat {
  position: absolute;
  inset: 0;
  margin: auto;
  border: 0.5px solid rgb(var(--brand-rgb) / .32);
  border-radius: 50%;
}
.globe__lat { border-color: rgb(var(--brand-rgb) / .22); }
.globe__mer:nth-child(1) { transform: rotateY(0deg); }
.globe__mer:nth-child(2) { transform: rotateY(30deg); }
.globe__mer:nth-child(3) { transform: rotateY(60deg); }
.globe__mer:nth-child(4) { transform: rotateY(90deg); }
.globe__mer:nth-child(5) { transform: rotateY(120deg); }
.globe__mer:nth-child(6) { transform: rotateY(150deg); }
.globe__lat--eq { transform: rotateX(90deg); }
.globe__lat--n  { transform: translateY(-28px) rotateX(90deg) scale(.78); }
.globe__lat--s  { transform: translateY(28px)  rotateX(90deg) scale(.78); }
@keyframes globe-spin { to { transform: rotateY(360deg); } }

.gcard-stage { position: relative; min-height: 158px; }
.gcard {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: .9rem 1rem 1.15rem;
  opacity: 0;
  transform: translateX(-7%);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.gcard.enter { opacity: 1; transform: none;            z-index: 2; }
.gcard.leave { opacity: 0; transform: translateX(7%);  z-index: 1; }
.gcard__head { display: flex; align-items: center; gap: .5rem; }
.gcard__flag {
  width: 22px;
  height: 15px;
  display: block;
  flex: none;
  object-fit: cover;
  border-radius: 2px;
  border: 0.5px solid var(--hairline);
}
.gcard__region { font-family: var(--font-display); font-weight: 600; font-size: .86rem; color: var(--ink); }
.gcard__tz {
  margin-left: auto;
  font-size: .6rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--brand);
  background: rgb(var(--brand-rgb) / .09);
  padding: .2rem .5rem;
  border-radius: 999px;
}
.gcard__slots { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .38rem; }
.gslot {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding-top: .38rem;
  border-top: 0.5px solid var(--hairline);
  font-size: .68rem;
}
.gslot:first-child { padding-top: 0; border-top: 0; }
.gslot__when { display: flex; flex-direction: column; line-height: 1.15; }
.gslot__part { font-weight: 600; color: var(--ink); }
.gslot__time { color: var(--ink-soft); font-size: .62rem; }
.gslot__ch {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: .35rem;
  color: var(--ink);
  font-weight: 500;
  white-space: nowrap;
}
.gslot__logo { width: 15px; height: 15px; display: block; flex: none; }

@media (prefers-reduced-motion: reduce) {
  .globe__grid { animation: none; }
}

/* boxes whose graphic should fill and centre in the space under the header */
.gbox--center { display: flex; flex-direction: column; }
.gbox--center .campstack,
.gbox--center .stratstage,
.gbox--center .pillarstage,
.gbox--center .voicestage,
.gbox--center .globestage {
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: 1.2rem;
}
/* globe's callout cards are absolutely positioned — keep the row full-width */
.gbox--center .globestage { align-items: stretch; }

/* ---- Campaigns that run themselves: rows rise in and stack ---- */
.campstack { display: none; margin-top: 2rem; }
.camplist { display: flex; flex-direction: column; gap: .5rem; max-width: 360px; }
.camplist.camp--reset .crow,
.camplist.camp--reset .campdate { transition: none; }

.crow {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .62rem .8rem;
  background: #FFFFFF;
  border: 0.5px solid var(--hairline);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.crow.show { opacity: 1; transform: none; }

/* date — plain text, not boxed */
.campdate {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .9rem;
  color: var(--ink);
  padding: 0 .15rem .1rem;
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.campdate.show { opacity: 1; transform: none; }

/* task summary */
.ctasks__label   { font-family: var(--font-display); font-weight: 600; font-size: .88rem; color: var(--ink); }
.ctasks__summary { margin-left: auto; font-size: .8rem; color: var(--ink-soft); }

/* process-step rows (recoloured icon + label) */
.cstep__icon {
  width: 18px;
  height: 18px;
  flex: none;
  display: block;
  background-color: var(--brand);
  -webkit-mask: center / contain no-repeat;
  mask: center / contain no-repeat;
}
.cstep__icon--node { -webkit-mask-image: url(/assets/icon-node.png); mask-image: url(/assets/icon-node.png); }
.cstep__icon--grid { -webkit-mask-image: url(/assets/icon-grid.png); mask-image: url(/assets/icon-grid.png); }
.cstep__label { font-size: .82rem; color: var(--ink); }

/* process card — single-line window with a label that scrolls up the phases */
.cproc__win {
  flex: 1;
  min-width: 0;
  height: 1.3rem;
  overflow: hidden;
}
.cproc__track {
  display: flex;
  flex-direction: column;
  transition: transform .4s var(--ease);
}
.cproc__line {
  height: 1.3rem;
  line-height: 1.3rem;
  font-size: .82rem;
  color: var(--ink);
  white-space: nowrap;
}
.cproc--s0 { transform: translateY(0); }
.cproc--s1 { transform: translateY(-1.3rem); }
.cproc--s2 { transform: translateY(-2.6rem); }
.cproc--s3 { transform: translateY(-3.9rem); }
.cproc--s4 { transform: translateY(-5.2rem); }
.camplist.camp--reset .cproc__track { transition: none; }

/* post rows */
.cpost__logo  { width: 18px; height: 18px; display: block; flex: none; }
.cpost__topic {
  flex: 1;
  min-width: 0;
  font-size: .82rem;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cpost__status {
  flex: none;
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--brand);
  background: rgb(var(--brand-rgb) / .09);
  padding: .24rem .55rem;
  border-radius: 999px;
  transition: background .25s var(--ease), color .25s var(--ease);
}
.cpost__status.is-final {
  color: #FFFFFF;
  background: var(--brand);
}
.cpost__status.is-published {
  background: var(--success);
}

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

/* ---- Campaigns (flat variant) — no card, text sits directly on the
   gbox background; exists only to compare against the boxed rows above.
   Sized to fit 8 post rows (LinkedIn/X/blog/Reddit) in the same overall
   height as the original 5-row version — smaller type, tighter padding. ---- */
.campstack--flat { margin-top: 1rem; }
.campstack--flat .camplist { gap: .16rem; }
.campstack--flat .crow {
  padding: .12rem 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.campstack--flat .campdate { padding: 0 0 .2rem; font-size: .8rem; }
.campstack--flat .ctasks__label   { font-size: .78rem; }
.campstack--flat .ctasks__summary { font-size: .7rem; }
.campstack--flat .cstep__icon,
.campstack--flat .cpost__logo { width: 14px; height: 14px; }
.campstack--flat .cpost__topic { font-size: .72rem; }

/* process card: same scrolling-window mechanic as the boxed version,
   just resized to the smaller line height used here */
.campstack--flat .cproc__win  { height: .95rem; }
.campstack--flat .cproc__line { height: .95rem; line-height: .95rem; font-size: .72rem; }
.campstack--flat .cproc--s0 { transform: translateY(0); }
.campstack--flat .cproc--s1 { transform: translateY(-.95rem); }
.campstack--flat .cproc--s2 { transform: translateY(-1.9rem); }
.campstack--flat .cproc--s3 { transform: translateY(-2.85rem); }
.campstack--flat .cproc--s4 { transform: translateY(-3.8rem); }

/* status: fixed-width, right-aligned column so word-length changes
   (Reading → Researching → ... → Ready for Approval) don't reflow the
   topic text next to it; plain colour instead of a filled pill keeps it
   quiet until a post actually finishes */
.campstack--flat .cpost__status {
  width: 6.6rem;
  font-size: .64rem;
  text-align: right;
  background: none;
  color: var(--ink-soft);
  padding: 0;
  border-radius: 0;
  transition: color .25s var(--ease);
}
.campstack--flat .cpost__status.is-final { color: var(--brand); }
.campstack--flat .cpost__status.is-published { color: var(--success); }

/* on narrow cards the box's own min-height doesn't grow with this much
   content, so the last row can run in behind .gbox__link's corner button —
   trim row height and type size a little further, mobile only */
@media (max-width: 760px) {
  .campstack--flat .camplist { gap: .1rem; }
  .campstack--flat .crow { padding: .06rem 0; }
  .campstack--flat .campdate { font-size: .72rem; padding-bottom: .1rem; }
  .campstack--flat .ctasks__label   { font-size: .7rem; }
  .campstack--flat .ctasks__summary { font-size: .62rem; }
  .campstack--flat .cstep__icon,
  .campstack--flat .cpost__logo { width: 12px; height: 12px; }
  .campstack--flat .cpost__topic { font-size: .66rem; }
  .campstack--flat .cpost__status { font-size: .58rem; width: 5.8rem; }
  .campstack--flat .cproc__win  { height: .82rem; }
  .campstack--flat .cproc__line { height: .82rem; line-height: .82rem; font-size: .66rem; }
  .campstack--flat .cproc--s0 { transform: translateY(0); }
  .campstack--flat .cproc--s1 { transform: translateY(-.82rem); }
  .campstack--flat .cproc--s2 { transform: translateY(-1.64rem); }
  .campstack--flat .cproc--s3 { transform: translateY(-2.46rem); }
  .campstack--flat .cproc--s4 { transform: translateY(-3.28rem); }
}

/* ---- Custom-built content strategy: a reference desk crafting a doc ---- */
.stratstage { display: none; margin-top: 1.4rem; }
.stratsvg { display: block; width: 100%; max-width: 340px; height: auto; }

.strat-ic   { fill: none; stroke: var(--brand); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.strat-star { fill: var(--brand); stroke: none; }
.strat-sheet { fill: #FFFFFF; stroke: var(--hairline); stroke-width: 1; }
.strat-core-bg { fill: #FFFFFF; stroke: var(--hairline); stroke-width: 1; }
.strat-label {
  fill: var(--ink);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 500;
  dominant-baseline: middle;
}
.strat-cap {
  fill: var(--ink);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
}

/* fixed source list — dim by default, highlighted while consulted */
.refsrc { opacity: .5; transition: opacity .35s var(--ease); }
.refsrc.on { opacity: 1; }
.refsrc__pill {
  fill: rgb(var(--brand-rgb) / .08);
  opacity: 0;
  transition: opacity .35s var(--ease);
}
.refsrc.on .refsrc__pill { opacity: 1; }

/* document title bar + content lines being written */
.refdoc__title { fill: rgb(var(--brand-rgb) / .14); transition: fill .4s var(--ease); }
.strat-core.is-done .refdoc__title { fill: var(--brand); }
.refline {
  stroke: var(--ink-soft);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset .45s var(--ease);
}
.refline.written { stroke-dashoffset: 0; }

/* threads from the active source to the line being written */
.refthread {
  fill: none;
  stroke: var(--brand);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: 0;
}
.refthread.go { animation: refthread .8s var(--ease) forwards; }
@keyframes refthread {
  0%   { opacity: 0; stroke-dashoffset: 100; }
  15%  { opacity: 1; }
  55%  { opacity: 1; stroke-dashoffset: 0; }
  100% { opacity: 0; stroke-dashoffset: 0; }
}

/* completion badge */
.refdoc__badge { opacity: 0; transition: opacity .3s var(--ease); }
.refdoc__badge circle { fill: var(--success); }
.strat-core.is-done .refdoc__badge { opacity: 1; }
.refdoc__check {
  fill: none;
  stroke: #FFFFFF;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
.strat-core.is-done .refdoc__check { animation: strat-tick-draw .4s var(--ease) .12s forwards; }
@keyframes strat-tick-draw { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
  .refline, .refthread, .refdoc__check, .refsrc, .refsrc__pill { transition: none; animation: none; }
}

/* ---- Content that sounds like you: generic text rewritten in your voice ---- */
.voicestage {
  display: none;
  position: relative;
  overflow: hidden;
  height: 210px;
  min-height: 210px;        /* floor so it never collapses when flexed */
  margin-top: 1.2rem;
  border-radius: 12px;
}
.voiceview {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: 1.1rem 1.25rem;
  transform-origin: 0 0;
  transition: transform .55s var(--ease);
}
.voicepara {
  margin: 0;
  font-size: 1rem;
  line-height: 1.9;
  color: var(--ink);
}
.vsent { transition: opacity .3s var(--ease); }
.voicepara.focusing .vsent { opacity: .28; }
.voicepara.focusing .vsent.active { opacity: 1; }
.vgen { transition: color .3s var(--ease); }
.vgen.struck { text-decoration: line-through; color: var(--ink-soft); }
.vyou { display: none; color: var(--brand); font-weight: 500; }
.vsent.swapped .vgen { display: none; }
.vsent.swapped .vyou {
  display: inline-block;
  animation: vtype .6s steps(28, end) forwards;
}
@keyframes vtype {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .voiceview, .vsent, .vyou { transition: none; animation: none; }
}

/* ------------------------------------------------------------
   COMPARISON TABLE — capabilities × tools, text cells (not ticks).
   Horizontal scroll on small screens.
   ------------------------------------------------------------ */
.cmp-scroll { overflow-x: auto; }
/* mobile: the table overflows sideways (min-width 600px below) and the cut-off
   column was the only clue more content existed. Standard CSS scrolling-shadows
   (covers scroll with the content via background-attachment: local, shadows
   don't), so an edge shadow appears exactly while there's more table off that
   side and hides itself once you've scrolled there — no JS. Painted on the
   container, so it only shows through cells without their own background;
   the highlighted .cmp__me column can briefly mask it, which is fine — that
   column is never the outermost one while there's still content to reach. */
@media (max-width: 760px) {
  .cmp-scroll {
    background:
      linear-gradient(90deg,  var(--canvas) 30%, rgb(252 252 251 / 0)) left  / 40px 100%,
      linear-gradient(270deg, var(--canvas) 30%, rgb(252 252 251 / 0)) right / 40px 100%,
      radial-gradient(farthest-side at 0 50%,    rgb(11 12 20 / .16), rgb(11 12 20 / 0)) left  / 14px 100%,
      radial-gradient(farthest-side at 100% 50%, rgb(11 12 20 / .16), rgb(11 12 20 / 0)) right / 14px 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
  }
}
.cmp {
  width: 100%;
  min-width: 600px;   /* fits inside .guide-article's 680px column with room for the highlighted column's own right padding; still well above any real mobile viewport, so .cmp-scroll's horizontal-scroll fallback there is unchanged */
  border-collapse: collapse;
  font-size: .9rem;
}
.cmp th,
.cmp td {
  text-align: left;
  vertical-align: top;
  padding: .9rem 1rem;
  border-bottom: 1px solid var(--hairline);
}
.cmp thead th {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  border-bottom: 2px solid var(--hairline);
}
.cmp tbody th {
  font-weight: 600;
  color: var(--ink);
  width: 22%;
}
.cmp td { color: var(--ink-soft); }
.cmp__me { background: var(--tint); }                 /* highlight the FirstOrg column */
.cmp thead .cmp__me { color: var(--brand); border-bottom-color: var(--brand); }

/* colour variant of the highlighted column, using a box colour instead of
   grey — each override selector matches or beats the specificity of the
   base .cmp/.cmp__me rule it replaces, regardless of source order */
.cmp .cmp__me--indigo { background: var(--brand); }
.cmp td.cmp__me--indigo,
.cmp th.cmp__me--indigo { color: #fff; }
.cmp thead th.cmp__me--indigo { color: #fff; border-bottom-color: var(--brand-deep); }

/* gradient variant — same idea, using the same gradient as
   .swatch--gradient-indigo instead of a flat fill */
.cmp .cmp__me--indigo-gradient { background: linear-gradient(135deg, var(--brand), var(--brand-deep)); }
.cmp td.cmp__me--indigo-gradient,
.cmp th.cmp__me--indigo-gradient { color: #fff; }
.cmp thead th.cmp__me--indigo-gradient { color: #fff; border-bottom-color: var(--brand-deep); }

/* duotone variant — same gradient as .swatch--duotone-indigo-red */
.cmp .cmp__me--duotone-indigo-red { background: linear-gradient(135deg, var(--brand), var(--accent)); }
.cmp td.cmp__me--duotone-indigo-red,
.cmp th.cmp__me--duotone-indigo-red { color: #fff; }
.cmp thead th.cmp__me--duotone-indigo-red { color: #fff; border-bottom-color: var(--accent); }

/* ------------------------------------------------------------
   PRINCIPLE — one white background. No full-width colour bands:
   section backgrounds are transparent. Content sits directly on the
   canvas (headlines, text, images) or inside bordered, width-limited
   boxes (cards). The dark footer is the only intentional exception.
   ------------------------------------------------------------ */
.tint { background: transparent; }

/* ------------------------------------------------------------
   BUTTONS — flat 6px plates. Primary CTA = pillar-box red, white text.
   ------------------------------------------------------------ */
.btn { font-size: .82rem; border-radius: 6px; }
.btn--lg { font-size: .86rem; }
.btn--primary {
  background: var(--accent);
  color: #fff;
  box-shadow: none;
}
.btn--primary:hover {
  background: var(--accent-deep);
  color: #fff;
  box-shadow: none;
  transform: translateY(-1px);
}
.btn--ghost { color: var(--brand); border-color: var(--hairline); }
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); }
.link-arrow { color: var(--brand); }

.nav__link { font-size: .85rem; }
.nav__sub  { font-size: .84rem; }

/* ------------------------------------------------------------
   HEADLINES — tighter tracking, lighter weight, compact scale.
   ------------------------------------------------------------ */
.hero__h1 { letter-spacing: -.045em; font-size: clamp(2.5rem, 6vw, 3.2rem); line-height: 1.14; }
.section-head__h2 { letter-spacing: -.035em; font-size: clamp(1.4rem, 5vw, 2.05rem); }
.section-head__h2 .accent { color: var(--write); }
/* line breaks come from the <br> tags, never a character cap */
.section-head__h2 { white-space: nowrap; max-width: none; }
@media (max-width: 760px) {
  .section-head__h2 { white-space: normal; }
  .section-head--center .section-head__h2 { max-width: 22ch; }
}
/* flowing variant — no <br> between the black lead-in and the .accent
   span; the two run together as one sentence and wrap naturally against
   the container, same as normal copy. Use when the black/accent split
   is a mid-sentence emphasis rather than a two-line "statement / punchline"
   composition (see Headline Styles in the Design Scheme for both side by
   side). Homepage Problem Statement uses this. */
.section-head__h2--flow { white-space: normal; }
.hero__h1,
.section-head__h2,
.what-point__title,
.benefit__title,
.trust-card__title,
.usecase__title,
.step__title,
.faq-item__q { font-weight: 600; }
.benefit__title,
.trust-card__title,
.usecase__title,
.what-point__title,
.step__title { font-size: 1rem; }
.faq-item__q { font-size: .9rem; }

/* body copy — compact (hero lead kept larger; see hero block) */
.hero__lead { font-size: clamp(1.05rem, 1.7vw, 1.3rem); line-height: 1.5; }
.what__body { font-size: clamp(.86rem, 1.1vw, .96rem); }
.benefit__body,
.trust-card__body,
.usecase__body,
.what-point__body,
.step__body,
.faq-item__a { font-size: .76rem; }

/* ------------------------------------------------------------
   FLAT TILES — white surfaces, no shadow, on the cream canvas.
   ------------------------------------------------------------ */
.what-point,
.benefit,
.trust-card,
.usecase { background: #FFFFFF; box-shadow: none; }
.benefit__icon { background: var(--tint); color: var(--ink); }
.usecase__tag { color: var(--ink); }
.trust-card__badge { background: var(--brand); color: #fff; }   /* keep red scarce → indigo chip */
.trust-card--auto { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }

.video__frame { background: var(--tint); box-shadow: var(--shadow-md); }
.video__play  { background: var(--accent); color: #fff; box-shadow: none; }

/* ------------------------------------------------------------
   FINAL CTA — no box. The headline, button and note sit directly on the
   section background (cream canvas), centred. Red button is the accent.
   ------------------------------------------------------------ */
.cta { padding-bottom: clamp(6rem, 13vw, 9.5rem); }
.cta__box {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(1.3rem, 3vw, 1.9rem);
  text-align: left;
}
.cta__h2 {
  color: var(--ink);
  font-weight: 600;
  font-size: clamp(1.8rem, 4vw, 2.7rem);
  letter-spacing: -.025em;
  line-height: 1.12;
  margin: 0 0 .5rem;
}
.cta__body {
  color: var(--ink-soft);
  font-size: clamp(.95rem, 1.4vw, 1.05rem);
  line-height: 1.5;
  margin: 0;
  max-width: none;        /* stay on one line until space genuinely runs out */
}
.cta__btn { flex: none; }
/* optional: CTA on one of the .swatch--* background treatments instead of
   plain canvas — text needs to flip white to stay readable */
.cta--on-color .cta__h2   { color: #fff; }
.cta--on-color .cta__body { color: rgb(255 255 255 / .82); }

/* corner metro-line decoration on a colour CTA — same graphic as the
   Background Treatments boxes, added via the .cta--deco hook in
   assets/app.js. Opt-in per page (see includes/cta.php's $cta_bg /
   $cta_deco), not applied to the plain default CTA. */
.cta--deco { position: relative; overflow: hidden; isolation: isolate; }
.cta--deco .gbox__deco { width: clamp(160px, 30%, 320px); }
.cta--deco .gbox__deco-line { stroke: rgb(255 255 255 / .4); }
.cta--deco .gbox__deco-station { fill: rgb(255 255 255 / .18); stroke: rgb(255 255 255 / .4); }

/* white-start, contrast-on-hover button — an alternative to .btn--primary
   for sitting on top of a colour CTA, where solid red can fight the
   background instead of popping. Same per-family contrast logic as the
   .swatch__link--* icons: amber pops on indigo/azure, indigo pops on amber. */
.btn--swatch { background: #fff; border-color: transparent; }
.btn--swatch--indigo { color: var(--brand); }
.btn--swatch--indigo:hover { background: var(--calendar); color: var(--ink); }
.btn--swatch--amber { color: #C2790C; }
.btn--swatch--amber:hover { background: var(--brand); color: #fff; }
.btn--swatch--azure { color: #0577A0; }
.btn--swatch--azure:hover { background: var(--calendar); color: var(--ink); }

/* ------------------------------------------------------------
   Remove the multi-colour (rainbow) bar everywhere it appears.
   ------------------------------------------------------------ */
.cta__glow,
.positioning__bar,
.page-hero__bar,
.plan--featured::before { display: none; }

/* ------------------------------------------------------------
   PAGE HERO — match the homepage hero: full-width, left-aligned
   copy with the same headline + lead type, the soft brand glow,
   and the same vertical rhythm. (Rainbow bar already hidden above.)
   ------------------------------------------------------------ */
.page-hero {
  text-align: left;
  padding-block: clamp(2rem, 5vw, 4rem) clamp(1.5rem, 3vw, 2.5rem);
  background:
    radial-gradient(1100px 520px at 78% -10%, rgb(var(--brand-rgb) / .05), transparent 60%);
}
.page-hero__inner { max-width: var(--shell); margin-inline: auto; }
.page-hero__h1 {
  letter-spacing: -.045em;
  font-size: clamp(2.5rem, 6vw, 3.2rem);
  line-height: 1.14;
  margin: 0 0 1rem;
}
.page-hero__h1 .accent { color: var(--write); }
.page-hero__lead {
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  line-height: 1.5;
  max-width: 56ch;
  margin: 0;
}

/* ------------------------------------------------------------
   REVIEW PAGES — competitor reviews with FirstOrg placed alongside.
   Reuses the home section system (section-head, gbox-grid, cmp). Adds a
   narrow prose column for the editorial copy that sits between the
   section blocks, plus a highlighted "choose FirstOrg" verdict card.
   ------------------------------------------------------------ */
.review-sec { padding-block: clamp(2.6rem, 6vw, 4.5rem); scroll-margin-top: calc(72px + 52px + 1.5rem); }
.review-sec--tint { background: var(--tint); }

.prose { max-width: 720px; margin-inline: auto; }
.prose > p { color: var(--ink-soft); font-size: 1.02rem; line-height: 1.65; margin: 0 0 1.1rem; }
.prose > p:last-child { margin-bottom: 0; }
.prose strong { color: var(--ink); font-weight: 600; }
.prose__note { margin-top: clamp(1.4rem, 3vw, 2rem); color: var(--ink-soft); font-size: 1.02rem; line-height: 1.65; }

/* grids and tables that follow an intro prose column get a top gap */
.review-sec .prose + .gbox-grid,
.review-sec .prose + .cmp-scroll { margin-top: clamp(1.6rem, 4vw, 2.6rem); }

/* .prose (only used on the two review pages) sits inside .guide-article now
   — keep it left-aligned like the rest of the article; the centered .prose
   treatment (margin-inline: auto) is a landing-page pattern, not an article
   one. Section heads use the plain (non --center) homepage format here, so
   no override is needed for those. */
.guide-article .prose { margin-inline: 0; }

/* numbered eyebrow inside a grey box (the "real catch" reasons) */
.gbox__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem; height: 1.9rem;
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .9rem;
  margin-bottom: .8rem;
  flex: none;
}

/* compact row card — icon/number beside one short line of title + body,
   for highlight lists that should read in a few seconds, not a paragraph.
   Pair with .gbox-grid--1 to stack these as full-width rows, not columns. */
.gbox--row {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.1rem 1.3rem;
}
.gbox--row .gbox__num { margin-bottom: 0; }
.gbox--row .gbox__content { min-width: 0; }
.gbox--row .gbox__title { margin-bottom: .25rem; font-size: 1.05rem; }
.gbox--row .gbox__body { font-size: .92rem; }
.gbox--row .gbox__deco { display: none; }

/* highlighted verdict / pivot card — FirstOrg in indigo */
.gbox--me { background: var(--brand); }
.gbox--me .gbox__title { color: #fff; }
.gbox--me .gbox__body  { color: rgba(244, 239, 230, .82); }
.gbox--me .gbox__eyebrow { color: rgba(244, 239, 230, .7); }

.gbox__eyebrow {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: .5rem;
}

/* ------------------------------------------------------------
   FOOTER — iron-black (the swatch's dark), cream text, and the London
   skyline line drawing as a faint cream watermark along the very
   bottom of the page (full width, 100px tall, masked over cream).
   ------------------------------------------------------------ */
.footer {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  border-top: 0;
  color: rgba(244, 239, 230, .72);
  /* reserve the skyline band at the bottom so content clears it */
  padding-bottom: 124px;
}
.footer__tagline,
.footer__col a,
.footer__base p { color: rgba(244, 239, 230, .62); }
.footer__col-title,
.footer .brand__name { color: var(--canvas); }
.footer__col a:hover,
.footer__base a { color: var(--canvas); }
.footer__base { border-top: 1px solid rgba(244, 239, 230, .14); }

.footer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 100px;
  background-color: var(--canvas);
  -webkit-mask: url('/assets/london-skyline.svg') no-repeat center bottom / 100% 100%;
          mask: url('/assets/london-skyline.svg') no-repeat center bottom / 100% 100%;
  opacity: .14;
  pointer-events: none;
  z-index: 0;
}
/* keep footer content above the skyline watermark */
.footer__inner,
.footer__base { position: relative; z-index: 1; }

/* ------------------------------------------------------------
   GUIDES & CASE STUDIES — hub listing cards, article breadcrumb,
   and the stat/quote blocks used in the case-study layout.
   ------------------------------------------------------------ */
.guide-crumb {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--ink-soft);
  margin-bottom: .9rem;
}
.guide-crumb a { color: var(--ink-soft); }
.guide-crumb a:hover { color: var(--brand); }

/* author + date line under a post hero's lead (blog articles) */
.guide-byline {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .82rem;
  letter-spacing: .02em;
  color: var(--ink-soft);
  margin: 1.1rem 0 0;
}
.guide-byline a { color: var(--ink); }
.guide-byline a:hover { color: var(--brand); }

.guide-hub-sec { padding-block: clamp(1.6rem, 4vw, 2.6rem); }
.guide-hub-sec + .guide-hub-sec { padding-top: 0; }

/* hub cards: same min-height as the homepage use-case cards, with the
   metro-line deco moved to the bottom-left corner (the homepage's own
   use-case cards no longer need this override — they're .swatch--grey now,
   which keeps the standard top-right position) */
.guide-hub-sec .gbox { min-height: clamp(180px, 20vw, 230px); }
.guide-hub-sec .gbox__deco {
  top: auto;
  right: auto;
  bottom: 0;
  left: 0;
  -webkit-mask-image: radial-gradient(circle at 0% 100%, #000 0%, #000 26%, transparent 70%);
          mask-image: radial-gradient(circle at 0% 100%, #000 0%, #000 26%, transparent 70%);
}

.guide-subgroup + .guide-subgroup { margin-top: clamp(2.4rem, 5vw, 3.4rem); }
.guide-subhead {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
  margin: 0 0 1.1rem;
  padding-bottom: .7rem;
  border-bottom: 1px solid var(--hairline);
}

.case-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 1.4rem);
  margin: clamp(1.6rem, 4vw, 2.4rem) 0;
}
@media (max-width: 760px) { .case-stats { grid-template-columns: 1fr; } }
.case-stat {
  padding: clamp(1.2rem, 2.5vw, 1.6rem);
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  text-align: left;
}
.case-stat__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(1.7rem, 4vw, 2.2rem);
  color: var(--brand);
}
.case-stat__label {
  display: block;
  color: var(--ink-soft);
  font-size: .86rem;
  margin-top: .3rem;
}

.case-quote {
  max-width: 720px;
  margin: clamp(1.8rem, 4vw, 2.6rem) auto;
  padding-left: clamp(1.2rem, 2.5vw, 1.6rem);
  border-left: 3px solid var(--accent);
}
.case-quote p {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.05rem, 2.4vw, 1.25rem);
  line-height: 1.5;
  color: var(--ink);
  margin: 0 0 .6rem;
}
.case-quote cite {
  display: block;
  font-style: normal;
  color: var(--ink-soft);
  font-size: .86rem;
}

.case-photo {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-md);
  margin: clamp(1.6rem, 4vw, 2.4rem) 0;
}
.case-photo img { display: block; width: 100%; height: auto; }

/* ------------------------------------------------------------
   GUIDE ARTICLE — sidebar running table of contents + a long-form,
   loosely-spaced article column for the how-to guides.
   ------------------------------------------------------------ */
.guide-body { padding-block: clamp(2rem, 5vw, 3.5rem); }
.guide-layout {
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 5.5rem);
  align-items: start;
}
@media (max-width: 900px) {
  .guide-layout { grid-template-columns: minmax(0, 1fr); }
  .guide-toc { display: none; }
}

/* nav is sticky at 72px tall, and the title bar below adds another 52px —
   clear both, with real breathing room, before the "on this page" label */
.guide-toc { position: sticky; top: calc(72px + 52px + clamp(1rem, 3vw, 1.5rem)); }

/* sticky title bar — fixed just under the nav, hidden until the real page
   title scrolls out of view, then fades in above the content. Doubles as
   the mobile replacement for the sidebar TOC (which is hidden below 900px). */
.guide-title-bar {
  position: fixed;
  top: 72px;
  left: 0;
  right: 0;
  z-index: 90;
  height: 52px;
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--hairline);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .2s var(--ease), visibility .2s var(--ease), transform .2s var(--ease);
}
.guide-title-bar.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.guide-title-bar__title {
  display: block;
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .92rem;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  box-sizing: border-box;
}
.guide-toc__label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: .9rem;
}
.guide-toc__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 2px solid var(--hairline);
}
.guide-toc__list li { margin: 0; }
.guide-toc__list a {
  display: block;
  padding: .38rem 0 .38rem .95rem;
  margin-left: -2px;
  border-left: 2px solid transparent;
  color: var(--ink-soft);
  font-size: .86rem;
  line-height: 1.4;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.guide-toc__list a:hover { color: var(--ink); }
.guide-toc__list a.is-active { color: var(--brand); border-left-color: var(--brand); font-weight: 600; }

.guide-article { max-width: 680px; }
.guide-article > *:first-child { margin-top: 0; }
/* :not(.section-head__h2) so the homepage-style two-line accent heading
   (reused for major section breaks — see feedback_article_layout_pattern
   memory) keeps its own type scale instead of being overridden here */
.guide-article h2:not(.section-head__h2) {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(1.3rem, 3vw, 1.6rem);
  color: var(--ink);
  margin: clamp(2.8rem, 6vw, 3.8rem) 0 1.1rem;
  scroll-margin-top: 1.6rem;
}
.guide-article .section-head { margin-top: clamp(2.8rem, 6vw, 3.8rem); }
.guide-article .section-head__h2 { scroll-margin-top: 1.6rem; }
.guide-article h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.08rem;
  color: var(--ink);
  margin: 1.9rem 0 .7rem;
}
.guide-article p {
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.7;
  margin: 0 0 1.25rem;
}
.guide-article p:last-child { margin-bottom: 0; }
.guide-article strong { color: var(--ink); font-weight: 600; }
.guide-article ul { list-style: disc; }     /* re-enable markers over the sitewide ul,ol{list-style:none} reset */
.guide-article ol { list-style: decimal; }
.guide-article ul,
.guide-article ol {
  margin: 0 0 1.3rem;
  padding-left: 1.3rem;
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.65;
}
.guide-article li { margin-bottom: .6rem; padding-left: .2rem; }
.guide-article li:last-child { margin-bottom: 0; }
.guide-article li::marker { color: var(--brand); font-weight: 600; }
.guide-article li strong { color: var(--ink); }
.guide-article blockquote {
  margin: clamp(1.8rem, 4vw, 2.4rem) 0;
  padding: 1.05rem 1.4rem;
  background: var(--tint);
  border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
}
.guide-article blockquote p {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--ink);
  margin: 0;
}
.guide-article blockquote cite {
  display: block;
  font-style: normal;
  color: var(--ink-soft);
  font-size: .84rem;
  margin-top: .5rem;
}
/* inline code — a small tint chip, kept quiet inside a sentence */
.guide-article code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .88em;
  color: var(--brand);
  background: var(--tint);
  padding: .15em .4em;
  border-radius: 5px;
}
/* code block — a bordered tint panel, not a dark "IDE" theme: the site's
   hard-no on dark-neon/AI-tool aesthetic (docs/design-language.md) rules out
   the usual black code-block convention */
.guide-article pre {
  margin: clamp(1.8rem, 4vw, 2.4rem) 0;
  padding: 1.1rem 1.4rem;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  overflow-x: auto;
}
.guide-article pre code {
  display: block;
  font-size: .88rem;
  line-height: 1.6;
  color: var(--ink);
  background: none;
  padding: 0;
  border-radius: 0;
  white-space: pre;
}

/* ------------------------------------------------------------
   IS THIS FOR ME — persona sections. Six ICP profiles: badge,
   headline, problems, current workaround, what FirstOrg offers,
   why it's better, and the guides picked for that segment.
   ------------------------------------------------------------ */

/* sticky single-row jump bar, pinned just under the main nav (72px tall).
   Desktop uses the .persona-toc sidebar instead — this bar is mobile-only. */
.persona-nav {
  position: sticky;
  top: 72px;
  z-index: 95;
  background: var(--tint);
  border-bottom: 1px solid var(--hairline);
}
@media (min-width: 901px) { .persona-nav { display: none; } }
.persona-nav__inner {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding-block: .65rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.persona-nav__inner::-webkit-scrollbar { display: none; }
.persona-nav__link {
  flex: none;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: .78rem;
  color: var(--ink-soft);
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: .38em .9em;
  white-space: nowrap;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.persona-nav__link:hover { color: var(--ink); border-color: var(--brand); }
.persona-nav__link.is-active {
  color: #fff;
  background: var(--brand);
  border-color: var(--brand);
}

/* clears the fixed nav (72px) + sticky persona pill bar (~53px) plus breathing room,
   so anchor jumps/scroll-spy don't land the heading underneath either bar */
/* sidebar layout (desktop) — mirrors .guide-layout from the help article
   pages: fixed-width jump list in the left column, personas stacked in the
   right. Below 900px it collapses to one column and the sidebar hides in
   favour of the .persona-nav pill bar above. */
.persona-body { padding-block: clamp(2rem, 5vw, 3.5rem); }

.persona-toc { position: sticky; top: calc(72px + clamp(1.5rem, 3vw, 2rem)); }
@media (max-width: 900px) { .persona-toc { display: none; } }

.persona {
  padding-block: clamp(3rem, 7vw, 5rem);
  border-top: 1px solid var(--hairline);
  scroll-margin-top: calc(72px + 1.5rem);
}
.persona:first-of-type { border-top: 0; padding-top: 0; }
@media (max-width: 900px) {
  .persona { scroll-margin-top: calc(72px + 53px); }
}

.persona__head {
  display: flex;
  align-items: flex-start;
  gap: clamp(1.2rem, 3vw, 2rem);
  margin-bottom: clamp(1.8rem, 4vw, 2.6rem);
}
.persona__badge { order: 0; }
.persona__id { order: 1; }
.persona--reverse .persona__badge { order: 1; }
.persona--reverse .persona__id { order: 0; }
@media (max-width: 640px) {
  .persona__head { flex-direction: column; }
  .persona__badge,
  .persona__id { order: initial; }
}

.persona__badge {
  position: relative;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  border: 1.5px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.persona__badge::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background: var(--tint);
}
.persona__badge svg {
  position: relative;
  width: 32px;
  height: 32px;
  color: var(--brand);
  stroke-width: 1.7;
}

.persona__h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2rem);
  letter-spacing: -.02em;
  margin: 0 0 .6rem;
}
.persona__blurb {
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 62ch;
  margin: 0;
}

.persona__section { margin-bottom: clamp(1.8rem, 4vw, 2.6rem); }
.persona__section:last-child { margin-bottom: 0; }

.persona__label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .74rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 .9rem;
}

.persona__problems { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.persona__problems li {
  position: relative;
  padding-left: 1.2rem;
  font-size: .96rem;
  line-height: 1.5;
  color: var(--ink);
}
.persona__problems li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink-soft);
}

.persona__solving {
  margin: 0;
  padding: 1.1rem 1.4rem;
  background: var(--tint);
  border-left: 3px solid var(--brand);
  border-radius: 0 10px 10px 0;
  color: var(--ink);
  font-size: .96rem;
  line-height: 1.6;
}

.persona__better { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .55rem; }
.persona__better li {
  position: relative;
  padding-left: 1.6rem;
  font-size: .96rem;
  line-height: 1.5;
  color: var(--ink);
}
.persona__better li svg {
  position: absolute;
  left: 0;
  top: .2em;
  width: 16px;
  height: 16px;
  color: var(--brand);
}

.persona__guides {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.6rem;
  align-items: baseline;
}
.persona__guides .link-arrow { font-size: .92rem; }

/* ------------------------------------------------------------
   CASE STUDIES HUB — tall, full-width cards (photo or brand panel on one
   side, story + stats + CTA on the other).
   ------------------------------------------------------------ */
.case-card-list { display: flex; flex-direction: column; gap: clamp(1.6rem, 3vw, 2.2rem); }
.case-card {
  display: grid;
  grid-template-columns: minmax(260px, 38%) 1fr;
  min-height: 420px;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
@media (max-width: 800px) {
  .case-card { grid-template-columns: 1fr; min-height: 0; }
}

.case-card__media {
  position: relative;
  min-height: 240px;
  background-size: cover;
  background-position: center;
}
.case-card__media--photo {
  background-image:
    linear-gradient(180deg, rgb(12 20 38 / .15) 0%, rgb(12 20 38 / .55) 100%),
    var(--case-card-photo);
}
.case-card__media--brand {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  background: linear-gradient(155deg, var(--brand) 0%, var(--brand-deep) 100%);
  overflow: hidden;
}
.case-card__media-stat {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1;
  font-size: clamp(3.6rem, 9vw, 6.2rem);
  color: rgb(255 255 255 / .14);
  white-space: nowrap;
}
.case-card__logo {
  position: absolute;
  left: clamp(1.2rem, 3vw, 1.8rem);
  bottom: clamp(1.2rem, 3vw, 1.8rem);
  width: 52px;
  height: 52px;
  display: block;
  filter: brightness(0) invert(1);
}

.case-card__body {
  padding: clamp(1.8rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.case-card__title {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(1.4rem, 3vw, 1.9rem);
  color: var(--ink);
  margin: .55rem 0 .9rem;
}
.case-card__excerpt {
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.6;
  max-width: 54ch;
  margin: 0 0 1.6rem;
}
.case-card__stats {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.4rem, 3vw, 2.4rem);
  margin-bottom: 1.8rem;
}
.case-card__stat-num {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: 1.35rem;
  color: var(--brand);
}
.case-card__stat-label {
  display: block;
  color: var(--ink-soft);
  font-size: .82rem;
  margin-top: .2rem;
}

/* ============================================================
   DESIGN SCHEME PAGE — layout helpers for /internal/design-scheme/
   only (dev-only reference page, not deployed to production — see
   docs/deployment.md). Typography/headline/button samples on that
   page reuse real site classes directly wherever possible.
   ============================================================ */
.dscheme-block { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.dscheme-sample {
  padding: clamp(1.5rem, 3vw, 2.2rem);
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  margin-bottom: 1rem;
}
/* strip the panel chrome when the sample is itself a card (e.g. a .gbox demo) */
.dscheme-sample--plain { background: transparent; border: none; padding: 0; }
.dscheme-sample .section-head { margin-bottom: 0; }
.dscheme-label {
  color: var(--ink-soft);
  font-size: .82rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  margin: 0 0 .7rem;
}
.dscheme-collapse__toggle {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .88rem;
  color: var(--brand);
  cursor: pointer;
  padding: .7em 1.1em;
  border: 1.5px solid var(--hairline);
  border-radius: 999px;
  list-style: none;              /* hide the default disclosure triangle */
  transition: border-color .2s var(--ease), color .2s var(--ease);
}
.dscheme-collapse__toggle::-webkit-details-marker { display: none; }
.dscheme-collapse__toggle::before {
  content: "";
  width: 8px; height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .2s var(--ease);
}
.dscheme-collapse[open] .dscheme-collapse__toggle::before { transform: rotate(45deg); }
.dscheme-collapse__toggle:hover { border-color: var(--brand); }
.dscheme-collapse[open] .dscheme-collapse__toggle { margin-bottom: 1.6rem; }

/* top-level section toggle — the section-head__h2 itself is the disclosure
   control; its .prose__note and all section content live inside, collapsed
   by default. .dscheme-section is a top-level wrapper (sibling of other
   top-level <section>s, not nested in any .shell) so it can contain more
   than one real <section> as children (e.g. an intro + several full-width
   demo sections) — .summary holds only a .shell-wrapped heading so the
   chevron+title still land in the same gutter-aligned column as everything
   below, instead of competing with the shell for horizontal space (that
   mismatch was the exact bug behind the FAQ/CTA alignment issue). */
.dscheme-section__summary { cursor: pointer; list-style: none; }
.dscheme-section__summary::-webkit-details-marker { display: none; }
.dscheme-section__summary .section-head {
  display: flex;
  align-items: baseline;
  gap: .7rem;
  margin-bottom: 0;
}
.dscheme-section__summary .section-head::before {
  content: "";
  flex: none;
  margin-bottom: .15em;
  width: 13px; height: 13px;
  border-right: 2.5px solid var(--brand);
  border-bottom: 2.5px solid var(--brand);
  transform: rotate(-45deg);
  transition: transform .2s var(--ease);
}
.dscheme-section[open] > .dscheme-section__summary .section-head::before { transform: rotate(45deg); }
/* .dscheme-section itself carries no padding (it's not a .how/.bigfeatures
   section, just a wrapper) — the summary supplies the same top padding a
   section would normally open with, plus matching bottom padding while
   collapsed so it still reads as a complete, self-contained section; once
   open, the first content <section> below supplies its own top padding, so
   the summary only needs a small margin to separate the two */
.dscheme-section > .dscheme-section__summary { padding-top: clamp(2.7rem, 6vw, 4.3rem); }
.dscheme-section:not([open]) > .dscheme-section__summary { padding-bottom: clamp(2.7rem, 6vw, 4.3rem); }
.dscheme-section[open] > .dscheme-section__summary { margin-bottom: clamp(1.6rem, 3vw, 2.2rem); }
.dscheme-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }
.dscheme-family {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 700;
  margin: 0 0 .3rem;
}
.dscheme-weight {
  font-family: var(--font-display);
  font-size: 1.1rem;
  margin: .3rem 0;
}
.dscheme-weight--400 { font-weight: 400; }
.dscheme-weight--500 { font-weight: 500; }
.dscheme-weight--600 { font-weight: 600; }
.dscheme-weight--700 { font-weight: 700; }
.dscheme-weight--800 { font-weight: 800; }
.dscheme-sizes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;   /* without this, grid stretches all 3 to the tallest — hiding the height difference */
  gap: clamp(1rem, 2vw, 1.4rem);
}
@media (max-width: 760px) { .dscheme-sizes { grid-template-columns: 1fr; } }
.dscheme-caption {
  margin: .7rem 0 0;
  color: var(--ink-soft);
  font-family: ui-monospace, monospace;
  font-size: .78rem;
}
.dscheme-boxwrap { scroll-margin-top: 5.5rem; }   /* clears the sticky nav when jumped to via #id */
/* the Tables section's heading lives outside .guide-article (see the demo
   markup's own comment for why), so it doesn't inherit that scope's
   scroll-margin-top — needs its own, sized for nav (72px) + sticky title
   bar (52px), same as .review-sec elsewhere */
#demo-tables { scroll-margin-top: calc(72px + 52px + 1.5rem); }
.dscheme-boxname {
  margin: .5rem 0 0;
  color: var(--ink-soft);
  font-family: ui-monospace, monospace;
  font-size: .72rem;
}
/* small dark stage for demoing .arrow-cta--on-dark — the indigo/amber/azure/
   grey variants below reuse real .gbox.swatch.swatch--solid-* cards instead,
   but there's no reusable "dark" swatch (the site's only dark surface is
   .uc-case's own case-study photo), so this is the one bespoke background */
.dscheme-bgchip {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  width: 160px;
  height: 110px;
  padding: 1rem;
  border-radius: var(--radius);
  background: #0C1426;
}

/* ============================================================
   BACKGROUND TREATMENTS — reusable solid / gradient / radial / duotone
   fills built from the palette above. Usable on any .gbox-style card
   site-wide via the .swatch--* modifiers below. Full visual reference
   (with class names) lives at /internal/design-scheme/ (dev-only, not
   deployed to production — see docs/deployment.md).
   ============================================================ */
.swatch { border: none; min-height: clamp(120px, 14vw, 160px); }
.swatch--half   { min-height: clamp(70px, 8vw, 90px); }
.swatch--double { min-height: clamp(240px, 28vw, 320px); }
/* the campaign-stack box sits next to the content-strategy box, which needs
   more room for its own content (6-item source list + document graphic);
   stacked in one column on mobile they can't share a row to auto-stretch to
   equal heights, so match them explicitly here instead of shrinking the
   campaign-stack graphic further */
@media (max-width: 760px) {
  .gbox:has(.campstack--flat) { min-height: 360px; }
}
.swatch .gbox__title {
  color: #FFFFFF;
  max-width: 75%;   /* stay clear of the metro-line decoration in the top-right corner */
  text-shadow: 0 1px 6px rgb(0 0 0 / .25);   /* keeps the white title legible on the lighter (amber) cards too */
}
.swatch .gbox__body {
  color: rgb(255 255 255 / .85);
  max-width: 75%;   /* stay clear of the metro-line decoration in the top-right corner */
  text-shadow: 0 1px 6px rgb(0 0 0 / .2);
}
/* .gbox__eyebrow (category label) on a colour treatment — same white+shadow
   pattern as .gbox__title/.gbox__body above; added for blog cards
   (blog/index.php), the first place an eyebrow landed on a .swatch. No
   .swatch--grey override needed: the base .gbox__eyebrow colour (var(--ink-soft))
   already reads correctly there, same as it does with no .swatch at all. */
.swatch .gbox__eyebrow {
  color: rgb(255 255 255 / .75);
  text-shadow: 0 1px 6px rgb(0 0 0 / .2);
}
/* white metro-line texture reads on every colour treatment below; the amber
   tint the site normally uses for this texture only still works on grey */
.swatch .gbox__deco-line { stroke: rgb(255 255 255 / .55); }
.swatch .gbox__deco-station { fill: rgb(255 255 255 / .18); stroke: rgb(255 255 255 / .55); }

/* the campaign-stack graphic (.campstack) is built for a light/cream card —
   its ink text and indigo-tint status pills disappear on a colour treatment.
   Recolour white to match .gbox__title/.gbox__body above. Status labels
   (in-progress and .is-final/.is-published alike) drop their pill entirely
   here — plain white text reads fine directly on the gradient, and the
   .is-final indigo-on-indigo / .is-published green-on-indigo pills were
   nearly illegible. Every status selector listed explicitly so none of
   them wins a specificity tie against the others by source order alone. */
.swatch .campdate,
.swatch .ctasks__label,
.swatch .cstep__label,
.swatch .cproc__line,
.swatch .cpost__topic { color: #FFFFFF; }
.swatch .ctasks__summary { color: rgb(255 255 255 / .7); }
.swatch .cstep__icon { background-color: #FFFFFF; }
.swatch .cpost__status,
.swatch .cpost__status.is-final,
.swatch .cpost__status.is-published { color: #FFFFFF; background: none; }

/* same story for the content-strategy graphic (.stratstage) — its source
   labels and caption are SVG <text> fills, not CSS color, hence `fill` */
.swatch .strat-label,
.swatch .strat-cap { fill: #FFFFFF; }
/* source icons — .strat-ic is stroked (outline icons), .strat-star is filled */
.swatch .strat-ic { stroke: #FFFFFF; }
.swatch .strat-star { fill: #FFFFFF; }

/* "dual-tone" headline — an accent-coloured <span> wrapping wherever the
   colour should start (a word, a phrase, however much copy calls for it).
   That span boundary is NOT a line break — don't add a <br> before it by
   reflex. Only add a <br> where a break is actually wanted; otherwise let
   the browser wrap the whole headline (plain text + accent span) normally,
   so a colour change that lands mid-line stays mid-line instead of forcing
   an extra line. Amber is the default accent (pops on indigo/azure); the
   amber box itself flips to indigo, since amber-on-amber doesn't read.
   Add to any .gbox__title, any card size. */
.gbox__title--duo { margin-bottom: .5rem; }
.swatch-accent { text-shadow: 0 1px 6px rgb(0 0 0 / .25); }
.swatch-accent--amber  { color: var(--calendar); }
.swatch-accent--indigo { color: var(--brand); }
/* grey card only: matches the real .section-head__h2 .accent teal exactly —
   that class only colours itself inside .section-head__h2, so the bare
   .accent span used elsewhere on a plain gbox__title rendered uncoloured */
.swatch-accent--site { color: var(--write); }

/* link-out: resting colour is keyed to the card's own hue so it doesn't read
   as the sitewide red CTA. On hover it must fill with a colour that
   contrasts against THIS card's own background — filling with the same hue
   (or leaving it white) makes the icon vanish, which was the bug: the plain
   `.swatch .gbox__link { background: ... }` resting-state rule and the base
   `.gbox__link:hover` rule are equal specificity, and the resting rule comes
   later in the file, so it was winning even on hover. Fixed by giving every
   hover rule below one full selector step (class+class+pseudo) more weight
   than the plain resting rule (class+class) it needs to beat. */
.swatch .gbox__link { background: rgb(255 255 255 / .85); }
.swatch .gbox__link:hover,
.swatch .gbox__link:focus-visible { background: var(--accent); border-color: var(--accent); color: #fff; }

.swatch__link--indigo { color: var(--brand); }
.swatch .swatch__link--indigo:hover,
.swatch .swatch__link--indigo:focus-visible { background: var(--calendar); border-color: var(--calendar); color: var(--ink); }

.swatch__link--amber { color: #C2790C; }
.swatch .swatch__link--amber:hover,
.swatch .swatch__link--amber:focus-visible { background: var(--brand); border-color: var(--brand); color: #fff; }

.swatch__link--azure { color: #0577A0; }
.swatch .swatch__link--azure:hover,
.swatch .swatch__link--azure:focus-visible { background: var(--calendar); border-color: var(--calendar); color: var(--ink); }

/* quarter — half of .swatch--half again; for banners/alerts (see Banners &
   Alerts section), not the Background Treatments grid. Tighter padding and
   a smaller title/body/link scale down with it — the base .gbox padding and
   1.3rem title would alone blow past this min-height. Placed after the
   generic .swatch .gbox__title/.gbox__body max-width:75% rule above (same
   0,2,0 specificity) so this max-width:68% actually wins by source order. */
.swatch--quarter {
  min-height: clamp(35px, 4vw, 45px);
  padding: clamp(.85rem, 1.7vw, 1.1rem) clamp(1.2rem, 2.4vw, 1.6rem);
}
.swatch--quarter .gbox__title {
  font-size: .95rem;
  max-width: 68%;
  margin-bottom: .2rem;
}
.swatch--quarter .gbox__body {
  font-size: .78rem;
  line-height: 1.4;
  max-width: 68%;
}
.swatch--quarter .gbox__link {
  width: 26px;
  height: 26px;
  border-radius: 6.5px;   /* same 25% ratio as the base 36px/9px link */
  right: clamp(.7rem, 1.4vw, 1rem);
  bottom: clamp(.7rem, 1.4vw, 1rem);
}
.swatch--quarter .gbox__link svg { width: 13px; height: 13px; }

/* eighth — half of .swatch--quarter again; everything (headline, body,
   link) runs inline in a single row instead of stacking, so .gbox switches
   to a flex row here rather than just shrinking further. Title stays fixed
   width, body takes the remaining space (max-width: none here, same
   source-order reasoning as quarter above, is what lets flex-grow actually
   fill the row) and truncates instead of wrapping, so the link lands flush
   at the row's end instead of stranded mid-row. */
.swatch--eighth {
  min-height: clamp(17.5px, 2vw, 22.5px);
  padding: clamp(.55rem, 1.1vw, .75rem) clamp(1rem, 2vw, 1.4rem);
  display: flex;
  align-items: center;
  gap: clamp(.75rem, 2vw, 1.25rem);
}
.swatch--eighth .gbox__title {
  font-size: .85rem;
  max-width: none;
  margin: 0;
  flex: none;
  white-space: nowrap;
}
.swatch--eighth .gbox__body {
  font-size: .78rem;
  max-width: none;
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.swatch--eighth .gbox__link {
  position: static;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 5px;   /* same 25% ratio as the base 36px/9px link */
}
.swatch--eighth .gbox__link svg { width: 10px; height: 10px; }

/* edge-to-edge banner — breaks .swatch--quarter/--eighth out of .shell to
   span the true browser width, for a real page-wide banner/alert rather
   than a card sitting in the content column. Same breakout technique as
   .video__frame--viewport: fixed 100vw + a negative margin equal to half
   the viewport minus half the (auto-centred) parent, then drop the
   rounding/border a floating card needs but a flush bar doesn't. Combine
   with either size class, e.g. class="gbox swatch swatch--eighth
   swatch--bleed swatch--solid-indigo". */
.swatch--bleed {
  width: 100vw;
  max-width: none;
  margin-inline: calc(50% - 50vw);
  border-radius: 0;
  border: 0;
}

/* row 1 — indigo: solid, gradient, radial */
.swatch--solid-indigo   { background: var(--brand); }
.swatch--gradient-indigo { background: linear-gradient(135deg, var(--brand), var(--brand-deep)); }
.swatch--radial-indigo {
  background: radial-gradient(120% 140% at 20% 15%, var(--brand-deep), var(--brand) 70%);
}

/* row 2 — amber: solid, gradient, radial */
.swatch--solid-amber    { background: var(--calendar); }
.swatch--gradient-amber { background: linear-gradient(135deg, var(--calendar), #C2790C); }
.swatch--radial-amber {
  background: radial-gradient(120% 140% at 20% 15%, #C2790C, var(--calendar) 70%);
}

/* row 3 — azure: solid, gradient, radial */
.swatch--solid-azure    { background: var(--publish); }
.swatch--gradient-azure { background: linear-gradient(135deg, var(--publish), #0577A0); }
.swatch--radial-azure {
  background: radial-gradient(120% 140% at 20% 15%, #0577A0, var(--publish) 70%);
}

/* row 4 — duotones out from indigo to each accent */
.swatch--duotone-indigo-amber { background: linear-gradient(135deg, var(--brand) 0%, var(--calendar) 100%); }
.swatch--duotone-indigo-red   { background: linear-gradient(135deg, var(--brand), var(--accent)); }
.swatch--duotone-indigo-azure { background: linear-gradient(135deg, var(--brand), var(--publish)); }

/* row 5 — the grey the rest of the site currently uses, as a reference point;
   keeps the site's normal dark title. Deco lines are indigo (not the
   amber the rest of the site uses on tint cards) — amber/coral/red were
   trialled and read too faint or just okay against grey; indigo won. */
.swatch--grey {
  background: var(--tint);
}
.swatch--grey .gbox__title {
  color: var(--ink);
  text-shadow: none;
}
.swatch--grey .gbox__body {
  color: var(--ink-soft);
  text-shadow: none;
}
/* .swatch .gbox__eyebrow (white, for colour treatments) otherwise wins here
   too — same fix as .gbox__title/.gbox__body above, just missed originally
   since the wrong assumption was that grey needed no override at all. */
.swatch--grey .gbox__eyebrow {
  color: var(--ink-soft);
  text-shadow: none;
}
.swatch--grey .gbox__link { background: rgb(255 255 255 / .55); }
.swatch--grey .gbox__deco-line { stroke: rgb(46 42 107 / .3); }
.swatch--grey .gbox__deco-station { fill: var(--tint); stroke: rgb(46 42 107 / .3); }

