/* ==========================================================================
   AdPillar STYLE — how the site looks
   --------------------------------------------------------------------------
   Load order in every page head (Bootstrap is NEVER modified):
     1. assets/vendor/bootstrap.css   vendor, read-only
     2. theme.css           fonts, brand tokens, Bootstrap remap
     3. style.css           THIS FILE

   WHAT THIS FILE IS
     Every visual that appears more than once — on one page or across pages: base element rules,
     Bootstrap components overridden by their own names, the handful of blocks
     Bootstrap has no equivalent for, and the responsive rules utilities
     cannot express. This is the file that grows as pages are signed off.

   WHAT NEVER GOES IN HERE
     A brand value written out. Every color, size, radius and shadow is a
     var(--ap-*) from theme.css. A hex or an unexplained number here means a
     token is missing or a value was hard-coded — point it at a token, or add the
     token to theme.css. Spacing is the one exception: it has no tokens — it is
     Bootstrap's spacer scale (0 / .25rem / .5rem / 1rem / 1.5rem / 3rem) written
     literally, plus var(--ap-space-section) for section rhythm. Values with no
     brand meaning stay literal: 0, 100%,
     auto, ratios, 50% radii, hairline widths, and the geometry inside a calc()
     or a shadow.
     A one-off: a visual that appears exactly once in the whole design stays
     inline in its page. A visual that appears more than once — on one page or
     across pages — is a class here.
     Exploration and archive CSS: those files style themselves.
     A second declaration of something already declared here or in a page head —
     the same visual in two places can be changed in one and not the other.

   SMACSS LAYERING — the order sections appear in
     base (element rules) → layout → components → state → theme.

   NAMING — the convention Bootstrap itself uses. Not BEM.
     Object + variant naming comes from OOCSS: .btn carries structure,
     .btn-primary carries appearance. Utilities come first: reach for
     .text-success or .gap-3 before writing anything. Hyphens only — the same
     shape as .card / .card-body / .card-title / .btn-primary.

     • Bootstrap owns it → keep its name, override it. Never rename or clone.
     • Utility exists → use it. .stat.bg-primary, .card-title.text-success —
       do NOT invent .stat-blue or .title-green.
     • Style the ELEMENT first: a, h2, ul get a base rule. A region that reads
       differently overrides its own descendants in ONE place —
       .site-footer a { }, not a class on every anchor.
     • New class only when 3+ properties differ (font, size, spacing, weight…)
       from what utilities already give you.
     • Variants are one class with a single dash, and the name says WHAT is
       being varied: .card-glass, .section-lg, .btn-lime. A generic adjective
       never stands alone on a class-only selector — .dashed would collide the
       moment a border wants it.
     • An element-scoped variant IS allowed a bare adjective, because the
       element does the scoping and OOCSS keeps it there: a.underline and
       a.underline-dashed style links, mark.underline styles the emphasis
       mark. Same word, different element, no collision.
     • No __ elements and no -- modifiers. A child that needs styling gets a
       named class (.stat-value) or is reached through its parent
       (.check-list li), never .block__child.
     • No stacking a base with its own variant: .card-glass works alone.
     • No vendor prefix on class names.

   Section numbering continues from theme.css (§1–§3 there, §3b–§12 here).

   UNITS
     rem for spacing, padding, margin, radii and type. Spacing values sit on
     Bootstrap's spacer scale: 0 / .25 / .5 / 1 / 1.5 / 3rem.
     clamp() for headings, stats and section rhythm.
     px only for hairlines, border widths and shadow geometry.
   ========================================================================== */

/* --------------------------------------------------------------------------
   BASE — the page itself
   -------------------------------------------------------------------------- */
body {
  margin: 0;
  font-family: var(--ap-font-body);
  color: var(--ap-color-body);
  background: var(--ap-color-paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   3b. COLOR UTILITIES
   Bootstrap's own six theme colors already work everywhere through the §3
   mapping: .text-primary .bg-success .border-info .link-danger .text-bg-warning
   and every *-subtle / *-emphasis pair need nothing here.

   This block completes the set for the brand colors Bootstrap has no name for,
   in exactly Bootstrap's own shapes, so any color can be applied as a utility:
     .text-NAME  .bg-NAME  .border-NAME  .text-bg-NAME
     .bg-NAME-subtle  .border-NAME-subtle  .text-NAME-emphasis
   Reach for a utility before writing a rule.
   -------------------------------------------------------------------------- */

/* Lime — the growth accent and the second conversion fill (.btn-lime, §6) */
.text-lime {
  color: var(--ap-color-lime) !important;
}
.bg-lime {
  background-color: var(--ap-color-lime-bright) !important;
}
.border-lime {
  border-color: var(--ap-color-lime) !important;
}
.text-bg-lime {
  color: var(--ap-color-ink) !important;
  background-color: var(--ap-color-lime-bright) !important;
}
.bg-lime-subtle {
  background-color: var(--ap-color-lime-tint) !important;
}
.border-lime-subtle {
  border-color: var(--ap-color-lime-line) !important;
}
.text-lime-deep {
  color: var(--ap-color-lime-deep) !important;
}
.text-lime-emphasis {
  color: var(--ap-color-lime-ink) !important;
}

/* Amber — the link ink, also usable as a surface */
.text-amber {
  color: var(--ap-color-amber) !important;
}
.bg-amber {
  background-color: var(--ap-color-amber) !important;
}
.border-amber {
  border-color: var(--ap-color-amber) !important;
}
.text-bg-amber {
  /* Literal white, deliberate and approved as a one-off — leave as is. */
  color: #fff !important;
  background-color: var(--ap-color-amber) !important;
}
.bg-amber-subtle {
  background-color: var(--ap-color-amber-tint) !important;
}
.border-amber-subtle {
  border-color: var(--ap-color-amber-line) !important;
}
.text-amber-emphasis {
  color: var(--ap-color-amber-dark) !important;
}

/* Named inks. .text-secondary / .text-body-secondary are Bootstrap's; these are
   the two ends of the ramp it has no name for. */
.text-ink {
  color: var(--ap-color-ink) !important;
}
.text-faint {
  color: var(--ap-color-faint) !important;
}
.text-ghost {
  color: var(--ap-color-ghost) !important;
}

/* Named surfaces */
.bg-paper {
  background-color: var(--ap-color-paper) !important;
}
.bg-raised {
  background-color: var(--ap-color-paper-raised) !important;
}
.bg-surface {
  background-color: var(--ap-color-surface) !important;
}
.bg-inset {
  background-color: var(--ap-color-surface-inset) !important;
}
.bg-sand {
  background-color: var(--ap-color-sand) !important;
}

/* Named lines. .border is Bootstrap's default (--ap-color-line); these pick a
   specific weight. */
.border-line {
  border-color: var(--ap-color-line) !important;
}
.border-line-soft {
  border-color: var(--ap-color-line-soft) !important;
}
.border-line-strong {
  border-color: var(--ap-color-line-strong) !important;
}
.border-line-emphasis {
  border-color: var(--ap-color-line-emphasis) !important;
}

/* Named faces. The body face is the default on everything; these name the other
   two so an element can take a face without a rule of its own. */
.font-display {
  font-family: var(--ap-font-display) !important;
}
.font-body {
  font-family: var(--ap-font-body) !important;
}
.font-sub {
  font-family: var(--ap-font-sub) !important;
}

/* THE LOGO — one image, three heights. .logo on its own is 44px: the top bar,
   and a page that opens with the mark. .logo-sm 34px is the footer and the
   slide-in panel. .logo-lg 54px heads an assessment screen. */
.logo {
  display: block;
  width: auto;
  height: 2.75rem;
}
.logo-sm {
  height: 2.125rem;
}
.logo-lg {
  height: 3.375rem;
}
/* A row of customer logos under a hero. Every mark sits at .logo-sm height and
   the same held-back opacity, so one bright logo cannot shout over the rest.
   A logo that no longer fits the row wraps onto a second line, and the strip is
   only one line tall, so it disappears whole instead of being cut in half. No
   width and no count is named anywhere: however many logos the row is given, it
   shows as many as the space holds. */
.logo-strip {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  overflow: hidden;
  max-height: 2.125rem;
  column-gap: 1.5rem;
  row-gap: 0;
}
.logo-strip img {
  flex: 0 0 auto;
  height: 2.125rem;
  width: auto;
  opacity: .82;
}

/* Single-purpose signals */
.text-positive {
  color: var(--ap-color-positive) !important;
}
/* a delta in the right direction */
.text-star {
  color: var(--ap-color-star) !important;
}
/* review stars */
.text-violet-soft {
  color: var(--ap-color-violet-soft) !important;
}
/* the annotation voice */

/* Bootstrap ships .shadow-sm / .shadow / .shadow-lg; the fourth step is ours.
   Cards, panels and media frames reach for these — never a bespoke shadow. */
.shadow-xl {
  box-shadow: var(--ap-shadow-xl) !important;
}

/* Lets a flex or grid child shrink below the width of its content, so long
   text truncates or wraps inside it instead of pushing the row wider.
   Bootstrap has no min-width utility. */
.min-w-0 {
  min-width: 0 !important;
}

/* --- Links ------------------------------------------------------------------
   One base rule: a link is amber ink. Sections re-point every link inside
   them in one place — the nav and footer carry .site-nav / .site-footer, and
   each re-points its own anchors in §10, so their links go quiet without
   tagging a single anchor. A button keeps its own face. The underline
   utilities are scoped to the anchor itself — a.underline / a.underline-dashed
   — so the bare word stays free for mark.underline in §11. */
a {
  color: var(--ap-color-amber);
  text-decoration: none;
}
a:hover {
  color: var(--ap-color-amber-dark);
}

.site-footer a {
  color: var(--ap-color-body);
}
.site-footer a:hover {
  color: var(--ap-color-ink);
}

a.underline,
a.underline-dashed {
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}
a.underline-dashed {
  text-decoration-style: dashed;
  text-decoration-color: color-mix(in srgb, currentColor 42%, transparent);
}
a.underline-dashed:hover {
  text-decoration-style: solid;
  text-decoration-color: currentColor;
}

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY
   Five faces, one job each.
     Anko      = the page's own voice: h1 and h2, and nothing else.
     Comfortaa = the secondary heading face: h3, card titles, modal titles —
                 and every number.
     Inter     = everything read to act: h4–h6, body, labels, UI, forms.
     Handlee   = annotations on diagrams.   Kalam = a person speaking.
   .display-* is the Comfortaa headline set: six sizes, all --ap-font-sub 600,
   ink, usable on any tag. It is the third heading voice beside Anko (h1/h2)
   and the tag scale.
   The .fs-* utilities ARE the scale — .fs-N is always --ap-fs-N. Headings pick
   the step that suits them, and two steps carry more than one heading:
     h1 → fs-1   h2 → fs-2   h3 → fs-4   h4, h5 → fs-5   h6 → fs-6
   --ap-fs-3 sits between a section heading and a card title. No element takes
   it by default; reach for it with .fs-3 or from a class that needs that size.
   -------------------------------------------------------------------------- */
h1,
h2,
.h1,
.h2 {
  font-family: var(--ap-font-display);
  font-weight: 400;
  color: var(--ap-color-ink);
  letter-spacing: -.012em;
  margin-top: 0;
}
h1,
.h1 {
  font-size: var(--ap-fs-1);
  line-height: 1.0;
  letter-spacing: -.01em;
  margin-bottom: 1.5rem;
}
h2,
.h2 {
  font-size: var(--ap-fs-2);
  line-height: 1.03;
  margin-bottom: 1rem;
}
/* h3 is where the voice changes. One declaration covers the heading and the two
   places a title is a title without being part of the outline. */
h3,
.h3,
.card-title,
.modal-title {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  color: var(--ap-color-ink);
  font-size: var(--ap-fs-4);
  line-height: 1.2;
  letter-spacing: 0;
  margin-top: 0;
  margin-bottom: .25rem;
}
h4,
h5,
h6,
.h4,
.h5,
.h6 {
  font-family: var(--ap-font-body);
  font-weight: 600;
  color: var(--ap-color-ink);
  line-height: 1.35;
  margin: 0 0 .25rem;
}
h4,
.h4 {
  font-size: var(--ap-fs-5);
}
h5,
.h5 {
  font-size: var(--ap-fs-5);
}
h6,
.h6 {
  font-size: var(--ap-fs-6);
  letter-spacing: .01em;
}

/* Bootstrap font-size utilities carry the same scale as the headings. */
.fs-1 {
  font-size: var(--ap-fs-1) !important;
}
.fs-2 {
  font-size: var(--ap-fs-2) !important;
}
.fs-3 {
  font-size: var(--ap-fs-3) !important;
}
.fs-4 {
  font-size: var(--ap-fs-4) !important;
}
.fs-5 {
  font-size: var(--ap-fs-5) !important;
}
.fs-6 {
  font-size: var(--ap-fs-6) !important;
}
/* The two steps under .fs-6 have no Bootstrap number, so they take the token's
   own name: a caption under a figure, the labels along a chart axis. */
.fs-xs {
  font-size: var(--ap-fs-xs) !important;
}
.fs-label {
  font-size: var(--ap-fs-label) !important;
}
.display-1,
.display-2,
.display-3,
.display-4,
.display-5,
.display-6 {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  color: var(--ap-color-ink);
  letter-spacing: 0;
}
.display-1 {
  font-size: var(--ap-fs-display-1);
  line-height: 1.0;
}
.display-2 {
  font-size: var(--ap-fs-display-2);
  line-height: 1.02;
}
.display-3 {
  font-size: var(--ap-fs-display-3);
  line-height: 1.04;
}
.display-4 {
  font-size: var(--ap-fs-display-4);
  line-height: 1.06;
}
.display-5 {
  font-size: var(--ap-fs-display-5);
  line-height: 1.08;
}
.display-6 {
  font-size: var(--ap-fs-display-6);
  line-height: 1.1;
}
.lead {
  font-size: var(--ap-fs-lead);
  font-weight: 400;
  line-height: 1.6;
  color: var(--ap-color-body);
  max-width: 60ch;
}
.small,
small {
  font-size: var(--ap-fs-6);
}

/* Italic Anko is the house emphasis — it lands on the payoff half of a headline. */
em,
.em {
  font-style: italic;
}

/* EMPHASIS MARKS — the <mark> element, exactly two forms, both lime.
   <mark>              : swipe that sits behind the lower third of the words. It
                         breaks across lines, so the bar is the element's own
                         background — an absolutely positioned pseudo-element
                         would paint on the first line only. box-decoration-break
                         redraws it on every line; the ends are square.
   <mark class="underline"> : stroke that sweeps just below the baseline. Stays
                         inline-block so it never breaks — the hand-drawn SVG is
                         one stroke stretched across the whole phrase.
   Bootstrap's own mark padding and highlight colour are reset here. */
mark {
  position: relative;
  display: inline;
  font-style: italic;
  z-index: 0;
  color: inherit;
  padding: 0 .04em;
  margin: 0 -.04em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  background: linear-gradient(rgba(226,239,74,.9), rgba(226,239,74,.9)) no-repeat 0 calc(100% - .05em) / 100% .34em;
}
mark.underline {
  display: inline-block;
  line-height: 1;
  padding: 0;
  margin: 0;
  background: none;
}
mark.underline::before {
  content: "";
  position: absolute;
  left: -.04em;
  right: -.04em;
  bottom: -.14em;
  height: .38em;
  z-index: -1;
  background: url(data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20200%2016%27%20preserveAspectRatio=%27none%27%3E%3Cpath%20d=%27M3,12%20C58,6%20138,3%20197,4%27%20fill=%27none%27%20stroke=%27%23E2EF4A%27%20stroke-width=%275%27%20stroke-linecap=%27round%27/%3E%3C/svg%3E) no-repeat 50% 50%/100% 100%;
}

/* Eyebrow — the pill that opens every section. Bootstrap has nothing like it.
   Caps are OPT-IN with Bootstrap's own .text-uppercase, so an eyebrow can carry
   a sentence ("Google Ads, built to drive sales") without a second class here. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .5625rem;
  font-size: var(--ap-fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--ap-color-blue);
  background: rgba(240,245,251,.7);
  border: 1px solid var(--ap-color-blue-line);
  border-radius: 50rem;
  padding: .4375rem .9375rem .4375rem .8125rem;
  margin-bottom: 1.5rem;
}
.eyebrow-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
/* Variants change three properties at once, so they earn their own class. */
.eyebrow-lime {
  color: var(--ap-color-lime-ink);
  background: rgba(255,255,255,.7);
  border-color: var(--ap-color-lime-line);
}
.eyebrow-violet {
  color: var(--ap-color-violet);
  background: rgba(240,236,250,.7);
  border-color: var(--ap-color-violet-line);
}

/* The two handwritten voices. Both are decoration with a job — never UI text,
   never body copy, never below their minimum size. */
.hand-note {
  font-family: var(--ap-font-note);
  font-weight: 600;
  font-size: var(--ap-fs-note);
  line-height: 1.35;
  color: var(--ap-color-violet-soft);
}
.quote {
  font-family: var(--ap-font-quote);
  font-weight: 300;
  font-size: var(--ap-fs-quote);
  line-height: 1.45;
  color: var(--ap-color-ink);
}

.label-caps {
  font-size: var(--ap-fs-label);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ap-color-faint);
}

/* --------------------------------------------------------------------------
   5. STAT — big Anko number with a label and a delta.
   Color comes from Bootstrap background utilities: .stat.bg-primary,
   .stat.bg-success, .stat.bg-danger … no per-color modifiers needed.
   -------------------------------------------------------------------------- */
.stat {
  display: flex;
  flex-direction: column;
  gap: .1875rem;
}
.stat-label {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-muted);
}
.stat-value {
  font-family: var(--ap-font-sub);
  font-weight: 500;
  color: var(--ap-color-ink);
  font-size: var(--ap-fs-stat);
  line-height: 1;
}
/* The delta states its own face and size, so it reads the same beside a value
   in a .stat-row and on its own as a standalone positive figure. */
