/* ============================================================
   PRODUCT PAGES — the tube-map kit.
   The faint metro network in the page background, graduated to a
   foreground storytelling device: each product page pulls one line
   (or the whole network) into full colour, drawn in the same
   wayfinding grammar as the site theme (london.css) — lines run
   horizontal / vertical / 45° only, hollow interchange circles,
   flat tiles, 6px corners.

   Line colours come from the london.css tokens:
     --strategy coral · --calendar amber · --write teal · --publish azure
   Structural ink: --brand (Johnston-blue indigo). Red stays CTA-only.

   Loaded via $extra_css on /product/* pages only.
   ============================================================ */

/* .svc-card__list on a colour .swatch (Full B2B Stack "Content" card) —
   same white + text-shadow convention as .swatch .gbox__title/.gbox__body
   in london.css, extended to the checklist since svc-card__list has no
   prior use on a colour treatment (only ever seen on swatch--grey). */
.swatch .svc-card__item {
  color: rgb(255 255 255 / .92);
  text-shadow: 0 1px 6px rgb(0 0 0 / .2);
}
.swatch .svc-card__item svg { color: #fff; }
/* swatch--grey still carries the base .swatch class, so it needs the same
   reset-back-to-ink treatment .swatch--grey already gives .gbox__title/
   .gbox__body above — without it, the white override above bleeds onto
   the grey cards too and washes the checklist out. */
.swatch--grey .svc-card__item {
  color: var(--ink);
  text-shadow: none;
}
.swatch--grey .svc-card__item svg { color: var(--publish); }

/* status pill (.gbox-media__badge, london.css) reused on a plain .gbox/
   .swatch card (Full B2B Stack section) — the card's own colour/texture
   surface stands in for "the image", so it gets the Design Scheme's
   on-image recipe verbatim: .gbox-media__frame .gbox-media__badge's own
   position: absolute; bottom: .75rem; right: .75rem; z-index: 1. Unlike
   an actual photo, the badge here overlays real checklist text, so the
   card also gets extra padding-bottom reserved for it — otherwise a
   longer list (or a longer label) runs straight into the pill instead of
   clearing it (see the .campstack--flat comment in london.css for the
   same trap elsewhere in this codebase). */
.gbox:has(> .gbox-media__badge) { padding-bottom: 3.4rem; }
.gbox > .gbox-media__badge {
  position: absolute;
  bottom: .75rem;
  right: .75rem;
  z-index: 1;
}

/* ------------------------------------------------------------
   HERO EYEBROW — the product's name, stated above the benefit
   headline so every product page names itself the same way its
   nav label and URL do. Small-caps label register (same voice as
   .tchange__head), white for the duotone hero it always sits on.
   ------------------------------------------------------------ */
.hero__eyebrow {
  font-family: var(--font-display);
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgb(255 255 255 / .85);
  margin: 0 0 1.1rem;
}

/* ------------------------------------------------------------
   ROUNDEL — each product page's station mark, shown in the hero.
   Ring in the page's line colour; bar always Johnston indigo.
   ------------------------------------------------------------ */
.roundel {
  position: relative;
  width: 86px;
  height: 86px;
  margin: 0 0 1.3rem;
}
.roundel::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 11px solid var(--brand);
  border-radius: 50%;
}
.roundel__bar {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--brand);
  color: #fff;
  font-family: var(--font-display);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1;
  padding: .45em .95em;
  white-space: nowrap;
}
.roundel--strategy::before { border-color: var(--strategy); }
.roundel--calendar::before { border-color: var(--calendar); }
.roundel--write::before    { border-color: var(--write); }
.roundel--publish::before  { border-color: var(--publish); }

/* ------------------------------------------------------------
   STATEMENT SECTION, loose variant — a bigger, more isolated
   version of london.css's .statement-sec (homepage headline-only
   pattern). The homepage's own .statement-sec is deliberately
   tight (padding-bottom trimmed to read as one continuous intro
   with the section right after it), which doesn't fit here: on a
   product page this statement stands alone between the hero and
   an unrelated section, so it needs room on both sides and a
   headline bigger than the standard .page-hero__h1 scale to still
   read as a standalone beat rather than a leftover hero line.
   ------------------------------------------------------------ */
.statement-sec--loose { padding-top: clamp(9.75rem, 21vw, 15rem); padding-bottom: clamp(4.5rem, 10vw, 7rem); }
.statement-sec--loose .page-hero__h1 { font-size: clamp(2.8rem, 7.5vw, 4.8rem); max-width: none; }

/* ------------------------------------------------------------
   MAP PANEL — a white "paper map" tile the SVG diagrams sit on.
   Desktop shows the SVG; under 720px the vertical journey strip
   fallback takes over.
   ------------------------------------------------------------ */
.tmap {
  background: var(--canvas);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  padding: clamp(1.2rem, 3vw, 2.2rem);
}
.tmap__viz { display: block; width: 100%; height: auto; }
.tmap__fallback { display: none; }
@media (max-width: 719px) {
  .tmap__viz { display: none; }
  .tmap__fallback { display: block; }
}
.tmap__caption {
  margin: 1.1rem 0 0;
  text-align: center;
  color: var(--ink-soft);
  font-size: .9rem;
}

