.elementor-kit-6{--e-global-color-primary:#6EC1E4;--e-global-color-secondary:#54595F;--e-global-color-text:#7A7A7A;--e-global-color-accent:#61CE70;--e-global-typography-primary-font-family:"Roboto";--e-global-typography-primary-font-weight:600;--e-global-typography-secondary-font-family:"Roboto Slab";--e-global-typography-secondary-font-weight:400;--e-global-typography-text-font-family:"Roboto";--e-global-typography-text-font-weight:400;--e-global-typography-accent-font-family:"Roboto";--e-global-typography-accent-font-weight:500;background-color:#0A0A0C;color:#F4F4F7;}.elementor-kit-6 e-page-transition{background-color:#FFBC7D;}.elementor-kit-6 a{color:#6D9CFF;}.elementor-section.elementor-section-boxed > .elementor-container{max-width:1140px;}.e-con{--container-max-width:1140px;}.elementor-widget:not(:last-child){--kit-widget-spacing:20px;}.elementor-element{--widgets-spacing:20px 20px;--widgets-spacing-row:20px;--widgets-spacing-column:20px;}{}h1.entry-title{display:var(--page-title-display);}.site-header .site-branding{flex-direction:column;align-items:stretch;}.site-header{padding-inline-end:0px;padding-inline-start:0px;}.site-footer .site-branding{flex-direction:column;align-items:stretch;}@media(max-width:1024px){.elementor-section.elementor-section-boxed > .elementor-container{max-width:1024px;}.e-con{--container-max-width:1024px;}}@media(max-width:767px){.elementor-section.elementor-section-boxed > .elementor-container{max-width:767px;}.e-con{--container-max-width:767px;}}:root { --bg:#0A0A0C; --bg-raised:#101014; --line:#22222A; --line-hi:#31313C; --fg:#F4F4F7; --fg-muted:#A2A2AF; --fg-dim:#7D7D8B; --accent:#2C70F5; --accent-hi:#6D9CFF; --accent-deep:#1B4FC4; --panel:#E4E9F3; --panel-hi:#FFFFFF; --panel-line:#C6CEDE; --panel-line-hi:#A9B4CA; --font-sans:Manrope; --e-gv-a7e3086:Inter; --e-gv-c66aaf4:JetBrains Mono; --t-body:1.125rem; --t-sm:0.9375rem; --t-xs:0.8125rem; --t-lede:clamp(1.1rem,1.85vw,1.375rem); --gutter:clamp(20px,5vw,48px); --t-h3:clamp(1.2rem,1.9vw,1.5rem); --t-h2:clamp(1.9rem,4vw,3rem); --t-h1:clamp(2.4rem,5.6vw,4.25rem); --t-display:clamp(2.6rem,6vw,5rem); --lh-tight:1.06; --lh-snug:1.25; --lh-body:1.65; --ls-tight:-0.03em; --ls-snug:-0.02em; --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:24px; --s-6:32px; --s-7:48px; --s-8:64px; --s-section:clamp(80px,12vw,180px); --wrap:1200px; --measure:58ch; --radius:12px; --radius-lg:20px; --radius-xl:28px; --wrap-narrow:760px; --panel-chip:#CFD6E5; --panel-ink:#0D1016; --panel-ink-2:#3E4655; --panel-ink-3:#596175; --panel-accent:#1546C4; --accent-wash:rgba(44,112,245,.10); --accent-line:rgba(44,112,245,.32); --btn-bg:#7FA8FF; --btn-bg-hi:#A3C4FF; --btn-ink:#06070A; --btn-dark-bg:#11151D; --btn-dark-bg-hi:#252C3B; --btn-dark-ink:#F5F7FB; --btn-ghost-line:#6E6E7E; --s-9:96px; --s-10:128px; --stars:#B8860B; --field-invalid-line:#B3261E; --field-err-text:#FF9C8B; --formok-bg:#DCF0E4; --formok-line:#9CCBAF; --formok-ink:#0C3D24; --formerr-bg:#FBE0DC; --formerr-line:#E0A79F; --formerr-ink:#5E1811; }
/* Start custom CSS *//* Mono stack for eyebrows, labels and numerals (D21). */
.elementor .logo-role,
.elementor .foot-col-title,
.elementor .eyebrow,
.elementor .eyebrow-plain,
.elementor .proof-item,
.elementor .card-i,
.elementor .outcome-client,
.elementor .tag,
.elementor .process-n,
.elementor .worktile-sector {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

/* Hero accent glow — was .hero::before. */
.elementor .hero-sec::before {
  content: "";
  position: absolute;
  inset-block-start: -30%;
  inset-inline: -15% auto;
  inline-size: 90%;
  block-size: 130%;
  pointer-events: none;
  background: radial-gradient(50% 42% at 28% 26%, rgba(44,112,245,.22) 0%, transparent 70%);
}

/* CTA band glow — was .ctaband::before. */
.elementor .ctaband::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(46% 78% at 50% 0%, rgba(44,112,245,.20) 0%, transparent 72%);
}

.elementor .h1-display em { font-style: normal; color: var(--accent-hi); }
.elementor .proof-item strong { color: var(--fg); font-weight: 700; }

/* Prose: inline links and emphasis inside body paragraphs. */
.elementor .prose-p a { color: var(--accent-hi); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.elementor .prose-p strong { color: var(--fg); font-weight: 700; }

/* Card headings that wrap a link inherit the card ink rather than link blue. */
.elementor .card-h3 a { color: inherit; text-decoration: none; }
.elementor .card-h3 a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Tick lists inside pillar cards — real <ul><li> with the accent square marker. */
.elementor .ticks ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.elementor .ticks li { position: relative; padding-inline-start: 24px; }
.elementor .ticks li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.6em;
  inline-size: 7px;
  block-size: 7px;
  border-radius: 2px;
  background: var(--panel-accent);
}

/* About portrait. aspect-ratio / object-fit / sticky live here, not in a global
   class, because values with no atomic equivalent can corrupt a whole rule (D26).
   860px matches site.css, which Elementor's named breakpoints do not offer. */
.elementor .portrait { aspect-ratio: 4 / 5; position: sticky; top: 110px; }
.elementor .portrait .portrait-img { width: 100%; height: 100%; object-fit: cover; object-position: center 18%; }
@media (max-width: 860px) {
  .elementor .portrait { position: static; aspect-ratio: 1 / 1; max-width: 210px; }
}

/* FAQ: hide the native marker and open on a lighter ground, as site.css does. */
.elementor .faq-summary { list-style: none; }
.elementor .faq-summary::-webkit-details-marker { display: none; }
.elementor .faq-item[open] { background-color: var(--panel-hi); }

/* Scroll reveal — fade and rise, matching site.css's .reveal (18px, .6s).
   CSS scroll-driven animation rather than Elementor Interactions, whose runtime
   is not enqueued on this install (D28). Guards: @supports, prefers-reduced-motion,
   and no JavaScript dependency at all.

   KNOWN AND ACCEPTED (D44, decided D46) — do not "fix" without asking Michael:
   animation-timeline: view() is continuous, unlike site.css's one-shot
   IntersectionObserver reveal, so a section that is only partly scrolled into view
   rests at opacity ~0.54. That composites --fg-muted down to 3.8:1 and links to
   3.65:1, both below WCAG AA, and costs 8-9 Lighthouse Accessibility points on
   /about/, /services/seo-aeo-geo/ and /case-studies/gcpay/ (91-92 vs the 95 budget
   in CLAUDE.md section 11). The fade was judged worth it. The fix, if that ever
   changes, is to drop `opacity` from this keyframe and animate the rise only. */
@keyframes mb-reveal {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .elementor .reveal-sec {
      animation: mb-reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }
  }
}