.stat-delta > .bi {
  line-height: 1;
}
.stat-delta {
  font-family: var(--ap-font-body);
  font-size: var(--ap-fs-6);
  font-weight: 700;
  color: var(--ap-color-positive);
}
/* Value and delta share one baseline. The delta is never written inside
   .stat-value — it is a sibling, so it keeps its own face and size. */
.stat-row {
  display: flex;
  align-items: baseline;
  gap: .5rem;
}
.stat-lg .stat-value {
  font-size: var(--ap-fs-stat-lg);
}
.stat-inline {
  flex-direction: row;
  align-items: baseline;
  gap: .5rem;
}

/* Any solid-background stat inverts its own text — works for every theme color */
.stat:is(.bg-primary, .bg-success, .bg-info, .bg-danger, .bg-dark) {
  padding: 1rem;
  border-radius: var(--ap-radius);
}
.stat:is(.bg-primary, .bg-success, .bg-info, .bg-danger, .bg-dark) .stat-value {
  /* Literal white, deliberate and approved as a one-off — leave as is. */
  color: #fff;
}
.stat:is(.bg-primary, .bg-success, .bg-info, .bg-danger, .bg-dark) .stat-label {
  color: rgba(255,255,255,.72);
}
.stat:is(.bg-primary, .bg-success, .bg-info, .bg-danger, .bg-dark) .stat-delta {
  color: var(--ap-color-lime-bright);
}
.stat.bg-warning .stat-value,
.stat.bg-warning .stat-label {
  color: var(--ap-color-ink);
}

/* --------------------------------------------------------------------------
   6. BUTTONS
   Bootstrap's .btn and its own variants. Contextual changes are modifiers.
     .btn-success  = convert (green). One per screenful.
     .btn-primary  = navigate (blue). Navbar, mega-menu, in-page wayfinding.
     .btn-outline-secondary = neutral.
     .btn-link     = tertiary. Keeps the button's box, drops fill and border.

   IMPORTANT — compiled variants don't inherit the §3 mapping.
   Utilities (.text-*, .bg-*, .border-*, .link-*) read --bs-*-rgb and are
   on-brand automatically. Component variants (.btn-*, .alert-*, .table-*,
   .list-group-item-*) ship with LITERAL hex baked into the compiled CSS, so
   each variant we use must have its --bs-btn-* vars re-pointed at a token
   here. Adding a new variant to the site means adding it to this block.
   -------------------------------------------------------------------------- */
.btn {
  --bs-btn-border-radius: 50rem;
  --bs-btn-font-family: var(--ap-font-body);
  --bs-btn-font-weight: 600;
  --bs-btn-font-size: .96875rem;
  --bs-btn-padding-x: 1.625rem;
  --bs-btn-padding-y: .9375rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5625rem;
  transition: background-color .2s ease, color .2s ease, transform .2s ease, box-shadow .2s ease;
  /* The glow is tinted from the button's own fill, so every variant gets a
  matching one and a variant added later needs no rule of its own.
  Switch it off with Bootstrap's .shadow-none. */
  box-shadow: 0 6px 18px -6px rgb(from var(--bs-btn-bg) r g b / .5);
}
/* Every button lifts a hair on hover, off the same --ap-nudge the icon nudges
   use, so the reduced-motion rule in §12 zeroes it with nothing else to write.
   A button moves a third of the nudge distance — subtler than a glyph, because
   the whole control is moving. §6b's direction words, scoped to .btn, change
   which way it goes, and .nudge-none holds it still. */
.btn:hover {
  transform: translateY(calc(var(--ap-nudge, 3px) / -3));
}
.btn.nudge-none:hover {
  transform: none;
}
.btn.nudge-up:hover {
  transform: translateY(calc(var(--ap-nudge) / -3));
}
.btn.nudge-down:hover {
  transform: translateY(calc(var(--ap-nudge) / 3));
}
.btn.nudge-start:hover {
  transform: translateX(calc(var(--ap-nudge) / -3));
}
.btn.nudge-end:hover {
  transform: translateX(calc(var(--ap-nudge) / 3));
}
.btn-lg {
  --bs-btn-padding-x: 1.75rem;
  --bs-btn-padding-y: 1rem;
  --bs-btn-font-size: 1rem;
}
.btn-sm {
  --bs-btn-padding-x: 1.25rem;
  --bs-btn-padding-y: .6875rem;
  --bs-btn-font-size: var(--ap-fs-6);
}
/* The step below .btn-sm, and the only size that also drops the weight: a link
   that has to sit under a form or in the foot of a dialog without reading as a
   second action. No padding at all, so it aligns flush with the column it sits
   in. Pair it with .btn-link.btn-muted. */
.btn-xs {
  --bs-btn-padding-x: 0;
  --bs-btn-padding-y: 0;
  --bs-btn-font-size: var(--ap-fs-6);
  --bs-btn-font-weight: 500;
}

/* Convert — green */
.btn-success {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--ap-color-green);
  --bs-btn-border-color: var(--ap-color-green);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-green-dark);
  --bs-btn-hover-border-color: var(--ap-color-green-dark);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-green-dark);
  --bs-btn-active-border-color: var(--ap-color-green-dark);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--ap-color-green);
  --bs-btn-disabled-border-color: var(--ap-color-green);
}

/* Disabled as neutral grey instead of the variant's own faded fill, for a
   control that spends most of its life disabled and should not read as a live
   button while it waits. Add it to any .btn; remove it to get Bootstrap's. */
.btn-disabled-neutral {
  --bs-btn-disabled-color: var(--ap-color-ghost);
  --bs-btn-disabled-bg: var(--ap-color-line);
  --bs-btn-disabled-border-color: var(--ap-color-line-strong);
}

/* Convert — lime. The alternative conversion fill, equal in weight to green:
   pick whichever suits the page.
   Ink text, like .btn-warning — white type on lime fails contrast badly. */
.btn-lime {
  --bs-btn-color: var(--ap-color-ink);
  --bs-btn-bg: var(--ap-color-lime-bright);
  --bs-btn-border-color: var(--ap-color-lime-bright);
  --bs-btn-hover-color: var(--ap-color-ink);
  --bs-btn-hover-bg: var(--ap-color-lime);
  --bs-btn-hover-border-color: var(--ap-color-lime);
  --bs-btn-active-color: var(--ap-color-ink);
  --bs-btn-active-bg: var(--ap-color-lime);
  --bs-btn-active-border-color: var(--ap-color-lime);
  --bs-btn-disabled-color: var(--ap-color-ink);
  --bs-btn-disabled-bg: var(--ap-color-lime-bright);
  --bs-btn-disabled-border-color: var(--ap-color-lime-bright);
}

/* Navigate — blue */
.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--ap-color-blue);
  --bs-btn-border-color: var(--ap-color-blue);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-blue-dark);
  --bs-btn-hover-border-color: var(--ap-color-blue-dark);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-blue-dark);
  --bs-btn-active-border-color: var(--ap-color-blue-dark);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--ap-color-blue);
  --bs-btn-disabled-border-color: var(--ap-color-blue);
}

/* Violet */
.btn-info {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--ap-color-violet);
  --bs-btn-border-color: var(--ap-color-violet);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--ap-color-violet) 82%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--ap-color-violet) 82%, black);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--ap-color-violet) 82%, black);
  --bs-btn-active-border-color: color-mix(in srgb, var(--ap-color-violet) 82%, black);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--ap-color-violet);
  --bs-btn-disabled-border-color: var(--ap-color-violet);
}

/* Caution — warm gold. Ink text: gold on white fails contrast with white type. */
.btn-warning {
  --bs-btn-color: var(--ap-color-ink);
  --bs-btn-bg: var(--ap-color-gold-warm);
  --bs-btn-border-color: var(--ap-color-gold-warm);
  --bs-btn-hover-color: var(--ap-color-ink);
  --bs-btn-hover-bg: var(--ap-color-gold-deep);
  --bs-btn-hover-border-color: var(--ap-color-gold-deep);
  --bs-btn-active-color: var(--ap-color-ink);
  --bs-btn-active-bg: var(--ap-color-gold-deep);
  --bs-btn-active-border-color: var(--ap-color-gold-deep);
  --bs-btn-disabled-color: var(--ap-color-ink);
  --bs-btn-disabled-bg: var(--ap-color-gold-warm);
  --bs-btn-disabled-border-color: var(--ap-color-gold-warm);
}

/* Destructive — red */
.btn-danger {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--ap-color-red);
  --bs-btn-border-color: var(--ap-color-red);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--ap-color-red) 82%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--ap-color-red) 82%, black);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--ap-color-red) 82%, black);
  --bs-btn-active-border-color: color-mix(in srgb, var(--ap-color-red) 82%, black);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--ap-color-red);
  --bs-btn-disabled-border-color: var(--ap-color-red);
}

/* Ink — the dark fill beside a conversion button, for the action that stays
   on the page rather than converting. */
.btn-dark {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--ap-color-ink);
  --bs-btn-border-color: var(--ap-color-ink);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--ap-color-ink) 88%, white);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--ap-color-ink) 88%, white);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--ap-color-ink) 88%, white);
  --bs-btn-active-border-color: color-mix(in srgb, var(--ap-color-ink) 88%, white);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--ap-color-ink);
  --bs-btn-disabled-border-color: var(--ap-color-ink);
}

/* Neutral outline */
.btn-outline-secondary {
  --bs-btn-color: var(--ap-color-ink);
  --bs-btn-bg: var(--ap-color-surface);
  --bs-btn-border-color: var(--ap-color-line-strong);
  --bs-btn-hover-color: var(--ap-color-ink);
  --bs-btn-hover-bg: var(--ap-color-sand);
  --bs-btn-hover-border-color: var(--ap-color-line-strong);
  --bs-btn-active-color: var(--ap-color-ink);
  --bs-btn-active-bg: var(--ap-color-sand);
  --bs-btn-active-border-color: var(--ap-color-line-strong);
  --bs-btn-disabled-color: var(--ap-color-muted);
  --bs-btn-disabled-border-color: var(--ap-color-line-strong);
}
.btn-outline-primary {
  --bs-btn-color: var(--ap-color-blue-dark);
  --bs-btn-border-color: var(--ap-color-blue);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-blue);
  --bs-btn-hover-border-color: var(--ap-color-blue);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-blue-dark);
  --bs-btn-active-border-color: var(--ap-color-blue-dark);
}
.btn-outline-success {
  --bs-btn-color: var(--ap-color-green-dark);
  --bs-btn-border-color: var(--ap-color-green);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-green);
  --bs-btn-hover-border-color: var(--ap-color-green);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-green-dark);
  --bs-btn-active-border-color: var(--ap-color-green-dark);
}