/* ---------- SVG: line strokes ---------- */
.tl {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.tl--strategy { stroke: var(--strategy); }
.tl--calendar { stroke: var(--calendar); }
.tl--write    { stroke: var(--write); }
.tl--publish  { stroke: var(--publish); }
.tl--brand    { stroke: var(--brand); }
.tl--ink      { stroke: var(--ink); }
/* feeder / National-Rail style connections into a line */
.tl--feeder { stroke: var(--ink-soft); stroke-width: 5; opacity: .5; }
/* dotted continuation stub ("line continues to…") */
.tl--stub { stroke-dasharray: 0.5 17; }

/* ---------- SVG: stations ---------- */
.tst { fill: #fff; stroke-width: 5; }
.tst--strategy { stroke: var(--strategy); }
.tst--calendar { stroke: var(--calendar); }
.tst--write    { stroke: var(--write); }
.tst--publish  { stroke: var(--publish); }
.tst--brand    { stroke: var(--brand); }
.tst--ink      { stroke: var(--ink); }
/* interchange: white circle, ink ring; --outer adds the second ring */
.tin { fill: #fff; stroke: var(--ink); stroke-width: 5; }
.tin--outer { fill: none; stroke: var(--ink); stroke-width: 3; }

/* ---------- SVG: labels ---------- */
.tmap-name {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  fill: var(--ink);
}
.tmap-name--int { font-size: 17px; font-weight: 700; }
.tmap-name--soft { fill: var(--ink-soft); font-weight: 500; }
.tmap-linename {
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  fill: var(--ink-soft);
}
.tmap-linename--strategy { fill: var(--strategy); }
.tmap-linename--calendar { fill: var(--calendar); }
.tmap-linename--write    { fill: var(--write); }
.tmap-linename--publish  { fill: var(--publish); }
.tmap-caption-svg {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 500;
  fill: var(--ink-soft);
}
/* fare-zone rings (SEO topic map) */
.tz-ring {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 2;
  stroke-dasharray: 6 8;
}
.tz-label {
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  fill: var(--ink-soft);
}
/* "YOU ARE HERE" tag */
.ttag { fill: var(--ink); }
.ttag-txt {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  fill: #fff;
}
/* the in-map roundel (Content Engine centre emblem) */
.tmap-roundel-ring { fill: none; stroke: var(--brand); stroke-width: 15; }
.tmap-roundel-bar { fill: var(--brand-deep); }
.tmap-roundel-txt {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .12em;
  fill: #fff;
}

/* ------------------------------------------------------------
   FLOW DIAGRAM — sharp systems-diagram language. Thin coloured
   connectors with directional arrows, crisp bordered stage nodes.
   The metro texture stays in the page background; these read as
   product diagrams, not railway maps.
   ------------------------------------------------------------ */
.fl {
  fill: none;
  stroke-width: 3.5;
  stroke-linecap: butt;
  stroke-linejoin: miter;
}
.fl--strategy { stroke: var(--strategy); }
.fl--calendar { stroke: var(--calendar); }
.fl--write    { stroke: var(--write); }
.fl--publish  { stroke: var(--publish); }
.fl--ink      { stroke: var(--ink); }
.fl--brand    { stroke: var(--brand); }
.farr { stroke: none; }
.farr--strategy { fill: var(--strategy); }
.farr--calendar { fill: var(--calendar); }
.farr--write    { fill: var(--write); }
.farr--publish  { fill: var(--publish); }
.fnode { fill: #fff; stroke-width: 2; }
.fnode--strategy { stroke: var(--strategy); }
.fnode--calendar { stroke: var(--calendar); }
.fnode--write    { stroke: var(--write); }
.fnode--publish  { stroke: var(--publish); }
.fnode__title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
  fill: var(--ink);
}
.fnode__title--strategy { fill: var(--strategy); }
.fnode__title--calendar { fill: var(--calendar); }
.fnode__title--write    { fill: var(--write); }
.fnode__title--publish  { fill: var(--publish); }
.fnode__sub {
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 500;
  fill: var(--ink-soft);
}
.fdot { fill: #fff; stroke: var(--ink); stroke-width: 3; }
.flabel {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  fill: var(--ink);
}
.flabel--sub {
  font-size: 11.5px;
  font-weight: 500;
  fill: var(--ink-soft);
}

/* slimmer strip variant to match the sharper language */
.tstrip--slim .tstrip__dot { width: 14px; height: 14px; border-width: 3px; }
.tstrip--slim .tstrip__stop::before { height: 4px; top: 5px; }
.tstrip--slim .tstrip__stop--int .tstrip__dot {
  width: 18px;
  height: 18px;
  border-width: 3px;
  margin-top: -2px;
  box-shadow: none;
}
@media (max-width: 719px) {
  .tstrip--slim .tstrip__stop { grid-template-columns: 18px 1fr; }
  .tstrip--slim .tstrip__stop::before { width: 4px; height: 100%; left: 7px; top: 7px; }
}

/* ------------------------------------------------------------
   JOURNEY STRIP — the in-carriage line diagram. Plain HTML/CSS:
   horizontal on desktop, rotates to a vertical station board on
   mobile. Colour set by .tstrip--<line>; individual stops can
   override with .tstrip__stop--<line> (multi-line journeys).
   ------------------------------------------------------------ */
.tstrip { margin: clamp(1.2rem, 3vw, 2rem) 0 0; }
.tstrip__line {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
}
.tstrip__stop {
  position: relative;
  flex: 1;
  text-align: center;
  padding-top: 0;
}
/* the segment leading INTO each stop */
.tstrip__stop::before {
  content: "";
  position: absolute;
  top: 5px;               /* dot is 18px tall → centre line at 9px, bar 8px */
  right: 50%;
  width: 100%;
  height: 8px;
  background: var(--ink);
}
.tstrip__stop:first-child::before { display: none; }
.tstrip__dot {
  position: relative;
  z-index: 1;
  display: block;
  width: 18px;
  height: 18px;
  margin: 0 auto;
  background: #fff;
  border: 4px solid var(--ink);
  border-radius: 50%;
  box-sizing: border-box;
}
/* interchange / "you" stop — bigger, ink double ring */
.tstrip__stop--int .tstrip__dot {
  width: 24px;
  height: 24px;
  margin-top: -3px;
  border-width: 5px;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px #fff, 0 0 0 5px var(--ink);
}
.tstrip__name {
  display: block;
  margin-top: .7rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .88rem;
  line-height: 1.25;
  color: var(--ink);
}
.tstrip__stop--int .tstrip__name { font-weight: 700; }
.tstrip__sub {
  display: block;
  margin-top: .15rem;
  font-size: .76rem;
  font-weight: 500;
  color: var(--ink-soft);
}
.tstrip__here {
  display: inline-block;
  margin-top: .35rem;
  background: var(--ink);
  color: #fff;
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  padding: .35em .7em;
}

/* line colour by strip */
.tstrip--strategy .tstrip__stop::before { background: var(--strategy); }
.tstrip--calendar .tstrip__stop::before { background: var(--calendar); }
.tstrip--write    .tstrip__stop::before { background: var(--write); }
.tstrip--publish  .tstrip__stop::before { background: var(--publish); }
.tstrip--strategy .tstrip__dot { border-color: var(--strategy); }
.tstrip--calendar .tstrip__dot { border-color: var(--calendar); }
.tstrip--write    .tstrip__dot { border-color: var(--write); }
.tstrip--publish  .tstrip__dot { border-color: var(--publish); }

/* per-stop overrides (multi-line journeys; segment leads INTO the stop) */
.tstrip .tstrip__stop--strategy::before { background: var(--strategy); }
.tstrip .tstrip__stop--calendar::before { background: var(--calendar); }
.tstrip .tstrip__stop--write::before    { background: var(--write); }
.tstrip .tstrip__stop--publish::before  { background: var(--publish); }
.tstrip .tstrip__stop--strategy .tstrip__dot { border-color: var(--strategy); }
.tstrip .tstrip__stop--calendar .tstrip__dot { border-color: var(--calendar); }
.tstrip .tstrip__stop--write .tstrip__dot    { border-color: var(--write); }
.tstrip .tstrip__stop--publish .tstrip__dot  { border-color: var(--publish); }
/* interchange dots stay ink even on coloured strips */
.tstrip .tstrip__stop--int .tstrip__dot { border-color: var(--ink); }

/* status modifiers — for a roadmap/timeline strip (company/index.php), where
   each stop is a project phase rather than one of the four pipeline stages
   above. Reuses existing palette (no new colours): publish (azure, already
   reads as "shipped") for done, brand for the phase in progress now, a plain
   hairline/ink-soft grey for anything still just planned. */
.tstrip .tstrip__stop--done::before { background: var(--publish); }
.tstrip .tstrip__stop--done .tstrip__dot { border-color: var(--publish); }
.tstrip .tstrip__stop--active::before { background: var(--brand); }
.tstrip .tstrip__stop--active .tstrip__dot { border-color: var(--brand); }
.tstrip .tstrip__stop--planned::before { background: var(--hairline); }
.tstrip .tstrip__stop--planned .tstrip__dot { border-color: var(--ink-soft); }

/* vertical form (mobile). Segments are drawn DOWNWARD from each stop:
   top of the bar sits at this dot's centre and height:100% lands it
   exactly on the next dot's centre, whatever the label heights. Colour
   therefore comes from the NEXT stop's line class, via :has(). */
@media (max-width: 719px) {
  .tstrip__line { flex-direction: column; }
  .tstrip__stop {
    flex: none;
    display: grid;
    grid-template-columns: 24px 1fr;
    column-gap: .9rem;
    align-items: start;
    text-align: left;
    padding: 0 0 1.5rem;
  }
  .tstrip__stop:last-child { padding-bottom: 0; }
  .tstrip__stop::before {
    top: 9px;
    bottom: auto;
    right: auto;
    left: 8px;                  /* 24px column → 18px dot centre at 9px, bar 8px */
    width: 8px;
    height: 100%;
  }
  .tstrip__stop:first-child::before { display: block; }
  .tstrip__stop:last-child::before { display: none; }
  /* a stop's own line class colours the segment INTO it, which in this
     orientation is the PREVIOUS stop's bar — reset own bars to ink… */
  .tstrip .tstrip__stop--strategy::before,
  .tstrip .tstrip__stop--calendar::before,
  .tstrip .tstrip__stop--write::before,
  .tstrip .tstrip__stop--publish::before { background: var(--ink); }
  /* …then recolour each bar by the line of the stop it leads to */
  .tstrip .tstrip__stop:has(+ .tstrip__stop--strategy)::before { background: var(--strategy); }
  .tstrip .tstrip__stop:has(+ .tstrip__stop--calendar)::before { background: var(--calendar); }
  .tstrip .tstrip__stop:has(+ .tstrip__stop--write)::before    { background: var(--write); }
  .tstrip .tstrip__stop:has(+ .tstrip__stop--publish)::before  { background: var(--publish); }
  .tstrip__dot { margin: 0 auto; grid-row: 1; }
  .tstrip__name { margin-top: 0; grid-column: 2; grid-row: 1; align-self: center; }
  .tstrip__sub, .tstrip__here { grid-column: 2; }
  .tstrip__here { justify-self: start; }
}

/* ------------------------------------------------------------
   MAP KEY — the legend under the network map (Content Engine).
   ------------------------------------------------------------ */
.tkey {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(.8rem, 1.6vw, 1.2rem);
  margin-top: clamp(1.2rem, 2.5vw, 1.8rem);
}
@media (max-width: 900px) { .tkey { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .tkey { grid-template-columns: 1fr; } }
.tkey__item {
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1rem 1.1rem 1.1rem;
}
.tkey__chip {
  display: block;
  width: 46px;
  height: 9px;
  border-radius: 4px;
}
.tkey__chip--strategy { background: var(--strategy); }
.tkey__chip--calendar { background: var(--calendar); }
.tkey__chip--write    { background: var(--write); }
.tkey__chip--publish  { background: var(--publish); }
.tkey__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .98rem;
  margin: .65rem 0 .2rem;
  color: var(--ink);
}
.tkey__desc {
  display: block;
  color: var(--ink-soft);
  font-size: .85rem;
  line-height: 1.5;
  margin: 0;
}

/* ------------------------------------------------------------
   CHANGE HERE FOR… — the sibling-page interchange strip.
   ------------------------------------------------------------ */
.tchange { padding-block: clamp(1.6rem, 3.5vw, 2.6rem); }
.tchange__head {
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 .9rem;
}
.tchange__row {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
}
.tchange__link {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .6rem 1.1rem;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .9rem;
  color: var(--ink);
  text-decoration: none;
  transition: border-color .15s var(--ease);
}
.tchange__link:hover { border-color: var(--ink); }
.tchange__dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex: none;
}
.tchange__dot--strategy { background: var(--strategy); }
.tchange__dot--calendar { background: var(--calendar); }
.tchange__dot--write    { background: var(--write); }
.tchange__dot--publish  { background: var(--publish); }
.tchange__dot--brand    { background: var(--brand); }
.tchange__dot--all {
  background: linear-gradient(90deg,
    var(--strategy) 0 25%, var(--calendar) 25% 50%,
    var(--write) 50% 75%, var(--publish) 75% 100%);
}

/* ------------------------------------------------------------
   STATION BOARD — the indigo enamel sign (Company Profile page).
   ------------------------------------------------------------ */
.stnboard {
  max-width: 720px;
  margin: clamp(1.4rem, 3vw, 2.2rem) auto 0;
  background: var(--brand);
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 3px rgb(255 255 255 / .85),
              inset 0 0 0 6px var(--brand);
  padding: 1.6rem clamp(1.2rem, 3vw, 2rem) 1.2rem;
  color: #fff;
}
.stnboard__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.15rem, 2.4vw, 1.45rem);
  letter-spacing: .14em;
  text-transform: uppercase;
  text-align: center;
  margin: 0 0 1.1rem;
}
.stnboard__rows { margin: 0; }
.stnboard__row {
  display: grid;
  grid-template-columns: minmax(140px, 190px) 1fr;
  gap: 1rem;
  padding: .85rem 0;
  border-top: 1px solid rgb(255 255 255 / .28);
}
@media (max-width: 540px) {
  .stnboard__row { grid-template-columns: 1fr; gap: .15rem; }
}
.stnboard__term {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .95rem;
  margin: 0;
}
.stnboard__desc {
  color: rgb(255 255 255 / .82);
  font-size: .92rem;
  line-height: 1.5;
  margin: 0;
}

/* ------------------------------------------------------------
   LINKEDIN POST ANATOMY — mock post card + callouts.
   ------------------------------------------------------------ */
.lipost-wrap {
  display: grid;
  grid-template-columns: minmax(0, 420px) 1fr;
  gap: clamp(1.4rem, 3.5vw, 3rem);
  align-items: center;
  margin-top: clamp(1.2rem, 3vw, 2rem);
}
@media (max-width: 820px) { .lipost-wrap { grid-template-columns: 1fr; } }
.lipost {
  background: var(--canvas);
  border: 0.5px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1.3rem 1.4rem 1.1rem;
}
.lipost__head {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-bottom: 1rem;
}
.lipost__avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--tint);
  border: 0.5px solid var(--hairline);
  flex: none;
}
.lipost__who { min-width: 0; }
.lipost__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .92rem;
  color: var(--ink);
}
.lipost__meta {
  display: block;
  font-size: .78rem;
  color: var(--ink-soft);
}
.lipost__hook {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.35;
  color: var(--ink);
  margin: 0 0 .9rem;
}
.lipost__bar {
  height: 10px;
  border-radius: 5px;
  background: var(--tint);
  margin-bottom: .55rem;
}
.lipost__bar--w80 { width: 80%; }
.lipost__bar--w92 { width: 92%; }
.lipost__bar--w65 { width: 65%; }
.lipost__cta {
  font-weight: 600;
  font-size: .92rem;
  color: var(--brand);
  margin: .9rem 0 0;
}
.lipost__foot {
  margin-top: 1rem;
  padding-top: .8rem;
  border-top: 1px solid var(--hairline);
  font-size: .8rem;
  color: var(--ink-soft);
}
/* callouts — station dots on the write line */
.licalls {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.2rem;
}
.licall {
  position: relative;
  padding-left: 2.1rem;
}
.licall::before {
  content: "";
  position: absolute;
  left: 0;
  top: .12rem;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  border: 4px solid var(--write);
  box-sizing: border-box;
}
.licall + .licall::after {
  content: "";
  position: absolute;
  left: 7px;
  bottom: calc(100% - .2rem);
  width: 4px;
  height: 1.2rem;
  background: var(--write);
}
.licall__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .98rem;
  color: var(--ink);
  margin: 0 0 .15rem;
}
.licall__body {
  color: var(--ink-soft);
  font-size: .9rem;
  line-height: 1.5;
  margin: 0;
}