/* Client marquee — two rows at different speeds, second reversed.
   animation/@keyframes are dropped by the converter and mask-image has no
   control, so both live here (D26).

   TWO BUGS FIXED HERE (D47) — keep both or the marquee silently stops:

   1. `--gap` IS RESERVED BY ELEMENTOR. It sets `--gap: 20px 20px` on atomic
      elements for its own flex-gap control, which beat the value set on .mq.
      The keyframe then evaluated to calc(-50% - 20px 20px/2) — invalid, so the
      `to` transform was dropped and the animation ran at a constant identity
      transform: playState "running", zero movement. It also explains the 20px
      marquee gap logged as D27. Namespaced to --mq-gap. Never use --gap here.
   2. The track is a flex item, so flex-shrink:1 squeezed it to the container
      width (1004px) and `width: max-content` never took effect, leaving a
      3545px scrollWidth. translateX(-50%) is relative to the element's own box,
      so the travel distance was wrong too. `flex: 0 0 auto` pins it. */
.elementor .mq {
  --mq-gap: clamp(36px,6vw,80px);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.elementor .mq .mq-track {
  width: max-content;
  flex: 0 0 auto;
  gap: var(--mq-gap);
  padding-inline-end: var(--mq-gap);
  animation: mb-slide 46s linear infinite;
  will-change: transform;
}
.elementor .mq-slow .mq-track { animation-duration: 68s; }
.elementor .mq-rev .mq-track { animation-direction: reverse; }
.elementor .mq:hover .mq-item { color: var(--fg-muted); }

@keyframes mb-slide {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-50% - var(--mq-gap)/2)); }
}

@media (prefers-reduced-motion: reduce) {
  .elementor .mq .mq-track { animation: none; transform: none; }
}/* End custom CSS */