.btn-outline-lime {
  --bs-btn-color: var(--ap-color-lime-ink);
  --bs-btn-border-color: var(--ap-color-lime);
  --bs-btn-hover-color: var(--ap-color-ink);
  --bs-btn-hover-bg: var(--ap-color-lime-bright);
  --bs-btn-hover-border-color: var(--ap-color-lime-bright);
  --bs-btn-active-color: var(--ap-color-ink);
  --bs-btn-active-bg: var(--ap-color-lime);
  --bs-btn-active-border-color: var(--ap-color-lime);
}

.btn-outline-warning {
  --bs-btn-color: var(--ap-color-gold-deep);
  --bs-btn-border-color: var(--ap-color-gold-warm);
  --bs-btn-hover-color: var(--ap-color-ink);
  --bs-btn-hover-bg: var(--ap-color-gold-warm);
  --bs-btn-hover-border-color: var(--ap-color-gold-warm);
  --bs-btn-active-color: var(--ap-color-ink);
  --bs-btn-active-bg: var(--ap-color-gold-deep);
  --bs-btn-active-border-color: var(--ap-color-gold-deep);
}
.btn-outline-danger {
  --bs-btn-color: var(--ap-color-red);
  --bs-btn-border-color: var(--ap-color-red);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-red);
  --bs-btn-hover-border-color: var(--ap-color-red);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-red);
  --bs-btn-active-border-color: var(--ap-color-red);
}
.btn-outline-info {
  --bs-btn-color: var(--ap-color-violet);
  --bs-btn-border-color: var(--ap-color-violet);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--ap-color-violet);
  --bs-btn-hover-border-color: var(--ap-color-violet);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--ap-color-violet);
  --bs-btn-active-border-color: var(--ap-color-violet);
}

/* Other compiled variants used on the site get the same treatment. */
.alert-success {
  --bs-alert-bg: var(--ap-color-green-tint);
  --bs-alert-border-color: var(--bs-success-border-subtle);
  --bs-alert-color: var(--ap-color-green-dark);
}
.alert-danger {
  --bs-alert-bg: var(--ap-color-red-tint);
  --bs-alert-border-color: var(--bs-danger-border-subtle);
  --bs-alert-color: var(--ap-color-red);
}
.alert-info {
  --bs-alert-bg: var(--ap-color-violet-tint);
  --bs-alert-border-color: var(--ap-color-violet-line);
  --bs-alert-color: var(--ap-color-violet);
}
.alert-warning {
  --bs-alert-bg: var(--ap-color-amber-tint);
  --bs-alert-border-color: var(--ap-color-amber-line);
  --bs-alert-color: var(--ap-color-amber);
}
/* An alert with a glyph in front of its text. The icon is a Bootstrap Icons
   glyph in the markup like every other icon here, so any variant carries any
   glyph and there is no icon rule to keep in step with it. */
.alert-icon {
  display: flex;
  gap: .5rem;
}
.alert-icon > svg,
.alert-icon > .bi {
  flex: 0 0 auto;
  margin-top: 2px;
}
/* Tertiary — the companion link beside a CTA. No fill, no border, but it keeps
   .btn's own box, so it sits on the CTA's baseline in a row and stacks with the
   same rhythm when the row wraps. Sizes are .btn-lg / .btn-sm like any other
   button; there is no separate set of link sizes. */
.btn-link {
  --bs-btn-color: var(--ap-color-amber);
  --bs-btn-hover-color: var(--ap-color-amber-dark);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--ap-color-amber-dark);
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
  --bs-btn-disabled-color: var(--ap-color-faint);
  text-decoration: none;
  /* No fill, so no glow: a tertiary link is not a raised control. */
  box-shadow: none;
}
.btn-link:hover {
  transform: none;
}
/* The quiet one: a link-button that steps back rather than invites — the Back
   link under a wizard form, the way out at the foot of a dialog. */
.btn-muted {
  --bs-btn-color: var(--ap-color-faint);
  --bs-btn-hover-color: var(--ap-color-body);
  --bs-btn-active-color: var(--ap-color-body);
}
/* An outline button has no fill for the glow to tint, so it would read black. */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-success,
.btn-outline-lime,
.btn-outline-info,
.btn-outline-warning,
.btn-outline-danger,
.btn-outline-light,
.btn-outline-dark {
  box-shadow: none;
}

/* Icons are authored in the MARKUP, never here. A Bootstrap Icons glyph
   inherits currentColor and the label's own size, so it tracks whatever variant
   it lands in with no icon rule to keep in sync — and the tag can be sized or
   swapped per instance. .btn already supplies inline-flex + gap for placement.
   This is the only icon rule, and it is structural: stop a long label from
   squashing the glyph. */
.btn > svg,
.btn > .bi {
  flex: 0 0 auto;
}

/* Icon-only button — carousel controls, close, step arrows. Square box, round
   corners, no label padding; the glyph is a Bootstrap Icons glyph in the markup like any
   other button icon. Colour and size come from the normal variants:
   .btn-icon.btn-outline-secondary, .btn-icon.btn-primary, .btn-icon.btn-sm. */
.btn-icon {
  --bs-btn-padding-x: 0;
  --bs-btn-padding-y: 0;
  width: 2.5rem;
  aspect-ratio: 1;
  border-radius: 50%;
}
/* An icon button is usually a direction control, so it does not lift: the
   movement goes on its glyph, or on the button with a §6b direction word. */
.btn-icon:hover {
  transform: none;
}
.btn-icon.btn-lg {
  width: 3rem;
}
.btn-icon.btn-sm {
  width: 2rem;
}
/* Full-width CTA on small screens only. Declared once, in the 767.98px block
   below — nothing here, so the button sizes to its content on desktop. */

/* A CTA pair: the action, then the companion link. Because .btn-link carries the
   button's own padding, the row needs no column gap — the link's box supplies it
   and the pair still sits flush left when it wraps to two lines. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}
.cta-row:has(.btn-link) {
  column-gap: 0;
}

/* A button that opens with a round icon disc in front of its label. The left
   padding is tightened so the disc sits close to the button's own edge; the
   disc's fill and glyph colour are utilities on the span:
     <a class="btn btn-dark btn-lg btn-lead"><span class="btn-lead-icon bg-lime text-ink"><i class="bi …"></i></span>Label</a> */
.btn-lead {
  padding-left: .625rem;
}
.btn-lead-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
}

/* --------------------------------------------------------------------------
   6b. HOVER NUDGE — motion, not appearance.
   Put the direction on the element that should move; it slides when its
   interactive parent is hovered. Direction is explicit, so a right-hand arrow
   travels right, a left-hand icon travels left, and an icon that shouldn't move
   simply gets no class. --ap-nudge tunes the distance on the instance
   (style="--ap-nudge:5px"). General purpose: any child of any hoverable thing,
   not just button icons. .nudge-group opts in an element Bootstrap doesn't
   already make interactive.
   A container is never a trigger. A card holding several controls would move
   every glyph inside it at once, wherever the pointer landed, so a card that
   wants its whole surface to nudge takes .nudge-group like anything else.
   -------------------------------------------------------------------------- */
.nudge-up,
.nudge-down,
.nudge-start,
.nudge-end {
  --ap-nudge: 3px;
  transition: transform .2s ease;
}
/* A direction word on a button would otherwise leave it with the line above's
   transform-only transition, so its fill and glow would snap on hover. */
.btn.nudge-up,
.btn.nudge-down,
.btn.nudge-start,
.btn.nudge-end {
  transition: background-color .2s ease, color .2s ease, transform .2s ease, box-shadow .2s ease;
}
:is(a, button, .btn, .nudge-group):hover .nudge-up {
  transform: translateY(calc(var(--ap-nudge) * -1));
}
:is(a, button, .btn, .nudge-group):hover .nudge-down {
  transform: translateY(var(--ap-nudge));
}
:is(a, button, .btn, .nudge-group):hover .nudge-start {
  transform: translateX(calc(var(--ap-nudge) * -1));
}
:is(a, button, .btn, .nudge-group):hover .nudge-end {
  transform: translateX(var(--ap-nudge));
}

/* --------------------------------------------------------------------------
   7. SURFACES — Bootstrap .card plus modifiers
   -------------------------------------------------------------------------- */
.card {
  --bs-card-bg: var(--ap-color-surface);
  --bs-card-border-color: var(--ap-color-line);
  --bs-card-border-radius: var(--ap-radius-lg);
  --bs-card-inner-border-radius: var(--ap-radius);
  --bs-card-spacer-x: 1.375rem;
  --bs-card-spacer-y: 1.375rem;
  --bs-card-title-color: var(--ap-color-ink);
  box-shadow: var(--ap-shadow);
}
.card-title {
  margin-bottom: .375rem;
}
/* face and size come from the h3 rule in §4 */
.card-text {
  font-size: var(--ap-fs-6);
  line-height: 1.5;
  color: var(--ap-color-muted);
}
/* Lift is a utility, not a card variant: .card.shadow-lg / .card.shadow-xl. */
.card-glass {
  background: rgba(255,255,255,.6);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-radius: 1.5rem;
}
.card-flush {
  border: 0;
  filter: drop-shadow(0 16px 28px rgba(60,50,40,.16));
  box-shadow: none;
}

/* FILE LIST — a folder's contents: a path bar, one row per item, a summary bar.
   Bootstrap's card header, flush list group and card footer, scoped to the
   block so a card header, list group or drawer elsewhere keeps Bootstrap's own
   defaults until that page decides what it wants. */
.file-list {
  --bs-card-cap-bg: var(--ap-color-surface-inset);
  --bs-card-cap-padding-y: .5rem;
  --bs-card-cap-padding-x: 1.5rem;
  overflow: hidden;
}
.file-list .card-header,
.file-list .card-footer {
  display: flex;
  align-items: center;
  min-height: 3.5rem;
  border-color: var(--ap-color-line-soft);
  color: var(--ap-color-muted);
}
.file-list .card-header {
  font-size: var(--ap-fs-lg);
}
/* The / between the folder names in the path bar. */
.file-list .file-path-sep {
  color: var(--ap-color-line-emphasis);
}
.file-list .card-footer {
  background: var(--ap-color-surface-inset);
  padding: .5rem 1.5rem;
}
.file-list .list-group {
  --bs-list-group-bg: var(--ap-color-surface);
  --bs-list-group-border-color: var(--ap-color-line-soft);
  --bs-list-group-item-padding-y: 1rem;
  --bs-list-group-item-padding-x: 1.5rem;
  --bs-list-group-action-hover-bg: var(--ap-color-surface-inset);
}
/* One row: tile, the name column, the size column, the button column. The size
   and button columns are the same width so a row with one button and a row with
   three end level. */
.directory-list-item {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.directory-item-name {
  flex: 1 1 auto;
  min-width: 0;
}
.directory-item-title {
  display: block;
  font-weight: 600;
  font-size: var(--ap-fs-lg);
  color: var(--ap-color-ink);
}
.directory-item-desc {
  display: block;
  font-size: var(--ap-fs-6);
  line-height: 1.5;
  color: var(--ap-color-muted);
}
.directory-item-meta {
  flex: 0 0 auto;
  width: 7rem;
  margin-right: 1rem;
  text-align: right;
  font-size: var(--ap-fs-6);
  white-space: nowrap;
}
.directory-item-actions {
  flex: 0 0 auto;
  width: 7rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .5rem;
}
/* The label-and-value rows in the file details panel. Ruled, last row bare. */
.file-detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .625rem 0;
  border-bottom: 1px solid var(--ap-color-line-soft);
}
.file-detail-row:last-child {
  border-bottom: 0;
}
/* The description under the title in the file details panel. */
.file-details .file-detail-desc {
  font-size: var(--ap-fs-lg);
  color: var(--ap-color-muted);
}
/* The preview image of the file, above its detail rows. */
.file-details .file-detail-preview {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius);
}

/* CONTENT GATE — the two layers behind the gate dialog on the gated resource
   page. Both fill the window under the dialog and are decorative.
   .content-gate-preview is the mat the blurred page image sits on; its padding
   grows from a phone edge to a desk-width one in one step, so there is no
   jump at a breakpoint. .content-gate-blur is the directory listing shown
   out of focus, unreachable by pointer or selection. */
.content-gate-preview {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(.5rem, 3.5vw, 3rem);
  background: var(--ap-color-line-emphasis);
}
.content-gate-preview-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.content-gate-blur {
  position: absolute;
  inset: 0;
  overflow: hidden;
  filter: blur(5px);
  pointer-events: none;
  user-select: none;
}

/* CHANNEL CARD — fixed-width card for a horizontal scroller: icon tile + label,
   an h3, one paragraph, and a slot pinned to the base so a row of cards ends
   level whatever each one holds. Width comes from .scroller-item, colour from a
   .bg-*-subtle utility on the icon tile. What goes IN the slot is per-instance
   and stays inline in the page — it is content, not a component. */
.channel-card {
  padding: 1.5rem;
  min-height: 23.75rem;
}
.channel-card-head {
  display: flex;
  align-items: center;
  gap: .6875rem;
  margin-bottom: 1rem;
}
.channel-card-slot {
  margin-top: auto;
}

/* TESTIMONIAL CARD — a person, what they said, and the number it moved.
   Goes on a .card.card-glass. The up/down colour follows the data, so it stays
   inline in the page; everything structural is here. */
.testimonial-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 1.5rem;
  overflow: hidden;
}
.testimonial-head {
  display: flex;
  align-items: flex-start;
  gap: .8125rem;
  margin-bottom: 1.125rem;
}
.testimonial-name {
  font-size: var(--ap-fs-5);
  font-weight: 600;
  color: var(--ap-color-ink);
}
.testimonial-role {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-muted);
}
.testimonial-stars {
  color: var(--ap-color-star);
  font-size: var(--ap-fs-xs);
  letter-spacing: .09375rem;
  white-space: nowrap;
  margin-top: .25rem;
}
.testimonial-card .quote {
  flex: 1 1 auto;
  margin: 0 0 1.5rem;
}
.testimonial-rule {
  height: 1px;
  background: var(--ap-color-line-strong);
  margin: 0 0 1rem;
}
.testimonial-result {
  display: flex;
  align-items: center;
  gap: .5rem;
}
.testimonial-metric {
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.1;
}
.testimonial-metric-label {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-muted);
}