/* ============================================================
   HIW FLOW — the two-column scroll-synced timeline on
   /how-it-works/. Narrow left rail (position: sticky, no JS
   needed for the pin itself) shows the running elapsed-time
   counter; right column is a plain stack of step cards in
   normal flow, so each step's height is independent of the
   others (see feedback: a shared-grid-row layout ties every
   column to the tallest row and creates dead gaps — avoided
   here on purpose). initHiwFlow() in app.js (IntersectionObserver,
   the site's default scroll-tracking idiom) swaps the rail's
   text as each step crosses into view. Default (no JS) state is
   the plain static stack — JS only ever upgrades, never assumes
   a hidden/pending start state.

   .hiw-flow__pin's top offset clears the sticky nav plus the
   pinned intro sentence above it — see .page-hero--hiw below.
   --hiw-pin-top is measured live off that stack's actual
   rendered height (initHiwFlow, app.js) rather than a hardcoded
   number, so the rail always sits flush with the top of the
   scrolling column even if the header/hero height changes.
   ============================================================ */
.hiw-flow__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}
@media (min-width: 761px) {
  .hiw-flow__grid { grid-template-columns: 140px 1fr; gap: 2.5rem; }
}
.hiw-flow__rail { display: none; }
@media (min-width: 761px) {
  .hiw-flow__rail { display: block; }
  .hiw-flow__pin { position: sticky; top: var(--hiw-pin-top, 233px); }
}

/* pinned intro sentence — stays fixed under the nav for the whole
   page, with every section below scrolling underneath it (desktop
   only: on a small screen a permanently-fixed banner eats too much of
   the already-scarce viewport, so it reverts to normal flow there).
   Full page-hero__h1 size (unchanged) — it just wraps to more lines
   here than a one-time hero would, since it's now pinned. */
@media (min-width: 761px) {
  .page-hero--hiw {
    position: sticky;
    top: 72px;
    z-index: 90;
    background: var(--canvas);
    padding-top: 2.4rem;
    padding-bottom: 1.1rem;
  }
}
.hiw-flow__clock {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  letter-spacing: -.02em;
  color: var(--brand);
}
.hiw-flow__clock-label {
  display: block;
  margin-top: .3rem;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.hiw-flow__steps { display: grid; gap: clamp(2.6rem, 6vw, 3.6rem); }
.hiw-flow__step {
  display: flex;
  align-items: flex-start;
  gap: 1.1rem;
}
.hiw-flow__step-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;
  flex: none;
  margin-top: .15rem;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
/* subtle highlight on the step the rail's counter currently matches —
   a nice-to-have affordance, not load-bearing (see the rail itself for
   the actual information) */
.hiw-flow__step.is-active .hiw-flow__step-num {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.hiw-flow__step-body { min-width: 0; }
.hiw-flow__step-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.15rem, 2vw, 1.35rem);
  color: var(--ink);
  margin: 0 0 .4rem;
}
.hiw-flow__step-text {
  max-width: 52ch;
  color: var(--ink-soft);
  font-size: .98rem;
  line-height: 1.55;
  margin: 0;
}