/* SPECIALIST SPOTLIGHT — one large portrait at a time with a caption plate over
   it, and a row of round faces under it to pick from. Every portrait, caption
   and face is written out in the markup; only .is-active moves between them, so
   the block holds any number of people with no change here. The one thing that
   stays in the markup per instance is each face's own background-image.
   The plate is centred text on purpose: it is a person speaking, not copy. */
.spotlight {
  position: relative;
  height: 29.375rem;
  overflow: hidden;
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius-xl);
}
.spotlight-layer,
.spotlight-cap {
  opacity: 0;
  transition: opacity .3s;
}
.spotlight-layer.is-active,
.spotlight-cap.is-active {
  opacity: 1;
}
.spotlight-layer {
  position: absolute;
  inset: 0;
}
.spotlight-layer img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The plate floats over the portrait, so it never takes the pointer — the faces
   under it are the control. */
.spotlight-cap {
  position: absolute;
  left: 1.25rem;
  right: 1.25rem;
  bottom: 1.25rem;
  padding: 1rem;
  background: rgba(255,255,255,.95);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--ap-color-line);
  border-radius: 1rem;
  pointer-events: none;
  text-align: center;
}
/* A plate is a short line inside a box, not a pull quote, so the quote voice
   sits at lede size here rather than its own. */
.spotlight-cap .quote {
  font-size: var(--ap-fs-lead);
  line-height: 1.5;
}
.spotlight-cap-name {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-muted);
  margin-top: .25rem;
}
.spotlight-avatars {
  display: flex;
  justify-content: center;
  min-width: 0;
  gap: clamp(.375rem, 1.1vw, .75rem);
}
/* The faces shrink to fit rather than wrap, so a row of six still sits on one
   line on a phone — hence the fluid gap above and flex-basis here. */
.spotlight-avatar {
  position: relative;
  flex: 0 1 4.125rem;
  width: 4.125rem;
  min-width: 0;
  height: auto;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--ap-color-surface) center / cover no-repeat;
  cursor: pointer;
  opacity: .55;
  box-shadow: 0 0 0 2px rgba(0,0,0,0);
  transition: box-shadow .25s, opacity .25s;
}
.spotlight-avatar.is-active {
  opacity: 1;
  box-shadow: 0 0 0 2px var(--ap-color-blue);
}

/* A row of round faces that overlap, each one tucked under the last by a
   quarter of its width. The faces are plain <img> with .rounded-circle and a
   white border utility. */
.avatar-stack {
  display: flex;
}
.avatar-stack > * + * {
  margin-left: -.75rem;
}

/* Round initials, where a photo would be too much */
.avatar {
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ap-color-blue);
  /* Literal white, deliberate and approved as a one-off — leave as is. */
  color: #fff;
  font-weight: 700;
  font-size: var(--ap-fs-5);
}

/* Tile inset inside a card */
.tile {
  background: var(--ap-color-surface-inset);
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius);
  padding: 1rem;
}

/* The white version of .tile: a small raised card inside a preview or a mock
   screen. Padding is the default; an instance that sits tighter takes py-* px-*. */
.tile-raised {
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius);
  padding: 1rem;
  box-shadow: var(--ap-shadow-sm);
}

/* The green "online" dot on the corner of a portrait. Its position is per
   instance, inline, because it depends on the size of the photo. */
.status-dot {
  position: absolute;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--ap-color-green);
  border: 3px solid var(--ap-color-surface);
}
.status-dot-lg {
  width: 1.375rem;
  height: 1.375rem;
}

/* Full-width sand panel with corner glows. */
.panel {
  position: relative;
  overflow: hidden;
  background: var(--ap-color-sand);
  border: 1px solid var(--ap-color-line-strong);
  border-radius: var(--ap-radius-panel);
}
/* Corner glow inside a .panel. Two colors, four corners, always combined:
   .panel-glow .panel-glow-lime .panel-glow-tr — nothing else is set per instance.
   Offsets are pixel-based, so a tall stacked panel keeps its glows on screen. */
.panel-glow {
  position: absolute;
  width: clamp(300px, 40vw, 500px);
  height: clamp(300px, 40vw, 500px);
  border-radius: 50%;
  filter: blur(34px);
  pointer-events: none;
}
.panel-glow-lime {
  background: radial-gradient(circle, var(--ap-color-blob-lime), transparent 66%);
}
.panel-glow-lilac {
  background: radial-gradient(circle, var(--ap-color-blob-lavender), transparent 66%);
}
.panel-glow-tl {
  top: clamp(-120px, -8vw, -60px);
  left: clamp(-120px, -8vw, -60px);
}
.panel-glow-tr {
  top: clamp(-120px, -8vw, -60px);
  right: clamp(-120px, -8vw, -60px);
}
.panel-glow-bl {
  bottom: clamp(-120px, -8vw, -60px);
  left: clamp(-120px, -8vw, -60px);
}
.panel-glow-br {
  bottom: clamp(-120px, -8vw, -60px);
  right: clamp(-120px, -8vw, -60px);
}

/* Icon tile fronting a feature row. Three sizes, nothing else varies:
     .icon-tile-sm  26px — inside a card (testimonial delta, list marker)
     .icon-tile     40px — the default, every feature row in a section
     .icon-tile-lg  46px — heading a card of its own (service card, contact)
   Colour is utilities: .bg-info-subtle .text-info, .bg-lime-subtle
   .text-lime-emphasis. The outline is Bootstrap's: .border .border-*-subtle. */
.icon-tile {
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: .6875rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.icon-tile > .bi {
  font-size: 1.1875rem;
  line-height: 1;
}
.icon-tile-sm > .bi {
  font-size: .8125rem;
}
.icon-tile-sm {
  width: 1.625rem;
  height: 1.625rem;
  border-radius: .5rem;
}
.icon-tile-lg {
  width: 2.875rem;
  height: 2.875rem;
  border-radius: .8125rem;
}

/* FILE TYPE — the tile in front of a file or a folder in a listing. Goes on an
   .icon-tile; the glyph is a Bootstrap Icons glyph in the markup like any other icon.
   Colour groups the kind rather than the extension, so two types that are read
   the same way look the same:
     folder, archive        gold      things that hold other things
     document, presentation red       things you read
     sheet                  green     things you work in
     image, video           blue      things you look at
     audio                  violet    things you listen to
     other                  grey      everything else
   The document and sheet outlines are Bootstrap's *-border-subtle vars, mapped
   in theme.css §3 — the same two values the alerts and badges use. */
.filetype {
  border: 1px solid;
}
.filetype-folder,
.filetype-archive {
  background: var(--ap-color-amber-tint);
  border-color: var(--ap-color-amber-line);
  color: var(--ap-color-gold-deep);
}
.filetype-doc,
.filetype-slides {
  background: var(--ap-color-red-tint);
  border-color: var(--bs-danger-border-subtle);
  color: var(--ap-color-red);
}
.filetype-sheet {
  background: var(--ap-color-green-tint);
  border-color: var(--bs-success-border-subtle);
  color: var(--ap-color-green-dark);
}
.filetype-image,
.filetype-video {
  background: var(--ap-color-blue-tint);
  border-color: var(--ap-color-blue-line);
  color: var(--ap-color-blue-dark);
}
.filetype-audio {
  background: var(--ap-color-violet-tint);
  border-color: var(--ap-color-violet-line);
  color: var(--ap-color-violet);
}
.filetype-other {
  background: var(--ap-color-surface-inset);
  border-color: var(--ap-color-line-strong);
  color: var(--ap-color-muted);
}

/* Feature row: icon + title + one line */
.feature {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
.feature-title {
  font-weight: 600;
  font-size: var(--ap-fs-5);
  color: var(--ap-color-ink);
}
.feature-desc {
  font-size: var(--ap-fs-6);
  line-height: 1.5;
  color: var(--ap-color-muted);
}

/* GREEN TICKS — two scopes, deliberately different, never mixed.
   .check-list  a one-line row of reassurances under a hero. Tick + label only.
   .check-grid  a block of claims in a section. Tick + title + one line, in
                columns. It borrows .feature-title / .feature-desc so the
                wording sits at the same size as an icon-tile feature row.
   A tick block never takes the outlined icon tiles a feature row uses. */
.check-list {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  list-style: none;
  padding: 0;
  margin: 0;
}
.check-list-item {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: var(--ap-fs-6);
  color: var(--ap-color-muted);
}
/* The tick is drawn, not typed: a "✓" character depends on the font having the
   glyph, and Inter does not, so it fell back to whatever the machine had. The
   mask scales with the row's own font-size. */
.check-list-item::before,
.check-grid-item::before {
  content: "";
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  background: var(--ap-color-green);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M4.5 12.8l5.2 5.2L19.5 6.4'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M4.5 12.8l5.2 5.2L19.5 6.4'/></svg>") center / contain no-repeat;
}
.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14.375rem, 1fr));
  gap: 1.5rem 2rem;
  list-style: none;
  padding: 0;
  margin: 0;
}
.check-grid-item {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
}
.check-grid-item::before {
  font-size: 1.125rem;
  margin-top: .15em;
}
/* One column whatever the width — a tick block in a narrow panel. */
.check-grid-vertical {
  grid-template-columns: minmax(0, 1fr);
}
/* Two columns whatever the width — a tick block of short titles beside a preview. */
.check-grid-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* SCHEDULE CALL — the booking card (Component___ScheduleCall). A title row, a
   month calendar, a time select, the caller's details, and a split booking
   button; once booked, the same card shows the confirmation. Day-cell state is
   .active / :disabled / .schedule-day-past, set in the component's markup.
   The shell is .card, and the card has three views, set by one class on it:
   nothing = the outlined card in the flow of a page; .schedule-card-flush = the
   same box with no outline, for a section that supplies its own; and
   .schedule-card-modal = flush plus a floating close button, for a dialog whose
   .modal-content it fills. The card's own .card-body padding is the padding in
   every view, so a dialog needs no .modal-body around it. */
.schedule-card {
  position: relative;
  width: 100%;
  max-width: 31.25rem;
  margin-inline: auto;
  box-shadow: var(--ap-shadow-xl);
}
.schedule-card-flush,
.schedule-card-modal {
  border-color: transparent;
  box-shadow: none;
}
.schedule-card-modal {
  border-radius: inherit;
}
.schedule-card .btn-close {
  display: none;
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 3;
}
.schedule-card-modal .btn-close {
  display: block;
}
/* The close button takes the top right corner, so the title row runs left. */
.schedule-card-modal .schedule-head {
  justify-content: flex-start;
}
.schedule-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .1875rem;
}

/* The lime panel: the booked confirmation, and the compact chosen-slot row */
.schedule-panel {
  background: var(--ap-color-lime-tint);
  border: 1px solid var(--ap-color-lime-line);
  border-radius: var(--ap-radius);
  padding: 1rem 1.0625rem;
  margin-bottom: 1rem;
}
.schedule-panel-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .75rem .875rem;
}
.schedule-panel-label {
  font-size: var(--ap-fs-label);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ap-color-lime-deep);
  margin-bottom: .25rem;
}
.schedule-panel-when {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-5);
  line-height: 1.2;
  color: var(--ap-color-ink);
}
.schedule-panel-note {
  font-size: var(--ap-fs-6);
  color: var(--ap-color-lime-ink);
  margin-top: .1875rem;
}

/* Calendar */
.schedule-cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .625rem;
}
.schedule-cal-month {
  flex: 1 1 auto;
  text-align: center;
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-5);
  color: var(--ap-color-ink);
}
.schedule-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: .375rem;
  margin-bottom: .875rem;
}
.schedule-dow {
  text-align: center;
  font-size: var(--ap-fs-label);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ap-color-ghost);
}
.schedule-day {
  font-family: var(--ap-font-body);
  font-size: var(--ap-fs-5);
  font-weight: 600;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  /* The box holds the shape and the number is centred in it, so the cell reads
     the same at every card width. */
  aspect-ratio: 1.15;
  min-height: 2.75rem;
  padding: .5rem .125rem;
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line-strong);
  border-radius: var(--ap-radius-sm);
  color: var(--ap-color-ink);
  cursor: pointer;
  transition: background-color .16s, border-color .16s;
}
.schedule-day-weekend {
  background: var(--ap-color-sand);
}
.schedule-day.active {
  background: var(--ap-color-lime-tint);
  border-color: var(--ap-color-lime-line);
  color: var(--ap-color-lime-ink);
}
.schedule-day:disabled {
  background: var(--ap-color-surface);
  border-color: var(--ap-color-line-soft);
  color: var(--ap-color-ghost);
  cursor: not-allowed;
}
.schedule-day-weekend:disabled {
  background: color-mix(in srgb, var(--ap-color-sand) 55%, #fff);
}
.schedule-day:disabled .schedule-day-num {
  opacity: .72;
}
.schedule-day-past .schedule-day-num {
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
}
.schedule-day-blank,
.schedule-day-blank:disabled {
  background: transparent;
  border-color: transparent;
  color: transparent;
  cursor: default;
}

/* The "how we meet" menu beside the booking button: Bootstrap's .dropup on a
   .btn-group, sized and coloured for the card it opens in. Each option is a
   name with a quiet <small> hint on the right. */
.schedule-card .dropdown-menu {
  --bs-dropdown-link-hover-bg: var(--ap-color-surface-inset);
  --bs-dropdown-link-active-bg: var(--ap-color-lime-tint);
  --bs-dropdown-link-active-color: var(--ap-color-ink);
  width: 14.375rem;
  padding: .375rem;
  border-color: var(--ap-color-line-strong);
  box-shadow: var(--ap-shadow-lg);
}
.schedule-card .dropdown-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .625rem;
  border-radius: var(--ap-radius-sm);
  padding: .625rem .75rem;
  font-size: var(--ap-fs-6);
  font-weight: 600;
  color: var(--ap-color-ink);
}
/* Bootstrap sizes a split toggle by its padding alone, which lands at 27px —
   under the 44px touch minimum. The floor is the card's, not every split
   button's. */
.schedule-card .dropdown-toggle-split {
  min-width: 3.25rem;
}
.schedule-card .dropdown-item small {
  font-size: var(--ap-fs-xs);
  font-weight: 400;
  color: var(--ap-color-muted);
}

/* Add-to-calendar: one button that swaps for three provider pills in place */
.schedule-add {
  position: relative;
  height: 3.125rem;
}
.schedule-add-btn,
.schedule-add-list {
  position: absolute;
  inset: 0;
  transition: opacity .22s ease, transform .26s cubic-bezier(.2,.7,.3,1);
}
.schedule-add-btn {
  padding: 0;
  font-size: var(--ap-fs-5);
}
.schedule-add-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .5rem;
}
/* Both the button and the three pills are in the markup; .is-open on
   .schedule-add swaps which one is live. */
.schedule-add .schedule-add-btn {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.schedule-add .schedule-add-list {
  opacity: 0;
  transform: scale(.97);
  pointer-events: none;
}
.schedule-add.is-open .schedule-add-btn {
  opacity: 0;
  transform: scale(.97);
  pointer-events: none;
}
.schedule-add.is-open .schedule-add-list {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.schedule-foot {
  text-align: center;
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-faint);
  margin-top: .625rem;
}
.schedule-note {
  text-align: center;
  font-size: var(--ap-fs-xs);
  line-height: 1.5;
  color: var(--ap-color-faint);
  margin-top: 1rem;
}

/* --------------------------------------------------------------------------
   8. BADGES — Bootstrap .badge; color via .text-bg-* / .bg-*-subtle
   -------------------------------------------------------------------------- */
.badge {
  --bs-badge-border-radius: 50rem;
  --bs-badge-font-weight: 600;
  --bs-badge-padding-x: .625rem;
  --bs-badge-padding-y: .25rem;
}
.badge.bg-lime-subtle {
  color: var(--ap-color-positive);
}
.badge.bg-info-subtle {
  color: var(--ap-color-violet);
}
/* “↑ 56%” */
.badge.bg-success-subtle {
  color: var(--ap-color-green-dark);
}
/* “● Live” */

/* --------------------------------------------------------------------------
   9. FORMS — Bootstrap controls, warmed up
   -------------------------------------------------------------------------- */
.form-control,
.form-select {
  border-radius: var(--ap-radius);
  border-color: var(--ap-color-line-emphasis);
  background-color: var(--ap-color-surface);
  color: var(--ap-color-ink);
  padding: .8125rem 1rem;
  font-size: var(--ap-fs-5);
}
/* background-color, not background — the shorthand would wipe out the caret
   image Bootstrap puts on .form-select. Caret restated here only to recolor it
   from Bootstrap's grey to --ap-color-muted. */
.form-select {
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%237C776E' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 16px 12px;
}
.form-control::placeholder {
  color: var(--ap-color-ghost);
}
.form-control:focus,
.form-select:focus {
  border-color: var(--ap-color-blue);
  box-shadow: 0 0 0 3px rgba(10,109,194,.16);
}
.form-label {
  font-size: var(--ap-fs-xs);
  font-weight: 600;
  color: var(--ap-color-muted);
  margin-bottom: .375rem;
}
/* The large label: a question read before its answers rather than a caption on
   a field, so it carries the secondary heading face at body size in full ink.
   Space under it is the same as any label — reach for mb-* when one needs more. */
.form-label-lg {
  font-family: var(--ap-font-sub);
  font-size: var(--ap-fs-5);
  color: var(--ap-color-ink);
}
/* The large field: Bootstrap's own size class, held at our padding and type,
   taller by a floor on its height. For a form that is the main thing in its
   section. */
.form-control-lg,
.form-select-lg {
  min-height: 3.5rem;
}
.form-text {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-faint);
}
/* Resize is opt-in, per element: a textarea resizes in both directions until it
   is told otherwise. Bootstrap has no equivalent utility. */
.resize-v {
  resize: vertical;
}
.resize-h {
  resize: horizontal;
}
.resize-all {
  resize: both;
}
.resize-none {
  resize: none;
}

/* Checkbox — Bootstrap's own control, on brand: the tick box is white like a
   .form-control and focus is the same blue ring every other control gets. The
   checked fill stays Bootstrap's blue; the lime fill belongs to .form-check-row,
   where the box sits inside a box. Bootstrap draws the tick itself, so there is
   no custom mark to keep in step. */
.form-check-input {
  /* Literal white, deliberate and approved as a one-off — leave as is. */
  background-color: #FFF;
  border-color: var(--ap-color-line-emphasis);
}
.form-check-input:focus {
  border-color: var(--ap-color-blue);
  box-shadow: 0 0 0 3px rgba(10,109,194,.16);
}

/* A group of checkboxes answering one question. It is also the hook the build's
   script listens on, and the element a new answer is appended into, so every
   set of answers carries it even when the layout comes from grid utilities on
   the same element. */
.check-group {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
/* Laid out as a grid, the row utilities on the same element own the direction
   and the gutters, so the stacked gap comes off. */
.check-group.row {
  flex-direction: row;
  gap: 0;
}
/* The field at the bottom of a group that adds an answer of their own. */
.check-add {
  font-size: var(--ap-fs-6);
  padding: .625rem .75rem;
}

/* Card — a checkbox wearing a tile, an icon above its label, for a grid of
   answers. The class goes on a <label> wrapping the input, so the whole tile is
   the hit area and the control stays a real checkbox with no JavaScript:
     <label class="form-check-card">
       <input class="form-check-input" type="checkbox"> <i class="bi bi-…"></i> <span>…</span>
     </label>
   Unchecked it is a neutral outline; checked it fills lime-tint. */
.form-check-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  text-align: center;
  font-size: var(--ap-fs-6);
  font-weight: 500;
  line-height: 1.25;
  color: var(--ap-color-body);
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line-emphasis);
  border-radius: var(--ap-radius);
  padding: 1rem .5rem;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
/* The input still has to be in the DOM and focusable: it is the control. */
.form-check-card .form-check-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.form-check-card svg {
  width: 1.375rem;
  height: 1.375rem;
}
.form-check-card > .bi {
  font-size: 1.375rem;
  line-height: 1;
}
.form-check-card:hover {
  color: var(--ap-color-ink);
  background: var(--ap-color-surface-inset);
}
.form-check-card:has(.form-check-input:checked) {
  color: var(--ap-color-lime-ink);
  background: var(--ap-color-lime-tint);
  border-color: var(--ap-color-lime-line);
}
.form-check-card:has(.form-check-input:focus-visible) {
  border-color: var(--ap-color-blue);
  box-shadow: 0 0 0 3px rgba(10,109,194,.16);
}

/* Row — the same checkbox full width, tick box showing, for a list of answers
   read one under another. Same <label> wrapper as .form-check-card. */
.form-check-row {
  display: flex;
  align-items: center;
  gap: .625rem;
  font-size: var(--ap-fs-6);
  font-weight: 500;
  color: var(--ap-color-body);
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius);
  padding: .625rem .75rem;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.form-check-row .form-check-input {
  margin: 0;
}
.form-check-row .form-check-input:checked {
  background-color: var(--ap-color-lime-deep);
  border-color: var(--ap-color-lime-deep);
}
.form-check-row:hover {
  color: var(--ap-color-ink);
  background: var(--ap-color-surface-inset);
}
.form-check-row:has(.form-check-input:checked) {
  color: var(--ap-color-lime-ink);
  background: var(--ap-color-lime-tint);
  border-color: var(--ap-color-lime-line);
}
.form-check-row:has(.form-check-input:focus-visible) {
  border-color: var(--ap-color-blue);
  box-shadow: 0 0 0 3px rgba(10,109,194,.16);
}

/* --------------------------------------------------------------------------
   10. SITE NAV & FOOTER
   The nav is not Bootstrap's .navbar: it is a flex row in a .container. Every
   assembly inside it that Bootstrap ships is Bootstrap's own: the desktop mega
   panels are .dropdown / .dropdown-menu, the mobile menu is .offcanvas, and the
   two expanding sections inside it are .accordion / .accordion-collapse. The
   markup for all of them is in the file at all times; only classes toggle.
   Everything in this section is scoped under .site-nav, because the nav reads
   differently from a page: quieter links, its own hover wash, its own row sizes.
   Two hovers, on purpose: a grey wash on the bar itself, sand everywhere a row
   sits on a surface.
   -------------------------------------------------------------------------- */
.site-nav a:not(.btn) {
  color: var(--ap-color-body);
}
.site-nav a:not(.btn):hover {
  color: var(--ap-color-ink);
}
/* The bar's own height. 20px is off the spacer scale on purpose: it sets the
   bar to 84px around the 44px logo, and both scale steps either side change the
   header height on every page. Manual override, approved. */
.site-nav-bar {
  position: relative;
  padding-top: 20px;
  padding-bottom: 20px;
  min-width: 0;
}
/* The paper surface behind the bar: absent at the top of a page, faded in once
   the page has scrolled, so a hero can run under a transparent header. */
.site-nav-surface {
  position: absolute;
  inset: 0;
  background: var(--ap-color-paper-raised);
  border-bottom: 1px solid var(--ap-color-line);
  box-shadow: var(--ap-shadow-nav);
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.site-nav.is-scrolled .site-nav-surface {
  opacity: 1;
}
.site-nav-links {
  font-size: var(--ap-fs-5);
  font-weight: 500;
  color: var(--ap-color-body);
  flex: 0 1 auto;
  min-width: 0;
}
/* One item in the desktop bar — a link or a menu button. */
.site-nav .site-nav-link {
  display: inline-flex;
  align-items: center;
  padding: .5rem 1rem;
  border: none;
  background: transparent;
  font: inherit;
  border-radius: var(--ap-radius-sm);
  color: var(--ap-color-body);
  cursor: pointer;
}
/* One wash, three ways in: pointer on the item, pointer anywhere on an open
   menu's trigger area, and the open menu itself. */
.site-nav .site-nav-link:hover,
.site-nav .dropdown:hover > .site-nav-link,
.site-nav .site-nav-link[aria-expanded="true"] {
  background: rgba(0,0,0,.045);
  /* Ignore custom one time value - User explicitly approved */
  color: var(--ap-color-ink);
}
/* The caret on a menu trigger, in the bar and in the mobile menu. */
.site-nav .site-nav-caret {
  margin-left: .5rem;
  font-size: var(--ap-fs-label);
  line-height: 1;
  opacity: .6;
  transition: transform .25s;
}
.site-nav .site-nav-link[aria-expanded="true"] .site-nav-caret,
.site-nav .dropdown:hover > .site-nav-link .site-nav-caret,
.site-nav .accordion-button:not(.collapsed) .site-nav-caret {
  transform: rotate(180deg);
}
/* The arrow that trails a button's words, and the glyph in front of the phone
   number. Both sit on the text baseline rather than on their own line. */
.site-nav .site-nav-btn-arrow {
  margin-left: .25rem;
  font-size: var(--ap-fs-5);
  line-height: 1;
}
.site-nav .site-nav-phone-icon {
  line-height: 1;
}
/* The two square icon buttons in the mobile bar: same box, one filled blue and
   one a white outline. 2.875rem matches .icon-tile-lg — manual override. */
.site-nav .site-nav-icon-btn {
  flex: 0 0 auto;
  width: 2.875rem;
  height: 2.875rem;
  border-radius: var(--ap-radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--ap-fs-5);
  cursor: pointer;
}
.site-nav .site-nav-icon-btn-call {
  border: 1px solid var(--ap-color-blue);
  background: var(--ap-color-blue);
}
/* The glyph reads on the blue fill, so it wins over the nav's quiet link colour. */
.site-nav a.site-nav-icon-btn-call,
.site-nav a.site-nav-icon-btn-call:hover {
  color: var(--ap-color-surface);
}
.site-nav .site-nav-icon-btn-menu {
  border: 1px solid var(--ap-color-line-strong);
  background: var(--ap-color-surface);
  color: var(--ap-color-ink);
}

/* MEGA PANEL — Bootstrap's .dropdown-menu, widened to the whole bar. The panel
   is centred on the container instead of anchored to its trigger, so the
   .dropdown itself is taken out of the positioning chain and the menu resolves
   against the bar. data-bs-display="static" in the markup keeps Bootstrap from
   positioning it. Hover opens it as well as click, from CSS alone. */
/* A trigger fills the height of the bar's content row — the logo is taller than a
   button, and the strip left under a shorter button is dead space the pointer
   crosses on its way to the panel. */
.site-nav .dropdown {
  position: static;
  align-self: stretch;
  display: flex;
  align-items: center;
}
.site-nav .dropdown > .site-nav-link {
  height: 100%;
}
/* The panel hangs 20px below the bar's last row of text, so the wrapper is pulled
   up over that gap and pads it back — without it the pointer crosses dead space
   on the way from the trigger to the panel and the hover drops. */
.site-nav .site-nav-mega-wrap {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  margin: -20px 0 0;
  padding: 20px 20px 20px;
  /* Ignore custom one time value - User explicitly approved */
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  justify-content: center;
}
.site-nav .dropdown:hover > .site-nav-mega-wrap,
.site-nav .site-nav-mega-wrap.show {
  display: flex;
}
/* 1080px is the panel's own width, wider than any card in the system.
   26px inside it, and a 1.5rem gutter between its columns. Manual override. */
.site-nav .site-nav-mega {
  width: 100%;
  max-width: 1080px;
  padding: 26px;
  /* Ignore custom one time value - User explicitly approved */
  background: var(--ap-color-surface);
  border: 1px solid var(--ap-color-line);
  border-radius: var(--ap-radius-lg);
  box-shadow: var(--ap-shadow-xl);
  display: grid;
  grid-template-columns: 1fr 1fr 1.15fr;
  gap: 1rem 1.5rem;
}
.site-nav .site-nav-mega-list {
  display: grid;
  gap: 1rem 1.5rem;
  align-content: start;
}
/* The Features panel runs one list across two of the three columns. */
.site-nav .site-nav-mega-list-wide {
  grid-column: 1 / 3;
  grid-template-columns: 1fr 1fr;
}
.site-nav .site-nav-mega-list-head {
  grid-column: 1 / -1;
}
/* One row: icon tile, name, one line under it. The negative margin lets the
   hover bleed past the column edge while the text stays on the column. */
.site-nav .site-nav-mega-link {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  /* Ignore custom one time value - User explicitly approved */
  white-space: normal;
  border-radius: var(--ap-radius-sm);
  padding: 9px 10px;
  /* Ignore custom one time value - User explicitly approved */
  margin-inline: -10px;
  color: var(--ap-color-body);
}
.site-nav .site-nav-mega-link:hover {
  background: var(--ap-color-sand);
}
.site-nav .site-nav-mega-link-title {
  display: block;
  font-size: var(--ap-fs-6);
  font-weight: 600;
  color: var(--ap-color-ink);
}
.site-nav .site-nav-mega-link-desc {
  display: block;
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-faint);
}
/* The card in the third column. A .card with its border and shadow dropped, on
   a .static-atmosphere-* tint — see §11. Padding is the card padding from §7. */