/* -- long variant: Section B (weeks/months). Fewer, more spaced-out
   steps, no per-step time badge (the headline already states the
   checkpoint, e.g. "One week later") -- */
.hiw-flow--long .hiw-flow__steps { gap: clamp(3rem, 7vw, 4.5rem); }
.hiw-flow--long .hiw-flow__clock { font-size: clamp(1.3rem, 2vw, 1.6rem); }
/* extra breathing room before the CTA — the section's last step (the
   small two-card split mock) ends light, and .prod-sec's normal bottom
   padding alone read as too tight running straight into the CTA */
.hiw-flow--long { padding-bottom: clamp(6rem, 12vw, 9rem); }

.hiw-flow__total {
  margin: clamp(2.2rem, 5vw, 3rem) 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.1rem, 1.8vw, 1.3rem);
  color: var(--ink);
}

/* -------- mock cards (the "visual, not verbose" per-step artwork) -------- */
.hiw-mock {
  margin-top: 1.1rem;
  background: var(--tint);
  border: .5px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1rem 1.3rem;
  max-width: 480px;
}
/* label/value rows are the Design Scheme's .cmp table (see
   /internal/design-scheme/ "Tables"), just the 2-column form (row
   label + one value, no comparison column) — sizing is scoped down
   to fit a small card instead of a full-width comparison table;
   cell typography, borders and left-alignment are stock .cmp. */