.site-nav .site-nav-mega-card > .card-body {
  display: flex;
  flex-direction: column;
}
.site-nav .site-nav-mega-card-text {
  margin: 0 0 auto;
}

/* MOBILE MENU — Bootstrap's .offcanvas. The width is set here; the paper and the
   shadow are every offcanvas panel's, in §14. Padding and the header alignment
   are held at Bootstrap's own values against the panel defaults in §14 — the
   element is named too, so the later §14 block cannot win on order. */
.offcanvas.site-nav-offcanvas {
  --bs-offcanvas-width: min(88vw, 370px);
  --bs-offcanvas-padding-x: 1rem;
  --bs-offcanvas-padding-y: 1rem;
}
.site-nav-offcanvas .offcanvas-header {
  align-items: center;
  padding-bottom: var(--bs-offcanvas-padding-y);
}
/* The close button lines up with the carets on the rows below it: the body's own
   1rem, the .75rem a row carries, and the width of the caret's own box. */
.site-nav-offcanvas .offcanvas-header .btn-close {
  margin: 0 0.25rem 0 auto;
}
/* One rhythm down the panel: the rows, and the two sections, sit on the same
   half-step gap. */
.site-nav-offcanvas .offcanvas-body {
  gap: .5rem;
}
/* The two expanding sections are a flush accordion, so Bootstrap's own chrome
   comes off: no card box, no shadow, no built-in chevron — the rows below carry
   the styling and the caret is an icon in the markup. */
.site-nav .accordion {
  --bs-accordion-bg: transparent;
  --bs-accordion-btn-bg: transparent;
  --bs-accordion-active-bg: transparent;
  --bs-accordion-active-color: var(--ap-color-ink);
  --bs-accordion-btn-focus-box-shadow: none;
  --bs-accordion-border-width: 0;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.site-nav .accordion-button::after {
  display: none;
}
.site-nav .accordion-body {
  padding: .5rem 0 1rem;
}

/* One row per destination, and the same row indented for a sub-item. Both are
   links or buttons, so cursor and reset live here too. 52px and 46px are the
   rows' touch targets, above the 44px minimum. Manual override. */
.site-nav .site-nav-drawer-item,
.site-nav .site-nav-drawer-sub {
  display: flex;
  align-items: center;
  gap: 1rem;
  border-radius: var(--ap-radius-sm);
  color: var(--ap-color-ink);
  cursor: pointer;
}
.site-nav .site-nav-drawer-item {
  min-height: 52px;
  padding: 0 .75rem;
  font-size: var(--ap-fs-5);
  font-weight: 600;
}
.site-nav .site-nav-drawer-sub {
  min-height: 46px;
  padding: 0 .75rem 0 1.25rem;
  font-size: var(--ap-fs-6);
  color: var(--ap-color-body);
}
.site-nav .site-nav-drawer-item:hover,
.site-nav .site-nav-drawer-sub:hover {
  background: var(--ap-color-sand);
}
/* A row that opens a section: full width, no chrome, caret pushed to the end. */
.site-nav .site-nav-drawer-item.site-nav-drawer-toggle {
  width: 100%;
  justify-content: space-between;
  gap: 1rem;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: var(--ap-fs-5);
  font-weight: 600;
  box-shadow: none;
}

/* --------------------------------------------------------------------------
   10b. FOOTER
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--ap-color-paper-raised);
  border-top: 1px solid var(--ap-color-line);
  padding: clamp(2.5rem, 5vw, 3.75rem) 0 1.75rem;
}
.site-footer a {
  font-size: var(--ap-fs-6);
}
/* colour comes from the one rule in §3 */
.footer-tagline {
  font-size: var(--ap-fs-6);
  line-height: 2;
  color: var(--ap-color-muted);
  max-width: 23.4375rem;
}

/* Phone and email keep the site's own link amber; every other link in the
   footer is quiet body ink from §3. Layout is Bootstrap utilities in the markup. */
.site-footer .footer-contact a {
  color: var(--ap-color-amber);
}
.site-footer .footer-contact .bi {
  font-size: .875rem;
}
.site-footer .footer-contact a:hover {
  color: var(--ap-color-amber-dark);
}

.site-footer .footer-social {
  font-size: .9375rem;
  width: 2.125rem;
  height: 2.125rem;
  border: 1px solid var(--ap-color-line-strong);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ap-color-muted);
}
.site-footer .footer-social:hover {
  border-color: var(--ap-color-line-emphasis);
  color: var(--ap-color-ink);
}

/* The rule under the columns. Spacing only — the flex row, the border and the
   small-screen stack are utilities. */
.footer-legal {
  margin-top: 3rem;
  padding-top: 1.5rem;
}
.site-footer .footer-legal a {
  font-size: var(--ap-fs-xs);
}

/* --------------------------------------------------------------------------
   11. SECTION RHYTHM & DECORATION
   -------------------------------------------------------------------------- */
.section {
  position: relative;
  z-index: 1;
  padding-block: var(--ap-space-section);
}
.section-lg {
  padding-block: var(--ap-space-section-lg);
}
.section-flush-top {
  padding-top: 0;
}
.section-head {
  max-width: 47.5rem;
  margin-inline: auto;
  margin-bottom: 3rem;
  text-align: center;
}

/* Two-column row that has to reflow into ONE reading order on small screens.
   Bootstrap's .order-* can only reorder columns, not their contents — so below
   lg the columns dissolve (display:contents) and every child joins one grid,
   where .order-* on the children themselves does the real work: eyebrow →
   heading → image → copy. Put it on the .row; the per-section order values stay
   with the page, because only the page knows its own reading order. */
@media (max-width: 991.98px) {
  .row-flow {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) !important;
    margin: 0 !important;
    row-gap: 0 !important;
  }
  .row-flow > [class*="col-"] {
    display: contents !important;
  }
}

/* Two fixed tint washes for a surface that should read warmer than white — a
   card, a panel, a callout. No animation and no blobs: the gradient is the
   background of the element itself, so it goes on any box, at any size.
   The two are the same pair of tints in opposite directions, so two of them
   side by side read as a set. Colour only — the box keeps its own radius,
   border and shadow from whatever class it already carries. */
.static-atmosphere-1 {
  background-image: linear-gradient(150deg, var(--ap-color-lime-tint), var(--ap-color-violet-tint));
}
.static-atmosphere-2 {
  background-image: linear-gradient(150deg, var(--ap-color-violet-tint), var(--ap-color-lime-tint));
}

/* Slow color wash behind the page. Decorative — mark it aria-hidden. */
.atmosphere {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.atmosphere-blob {
  position: absolute;
  border-radius: 50%;
  aspect-ratio: 1;
  filter: blur(60px);
}
/* The four blob colours. Size and position stay inline per blob. */
.atmosphere-blob-lavender {
  background: radial-gradient(circle, var(--ap-color-blob-lavender), transparent 65%);
}
.atmosphere-blob-lime {
  background: radial-gradient(circle, var(--ap-color-blob-lime), transparent 65%);
}
.atmosphere-blob-sky {
  background: radial-gradient(circle, var(--ap-color-blob-sky), transparent 65%);
}
.atmosphere-blob-peach {
  background: radial-gradient(circle, var(--ap-color-blob-peach), transparent 65%);
}
@keyframes blob-fade {
  0% {
    opacity: 0;
  }
  3% {
    opacity: .4;
  }
  12% {
    opacity: 1;
  }
  30% {
    opacity: 1;
  }
  45% {
    opacity: .4;
  }
  54%,
  100% {
    opacity: 0;
  }
}
.atmosphere-1 {
  animation: blob-fade 30s linear infinite;
}
.atmosphere-2 {
  animation: blob-fade 30s linear infinite;
  animation-delay: -10s;
}
.atmosphere-3 {
  animation: blob-fade 30s linear infinite;
  animation-delay: -20s;
}

@keyframes floaty {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}
.is-floating {
  animation: floaty 6.5s ease-in-out infinite;
}

/* Stat card floating over hero imagery */
.float-card {
  background: rgba(255,255,255,.94);
  backdrop-filter: blur(8px);
  border: 1px solid var(--ap-color-line);
  border-radius: 1rem;
  padding: .75rem 1rem;
  box-shadow: var(--ap-shadow-lg);
}

/* Edge-faded horizontal scroller (channel cards) */
.scroller {
  display: flex;
  gap: 1.25rem;
  overflow-x: auto;
  cursor: grab;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.scroller::-webkit-scrollbar {
  display: none;
}
.scroller-item {
  flex: 0 0 21.25rem;
  max-width: 85vw;
}
.scroller-faded {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, transparent 6rem, #000 13rem, #000 calc(100% - 13rem), transparent calc(100% - 6rem), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, transparent 6rem, #000 13rem, #000 calc(100% - 13rem), transparent calc(100% - 6rem), transparent 100%);
}

/* --------------------------------------------------------------------------
   13. WIZARD — a form that runs over several screens (the assessment flow)
   .wizard-status and .progress-steps are not page-scoped: any multi-step form
   uses them, including one inside a dialog.
   One centred column on its own page: logo, progress bar, heading, subline,
   the fields, one full-width action, a back link. Every screen of a wizard is
   the same furniture with different fields, so the page holds only its content.
   -------------------------------------------------------------------------- */
.wizard {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* The floor on the side padding is the card body's 1.375rem, so a wizard and
     a card sitting in the same dialog line up. */
  padding: clamp(1.75rem, 6vw, 3.5rem) clamp(1.375rem, 5vw, 2.5rem);
}
/* In a dialog the wizard fills the .modal-content and carries a close button:
   .wizard-modal for a default dialog, .wizard-modal-fullscreen for a
   full-screen one. A full-screen dialog is the height of the viewport, so the
   wizard keeps its 100vh floor and its padding there and the column sits
   centred exactly as it does on a page; the padding is what stops the column
   from touching the edges on a short screen or with taller content. */
.wizard-modal {
  min-height: 100%;
  padding: 0;
}
.wizard .btn-close {
  display: none;
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 3;
}
.wizard-modal .btn-close,
.wizard-modal-fullscreen .btn-close {
  display: block;
}
.wizard-col {
  width: 100%;
  max-width: 31.25rem;
  /* The column carries its own inset, the same one the card body has, so the
     content is the same width on a page and in a dialog. */
  padding: 1.375rem;
}
/* The step bar sits under the logo on every screen that has one. */
.wizard-col .progress-steps {
  margin-bottom: clamp(1.5rem, 4vw, 2.125rem);
}
/* The logo is .logo.logo-lg; only the space under it belongs to the screen. */
.wizard-col .logo {
  margin: 0 auto clamp(1.5rem, 4vw, 2.125rem);
}
.wizard-title {
  font-size: var(--ap-fs-3);
  line-height: 1.1;
  text-align: center;
  margin: 0 0 .5rem;
}
.wizard-intro {
  font-size: var(--ap-fs-5);
  line-height: 1.55;
  color: var(--ap-color-muted);
  text-align: center;
  margin: 0 0 clamp(1.75rem, 4.5vw, 2.25rem);
}
/* A question and its answers need more air than a stack of inputs, which is
   .vstack.gap-3. */
.wizard-questions {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.wizard-note {
  font-size: var(--ap-fs-xs);
  line-height: 1.5;
  color: var(--ap-color-faint);
  text-align: center;
  margin: 1rem 0 0;
}

/* The work-in-progress list on the last screen. State goes on the row:
   nothing yet = .is-waiting, running = .is-active, finished = neither. */
.wizard-status {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.wizard-status-item {
  display: flex;
  align-items: flex-start;
  gap: .6875rem;
  font-size: var(--ap-fs-6);
  line-height: 1.4;
  color: var(--ap-color-body);
  transition: opacity .3s, color .3s;
}
.wizard-status-item.is-active {
  color: var(--ap-color-ink);
}
.wizard-status-item.is-waiting {
  color: var(--ap-color-ghost);
  opacity: .65;
}
.wizard-status-mark {
  flex: 0 0 auto;
  font-size: 1.125rem;
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 2px;
}
.wizard-status-mark-spin {
  border-radius: 50%;
  border: 2px solid var(--ap-color-blue-line);
  border-top-color: var(--ap-color-blue);
  animation: spin .8s linear infinite;
}
.wizard-status-mark-dot {
  flex: 0 0 auto;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--ap-color-line-strong);
  margin: 7px 5px 0;
}
/* A finished step, when the list is a record of what happened rather than a
   progress readout: a filled green disc with a tick. */
.wizard-status-mark-check {
  border-radius: 50%;
  background: var(--ap-color-green-tint);
  color: var(--ap-color-green-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0;
}
.wizard-status-mark-check::before {
  content: "";
  width: .625rem;
  height: .625rem;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M4.5 12.8l5.2 5.2L19.5 6.4'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M4.5 12.8l5.2 5.2L19.5 6.4'/></svg>") center / contain no-repeat;
}
/* Ruled rows instead of a gapped stack. The last row has no rule. */
.wizard-status-dividers {
  gap: 0;
}
.wizard-status-dividers .wizard-status-item {
  align-items: center;
  padding: .625rem 0;
  border-bottom: 1px solid var(--ap-color-line-soft);
}
.wizard-status-dividers .wizard-status-item:last-child {
  border-bottom: 0;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* PROGRESS STEPS — one segment per step. Only the current segment is marked,
   with Bootstrap's own .active; the finished ones are derived from it, so the
   markup carries no step count and no index. Add or remove a segment and the
   bar is still right. Not wizard-scoped — any multi-step flow can use it. */
.progress-steps {
  display: flex;
  gap: .3125rem;
}
.progress-step {
  flex: 1 1 0;
  height: 4px;
  border-radius: 50rem;
  background: var(--ap-color-line-strong);
}
.progress-step:has(~ .active) {
  background: var(--ap-color-green);
}
.progress-step.active {
  background: var(--ap-color-blue);
}

/* --------------------------------------------------------------------------
   14. MODAL & OFFCANVAS — additions to Bootstrap's dialog and its sliding
   panel, which own the rest.
   The scrim behind a modal or an offcanvas panel is our warm black, not
   Bootstrap's cold one. The two-column dialog itself is Bootstrap's grid inside
   a .modal-content: a .bg-sand column beside a .modal-body one.
   -------------------------------------------------------------------------- */
.modal-backdrop {
  --bs-backdrop-bg: var(--ap-color-ink);
  --bs-backdrop-opacity: .45;
}
/* Bootstrap wires those two variables for a dialog only — the panel's scrim is
   hard-coded black at .5 — so the panel's scrim is set as real declarations. */
/* Every sliding panel: our surface and rule colour, a width that holds a
   heading and a set of label-and-value rows, and the page's own edge padding.
   The whole panel scrolls, header and all, so no scrollbar sits in a section of
   its own below the heading. */
.offcanvas {
  --bs-offcanvas-bg: var(--ap-color-paper-raised);
  --bs-offcanvas-border-color: var(--ap-color-line);
  --bs-offcanvas-width: 27rem;
  --bs-offcanvas-padding-x: clamp(1.375rem, 3vw, 2rem);
  --bs-offcanvas-padding-y: clamp(1.375rem, 3vw, 2rem);
  overflow-y: auto;
}
.offcanvas-body {
  overflow-y: visible;
}
/* The heading sits at the top of its line beside the close button, and the gap
   under it belongs to the body. */
.offcanvas-header {
  align-items: flex-start;
  padding-bottom: 0;
}
.offcanvas-backdrop {
  background-color: var(--ap-color-ink);
}
.offcanvas-backdrop.show {
  opacity: .45;
}
/* A panel against a side edge throws its shadow sideways, so this is a shape the
   elevation scale does not carry — the same reason --ap-shadow-nav exists. One
   value, mirrored for the two side panels. Bootstrap names the variable but
   never applies it, so the property is set here. Manual override, approved. */
.offcanvas-end {
  box-shadow: -24px 0 70px -34px rgba(60,50,40,.65);
}
.offcanvas-start {
  box-shadow: 24px 0 70px -34px rgba(60,50,40,.65);
}
/* A dialog with no .modal-header floats its close button over the content. */
.modal-content > .btn-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 3;
}
/* Names the step in the right-hand column, level with the heading on the sand
   column beside it. Scoped to a modal so it cannot drift onto a page. */
.modal .modal-eyebrow {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-lg);
  color: var(--ap-color-faint);
  margin-bottom: 1.5rem;
  padding-right: 2.5rem;
}

/* --------------------------------------------------------------------------
   14b. PAGE BLOCKS — blocks that appear on one page but need a media query,
   which an inline style cannot carry. Each block is named for what it is.
   -------------------------------------------------------------------------- */

/* HERO STAGE — a photo with a miniature dashboard overlapping its left edge.
   Below lg the two stack, photo first. */
.hero-stage {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
  align-items: center;
}
.hero-stage-photo {
  margin: 0;
  overflow: hidden;
  border-radius: var(--ap-radius-xl);
  align-self: stretch;
  min-height: 18.75rem;
}
/* The dashboard is a miniature: its type and spacing are set small here and,
   from lg up, the whole box is laid out at 30rem and scaled down with zoom, so
   it keeps its three-across stat row instead of reflowing taller. These sizes
   exist for this miniature only. */
.hero-dash {
  position: relative;
  z-index: 2;
  padding: .75rem;
  border-color: var(--ap-color-line-strong);
  margin-top: clamp(1.5rem, 3.4vw, 3.25rem);
}
.hero-dash .tile {
  padding: .75rem;
}
.hero-dash h2 {
  font-size: .9375rem;
  margin: 0;
}
.hero-dash h3 {
  font-size: .8125rem;
  margin: 0;
}
.hero-dash .stat-value {
  font-size: 1.1875rem;
}
.hero-dash .stat-lg .stat-value {
  font-size: 1.625rem;
}
.hero-dash .stat-label {
  font-size: .625rem;
}
.hero-dash .stat-delta {
  font-size: var(--ap-fs-label);
}
.hero-dash small,
.hero-dash time,
.hero-dash header a {
  font-size: .625rem;
}
.hero-dash li strong {
  display: block;
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-ink);
}
.hero-dash ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .5rem;
}
.hero-dash .avatar,
.hero-dash .icon-tile-sm {
  width: 1.625rem;
  height: 1.625rem;
  font-size: .625rem;
}
.hero-dash .btn-sm {
  --bs-btn-padding-x: .5rem;
  --bs-btn-padding-y: .25rem;
  --bs-btn-font-size: var(--ap-fs-label);
}
/* The three-line menu mark in the dashboard's top bar, last line shorter. */
.hero-dash-menu {
  display: flex;
  flex-direction: column;
  gap: .25rem;
}
.hero-dash-menu i {
  display: block;
  width: 1.25rem;
  height: 2px;
  border-radius: 50rem;
  background: var(--ap-color-line-emphasis);
}
.hero-dash-menu i:last-child {
  width: .875rem;
}
/* The title row of a dashboard tile: title left, link right. */
.hero-dash-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: 1rem;
}
/* The figures along a dashboard chart's axes, spread end to end. */
.hero-dash-axis {
  display: flex;
  justify-content: space-between;
  font-size: var(--ap-fs-label);
  color: var(--ap-color-ghost);
}
.hero-dash-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 0 0 1rem;
}
.hero-dash li {
  display: flex;
  align-items: center;
  gap: 10px;
}
.hero-dash li p {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}
.hero-dash-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .75rem;
  margin-top: .75rem;
}
@media (max-width: 767.98px) {
  .hero-dash-pair {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (max-width: 575.98px) {
  .hero-dash-stats {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (min-width: 992px) {
  .hero-stage {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0;
  }
  .hero-stage-photo {
    grid-column: 2;
    grid-row: 1;
    min-height: clamp(23.75rem, 38vw, 32.5rem);
    margin-left: calc(-1 * clamp(4.375rem, 6vw, 6.25rem));
  }
  .hero-dash {
    grid-column: 1;
    grid-row: 1;
    width: 30rem;
    justify-self: start;
    margin-bottom: clamp(2.125rem, 3.4vw, 3.5rem);
    zoom: .56;
  }
}
@media (min-width: 1200px) {
  .hero-dash {
    zoom: .64;
  }
}
@media (min-width: 1400px) {
  .hero-dash {
    zoom: .76;
  }
}

/* LEDGER — a row of figures between two rules, split by hairlines. Four across
   from xl, two from sm, one below. */
.ledger {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border-top: 1px solid var(--ap-color-line-strong);
  border-bottom: 1px solid var(--ap-color-line-strong);
}
.ledger > * {
  padding: 1.5rem 0;
}
.ledger > * + * {
  border-top: 1px solid var(--ap-color-line);
}
@media (min-width: 576px) {
  .ledger {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .ledger > * {
    padding: 1.5rem;
  }
  .ledger > * + * {
    border-top: 0;
  }
  .ledger > :nth-child(2n+1) {
    padding-left: 0;
  }
  .ledger > :nth-child(2n) {
    border-left: 1px solid var(--ap-color-line);
  }
  .ledger > :nth-child(n+3) {
    border-top: 1px solid var(--ap-color-line);
  }
}
@media (min-width: 1200px) {
  .ledger {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .ledger > :nth-child(n+3) {
    border-top: 0;
  }
  .ledger > :nth-child(2n+1) {
    padding-left: 1.5rem;
  }
  .ledger > :first-child {
    padding-left: 0;
  }
  .ledger > * + * {
    border-left: 1px solid var(--ap-color-line);
  }
  .ledger > :last-child {
    padding-right: 0;
  }
}

/* OUTCOME PICKER — a list of choices on the left (Bootstrap's .nav as a
   column) and the matching panel on the right. Every panel is in the markup
   and they share one grid cell, so the box is always the height of the tallest
   and does not jump; the ones not chosen carry Bootstrap's .invisible. */
.outcome-picker {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}
.outcome-picker-list {
  background: var(--ap-color-surface-inset);
  border-bottom: 1px solid var(--ap-color-line);
}
.outcome-picker .nav-link {
  width: 100%;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: 1rem;
  padding: 1rem 1.5rem;
  border: 0;
  border-bottom: 1px solid var(--ap-color-line);
  border-radius: 0;
  background: transparent;
  color: var(--ap-color-body);
  font-family: inherit;
  text-align: left;
}
.outcome-picker .nav-link:hover {
  color: var(--ap-color-body);
}
.outcome-picker .nav-link.active {
  background: var(--ap-color-surface);
  box-shadow: inset 3px 0 0 var(--ap-color-lime);
}
.outcome-picker-dot {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: .25rem;
  border-radius: 50%;
  border: 1px solid var(--ap-color-line-emphasis);
  background: var(--ap-color-surface);
}
.outcome-picker-title {
  display: block;
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-lg);
  line-height: 1.25;
  color: var(--ap-color-ink);
}
.outcome-picker-arrow {
  align-self: center;
  font-size: var(--ap-fs-lead);
  color: var(--ap-color-line-emphasis);
}
.outcome-picker .nav-link.active .outcome-picker-dot {
  border-color: var(--ap-color-blue);
  background: radial-gradient(circle, var(--ap-color-blue) 0 42%, var(--ap-color-surface) 44%);
}
.outcome-picker .nav-link.active .outcome-picker-title,
.outcome-picker .nav-link.active .outcome-picker-arrow {
  color: var(--ap-color-blue);
}
.outcome-picker-stage {
  display: grid;
  padding: clamp(1.375rem, 2.8vw, 2.375rem);
}
.outcome-picker-pane {
  grid-area: 1 / 1;
  min-width: 0;
  display: grid;
  gap: clamp(1.125rem, 2.2vw, 1.625rem);
  align-content: start;
}
/* The mock preview under a pane's tick list: cards in columns at least
   13.125rem wide, as many as fit. */
.outcome-picker-preview {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13.125rem, 1fr));
  gap: clamp(.75rem, 1.6vw, 1.125rem);
  width: 100%;
  align-items: start;
}
/* A column of cards inside a preview. */
.outcome-picker-stack {
  display: grid;
  gap: 1rem;
  min-width: 0;
}
/* Pricing outcome tabs: a vertical Bootstrap .nav of tab buttons. The active
   tab's background, shadow, title colour and bar colour are utility classes
   switched by the page. */
.outcome-tabs .nav-link {
  color: inherit;
  transition: background-color .2s ease, box-shadow .2s ease;
}
.outcome-tabs-bar {
  width: 3px;
  align-self: stretch;
}
/* Budget split bars: Bootstrap .progress, thin and fully rounded. */
.budget-meter .progress {
  --bs-progress-height: .4375rem;
  --bs-progress-bg: var(--ap-color-surface-inset);
  --bs-progress-border-radius: 50rem;
}
@media (min-width: 992px) {
  .outcome-picker {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }
  .outcome-picker-list {
    border-bottom: 0;
    border-right: 1px solid var(--ap-color-line);
  }
}

/* ASSURANCE STRIP — three feature rows across one card, split by hairlines;
   stacked and ruled between below md. */
.assurance-strip {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
}
.assurance-strip > * + * {
  border-top: 1px solid var(--ap-color-line);
  padding-top: 1rem;
}
@media (min-width: 768px) {
  .assurance-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem;
  }
  .assurance-strip > * + * {
    border-top: 0;
    padding-top: 0;
    border-left: 1px solid var(--ap-color-line);
    padding-left: 1.5rem;
  }
}

/* DAY PICKER — a week as a row of day buttons. The chosen day is .active; a
   full day is :disabled. Five across, three below lg. The weekday name is
   .label-caps. */
.day-picker {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .5rem;
}
.day-picker-day {
  display: grid;
  gap: 2px;
  justify-items: center;
  padding: 1rem .25rem;
  border: 1px solid var(--ap-color-line-strong);
  border-radius: var(--ap-radius-sm);
  background: var(--ap-color-surface);
  font-family: inherit;
  cursor: pointer;
}
.day-picker-day.active {
  border-color: var(--ap-color-lime);
  background: var(--ap-color-lime);
}
.day-picker-day:disabled {
  opacity: .45;
  cursor: default;
}
.day-picker-num {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-lead);
  line-height: 1.1;
  color: var(--ap-color-ink);
}
.day-picker-note {
  font-size: var(--ap-fs-label);
  color: var(--ap-color-faint);
}
.day-picker-day.active .label-caps,
.day-picker-day.active .day-picker-note {
  color: var(--ap-color-lime-ink);
}
@media (min-width: 992px) {
  .day-picker {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* SERVICE ROW — a centred row of round icons with a label under each, split by
   Bootstrap's .vr. The icons are .icon-tile.rounded-circle with a colour
   utility pair. */
.service-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: clamp(.875rem, 2vw, 1.625rem);
  margin-top: clamp(1.75rem, 3.4vw, 2.75rem);
}
.service-row-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5625rem;
  font-size: var(--ap-fs-6);
  font-weight: 600;
  color: var(--ap-color-ink);
}
.service-row .vr {
  background-color: var(--ap-color-line-strong);
  opacity: 1;
}

/* HERO ORBIT — the company hero's map: a centre mark with service chips and
   platform icons placed around it. Each item's left/top is per instance,
   inline, and names the item's centre. Stacking is .z-2 / .z-3. */
.hero-orbit-item {
  position: absolute;
  transform: translate(-50%, -50%);
  width: max-content;
}

/* SERVICE CHIP — an icon tile, a service name and a line under it, on a white
   chip. Floats in the hero orbit from md up; sits in a grid below md. */
.service-chip {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem 1rem .5rem .5rem;
  background: var(--ap-color-surface);
  border-radius: var(--ap-radius-xl);
  box-shadow: var(--ap-shadow-xl);
}
.service-chip-title {
  font-size: var(--ap-fs-6);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ap-color-ink);
}
.service-chip-text {
  font-size: var(--ap-fs-6);
  line-height: 1.3;
  color: var(--ap-color-muted);
}