.hiw-mock .cmp { min-width: 0; width: 100%; font-size: .92rem; }
.hiw-mock .cmp th,
.hiw-mock .cmp td { padding: .55rem 0; }
.hiw-mock .cmp tbody th { width: auto; white-space: nowrap; padding-right: 1rem; }
.hiw-mock .cmp tr:last-child th,
.hiw-mock .cmp tr:last-child td { border-bottom: 0; }
/* the row the user is shown editing in Step 3 */
.hiw-mock .cmp tr.hiw-mock__row--edited th,
.hiw-mock .cmp tr.hiw-mock__row--edited td { background: rgb(var(--brand-rgb) / .06); }
.hiw-mock .cmp tr.hiw-mock__row--edited td { color: var(--brand); }
.hiw-mock__pill {
  display: inline-block;
  margin-left: .5rem;
  background: var(--ink);
  color: #fff;
  font-size: .58rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: .3em .6em;
  border-radius: 999px;
  vertical-align: middle;
}

/* connect-channels mock (Step 4) */
.hiw-mock--connect {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.4rem 1.3rem;
}
.hiw-mock__badge {
  width: 44px; height: 44px;
  border-radius: 10px;
  object-fit: contain;
  background: #fff;
  border: .5px solid var(--hairline);
  padding: 8px;
  flex: none;
}
.hiw-mock__link-line {
  flex: 1;
  height: 2px;
  max-width: 90px;
  background: var(--publish);
  transform-origin: left center;
}
.hiw-mock__check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  border-radius: 999px;
  background: var(--publish);
  color: var(--ink);
  flex: none;
}
.hiw-mock__check svg { width: 15px; height: 15px; }
/* pre-JS/reduced-motion default: fully visible, static — JS only adds
   .js-hiw-anim (immediately, gated on !reduceMotion) to opt into the
   hidden-then-reveal animated version */
.js-hiw-anim .hiw-mock--connect .hiw-mock__link-line { opacity: 0; transform: scaleX(0); }
.js-hiw-anim .hiw-mock--connect .hiw-mock__check { opacity: 0; transform: scale(.4); }
.hiw-mock--connect.is-connected .hiw-mock__link-line {
  animation: hiwConnectLine .5s var(--ease) forwards;
}
.hiw-mock--connect.is-connected .hiw-mock__check {
  animation: hiwConnectCheck .3s var(--ease) .45s forwards;
}
@keyframes hiwConnectLine { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: scaleX(1); } }
@keyframes hiwConnectCheck { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }

/* post mock (Step 6) */
.hiw-mock--post { max-width: 420px; }
.hiw-mock__post-head { display: flex; align-items: center; gap: .65rem; margin-bottom: .7rem; }
.hiw-mock__avatar {
  width: 36px; height: 36px;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .85rem;
  flex: none;
}
.hiw-mock__post-name { display: block; font-family: var(--font-display); font-weight: 700; font-size: .9rem; color: var(--ink); }
.hiw-mock__post-role { display: block; font-size: .78rem; color: var(--ink-soft); }
.hiw-mock__post-text { font-size: .92rem; line-height: 1.5; color: var(--ink); margin: 0; }
.hiw-mock__post-stats {
  display: flex;
  gap: 1rem;
  margin-top: .8rem;
  padding-top: .7rem;
  border-top: 1px solid var(--hairline);
  font-size: .8rem;
  color: var(--ink-soft);
}

/* streak mock (Section B, Step 1) — 7 dots, one per day of the week */
.hiw-mock--streak { display: flex; justify-content: center; gap: .5rem; padding: 1.2rem; }
.hiw-mock__day {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--publish);
}
.hiw-mock__day--soft { background: var(--hairline); }

/* chart mocks (Section B) — small illustrative line charts in the same
   .hiw-mock tint card as the other per-step artwork. Line colors follow
   the entities they carry sitewide: content/inbound = publish azure,
   the not-yet-live outbound arm = structural brand indigo (amber fails
   the palette validator's lightness band at line weight). Identity
   never rides on color alone — outbound is dashed, both lines carry
   direct ink labels (.flabel), which is also the contrast relief the
   validator requires for azure on the tint surface. */
.hiw-mock--chart { padding: 1.1rem 1.2rem .9rem; }
.hiw-mock--chart svg { display: block; width: 100%; height: auto; }
.hiw-chart__axis { fill: none; stroke: var(--hairline); stroke-width: 1.5; }
.hiw-chart__line--dashed { stroke-dasharray: 7 6; }
.farr--brand { fill: var(--brand); }

@media (prefers-reduced-motion: reduce) {
  .hiw-flow__step-num { transition: none; }
  .js-hiw-anim .hiw-mock--connect .hiw-mock__link-line,
  .js-hiw-anim .hiw-mock--connect .hiw-mock__check { opacity: 1; transform: none; }
  .hiw-mock--connect.is-connected .hiw-mock__link-line,
  .hiw-mock--connect.is-connected .hiw-mock__check { animation: none; }
}

@media (max-width: 760px) {
  /* .cmp's own mobile fallback is a horizontal scroll (see the Design
     Scheme note on .cmp-scroll) — fine for a full-width comparison
     table, but not for these small mock cards, so the label/value
     pairs unroll into a stacked block instead, same as before. */
  .hiw-mock .cmp,
  .hiw-mock .cmp tbody,
  .hiw-mock .cmp tr,
  .hiw-mock .cmp th,
  .hiw-mock .cmp td { display: block; width: auto; }
  .hiw-mock .cmp th,
  .hiw-mock .cmp td { padding: .15rem 0; border-bottom: 0; }
  .hiw-mock .cmp tr { padding-bottom: .5rem; margin-bottom: .5rem; border-bottom: 1px solid var(--hairline); }
  .hiw-mock .cmp tr:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
  .hiw-mock--connect { gap: .5rem; padding-inline: .8rem; }
  .hiw-mock__link-line { max-width: 40px; }
}

/* ============================================================
   DEEP LATTICE VOICE DIAGRAM — "Craft Your Content In Your Unique
   Voice" (product/index.php). Same "sources feed a central core"
   idea as the Nerve Centre diagram on /product/deep-lattice/
   (.dl-lattice in deep-lattice.css, not loaded here), redrawn as a
   ring of memory-source nodes on the left arrowing IN to a Deep
   Lattice hub that's pushed toward the left of the frame, with a
   single output trunk on the right branching OUT into three
   outcomes — the ring deliberately has no node due east of the
   core, leaving that side clear for the trunk. Title/body live in
   the section head above the card, not on the card itself.
   Below 760px, .dlv swaps for .dlv-m — the same sources-feed-a-core
   structure, redrawn top-to-bottom instead of left-to-right: two
   columns of source nodes arrow down into the core, then one trunk
   arrows down and branches into the same 3 outcomes below it. */
.dlv { display: block; width: 100%; height: auto; }
@media (max-width: 760px) { .dlv { display: none; } }

.dlv-node {
  fill: rgb(255 255 255 / .14);
  stroke: rgb(255 255 255 / .45);
  stroke-width: 1.5;
}
.dlv-node--out { fill: rgb(255 255 255 / .22); }
.dlv-node__label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  fill: #fff;
  text-anchor: middle;
  dominant-baseline: middle;
}
.dlv-core { fill: rgb(255 255 255 / .18); stroke: rgb(255 255 255 / .6); stroke-width: 1.5; }
.dlv-core__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: .01em;
  fill: #fff;
  text-anchor: middle;
}
.dlv-line {
  fill: none;
  stroke: rgb(255 255 255 / .65);
  stroke-width: 2;
  stroke-linecap: round;
}

/* mobile diagram — same node/core/line classes as .dlv reused for
   colour/fill so the two stay visually consistent, but .dlv-m's
   viewBox is drawn at roughly mobile-card scale (~530 units wide vs
   .dlv's ~1070) rather than just being .dlv's own viewBox squeezed
   narrower, so 1 SVG unit stays close to 1 rendered px and text
   doesn't shrink into illegibility — font-size/stroke-width are
   bumped vs. .dlv's to land at the same physical size at that scale. */
.dlv-m { display: none; }
@media (max-width: 760px) { .dlv-m { display: block; width: 100%; height: auto; margin-top: 1.2rem; } }
.dlv-m .dlv-node__label { font-size: 20px; }
.dlv-m .dlv-core__title { font-size: 24px; }
.dlv-m .dlv-node,
.dlv-m .dlv-core { stroke-width: 2; }
.dlv-m .dlv-line { stroke-width: 2.5; }