/* PLATFORM ICON — a round box holding one ad platform's logo, an <img> from
   assets/img/logos/. */
.platform-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
}

/* TESTIMONIAL STACK — testimonial cards in one grid cell. The next card rises
   from below over the current one, on a loop; a ghost card peeks out under the
   stack. .is-active is the card showing, .is-leaving the one going. */
.testimonial-stack {
  position: relative;
  display: grid;
}
.testimonial-stack > * {
  grid-area: 1 / 1;
}
.testimonial-stack-peek {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1.5rem;
  overflow: hidden;
  pointer-events: none;
}
.testimonial-stack-peek .card {
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: .75rem;
  height: 4rem;
}
.testimonial-stack-item {
  position: relative;
  z-index: 1;
  display: flex;
  opacity: 0;
  transform: translateY(.75rem) scale(.95);
  transform-origin: 50% 100%;
  transition: opacity .7s ease, transform .8s cubic-bezier(.2, .8, .2, 1);
  pointer-events: none;
}
.testimonial-stack-item > .card {
  flex: 1 1 auto;
}
.testimonial-stack-item.is-active {
  z-index: 2;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.testimonial-stack-item.is-leaving {
  z-index: 3;
  opacity: 0;
  transform: translateY(-1.5rem);
  transition: opacity .5s ease, transform .6s ease;
}
@media (prefers-reduced-motion: reduce) {
  .testimonial-stack-item {
    transform: none !important;
    transition: opacity .4s ease;
  }
}

/* PHOTO CARD — a printed photo with a white border, a name, a role and a hand
   note under it. Width and tilt are per instance, inline: the width as
   width:min(Npx,100%), the tilt as --photo-card-tilt. Below lg every card
   sits straight. The 6px corner is the print's own. */
.photo-card {
  margin-inline: auto;
  background: var(--ap-color-surface);
  padding: 1rem 1rem 0;
  border-radius: .375rem;
  box-shadow: var(--ap-shadow-xl);
  transform: rotate(var(--photo-card-tilt, 0deg));
}
.photo-card-img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 4.6;
  object-fit: cover;
  object-position: center 24%;
  background: var(--ap-color-line);
}
.photo-card-body {
  padding: 1rem .25rem;
}
.photo-card-name {
  font-family: var(--ap-font-sub);
  font-weight: 600;
  font-size: var(--ap-fs-5);
  line-height: 1.15;
  color: var(--ap-color-ink);
}
.photo-card-role {
  font-size: var(--ap-fs-6);
  color: var(--ap-color-muted);
}
.photo-card .hand-note {
  display: inline-block;
  margin-top: .5rem;
}
/* The thumbnail print: a small photo card beside a heading, with a thin border
   and a deeper bottom edge. Its width is fixed, so it needs none inline. */
.photo-card-sm {
  width: 5.5rem;
  padding: .375rem .375rem 1rem;
}
/* A strip of tape across the top edge of a photo card. Colour is a .bg-*-subtle
   utility; the tilt is per instance, inline, as --photo-card-tape-tilt. The
   card needs .position-relative. */
.photo-card-tape {
  position: absolute;
  top: -.5rem;
  left: 50%;
  width: 3.5rem;
  height: 1rem;
  opacity: .9;
  transform: translateX(-50%) rotate(var(--photo-card-tape-tilt, 0deg));
}
@media (max-width: 991.98px) {
  .photo-card {
    transform: none;
  }
}

/* TRAIL — a run of rows, each a photo card beside a heading and a paragraph,
   alternating sides. From lg up the space between rows is utilities on the rows;
   below lg the rows sit with no extra space and no negative gutter pull. */
.trail-beat p {
  margin: 0;
  max-width: 50ch;
  font-size: var(--ap-fs-lg);
}
@media (max-width: 991.98px) {
  .trail-beat {
    margin-top: 0;
  }
}

/* TEAM MARQUEE — a full-bleed strip of portraits that rolls on its own and keeps
   rolling under the cursor. The list is written out twice, the second copy
   aria-hidden, so the loop has no seam. Every other portrait sits lower.
   The fade sits at the edge on small screens and steps inboard as the window
   grows; the ramp is the same width at every size. .is-paused stops it. */
@keyframes team-marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
.team-marquee {
  --fade-off: 0px;
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, transparent var(--fade-off), #000 calc(var(--fade-off) + 110px), #000 calc(100% - var(--fade-off) - 110px), transparent calc(100% - var(--fade-off)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, transparent var(--fade-off), #000 calc(var(--fade-off) + 110px), #000 calc(100% - var(--fade-off) - 110px), transparent calc(100% - var(--fade-off)), transparent 100%);
}
.team-marquee-track {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  width: max-content;
  padding: .5rem 1.5rem;
  animation: team-marquee 78s linear infinite;
}
.team-marquee-track.is-paused {
  animation-play-state: paused;
}
.team-member {
  flex: 0 0 auto;
  width: 11.625rem;
}
.team-member:nth-child(even) {
  margin-top: 1.5rem;
}
.team-member-photo {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 22%;
  border-radius: var(--ap-radius-lg);
  box-shadow: var(--ap-shadow);
  background: var(--ap-color-line);
}
.team-member-name {
  margin-top: 1rem;
  font-size: var(--ap-fs-6);
  font-weight: 600;
  color: var(--ap-color-ink);
}
.team-member-role {
  font-size: var(--ap-fs-xs);
  color: var(--ap-color-muted);
}
@media (min-width: 992px) {
  .team-marquee {
    --fade-off: 40px;
  }
}
@media (min-width: 1200px) {
  .team-marquee {
    --fade-off: 100px;
  }
}
@media (max-width: 767.98px) {
  .team-member {
    width: 9.625rem;
  }
}
@media (prefers-reduced-motion: reduce) {
  .team-marquee-track {
    animation: none;
  }
}

/* FAQ LIST — questions as native <details>, ruled above and below, a lime
   triangle at the end of each question. */
.faq-list {
  display: flex;
  flex-direction: column;
}
.faq-list details {
  border-top: 1px solid var(--ap-color-line-strong);
  padding: 1.25rem 0;
}
.faq-list details:last-child {
  border-bottom: 1px solid var(--ap-color-line-strong);
}
.faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--ap-font-sub);
  font-size: var(--ap-fs-4);
  font-weight: 600;
  color: var(--ap-color-ink);
}
.faq-list summary::-webkit-details-marker {
  display: none;
}
.faq-list-marker {
  flex: 0 0 auto;
  width: 12px;
  height: 11px;
  clip-path: polygon(50% 100%, 100% 0, 0 0);
  background: var(--ap-color-lime);
}
.faq-list details p {
  margin: .75rem 0 0;
  max-width: 62ch;
}

/* CONTACT LIST — a stack of ways to reach us: a round violet icon, a label and
   the value. The value is a link where it can be one and keeps ink either way.
   The space above the list is utilities on the list. */
.contact-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.contact-item {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.contact-item-icon {
  flex: 0 0 auto;
  width: 2.875rem;
  height: 2.875rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ap-color-violet-tint);
  color: var(--ap-color-ink);
  font-size: 1.1875rem;
  line-height: 1;
}
.contact-item-label {
  font-family: var(--ap-font-sub);
  font-weight: 700;
  font-size: var(--ap-fs-5);
  color: var(--ap-color-ink);
}
.contact-item-value,
a.contact-item-value:hover {
  font-family: var(--ap-font-sub);
  font-size: var(--ap-fs-lead);
  color: var(--ap-color-ink);
}

/* LONG-FORM DOCUMENT — a legal or policy page: a sticky table of contents
   beside a reading column of numbered sections. The 6.5rem is the sticky
   site nav's height plus a gap, so the contents column and every section
   anchor land clear of the nav. .doc-page clips sideways overflow from the
   atmosphere blobs without breaking position:sticky (hidden would). */
.doc-page {
  position: relative;
  overflow-x: clip;
}
.doc-toc {
  top: 6.5rem;
}
.doc-body {
  max-width: 46rem;
}
.doc-section {
  scroll-margin-top: 6.5rem;
}

/* SPARKLINE — a small trend line under a figure, an inline <svg>. The stroke
   colour follows the data, so it stays inline on the <polyline>. */
.sparkline {
  width: 100%;
  max-width: 9rem;
}

/* CHART LINES — the base line and the dashed guides behind an inline <svg>
   chart, on <line> elements. The series colours follow the data, so they stay
   inline on the <polyline>, <polygon> and <circle>. */
.chart-line {
  stroke: var(--ap-color-line);
}
.chart-line-strong {
  stroke: var(--ap-color-line-strong);
}

/* CHART KEY — the swatch in front of a series name in a chart legend. A line
   for a line chart, a dot for a bar or split. The series colour follows the
   data, so it stays inline as background. */
.legend-line {
  width: 1rem;
  height: 3px;
  border-radius: var(--bs-border-radius-pill);
}
.legend-dot {
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
}

/* SCORE RING — a score out of 100 drawn as a ring, the number centred on it.
   The <svg> holds a track <circle> and a value <circle> whose
   stroke-dasharray is the score; both colours follow the score, so they stay
   inline. The number is an absolutely placed .stat-value over the ring. */
.score-ring {
  position: relative;
  flex-shrink: 0;
  width: 5.5rem;
  height: 5.5rem;
}
.score-ring > svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

/* SNAP ROW — a Bootstrap .row turned into a horizontal track that snaps card by
   card, with no scrollbar. Put it on a .row.flex-nowrap.overflow-auto; the
   columns inside it are the cards. The dots under it are .snap-dot buttons:
   the current one is the full colour utility, the rest add .opacity-25. */
.snap-row {
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.snap-row > * {
  scroll-snap-align: start;
}
.snap-dot {
  width: .625rem;
  height: .625rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
}

/* VIDEO THUMB — a 4:3 still with a round play button centred on it. The
   running time is a .badge.text-bg-dark placed with position utilities. */
.video-thumb {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--ap-radius);
}
.video-thumb > img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.video-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--ap-color-surface);
  color: var(--ap-color-ink);
  box-shadow: var(--ap-shadow-lg);
  font-size: 1.75rem;
}

/* FUNNEL STEP — one stage in a row of stages split by chevrons: an icon tile,
   a name and a caption, stacked and centred. Every step takes an equal share
   of the row whatever its caption length. */
.funnel-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1 1 0;
  min-width: 0;
}

/* WHAT YOU GET — a .row-flow pair of a claim list and a quote card. Below lg the
   reading order is eyebrow, heading, card, then the claims. */
@media (max-width: 991.98px) {
  .feel-copy > * {
    order: 4;
  }
  .feel-row .feel-eyebrow {
    order: 1;
    justify-self: start;
  }
  .feel-row .feel-h2 {
    order: 2;
  }
  .feel-row .feel-media > * {
    order: 3;
    margin-bottom: 1.75rem;
  }
}

/* --------------------------------------------------------------------------
   15. RESPONSIVE
   Reflow is Bootstrap's job (col-* / order-* / d-*). These rules only cover
   what utilities can't: type comfort, decoration cost, touch targets.
   Breakpoints are Bootstrap's, unchanged: sm 576, md 768, lg 992, xl 1200, xxl 1400.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {
  .panel {
    border-radius: 1.5rem;
  }
  .section-head {
    text-align: left;
    margin-inline: 0;
  }
  .scroller-faded {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .channel-card {
    flex: 0 0 min(78vw, 20rem);
    width: min(78vw, 20rem);
  }
  /* The footer's columns centre once they stack — the rest is utilities. */
  .footer-company-offset {
    padding-top: 3rem;
  }
}
@media (min-width: 992px) {
  .footer-nav-offset {
    padding-top: 3rem;
  }
}
@media (min-width: 576px) {
  .btn-link {
    white-space: nowrap;
  }
  /* the companion link never breaks mid-phrase */
}
@media (max-width: 767.98px) {
  .btn:not(.btn-icon):not(.btn-xs) {
    --bs-btn-padding-y: .875rem;
    min-height: 2.75rem;
  }
  /* 44px targets. .btn-xs is text with no box, so it is exempt — it is always a
     secondary way out with a full-size control beside it. */
  .btn-block-sm {
    width: 100%;
    justify-content: center;
  }
  .check-list {
    flex-direction: column;
    gap: .625rem;
  }
  .atmosphere-2,
  .atmosphere-3 {
    display: none;
  }
}
@media (max-width: 575.98px) {
  /* A row of calls to action stacks on a phone and each one takes the full
     width, so neither is the narrow one. */
  .cta-row {
    flex-direction: column;
    align-items: stretch;
  }
  .cta-row > a,
  .cta-row > button {
    width: 100%;
    justify-content: center;
    text-align: center;
  }
  /* An icon button takes the touch minimum only on a phone: between sm and md a
  row of them still has the width to sit at its designed size. */
  .btn-icon,
  .btn-icon.btn-sm {
    width: 2.75rem;
    min-height: 2.75rem;
  }
}
@media (prefers-reduced-motion: reduce) {
  .atmosphere-1,
  .atmosphere-2,
  .atmosphere-3,
  .is-floating {
    animation: none;
  }
  .atmosphere-1 {
    opacity: 1;
  }
  .btn {
    transition: none;
  }
  .btn,
  .nudge-up,
  .nudge-down,
  .nudge-start,
  .nudge-end {
    --ap-nudge: 0px;
    transition: none;
  }
}