/* ============================================================
   APPROVALS + TRUST LEVEL SCREENSHOTS — "No Surprises. Ever."
   (product/index.php). Two real product screenshots shown as a
   tilted floating card stack, like two playing cards held fanned:
   the Approvals shot sits behind on the right, the Trust Level shot
   sits in front on the left, overlapping enough that only the right
   ~60% of the back card shows. Matted on three sides (tint shows
   through top/left/right), flush at the bottom, the whole stack
   rotated back on its bottom edge so it reads as viewed from
   slightly above. .gbox-media__img's absolute+inset:0 fill is
   overridden — .stack-shot handles sizing/position instead.
   ============================================================ */
.gbox-media__frame--shot {
  min-height: 0;
  overflow: visible;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: clamp(1.75rem, 4.5vw, 3rem);
  padding-bottom: 0;
  perspective: 1600px;
}
/* Bottom card scales with the frame (min() cap + %); top card is a
   fixed size independent of that — see .stack-shot__img--top — so
   growing the bottom card doesn't drag the top card's size up with
   it. Deliberately NOT the same size: two different screens, shown
   as two distinct cards, not a matched pair. */
.stack-shot {
  position: relative;
  width: min(900px, 78%);
  transform: rotateX(8deg);
  transform-origin: center bottom;
}
.stack-shot__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
}
.stack-shot__img--bottom { position: relative; z-index: 1; }
/* Fixed size, NOT a percentage of .stack-shot — this is what keeps it
   from growing in lockstep with the (larger) bottom card as that one
   scales with the viewport. Left offset is fixed too, for the same
   reason: a constant peek amount regardless of how big the back card gets. */
.stack-shot__img--top {
  position: absolute;
  z-index: 2;
  width: clamp(200px, 30vw, 371px);
  left: clamp(-115px, -17vw, -60px);
  bottom: 0;
}

/* The overlapping tilted stack reads fine at desktop width, but the
   fanned-card overlap plus the 3D tilt makes small screenshot text
   unreadable once the whole thing shrinks to a phone-width card —
   same call as .dlv going display:none below 760px for its own
   diagram. Below 760px: two plain, untilted, full-width cards
   stacked vertically instead, one image each. */
.shot-mobile { display: none; }
@media (max-width: 760px) {
  .shot-desktop { display: none; }
  .shot-mobile { display: grid; gap: 1.1rem; }
}
.gbox-media__frame--shot-m {
  min-height: 0;
  display: flex;
  justify-content: center;
  padding: clamp(1rem, 5vw, 1.5rem);
}
.gbox-media__frame--shot-m .gbox-media__img {
  position: static;
  width: 100%;
  height: auto;
  inset: auto;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: var(--shadow-md);
}
/* Approvals is a 3-pane screen (nav / list / detail) — shown uncropped
   at mobile width its text is too small to read. Cropped+zoomed
   instead: object-position pushes the crop window right, dropping
   most of the left nav sidebar while keeping the "Approvals" title
   (which sits just right of the sidebar) in frame, then the (now
   larger) list + most of the detail pane after it. Image is wider
   than the crop ratio, so cover only crops horizontally — the full
   height, title bar included, is always shown. */
.gbox-media__frame--shot-m .gbox-media__img--zoom-approvals {
  height: auto;
  aspect-ratio: 1.7;
  object-fit: cover;
  object-position: 40% center;
}

/* ============================================================
   CONTENT FORMATS — "The Right Format For Every Topic"
   (product/index.php). .gbox-grid--3 collapses to one column below
   760px like every other 3-up grid, but these cards are tall,
   busy embedded-post mockups — the sitewide default gap reads too
   tight stacked vertically, so give this specific grid more room
   on mobile only (same reasoning as .capabilities' own
   .gbox-grid + .gbox-grid spacing bump on the homepage).
   ============================================================ */
@media (max-width: 760px) {
  .format-grid { row-gap: 2.4rem; }
}

/* section-head lead paragraph + arrow-cta pairing — .prod-lead has no
   bottom margin of its own (other .prod-lead uses have nothing after
   them), so give the button breathing room here specifically. */
.section-head .arrow-cta--text { margin-top: 1.4rem; }

/* Craft Your Content card's diagram — arrow-cta--text dropped into
   normal flow right after the diagram svg (.dlv-m is the last svg in
   DOM order, .dlv sits earlier and is display: none below 760px),
   replacing the old corner-pinned .gbox__link icon. .arrow-cta itself
   is inline-flex with no positioning, so it defaults to the card's
   bottom-left; switch it to a content-sized flex box with an auto
   left margin to push it to the bottom-right instead, echoing where
   .gbox__link always sits. */
.dlv-m + .arrow-cta--text {
  display: flex;
  width: fit-content;
  margin-top: 1.4rem;
  margin-left: auto;
}



/* Metrics section's stack-shot — the front card (Messaging Pillars +
   Consistency) is a dense dashboard, unlike Approvals' simpler Trust
   Level card, so the shared .stack-shot__img--top size reads too
   small to make sense of. Scoped override, double the width — left
   offset stays put so it still peeks the same amount past the back
   card's edge rather than sliding further off it. */
.stack-shot--metrics .stack-shot__img--top {
  width: clamp(400px, 60vw, 742px);
}
