/** Shopify CDN: Minification failed

Line 3055:11 Unexpected "<"

**/
:root {
  --p:       #0a1838;
  --p-2:     #14365e;
  --bgd:     #0a1632;

  --a:       #f0614a;
  --a-2:     #fd9786;
  --a-ink:   #cd2a10;

  --m:       #5b6b7c;
  --mm:      #68758a;
  --bg:      #fcfcfd;
  --bga:     #f3f5f8;
  --br:      #e6eaf0;
  --br-2:    #eef1f5;
  --ph:      #6b7789;

  --on-dark:      #fff;
  --on-dark-2:    rgba(255, 255, 255, .85);
  --on-dark-3:    rgba(255, 255, 255, .70);
  --on-dark-br:   rgba(255, 255, 255, .12);
  --on-dark-fill: rgba(255, 255, 255, .06);

  --grad:     linear-gradient(135deg, #0a1838 0%, #14365e 100%);
  --grad-alt: linear-gradient(135deg, #14365e 0%, #1d4a7d 100%);
  --grad-a:   linear-gradient(135deg, var(--a) 0%, var(--a-2) 100%);

  --grad-a-btn: var(--grad-a);

  --shadow-sm: 0 1px 2px   rgba(10, 24, 56, .06);
  --shadow:    0 2px 8px   rgba(10, 24, 56, .08);
  --shadow-lg: 0 12px 28px rgba(10, 24, 56, .10);
  --shadow-xl: 0 24px 56px rgba(10, 24, 56, .14);

  --r:       16px;
  --r-lg:    22px;
  --r-btn:   10px;
  --r-btn-lg: 50px;
  --r-pill:  999px;

  --container: 1440px;
  --gutter:    20px;

  --section-y: clamp(56px, 6vw, 112px);
  --font: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --fs-h1-hero: clamp(26px, 4.4vw, 54px);
  --fs-h1:      clamp(25px, 3.8vw, 46px);
  --fs-h2:      clamp(20px, 2.6vw, 34px);
  --fs-h3:      clamp(17px, 1.4vw, 20px);
  --fs-h4:      15px;
  --fs-body:    16px;
  --fs-lede:    clamp(16px, 1.15vw, 19px);
  --fs-card:    15px;
  --fs-btn:     15px;
  --fs-eyebrow: 12px;

  --ease:       cubic-bezier(.4, 0, .2, 1);
  --ease-panel: cubic-bezier(.16, 1, .3, 1);
  --dur-fast:   .15s;
  --dur:        .22s;
  --dur-slow:   .32s;
}

@media (max-width: 900px) {
  :root { --gutter: 16px; }
}


*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--p);
  font-family: var(--font);
  font-optical-sizing: auto;
  font-size: var(--fs-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; height: auto; }

svg text { font-family: var(--font); }
button, input, select, textarea { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  margin: 0; font-weight: 700; color: var(--p);
  text-wrap: balance;
  overflow-wrap: break-word;
}
h1 { font-size: var(--fs-h1); line-height: 1.08; letter-spacing: -.02em; }
h2 { font-size: var(--fs-h2); line-height: 1.15; letter-spacing: -.01em; }
h3 { font-size: var(--fs-h3); font-weight: 700; letter-spacing: -.01em; }
h4 { font-size: var(--fs-h4); font-weight: 700; }

p { margin: 0 0 1em; max-width: 56ch; text-wrap: pretty; overflow-wrap: break-word; }
p:last-child { margin-bottom: 0; }

a { color: var(--a-ink); text-underline-offset: .18em; }
a:hover { color: var(--a); }

.lede {
  font-size: var(--fs-lede);
  line-height: 1.6;
  letter-spacing: -.005em;
  color: var(--m);
  max-width: 64ch;
}

.stat, .num, [data-count] { font-feature-settings: 'tnum'; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sr-hidden{visibility:hidden;}

.sr-only:focus-visible {
  position: fixed; z-index: 300;
  top: 12px; inset-inline-start: 12px;
  width: auto; height: auto;
  margin: 0; padding: 12px 18px;
  overflow: visible; clip: auto;
  background: var(--p); color: #fff;
  border-radius: var(--r-btn);
  box-shadow: var(--shadow-lg);
  font-size: 15px; font-weight: 600;
  text-decoration: none;
  outline: 2px solid var(--a);
  outline-offset: 2px;
}

html { scroll-padding-top: 88px; }

.wrap {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section--center > .wrap { margin-inline: auto; }
.section--center .section__head { text-align: center; margin-inline: auto; }
.section--center .section__head .lede { margin-inline: auto; }
.wrap--left { margin-inline: 0; }

.section { padding-block: var(--section-y); }
.section--alt  { background: var(--bga); }
.section--navy { background: var(--bgd); }
.section--grad { background: var(--grad); }

.section--navy, .section--grad { color: var(--on-dark-2); }
.section--navy h1, .section--navy h2, .section--navy h3, .section--navy h4,
.section--grad h1, .section--grad h2, .section--grad h3, .section--grad h4 {
  color: var(--on-dark);
}
.section--navy .lede, .section--grad .lede { color: var(--on-dark-2); }

.section__head { max-width: 760px; margin-bottom: 44px; }
.section__head > h2 { margin-block: 12px 14px; }

.grid { display: grid; gap: 20px; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }

.eyebrow {
  display: inline-block;
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--a-ink);
}
.section--navy .eyebrow, .section--grad .eyebrow { color: var(--a); }

.overline {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .15em;
  color: var(--mm);
  font-feature-settings: 'tnum';
}
.section--navy .overline, .section--grad .overline { color: var(--on-dark-3); }

.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-btn-lg);
  font-size: var(--fs-btn); font-weight: 600; letter-spacing: -.01em;
  text-decoration: none; cursor: pointer;
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn:hover { transform: translateY(-2px); }
.btn-p { background: var(--grad-a-btn); color: #fff; box-shadow: var(--shadow-sm); }
.btn-p:hover { box-shadow: var(--shadow-lg); color: #fff; }

.btn-s { background: transparent; border-color: var(--br); color: var(--p); }
.btn-s:hover { border-color: rgba(240, 97, 74, .25); color: var(--p); }

.btn-w {
  background: var(--on-dark-fill);
  border-color: var(--on-dark-br);
  color: #fff;
  backdrop-filter: blur(8px);
}
.btn-w:hover { background: rgba(255, 255, 255, .12); color: #fff; }

.mw-btn {
  display: inline-flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100%;
  padding: 12px 18px;
  border: 1px solid var(--br); border-radius: var(--r-btn);
  color: var(--p); text-decoration: none; font-weight: 600; font-size: var(--fs-btn);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.mw-btn:hover { border-color: rgba(240, 97, 74, .25); transform: translateY(-2px); color: var(--p); }
.mw-arrow { width: 18px; height: 18px; transition: transform var(--dur) var(--ease); }
.mw-btn:hover .mw-arrow { transform: translateX(4px); }
.rtl .mw-btn:hover .mw-arrow { transform: translateX(-4px) scaleX(-1); }
.rtl .mw-arrow { transform: scaleX(-1); }

.sh-pill, .mi-cat, .mp-cat {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  font-size: 13px; font-weight: 600;
  background: var(--bga); color: var(--m);
  border: 1px solid var(--br-2);
}
.mp-cat-blue { background: rgba(20, 54, 94, .08);  color: var(--p-2); border-color: rgba(20, 54, 94, .14); }
.mp-cat-navy { background: rgba(10, 24, 56, .06);  color: var(--p);   border-color: rgba(10, 24, 56, .12); }

.hh-chips { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.hh-chips li {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px; border-radius: var(--r-pill);
  background: var(--on-dark-fill); border: 1px solid var(--on-dark-br);
  color: #fff; font-size: 13px; font-weight: 600;
}
.hh-chips svg { width: 15px; height: 15px; }

.card, .practice, .rs-card, .bento-card, .step-card, .app-card2 {
  background: #fff;
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.card:hover, .practice:hover, .rs-card:hover, .bento-card:hover, .step-card:hover, .app-card2:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(240, 97, 74, .25);
}

.practice { padding: 26px; }
.p-icon {
  display: grid; place-items: center;
  width: 44px; height: 44px; margin-bottom: 16px;
  border-radius: var(--r-btn);
  background: var(--bga); color: var(--a-ink);
}
.p-icon svg { width: 21px; height: 21px; }
.practice h3 { margin-bottom: 8px; }
.p-desc { font-size: var(--fs-card); line-height: 1.6; color: var(--m); }
.bento { display: grid; gap: 20px; grid-template-columns: repeat(4, 1fr); }
.bento-card { padding: 26px; position: relative; overflow: hidden; }
.bento-card--wide { grid-column: span 2; }
.bento-card--full { grid-column: span 4; }
.bento-card > .overline { position: absolute; top: 22px; inset-inline-end: 24px; }
.bento-card h3 { margin-bottom: 10px; padding-inline-end: 48px; }
.bento-card p { font-size: var(--fs-card); color: var(--m); }
@media (max-width: 900px) {
  .bento { grid-template-columns: minmax(0, 1fr); }
  .bento-card--wide, .bento-card--full { grid-column: span 1; }
}
.rs-card { padding: 26px; }
.stars { color: var(--a-ink); letter-spacing: .12em; margin-bottom: 12px; }
.rs-card p { font-size: var(--fs-card); color: var(--p); }
.who { display: flex; align-items: center; gap: 12px; margin-top: 18px; }
.avatar {
  display: grid; place-items: center;flex-shrink:0;
  width: 40px; height: 40px; border-radius: var(--r-pill);
  background: var(--grad); color: #fff;
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
}
.who strong { display: block; font-size: 14px; }
.who span { font-size: 12.5px; color: var(--mm); }
.step-card { padding: 24px; cursor: pointer; }
.step-card__head { display: flex; align-items: flex-start; gap: 14px; }
.step-card__head h4 { flex: 1; }
.step-toggle {
  display: grid; place-items: center;
  width: 28px; height: 28px; flex: none;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  background: transparent; color: var(--m); cursor: pointer;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.step-card.is-open .step-toggle { transform: rotate(45deg); border-color: var(--a); color: var(--a-ink); }
.step-card__body {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-panel);
}
.step-card.is-open .step-card__body { grid-template-rows: 1fr; }
.step-card__body > div { overflow: hidden; }
.step-card__body p { font-size: var(--fs-card); color: var(--m); padding-top: 12px; }
.sh-form-card {
  background: #fff;
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: 28px;
}
.sh-row { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); }
.sh-field { margin-bottom: 14px; position: relative; }
.sh-lab { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 600; color: var(--p); }

.sh-field input, .sh-field select, .sh-field textarea {
  width: 100%;
  padding: 11px 14px;
  background: var(--bg);
  border: 1.5px solid var(--br);
  border-radius: var(--r-btn);
  color: var(--p);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.sh-field input::placeholder, .sh-field textarea::placeholder { color: var(--ph); }

.sh-field input:focus, .sh-field select:focus, .sh-field textarea:focus {
  outline: none;
  border-color: var(--a);
  box-shadow: 0 0 0 4px rgba(240, 97, 74, .12);
}
.sh-field.has-error input, .sh-field.has-error select, .sh-field.has-error textarea {
  border-color: var(--a-ink);
}
.sh-error { display: block; margin-top: 5px; font-size: 12.5px; color: var(--a-ink); font-weight: 600; }
.sh-field-area textarea { resize: vertical; min-height: 96px; }
.sh-count {
  position: absolute; bottom: 10px; inset-inline-end: 12px;
  font-size: 11.5px; color: var(--mm); font-feature-settings: 'tnum';
}

.sh-submit { width: 100%; justify-content: center; margin-top: 4px; }
.sh-privacy {
  display: flex; align-items: center; gap: 8px;
  margin-top: 14px; font-size: 12.5px; color: var(--mm);
}
.sh-privacy svg { width: 15px; height: 15px; flex: none; }
.sh-trap { position: absolute; left: -9999px; opacity: 0; pointer-events: none; }
.sh-error[data-kind] {
  margin-top: 0;
  margin-bottom: 18px;
  padding: 12px 14px;
  border-radius: var(--r-btn);
  font-size: var(--fs-card);
  font-weight: 500;
  line-height: 1.5;
}
.sh-error[data-kind="ok"] {
  color: var(--p);
  background: rgba(20, 54, 94, .07);
  border-inline-start: 3px solid var(--p-2);
}
.sh-error[data-kind="again"] {
  color: var(--m);
  background: var(--bga);
  border-inline-start: 3px solid var(--br);
}
.sh-error[data-kind="error"] {
  color: var(--a-ink);
  background: rgba(240, 97, 74, .08);
  border-inline-start: 3px solid var(--a-ink);
}
.sh-error[hidden] { display: none; }
.hdr {
  position: fixed; inset-inline: 0; top: 0; z-index: 100;
  padding: 14px var(--gutter);
  transition: padding var(--dur) var(--ease);
}
.hdr__inner {
  max-width: var(--container); margin-inline: auto;
  display: flex; align-items: center; gap: 20px;
  padding: 10px 12px 10px 20px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              padding var(--dur) var(--ease);
}
.hdr.is-stuck .hdr__inner {
  background: rgba(252, 252, 253, .86);
  backdrop-filter: blur(14px);
  border-color: var(--br);
  box-shadow: var(--shadow);
  padding: 6px 8px 6px 16px;
}
.hdr.is-stuck .hdr__logo { font-size: 15px; }
.hdr.is-stuck .hdr__nav a,
.hdr.is-stuck .hdr__nav-btn { font-size: 14px; padding-block: 6px; }

.hdr__logo { display: flex; align-items: center; gap: 9px; text-decoration: none; color: #fff; font-weight: 700; letter-spacing: -.02em; }
.hdr.is-stuck .hdr__logo { color: var(--p); }

.hdr__nav { display: flex; gap: 4px; margin-inline: auto; }
.hdr__nav a {
  padding: 8px 13px; border-radius: var(--r-btn);
  color: var(--on-dark-2); text-decoration: none;
  font-size: 15px; font-weight: 500;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.hdr__nav a:hover { background: var(--on-dark-fill); color: #fff; }
.hdr.is-stuck .hdr__nav a { color: var(--p-2); }
.hdr.is-stuck .hdr__nav a:hover { background: var(--bga); color: var(--p); }

.hdr__burger { display: none; }

@media (max-width: 1023px) {
  .hdr__nav { display: none; }
  .hdr__burger {
    display: flex; justify-content: center;align-items:center;padding:0;
    width: 40px; height: 40px; margin-inline-start: auto;
    background: var(--on-dark-fill); border: 1px solid var(--on-dark-br);
    border-radius: var(--r-btn); color: #fff; cursor: pointer;
  }
  .hdr.is-stuck .hdr__burger { background: var(--bga); border-color: var(--br); color: var(--p); }
}

.drawer {
  position: fixed; inset: 0; z-index: 200;
  background: var(--bgd); color: #fff;
  padding: 80px var(--gutter) 40px;
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease-panel);
  overflow-y: auto;
}
.rtl .drawer { transform: translateX(-100%); }

.scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(10, 22, 50, .42);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.modal__panel::-webkit-scrollbar {
    display: none;
}
.scrim.is-on { opacity: 1; visibility: visible; transition-delay: 0s; }
.modal_lay .scrim.is-on {
    opacity: 0;
    visibility: hidden;
}
.ftr__meta dd {
    display: flex;
    flex-direction: column;
}

@media (prefers-reduced-motion: reduce) {
  .scrim { transition: none; }
}
.drawer.is-open { transform: translateX(0); }
.drawer a { display: block; padding: 14px 0; color: #fff; text-decoration: none; font-size: 20px; font-weight: 700; border-bottom: 1px solid var(--on-dark-br); }
.drawer__close { position: absolute; top: 22px; inset-inline-end: var(--gutter); width: 40px; height: 40px;padding:0; display: flex;justify-content:center; align-items: center; background: var(--on-dark-fill); border: 1px solid var(--on-dark-br); border-radius: var(--r-btn); color: #fff; cursor: pointer; }
.hero {
  position: relative; overflow: hidden;
  background: var(--grad); color: var(--on-dark-2);
  padding-block: clamp(140px, 18vh, 190px) var(--section-y);
}
.hero__particles {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__particles .particles-js-canvas-el { display: block; }
.hero__particles::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to right,
    rgba(10, 24, 56, .62) 0%,
    rgba(10, 24, 56, .42) 26%,
    rgba(10, 24, 56, .10) 46%,
    rgba(10, 24, 56, 0) 62%
  );
}
.hero > .wrap { position: relative; z-index: 1; }

.hero h1 { font-size: var(--fs-h1-hero); line-height: 1.07; color: #fff; margin-block: 18px 16px; max-width: 18ch; }
/* The sub-heading under an app page's h1: the sentence that says what the app
   does, now that the h1 is the app's name. Sized between the h1 and the lede so
   the three lines read as a descending hierarchy rather than two ledes. */
.hero__sub {
  font-size: var(--fs-h2); line-height: 1.2; letter-spacing: -.01em;
  font-weight: 600; color: #fff; margin-block: -6px 14px; max-width: 26ch;
}
.hero .lede { color: var(--on-dark-2); max-width: 52ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }

.hero__badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: var(--r-pill);
  background: var(--on-dark-fill); border: 1px solid var(--on-dark-br);
  font-size: var(--fs-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em; color: #fff;
}
.hero__badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--a); }

.stats {
  display: grid; gap: 24px; margin-top: 64px;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
}
.stat { border-top: 1px solid var(--on-dark-br); padding-top: 16px; }
.stat b { display: block; font-size: clamp(20px, 2.4vw, 30px); font-weight: 700; letter-spacing: -.03em; color: #fff; }
.stat span { display: block; margin-top: 4px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--on-dark-3); }

.marquee { overflow: hidden; padding-block: 36px; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee__track {
  --mq-gap: 64px;
  display: flex; gap: var(--mq-gap); width: max-content;
  animation: marquee-rtl 38s linear infinite;
}
@media (hover: hover) {
  .marquee:hover .marquee__track { animation-play-state: paused; }
}
.marquee img { height: 26px; width: auto; filter: grayscale(1); opacity: .5; transition: opacity var(--dur) var(--ease), filter var(--dur) var(--ease); }
.marquee img:hover { filter: grayscale(0); opacity: 1; }

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

.marquee__track.is-reverse { animation-name: marquee-ltr; }

.rtl .marquee__track { animation-name: marquee-ltr; }
.rtl .marquee__track.is-reverse { animation-name: marquee-rtl; }
.marquee--cards { padding-block: 12px; }
.marquee--cards .marquee__track { --mq-gap: 20px; align-items: stretch; }
.marquee--cards .rs-card { width: 340px; flex: none; }
.marquee-stack { display: grid; gap: 20px; }

@media (max-width: 700px) {
 
  .marquee--cards .rs-card { width: 280px; }
}

.tabs { display: inline-flex; gap: 4px; padding: 4px; border-radius: var(--r-pill); background: var(--on-dark-fill); border: 1px solid var(--on-dark-br); }
.tabs button {
  padding: 8px 18px; border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--on-dark-2);
  font-size: 14px; font-weight: 600; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.tabs button[aria-selected="true"] { background: var(--grad-a); color: #fff; }

.slider { position: relative; }
.slider__track {
  display: flex; gap: 20px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; padding-bottom: 4px;
}
.slider__track::-webkit-scrollbar { display: none; }
.slider__track > * { scroll-snap-align: start; flex: 0 0 clamp(240px, 30%, 340px); }
.slider__nav { display: flex; gap: 8px; margin-top: 24px; }
.slider__nav button {
  width: 40px; height: 40px; display: flex; justify-content:center; align-items: center;padding:0;
  border-radius: var(--r-pill); cursor: pointer;
  background: var(--on-dark-fill); border: 1px solid var(--on-dark-br); color: #fff;
  transition: background var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.slider__nav button:hover { background: rgba(255, 255, 255, .14); }
.slider__nav button[disabled] { opacity: .35; cursor: default; }
.section--alt .slider__nav button, .section:not(.section--navy):not(.section--grad) .slider__nav button {
  background: #fff; border-color: var(--br); color: var(--p);
}

.acc__item { border-bottom: 1px solid var(--br); }
.acc__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  width: 100%; padding: 20px 0;
  background: none; border: 0; cursor: pointer; text-align: start;
  font-size: var(--fs-h4); font-weight: 700; color: var(--p);
}
.acc__icon { flex: none; width: 22px; height: 22px; color: var(--m); transition: transform var(--dur) var(--ease); }
.acc__item.is-open .acc__icon { transform: rotate(45deg); color: var(--a-ink); }
.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-slow) var(--ease-panel); }
.acc__item.is-open .acc__panel { grid-template-rows: 1fr; }
.acc__panel > div { overflow: hidden; }
.acc__panel p { color: var(--m); padding-bottom: 20px; }

.modal {
  position: fixed; inset: 0; z-index: 300;
  display: grid; place-items: center; padding: var(--gutter);
  background: rgba(10, 22, 50, .82); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.modal.is-open { opacity: 1; visibility: visible; }
.modal__box { width: min(880px, 100%); aspect-ratio: 16 / 9; border-radius: var(--r); overflow: hidden; background: #000; }
.modal__box iframe, .modal__box video { width: 100%; height: 100%; border: 0; }
.modal__close { position: absolute; top: 20px; inset-inline-end: 20px; width: 42px; height: 42px; display: grid; place-items: center; border-radius: var(--r-pill); background: var(--on-dark-fill); border: 1px solid var(--on-dark-br); color: #fff; cursor: pointer; }

.ftr { background: var(--bgd); color: var(--on-dark-3); padding-block: 72px 0; }
.ftr__cols {
  display: grid; gap: 40px 32px;
  grid-template-columns: 0.85fr 1.15fr 1.15fr 0.95fr 1.1fr;
}
.ftr .ftr__h { color: #fff; margin-bottom: 16px; font-size: 15px; }
.ftr .ftr__h + ul { margin-bottom: 30px; }
.ftr ul { list-style: none; margin: 0; padding: 0; }
.ftr li { margin-bottom: 10px; }
.ftr a { color: var(--on-dark-3); text-decoration: none; font-size: 14.5px; transition: color var(--dur) var(--ease); }
.ftr a:hover { color: #fff; }
.ftr__meta { margin-bottom: 20px; }
.ftr__meta dt {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .13em;
  color: var(--on-dark-4, rgba(255, 255, 255, .5)); margin-bottom: 5px;
}
.ftr__meta dd { margin: 0 0 16px; font-size: 14.5px; color: #fff; }
.ftr__note { font-size: 13px; line-height: 1.6; color: var(--on-dark-3); max-width: 30ch; margin: 20px 0 0; }
.ftr__bottom {
  margin-top: 56px; padding-block: 26px;
  border-top: 1px solid var(--on-dark-br);
  display: flex; flex-wrap: wrap; gap: 16px 24px; align-items: center; justify-content: space-between;
}
.ftr__mark { font-size: 19px; font-weight: 700; letter-spacing: -.02em; color: #fff; text-decoration: none; }
.ftr__mark span { color: var(--a-2); }   /* --a is 3.79:1 on this navy; --a-2 is 5.79:1 */
.ftr__legal { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 13.5px; }
.ftr__copy {
  padding-block: 20px;
  border-top: 1px solid var(--on-dark-br);
  text-align: center; font-size: 13px;
}

@media (max-width: 1180px) {
  .ftr__cols { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 700px) {
  .ftr__cols { grid-template-columns: repeat(2, 1fr); gap: 32px 24px; }
  .ftr__bottom { justify-content: flex-start; }
}
@media (max-width: 460px) {
  .ftr__cols { grid-template-columns: minmax(0, 1fr); }
}

.tlx-motion [data-rv] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.tlx-motion [data-rv].is-in { opacity: 1; transform: none; }

/* ABOVE THE FOLD IS NEVER HIDDEN.
   Every page's LCP element sits inside `section.hero` — the h1, the lede, the
   CTAs, the stat block — and every one of them carries data-rv, so the rule
   above was holding the largest text node on the page at opacity: 0 until JS
   added .is-in, or until motion-boot's 2.5s failsafe gave up. Measured on
   mobile: homepage LCP 4397ms of which 4073ms (93%) was render delay; service
   page 3886ms of which 3260ms (84%). A text node does not take four seconds to
   paint unless something is suppressing it — this was the something.

   With .hero exempt the LCP element paints on the first frame, from CSS alone,
   with no JS anywhere in its path. Reveal still observes these elements and
   still adds .is-in; this rule just makes both states identical, so nothing
   below the fold changes and no markup had to move.

   Do NOT "simplify" this by deleting the rule and stripping data-rv from the
   hero markup instead. That is the same fix spread across two liquid sections
   and 29 static pages, and the next hero anyone writes will miss it. Anything
   that can be the LCP element belongs on this side of the line.

   Mirrored in assets/css/style.css — change one, change the other. */
.tlx-motion .hero [data-rv],
.tlx-motion .hero[data-rv] {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ...AND `.hero` IS NOT THE ONLY THING ABOVE THE FOLD IN THIS THEME.
   The static site can rely on .hero because all 30 of its pages open with one.
   The theme cannot: five templates open with a plain `<section class="section">`
   whose <h1 data-rv="0"> is the LCP element, and the rule above misses every
   one of them —

     page.json                 -> main-page              (generic page fallback)
     cart.json                 -> main-cart
     collection.json           -> main-collection
     list-collections.json     -> main-list-collections
     search.json               -> main-search

   So the exemption is anchored to POSITION, not to a class name: whatever
   section renders first inside <main id="main"> is above the fold by
   definition, and owns LCP whether or not anyone remembered to call it a hero.
   Shopify wraps each section in <div id="shopify-section-…">, so the first
   child of <main> is that wrapper; on the static site it is the <section>
   itself. `#main` is an id, so this outranks the `[data-rv]` hide rule above
   without !important.

   The cost, stated plainly: the first section loses its reveal animation
   entirely, including any card grid inside it (the collection and search
   result grids are the notable ones). That is the same trade the .hero rule
   already makes — .hero exempts hero__media at data-rv="5" too — and it is the
   right way round: LCP is correctness, the stagger is decoration. Narrow this
   to `.section__head [data-rv]` if the grids' animation is ever worth more
   than robustness, but be aware that reintroduces the "the next section anyone
   writes will miss it" failure this rule exists to prevent.

   Mirrored in assets/css/style.css — change one, change the other. */
.tlx-motion #main > :first-child [data-rv],
.tlx-motion #main > :first-child[data-rv] {
  opacity: 1;
  transform: none;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .12s !important;
  }
  .btn:hover, .card:hover, .practice:hover, .rs-card:hover,
  .bento-card:hover, .step-card:hover, .mw-btn:hover { transform: none !important; }
  [data-rv] { opacity: 1 !important; transform: none !important; }
}

.rtl .stat { text-align: right; }
.rtl .slider__nav svg { transform: scaleX(-1); }

.mega-panel {
  position: absolute;
  inset-inline-start: 50%;
  transform: translateX(-50%) translateY(-6px);
  top: calc(100% + 10px);
  width: min(1120px, calc(100vw - 2 * var(--gutter)));
  background: var(--bg);
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  padding: 28px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .18s var(--ease), transform .18s var(--ease), visibility 0s linear .18s;
  z-index: 60;
}

.mega-panel.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition: opacity .18s var(--ease), transform .18s var(--ease), visibility 0s linear 0s;
}

.mega-inner {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(4, 1fr);
}

.mega-col__head {
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--br-2);
}

.mega-link {
  display: block;
  padding: 8px 10px;
  margin-inline: -10px;
  border-radius: var(--r-btn);
  text-decoration: none;
  transition: background .15s var(--ease);
}
.mega-link:hover { background: var(--bga); }
.mega-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--a);
}

.mega-link__name {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: var(--p);
  letter-spacing: -.005em;
}
.mega-link:hover .mega-link__name { color: var(--a-ink); }
.mega-link__desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 2px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--m);
  max-width: none;
}
.mega-badge {
  display: inline-block;
  margin-inline-start: 6px;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .1);
  color: var(--a-ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  vertical-align: middle;
}
.mega-badge--review {
  background: rgba(20, 54, 94, .1);
  color: var(--p-2);
}
.mega-promo {
  background: var(--bga);
  border-radius: var(--r);
  padding: 20px;
  align-self: start;
}
.mega-promo h4 { margin-bottom: 8px; }
.mega-promo p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--m);
  max-width: none;
  margin-bottom: 14px;
}

@media (max-width: 1023px) {
  .mega-panel { display: none; }
}

.hdr__nav-btn {
  display: flex; align-items: center; gap: 5px;
  padding: 8px 13px; border-radius: var(--r-btn);
  background: none; border: 0; cursor: pointer;
  color: var(--on-dark-2);
  font-family: inherit; font-size: 15px; font-weight: 500;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.hdr__nav-btn:hover { background: var(--on-dark-fill); color: #fff; }
.hdr.is-stuck .hdr__nav-btn { color: var(--p-2); }
.hdr.is-stuck .hdr__nav-btn:hover { background: var(--bga); color: var(--p); }

.hdr.is-stuck .hdr__inner > .btn-w {
  background: var(--p);
  border-color: var(--p);
  color: #fff;
  font-size: 14px;
  padding: 9px 16px;
}
.hdr.is-stuck .hdr__inner > .btn-w:hover {
  background: var(--p-2);
  border-color: var(--p-2);
}

@media (max-width: 1023px) { .hdr__nav-btn { display: none; } }

.drawer__group > button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 14px 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--on-dark-br);
  font-family: inherit;
  font-size: 20px;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
  text-align: start;
}
.drawer__group > button svg {
  transition: transform .2s var(--ease);
  flex: none;
}
.drawer__group > button[aria-expanded="true"] svg { transform: rotate(180deg); }

.drawer__panel {
  display: none;
  padding-block: 6px 14px;
  padding-inline-start: 12px;
}
.drawer__panel.is-open { display: block; }
.drawer__panel a {
  display: block;
  padding: 8px 0;
  border-bottom: 0;
  font-size: 16px;
  font-weight: 500;
  color: var(--on-dark-2);
  text-decoration: none;
}
.drawer__panel a:hover { color: var(--a); }

.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--m);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.marquee__item:hover { color: var(--p); }
.marquee__mark { width: 22px; height: 22px; flex: none; }

.app-carousel .slider__track { gap: 24px; align-items: stretch; }
.app-carousel .slider__track > * { flex: 0 0 clamp(260px, 46vw, 560px); }
@media (max-width: 900px) {
  .app-carousel .slider__track > * { flex: 0 0 calc(100% - 8px); }
}
 .svc-index__card--feature {
        grid-template-columns: minmax(0, 1fr) !important;
        gap: 24px !important;
    }
        .svc-index__card--feature {
        padding: 24px !important;
    }
  .svc_block_wrap{opacity:1;}

.app-carousel__controls {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 16px; margin-top: 24px;
}
.app-carousel .slider__nav { margin-top: 0; }

.slider__dots { display: flex; flex-wrap: wrap; gap: 16px; }
.slider__dot {
  width: 9px; height: 9px; padding: 0; flex: none;
  border-radius: var(--r-pill); border: 0; cursor: pointer;
  background: var(--br);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.slider__dot:hover { background: rgba(240, 97, 74, .35); }
.slider__dot.is-active { background: var(--a-ink); transform: scale(1.2); }
.slider__dot:focus-visible { outline: 2px solid var(--a); outline-offset: 2px; }

.app-card2 {
  display: grid; grid-template-columns: 1.05fr 1fr; gap: 28px;
  padding: 32px; align-items: stretch;
}
.section_spacing_top{padding-top: 68px;}
@media (max-width: 900px) {
  .section_spacing_top{padding-top: var(--svc-gap);}
  .app-card2 { grid-template-columns: minmax(0, 1fr); padding: 26px; }
}

.app-card2__info { display: flex; flex-direction: column; min-width: 0; }

.app-card2__head { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.app-card2__icon {
  display: grid; place-items: center; flex: none;
  width: 64px; height: 64px; border-radius: var(--r);
  background: var(--grad-a);
  color: #fff;
}
.app-card2__icon svg { width: 30px; height: 30px; }

.app-card2__name { font-size: 19px; font-weight: 700; letter-spacing: -.01em; margin-bottom: 4px; }
.app-card2__desc { font-size: var(--fs-card); line-height: 1.6; color: var(--m); max-width: none; margin-bottom: 20px; }

.app-feat { list-style: none; margin: 0 0 22px; padding: 0; display: flex; flex-direction: column; gap: 12px; }

.app-feat li {
  display: flex; align-items: flex-start; gap: 10px;
  font-size: var(--fs-card); line-height: 1.6; color: var(--m);
}
.app-feat__icon {
  margin-top: .18em;
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .1); color: var(--a-ink);
}
.app-feat__icon svg { width: 13px; height: 13px; }

.app-card2__more {
  position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: auto; align-self: flex-start;
  font-size: var(--fs-card); font-weight: 600;
  text-decoration: none;
}
.app-card2__more svg { width: 16px; height: 16px; transition: transform var(--dur) var(--ease); }
.app-card2__more:hover svg { transform: translateX(4px); }
.rtl .app-card2__more:hover svg { transform: translateX(-4px) scaleX(-1); }
.rtl .app-card2__more svg { transform: scaleX(-1); }

.app-mock {
  background: var(--bga); border: 1px solid var(--br-2); border-radius: var(--r);
  overflow: hidden; display: flex; flex-direction: column; min-height: 220px;
}
.app-mock__bar {
  display: flex; align-items: center; gap: 6px;
  padding: 12px 14px; border-bottom: 1px solid var(--br-2); background: #fff;
}
.app-mock__bar span { width: 8px; height: 8px; border-radius: 50%; background: var(--br); }
.app-mock__bar em {
  margin-inline-start: 8px; font-style: normal;
  font-size: 12px; font-weight: 700; color: var(--p);
}
.app-mock__body {
  flex: 1; position: relative;
  padding: 44px 16px 16px; display: flex; flex-direction: column; gap: 10px; justify-content: center;
}
.app-mock__body::before, .app-mock__body::after {
  content: ''; position: absolute; top: 16px;
  height: 10px; border-radius: var(--r-pill);
  background: var(--br-2); border: 1px solid var(--br);
}
.app-mock__body::before { inset-inline-start: 16px; width: 74px; }
.app-mock__body::after { inset-inline-start: 98px; width: 46px; }

.app-mock__opt-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--m); }

.app-mock__field { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--r-btn); background: #fff; border: 1px solid var(--br-2); }
.app-mock__field i { width: 24px; height: 24px; flex: none; border-radius: var(--r-btn); background: rgba(240, 97, 74, .12); }
.app-mock__field > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.app-mock__field b { font-size: 11px; font-weight: 600; color: var(--p); }
.app-mock__field u { font-size: 9px; font-weight: 600; color: var(--m); text-decoration: none; }
.app-mock__field u.is-warn { color: var(--a-ink); font-weight: 700; }

.app-mock__search { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: var(--r-pill); background: #fff; border: 1px solid var(--br); }
.app-mock__search i { width: 12px; height: 12px; flex: none; border-radius: 50%; border: 2px solid var(--m); }
.app-mock__search b { font-size: 10px; font-weight: 500; color: var(--m); }

.app-mock__chiprow { display: flex; gap: 6px; flex-wrap: wrap; }
.app-mock__chip { font-size: 10px; font-weight: 700; padding: 6px 10px; border-radius: var(--r-pill); background: #fff; border: 1px solid var(--br); color: var(--m); }
.app-mock__chip.is-active { background: var(--p); border-color: var(--p); color: #fff; }
.app-mock__chip.is-disabled { color: var(--m); text-decoration: line-through; opacity: .6; background: var(--br-2); border-color: var(--br-2); }

.app-mock__item { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--r-btn); background: #fff; border: 1px solid var(--br-2); }
.app-mock__item i { width: 22px; height: 22px; flex: none; border-radius: var(--r-btn); background: rgba(240, 97, 74, .12); }
.app-mock__item b { flex: 1; font-size: 11px; font-weight: 600; color: var(--p); }
.app-mock__item u { font-size: 10px; font-weight: 700; color: var(--m); text-decoration: none; }

.app-mock__badge { align-self: flex-start; font-size: 10px; font-weight: 700; color: var(--a-ink); background: rgba(240, 97, 74, .1); padding: 4px 10px; border-radius: var(--r-pill); }

.app-mock__cartfoot { display: flex; align-items: center; justify-content: space-between; padding-top: 10px; border-top: 1px dashed var(--br); }
.app-mock__cartfoot span { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--m); }
.app-mock__cartfoot b { font-size: 15px; font-weight: 700; color: var(--p); }
.app-mock__cta {
  text-align: center; padding: 10px; border-radius: var(--r-btn);
  background: var(--grad-a); font-size: 11px; font-weight: 700;
  color: var(--p);
}
.app-mock__cta.is-split { display: flex; align-items: center; justify-content: space-between; }

.app-mock__timeline { display: flex; flex-direction: column; }
.app-mock__step { display: flex; align-items: center; gap: 10px; position: relative; padding-block: 8px; }
.app-mock__step i { width: 16px; height: 16px; flex: none; border-radius: 50%; background: var(--br-2); border: 2px solid var(--br); position: relative; z-index: 1; }
.app-mock__step:not(:last-child)::before { content: ''; position: absolute; inset-inline-start: 7px; top: 24px; width: 2px; height: 100%; background: var(--br); }
.app-mock__step.is-done i { background: var(--a-ink); border-color: var(--a-ink); }
.app-mock__step.is-done:not(:last-child)::before { background: var(--a-ink); opacity: .35; }
.app-mock__step.is-current i { background: #fff; border-color: var(--a-ink); box-shadow: 0 0 0 3px rgba(240, 97, 74, .18); }
.app-mock__step b { flex: 1; font-size: 11px; font-weight: 600; color: var(--p); }
.app-mock__step u { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 3px 8px; border-radius: var(--r-pill); text-decoration: none; background: var(--br-2); color: var(--m); }
.app-mock__step.is-done u { background: rgba(240, 97, 74, .12); color: var(--a-ink); }
.app-mock__step.is-current u { background: var(--p); color: #fff; }
.app-mock__pingline { display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 10px 12px; border-radius: var(--r-btn); background: #fff; border: 1px solid var(--br-2); }
.app-mock__pingline i { width: 20px; height: 20px; flex: none; border-radius: 50%; background: rgba(240, 97, 74, .14); }
.app-mock__pingline b { font-size: 10px; font-weight: 600; color: var(--m); line-height: 1.4; }
.app-mock--tracker .app-mock__body { justify-content: flex-start; gap: 14px; }
.app-mock__trackhead { display: flex; align-items: baseline; justify-content: space-between; }
.app-mock__trackhead b { font-size: 13px; font-weight: 700; color: var(--p); }
.app-mock__trackhead u { font-size: 9px; font-weight: 700; text-decoration: none; color: var(--a-ink); background: rgba(240, 97, 74, .12); padding: 3px 8px; border-radius: var(--r-pill); text-transform: uppercase; letter-spacing: .04em; }
.app-mock__trackbar { height: 6px; border-radius: var(--r-pill); background: var(--br-2); overflow: hidden; }
.app-mock__trackbar i { display: block; width: 70%; height: 100%; border-radius: var(--r-pill); background: var(--grad-a); }
.app-mock__trackpins { display: flex; justify-content: space-between; }
.app-mock__trackpins span { width: 12px; height: 12px; border-radius: 50%; background: var(--br-2); border: 2px solid var(--br); }
.app-mock__trackpins span.is-done { background: var(--a-ink); border-color: var(--a-ink); }
.app-mock__trackpins span.is-current { background: #fff; border-color: var(--a-ink); box-shadow: 0 0 0 3px rgba(240, 97, 74, .18); }
.app-mock__trackfoot { margin-top: auto; font-size: 10px; font-weight: 600; color: var(--m); text-align: center; padding-top: 14px; border-top: 1px dashed var(--br); }

.app-mock__togglerow { display: flex; align-items: center; gap: 8px; }
.app-mock__toggle { width: 28px; height: 16px; flex: none; border-radius: var(--r-pill); background: var(--br); position: relative; }
.app-mock__toggle i { position: absolute; top: 2px; inset-inline-start: 2px; width: 12px; height: 12px; border-radius: 50%; background: #fff; }
.app-mock__toggle.is-active { background: var(--a-ink); }
.app-mock__toggle.is-active i { inset-inline-start: 14px; }
.app-mock__togglerow b { font-size: 10px; font-weight: 600; color: var(--p); }

.app-mock__swatches { display: flex; gap: 8px; }
.app-mock__swatch { width: 22px; height: 22px; flex: none; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px var(--br); }
.app-mock__swatch.is-active { box-shadow: 0 0 0 2px var(--a-ink); }
.app-mock__callout {
  background: #fff; border: 1px solid var(--br); border-radius: var(--r-btn);
  padding: 8px 10px; box-shadow: var(--shadow); font-size: 9px; line-height: 1.5; color: var(--m);
}
.app-mock__callout em { display: block; font-style: normal; font-weight: 700; font-size: 8px; text-transform: uppercase; letter-spacing: .06em; color: var(--a-ink); margin-bottom: 2px; }

.app-mock__scorewrap { display: flex; align-items: center; gap: 12px; }
.app-mock__ring { position: relative; width: 56px; height: 56px; flex: none; border-radius: 50%; display: grid; place-items: center; }
.app-mock__ring::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--a-ink) 0deg var(--ring-deg, 260deg), var(--br-2) var(--ring-deg, 260deg) 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 7px), #000 calc(100% - 7px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 7px), #000 calc(100% - 7px));
}
.app-mock__ring b { position: relative; z-index: 1; font-size: 15px; font-weight: 700; color: var(--p); }
.app-mock__scoremeta { display: flex; flex-direction: column; gap: 2px; }
.app-mock__scoremeta span { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--m); }
.app-mock__scoremeta em { font-style: normal; font-size: 13px; font-weight: 700; color: var(--p); }
.app-mock__chart { display: flex; align-items: flex-end; gap: 7px; height: 48px; }
.app-mock__chart i { flex: 1; border-radius: 3px 3px 0 0; background: rgba(240, 97, 74, .22); }
.app-mock__chart i:nth-child(1) { height: 45%; }
.app-mock__chart i:nth-child(2) { height: 70%; }
.app-mock__chart i:nth-child(3) { height: 55%; }
.app-mock__chart i:nth-child(4) { height: 85%; background: rgba(240, 97, 74, .4); }
.app-mock__chart i:nth-child(5) { height: 62%; }
.app-mock__chart i:nth-child(6) { height: 40%; }
.eyebrow-pill {
  display: inline-flex; align-items: center;
  padding: 6px 16px; margin-bottom: 14px;
  border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .1);
  color: var(--a-ink);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.svc-card { display: flex; flex-direction: column; }
.svc-card h3 { margin-bottom: 8px; }
.svc-card .p-desc { margin-bottom: 18px; }

.svc-icon {
  display: grid; place-items: center;
  width: 56px; height: 56px; margin-bottom: 18px;
  border-radius: var(--r);
  background: rgba(240, 97, 74, .1);
  color: var(--a-ink);
}
.svc-icon svg { width: 24px; height: 24px; }

.svc-list { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.svc-list li { position: relative; padding-inline-start: 20px; }
.svc-list li::before {
  content: '→';
  position: absolute; inset-inline-start: 0; top: 0;
  color: var(--a-ink); font-weight: 600;
}
.rtl .svc-list li::before { display: inline-block; transform: scaleX(-1); }
.svc-list a {
  display: inline-block;
  color: var(--p); text-decoration: none;
  font-size: var(--fs-card); font-weight: 500;
}
.svc-list a:hover { color: var(--a-ink); text-decoration: underline; }
.svc-explore {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: auto;
  font-size: var(--fs-card); font-weight: 600;
  text-decoration: underline;
}
.svc-card--featured {
  border-color: rgba(240, 97, 74, .3);
  background: rgba(240, 97, 74, .025);
}

.crumb { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 22px; font-size: 13px; font-weight: 500; }
.crumb a { color: var(--on-dark-3); text-decoration: none; transition: color var(--dur) var(--ease); }
.crumb a:hover { color: #fff; }
.crumb span[aria-current] { color: var(--a-2); }
.crumb svg { width: 14px; height: 14px; color: var(--on-dark-3); flex: none; }
.hero--svc { padding-block: clamp(120px, 15vh, 156px) clamp(56px, 7vh, 72px); }
.hero--svc .lede { margin-top: 18px; }
.svc-layout { display: block; }

.onpage { position: sticky; top: 104px; }
.onpage__title { margin-bottom: 14px; }
.onpage__list { display: grid; gap: 2px; border-inline-start: 1px solid var(--br); }
.onpage__link {
  display: block;
  padding: 8px 0 8px 16px;
  margin-inline-start: -1px;
  border-inline-start: 2px solid transparent;
  font-size: 13.5px; font-weight: 500; line-height: 1.4;
  color: var(--m); text-decoration: none;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.onpage__link:hover { color: var(--p); }
.onpage__link.is-active { color: var(--a-ink); border-inline-start-color: var(--a); font-weight: 600; }

.svc-block + .svc-block { margin-top: 72px; }
.svc-block > h2 { margin-block: 12px 14px; }
.svc-block > .lede { margin-bottom: 32px; }

.svc-block > h2 + :not(.lede), .svc-block > .lede + * {
    margin-top: 40px;
}
.split { display: grid; gap: 40px; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); align-items: center; }
.split--flip .split__body { order: 2; }
.split__body h3 { margin-bottom: 12px; }
.split__body p { color: var(--m); margin-bottom: 18px; }
.split img{border-radius: var(--r-lg);}
.media-frame {
  aspect-ratio: 4 / 3;
  border-radius: var(--r-lg);
  border: 1px dashed var(--br);
  background:
    linear-gradient(135deg, rgba(240, 97, 74, .05), rgba(20, 54, 94, .05)),
    var(--bga);
  display: grid; place-items: center;
  color: var(--m); font-size: 12px; font-weight: 700;   /* --mm measured 4.06:1 on this tint; --m is 4.76:1 */
  text-transform: uppercase; letter-spacing: .12em;
}
.cmp-scroll {
  overflow-x: auto;
  border-radius: var(--r-lg);
  border: 1px solid var(--br-2);
  background: #fff;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.media-frame--art {
  border-style: solid;
  border-color: var(--br-2);
  background: var(--bga);
  overflow: hidden;
  display: block;
  text-transform: none; letter-spacing: normal;
}
.media-frame--art > svg,
.media-frame--art > img { width: 100%; height: 100%; display: block; }
@media (max-width: 720px) {
  .cmp-scroll {
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent 100%);
    mask-image: linear-gradient(90deg, #000 88%, transparent 100%);
  }
}
.cmp { width: 100%; min-width: 560px; border-collapse: collapse; font-size: var(--fs-card); }
.cmp th, .cmp td { padding: 15px 20px; text-align: start; border-bottom: 1px solid var(--br-2); vertical-align: top; }
.cmp thead th { background: var(--bga); font-weight: 700; color: var(--p); white-space: nowrap; }
.cmp tbody th { font-weight: 600; color: var(--p); }
.cmp td { color: var(--m); }
.cmp tbody tr:last-child th, .cmp tbody tr:last-child td { border-bottom: 0; }
.cmp .cmp--ours { background: rgba(240, 97, 74, .04); color: var(--p); font-weight: 500; }
.cmp thead .cmp--ours { background: rgba(240, 97, 74, .1); color: var(--a-ink); }

.proc { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); counter-reset: proc; }
.proc__card { padding: 24px; }
.proc__n {
  display: block; margin-bottom: 12px;
  font-size: 13px; font-weight: 700; letter-spacing: .12em;
  font-variant-numeric: tabular-nums;
  color: var(--a-ink);
}
.proc__card h3 { margin-bottom: 8px; font-size: 17px; }
.proc__card p { font-size: var(--fs-card); line-height: 1.6; color: var(--m); }
.proc__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }

.proc__tag { padding: 3px 9px; border-radius: var(--r-pill); background: rgba(20, 54, 94, .05); color: var(--m); font-size: 11.5px; font-weight: 600; }
.cta-band { text-align: center; }
.cta-band h2 { color: #fff; }
.cta-band .lede { margin-inline: auto; margin-block: 14px 28px; }
.cta-band__row { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }

@media (max-width: 1080px) {
  .svc-layout { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .onpage { position: static; }
  .onpage__list { display: flex; flex-wrap: wrap; gap: 8px; border-inline-start: 0; }
  .onpage__link { padding: 7px 13px; border: 1px solid var(--br); border-radius: var(--r-pill); margin-inline-start: 0; }
  .onpage__link.is-active { border-color: var(--a); }
  .svc-block + .svc-block { margin-top: 56px; }
}
@media (max-width: 700px) {
  .split--flip .split__body { order: 0; }
}
.bgrid {
  --bgrid-line: var(--br-2);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #fff;
  box-shadow: 0 0 0 1px var(--br-2);
}
.bgrid__cell {
  position: relative;
  display: flex; flex-direction: column;
  padding: 30px 32px 34px;
  min-height: 300px;
  background: transparent;
  box-shadow:
    -1px 0 0 0 var(--bgrid-line),
    0 -1px 0 0 var(--bgrid-line);
  transition: background var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.bgrid__cell--w2 { grid-column: span 2; }

.bgrid__cell h3 { margin-bottom: 10px; font-size: 17px; }
.bgrid__cell p { font-size: var(--fs-card); line-height: 1.62; color: var(--m); max-width: 46ch; }
.bgrid__cell code {
  font-family: inherit; font-weight: 600;
  color: var(--a-ink);
  background: rgba(240, 97, 74, .09);
  border-radius: 5px; padding: 1px 6px; font-size: .94em;
}

.bgrid__art { margin-top: auto; padding-top: 26px; display: grid; place-items: center; }
.bgrid__art svg { width: min(100%, 300px); height: auto; display: block; }

.bgrid__cell--feature { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 320px); gap: 32px; align-items: center; }
.bgrid__cell--feature h3 { font-size: clamp(18px, 2vw, 27px); letter-spacing: -.02em; line-height: 1.2; margin-bottom: 14px; }
.bgrid__cell--feature .bgrid__art { margin-top: 0; padding-top: 0; }
.bgrid__cell--feature .bgrid__art svg { width: 100%; }
.bgrid__facts { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.bgrid__facts li {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: var(--fs-card); font-weight: 500; color: var(--p);
}
.bgrid__facts li::after {
  content: ''; width: 13px; height: 13px; flex: none;
  background: currentColor; color: var(--mm);
  -webkit-mask: var(--chev) center / contain no-repeat;
  mask: var(--chev) center / contain no-repeat;
}
.bgrid { --chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3Cpolyline points='12 5 19 12 12 19'/%3E%3C/svg%3E"); }
@media (hover: hover) {
  .bgrid__cell:hover {
    z-index: 1;
    background: #fff;
    box-shadow: 0 0 0 1px var(--br), var(--shadow-lg);
  }
  /* Dark skin: the panel is navy, so "lifted" is a lighter wash rather than a
     white card, and the shadow has to be near-black to register at all. */
  .bgrid--dark .bgrid__cell:hover {
    background: rgba(255, 255, 255, .05);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .22), 0 14px 30px rgba(0, 0, 0, .3);
  }
}

/* --- dark skin ------------------------------------------------------------ */
.bgrid--dark {
  --bgrid-line: var(--on-dark-br);
  background: var(--bgd);
  background-image: linear-gradient(135deg, rgba(20, 54, 94, .55) 0%, rgba(10, 22, 50, 0) 60%);
  color: var(--on-dark-2);
  box-shadow: none;
}
.bgrid--dark .bgrid__cell h3 { color: #fff; }
.bgrid--dark .bgrid__cell p { color: var(--on-dark-3); }
.bgrid--dark .bgrid__cell b { color: #fff; font-weight: 600; }
/* Never --a on this ground: at 14px it fails, and --a-ink is a light-ground
   colour. --a-2 measures 5.87:1 against the lighter end of the navy. */
.bgrid--dark .bgrid__cell code { color: var(--a-2); background: rgba(255, 255, 255, .06); }
.bgrid--dark .bgrid__facts li { color: #fff; }
.bgrid--dark .bgrid__facts li::after { color: var(--on-dark-3); }

/* --- responsive ----------------------------------------------------------- */
@media (max-width: 980px) {
  .bgrid { grid-template-columns: repeat(2, 1fr); }
  .bgrid__cell--feature { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .bgrid__cell--feature .bgrid__art { margin-top: auto; padding-top: 24px; }
}
@media (max-width: 620px) {
  .bgrid { grid-template-columns: minmax(0, 1fr); }
  .bgrid__cell--w2 { grid-column: span 1; }
  .bgrid__cell { min-height: 0; padding: 26px 24px 30px; }
}

/* --- industry icon grid ----------------------------------------------------
   Six across, centred label under a line icon. Deliberately not `.card` — these
   are a vocabulary list, not six things to compare, and boxing them would give
   each one weight it has not earned. One cell is boxed, and only because it is
   the one that leads somewhere (B2B links to its own service page).

   The icons are --a at 1.7px stroke on --bg: 3.14:1, which clears the 3:1 floor
   for non-text graphics — but only just, and only on --bg. On --bga the same
   colour measures 2.95:1 and fails, so do NOT move this grid into a
   `.section--alt`. The LABELS are --p, not accent: an accent label at 15px
   would be the exact --a-ink trap the house rule warns about. */
.ind-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px 8px;
}
.ind-cell {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 26px 12px;
  border: 1px solid transparent;
  border-radius: var(--r);
  text-align: center;
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.ind-cell svg { width: 34px; height: 34px; color: var(--a); flex: none; }
.ind-cell span { font-size: 15px; font-weight: 600; color: var(--p); letter-spacing: -.01em; }

/* No box at rest — the grid reads as a list. The border is the hover response,
   on every cell, so nothing is permanently outlined for no reason. Gated on
   `hover: hover`: on touch there is nothing to hover away from, and a sticky
   outline on the last-tapped cell is the bug this replaced. */
@media (hover: hover) {
  .ind-cell:hover { border-color: var(--a); background: #fff; }
  .ind-cell--link:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
}
/* The one cell that goes somewhere still gets a pointer and the lift; it just
   no longer advertises itself with a permanent box. */
.ind-cell--link { cursor: pointer; }

@media (max-width: 1080px) { .ind-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .ind-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 460px)  { .ind-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ind-cell { padding: 20px 8px; } }

/* --- process stepper -------------------------------------------------------
   Horizontal accordion: one open panel, the rest collapsed to a navy spine.

   Three things used to snap in a single frame and read as a blink:
     1. the body went display:none -> block, so it could never animate;
     2. it became visible while the panel was still WIDENING, so the copy was
        laid out in a 78px column and reflowed to full width in front of you;
     3. `transition: background` between --grad and --bga did nothing — a
        gradient cannot be interpolated to a flat colour.

   So: the open ground is now the BASE background and the navy is a layer on
   top of it faded by opacity; the body is always in the DOM, collapsed with
   grid-template-rows and hidden with `visibility` (still out of the
   accessibility tree, same as display:none was); and on desktop its fade is
   DELAYED until the width has settled, so nothing reflows in view.
   ========================================================================== */
.pstack { display: flex; gap: 10px; align-items: stretch; min-height: 430px; }

.pstack__item {
  position: relative;
  display: flex; flex-direction: column;
  flex: 0 1 78px;
  min-width: 78px;
  border-radius: var(--r-lg);
  background: var(--bga);          /* the OPEN ground; navy is the ::before layer */
  color: var(--on-dark-2);
  overflow: hidden;
  /* flex-grow, not width/flex-basis: every panel keeps the same 78px basis and
     only its share of the free space changes, so closed spines never jitter. */
  transition: flex-grow var(--dur-slow) var(--ease-panel),
              color var(--dur-slow) var(--ease);
}
.pstack__item::before {
  content: '';
  position: absolute; inset: 0;
  background: var(--grad);
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease);
}
.pstack__item.is-open { flex-grow: 1; color: var(--m); }
.pstack__item.is-open::before { opacity: 0; }

/* Both children sit above the navy layer. Nothing else competes on z-index. */
.pstack__trigger, .pstack__body { position: relative; z-index: 1; }

.pstack__trigger {
  flex: 1 1 auto;
  display: flex; flex-direction: column; align-items: flex-start; gap: 14px;
  width: 100%;
  padding: 26px 20px;
  border: 0; background: none; color: inherit; font: inherit;
  text-align: start; cursor: pointer;
  transition: padding var(--dur-slow) var(--ease-panel);
}
/* Open: stop filling the panel, just head it. */
.pstack__item.is-open .pstack__trigger { flex: none; padding-bottom: 0; cursor: default; }
.pstack__trigger:focus-visible { outline: 2px solid var(--a); outline-offset: -4px; }

/* Number. tnum so the numerals share a width, same rule as the stats band. */
.pstack__n {
  font-size: 15px; font-weight: 700; letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--on-dark-3);
  transition: color var(--dur-slow) var(--ease);
}
.pstack__item.is-open .pstack__n { color: var(--m); }   /* --mm was 4.27:1 on --bga; --m is 5.01:1 */

/* Vertical label on a collapsed spine — reads bottom-to-top. Absolutely
   positioned rather than margin-top:auto so it can FADE instead of being
   display:none'd: in flow it would keep the open trigger ~100px tall and push
   the body down. It is aria-hidden and the button carries its own aria-label,
   so opacity/visibility loses nothing the old display:none kept. On the way
   back in it waits for the navy to return — white text on --bga is invisible. */
.pstack__spine {
  position: absolute;
  inset-inline-start: 20px;
  bottom: 26px;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em;
  color: #fff;
  white-space: nowrap;
  transition: opacity var(--dur) var(--ease) var(--dur-slow),
              visibility 0s linear 0s;
}
.pstack__item.is-open .pstack__spine {
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-fast) var(--ease),
              visibility 0s linear var(--dur-fast);
}

/* Collapsed: zero-height grid row + visibility:hidden, which keeps the copy
   out of the accessibility tree exactly as display:none did. */
.pstack__body {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;
  transition: grid-template-rows var(--dur-slow) var(--ease-panel),
              opacity var(--dur-fast) var(--ease),
              visibility 0s linear var(--dur-fast);
}
.pstack__body-clip { overflow: hidden; min-width: 0; }
.pstack__body-in {
  padding: 18px 30px 32px;
  transform: translateY(8px);
  transition: transform var(--dur) var(--ease);
}
.pstack__body h3 {
    font-size: clamp(19px, 2.1vw, 28px);
    color: var(--a-ink);
    margin-bottom: 14px;
    letter-spacing: -.02em;
}
.pstack__body p {
    font-size: var(--fs-card);
    line-height: 1.65;
    color: var(--m);
    max-width: 52ch;
}
.pstack__lead {
    font-size: 16px;
    font-weight: 600;
    color: var(--p);
    margin-bottom: 12px;
    max-width: 46ch;
}
.pstack__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 18px;
}
.pstack__tag {
    padding: 4px 11px;
    border-radius: var(--r-pill);
    background: #fff;
    border: 1px solid var(--br);
    color: var(--m);
    font-size: 12px;
    font-weight: 600;
}
.pstack__item.is-open .pstack__body {
  grid-template-rows: 1fr;
  opacity: 1;
  visibility: visible;
  /* The delay is the fix. The panel widens for --dur-slow; the copy is held at
     opacity 0 for exactly that long and fades in once the column has settled,
     so the 78px -> full-width reflow happens off-screen. Shorten this and the
     reflow becomes visible again. */
  transition: grid-template-rows var(--dur-slow) var(--ease-panel),
              opacity var(--dur) var(--ease) var(--dur-slow),
              visibility 0s linear 0s;
}
.pstack__item.is-open .pstack__body-in {
  transform: none;
  transition: transform var(--dur) var(--ease) var(--dur-slow);
}

/* Below 1024px the spines have nowhere to go — seven at 78px overflow a phone,
   and vertical text in a full-width strip is unreadable. Stack it: the
   accordion still works, it just opens downward. */
@media (max-width: 1023px) {
  .pstack { flex-direction: column; min-height: 0; gap: 8px; }
  .pstack__item { flex: none; min-width: 0; }
  .pstack__trigger { flex-direction: row; align-items: center; gap: 16px; padding: 18px 22px; }
  .pstack__item.is-open .pstack__trigger { padding-bottom: 0; }
  .pstack__spine {
    position: static;
    writing-mode: horizontal-tb; transform: none; letter-spacing: .1em;
  }
  /* Nothing is widening here, so there is nothing to wait for: the copy fades
     in with the height rather than after it. The full --dur-slow delay would
     just read as lag on a phone. */
  .pstack__item.is-open .pstack__body {
    transition: grid-template-rows var(--dur-slow) var(--ease-panel),
                opacity var(--dur) var(--ease) .06s,
                visibility 0s linear 0s;
  }
  .pstack__item.is-open .pstack__body-in { transition-delay: .06s; }
  .pstack__body-in { padding: 16px 22px 26px; }
}

/* The global reduced-motion rule caps durations but not delays, and a .32s
   delay on a .12s fade is worse than no animation at all. */
@media (prefers-reduced-motion: reduce) {
  .pstack__item, .pstack__item::before, .pstack__trigger,
  .pstack__body, .pstack__body-in, .pstack__spine { transition-delay: 0s !important; }
  .pstack__body-in { transform: none !important; }
}

/* --- services index --------------------------------------------------------
   Card list for /services/. Reuses the .card visual language rather than
   introducing another one; the whole card is the link, so the heading carries
   the arrow and nothing inside needs its own focusable element. */
.svc-index { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.svc-index__card {
  display: block;
  padding: 26px;
  background: #fff;
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.svc-index__feats {
    list-style-type: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.svc-index__feats li {
    position: relative;
    padding-inline-start: 26px;
    font-size: var(--fs-card);
    line-height: 1.5;
    color: var(--m);
}
.svc-index__feats li::before {
    content: '';
    position: absolute;
    inset-inline-start: 0;
    top: .25em;
    width: 16px;
    height: 16px;
    border-radius: var(--r-pill);
    background: rgba(240, 97, 74, .12);
}
.svc-index__feats li::after {
    content: '';
    position: absolute;
    inset-inline-start: 4.5px;
    top: .54em;
    width: 6.5px;
    height: 3.5px;
    border-inline-start: 2px solid var(--a-ink);
    border-block-end: 2px solid var(--a-ink);
    transform: rotate(-45deg);
}
.svc-index__card--feature {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
    gap: 40px;
    align-items: center;
    padding: 32px;
    border-color: #f0614a;
    background: rgba(240, 97, 74, .03);
        grid-column: 1 / -1;
}
.svc-index__card h3 {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 10px; color: var(--p);
}
.svc-index__card p { max-width: 56ch; font-size: var(--fs-card); line-height: 1.6; color: var(--m); margin: 0; }
.svc-index__card .mw-arrow { width: 18px; height: 18px; flex: none; color: var(--mm); transition: transform var(--dur) var(--ease), color var(--dur) var(--ease); }
@media (hover: hover) {
  .svc-index__card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: rgba(240, 97, 74, .25); }
  .svc-index__card:hover .mw-arrow { transform: translateX(4px); color: var(--a-ink); }
}
.svc-index__card:focus-visible { outline: 2px solid var(--a); outline-offset: 3px; }

/* --- booking modal ---------------------------------------------------------
   The .modal backdrop above was written for the video dialog, whose box is a
   16/9 black frame. A form needs a different panel, so the panel is its own
   class rather than an override that would fight the video one.

   `visibility` is stepped on the way out only, matching .mega-panel: the fade
   must be seen before the layer stops taking up space, but on the way in it
   flips synchronously so the focus() call in Modal.open() actually lands. */
.modal__panel {
  width: min(560px, 100%);
  /* 100vh on mobile Safari is the viewport WITHOUT the URL bar, so a tall modal
     is cut off behind it. dvh tracks the visible area; vh stays as the fallback. */
  max-height: calc(100vh - 2 * var(--gutter));
  max-height: calc(100dvh - 2 * var(--gutter));
  overflow-y: auto;
  background: var(--bg);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  padding: 32px;
  position: relative;
}
.modal__head { margin-bottom: 22px; padding-inline-end: 44px; }
.modal__head h2 { font-size: clamp(19px, 2.2vw, 26px); margin-bottom: 8px; }
.modal__head p { font-size: var(--fs-card); line-height: 1.6; color: var(--m); margin: 0; max-width: none; }

/* Sits inside the light panel, so this needs light-ground colours rather than
   the .modal__close above, which is styled for the dark video backdrop. */
.modal__x {
  position: absolute; top: 20px; inset-inline-end: 20px;
  width: 36px; height: 36px;
  display: flex; justify-content:center; align-items: center;padding:0;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  background: #fff; color: var(--m); cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.modal__x:hover { border-color: var(--a); color: var(--a-ink); }
.modal__x svg { width: 17px; height: 17px; }

/* The form card inside the modal is already on a light panel, so it drops the
   card chrome it carries on the navy contact section. */
.modal__panel .sh-form-card { background: none; border: 0; box-shadow: none; padding: 0; }

@media (max-width: 560px) {
  .modal__panel { padding: 26px 20px; }
  .modal__head { padding-inline-end: 40px; }
}

/* --- contact detail band ---------------------------------------------------
   Three columns: phone, address, email. Sits directly under the hero, so it is
   --bga rather than white — it needs to read as a continuation of the header
   block rather than as the first content section. */
.cband { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.cband__item { display: flex; gap: 16px; align-items: flex-start; }
.cband__icon {
  display: grid; place-items: center;
  width: 42px; height: 42px; flex: none;
  border-radius: var(--r-btn);
  background: #fff; border: 1px solid var(--br);
  color: var(--a-ink);            /* icon on white — --a would be 3.14:1 */
}
.cband__icon svg { width: 19px; height: 19px; }
.cband__label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--mm); margin-bottom: 5px; }
.cband__value { font-size: var(--fs-card); line-height: 1.55; color: var(--p); font-weight: 500; margin: 0; max-width: none; }
.cband__value a { color: var(--p); text-decoration: none; border-bottom: 1px solid var(--br); }
.cband__value a:hover { color: var(--a-ink); border-bottom-color: var(--a); }

/* --- service-type chips in a form -----------------------------------------
   Checkboxes styled as selectable chips. The input stays in the DOM and keeps
   its native semantics — it is visually hidden, not display:none, so it is
   still focusable and still announced. The chip is the <label>, so clicking
   anywhere on it toggles the box for free. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips__item { position: relative; }
.chips__item input {
  position: absolute; opacity: 0;
  width: 100%; height: 100%; margin: 0;
  cursor: pointer;
}
.chips__item span {
  display: block;
  padding: 9px 15px;
  border: 1px solid var(--br);
  border-radius: var(--r-pill);
  background: #fff;
  font-size: 13.5px; font-weight: 600; color: var(--m);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.chips__item input:hover + span { border-color: var(--a); color: var(--p); }
/* Focus lands on the visually-hidden input, so the ring has to be drawn on the
   chip beside it — otherwise keyboard users get no visible focus at all. */
.chips__item input:focus-visible + span { outline: 2px solid var(--a); outline-offset: 2px; }
.chips__item input:checked + span {
  border-color: var(--a);
  background: rgba(240, 97, 74, .08);
  color: var(--a-ink);            /* 13.5px accent — --a-ink on the tint, 4.8:1 */
}


/* --- 404 -------------------------------------------------------------------
   Built as a real `.hero`, not a bespoke layout. That is the whole point: the
   heading picks up --fs-h1-hero, #fff and the hero line-height, and the lede
   picks up --on-dark-2, so the page uses the site's own type scale instead of
   a one-off. An earlier version set its own clamp() and ran to 62px, half again
   larger than any other heading on the site.

   Copy sits left and the illustration right, matching the homepage hero — which
   also puts the copy under the darkest part of the scrim, where the particle
   field is damped enough for white text. */
.e404 { display: grid; gap: 44px; grid-template-columns: minmax(0, 1fr) minmax(0, 460px); align-items: center; }

/* 12px accent on navy. --a-ink is a light-ground colour and would be unreadable
   here; --a is 3.79:1 against the gradient's light end and fails at this size.
   --a-2 measures 5.79:1 on that same worst case. */
.e404__code { color: var(--a-2); margin-bottom: 12px; }

/* Same reasoning at display size: --a would technically clear the 3:1 large-text
   floor, but sitting beside white type on navy it reads muddy rather than
   accented. */
.e404 h1 { max-width: 16ch; }
.e404 h1 em { font-style: normal; color: var(--a-2); }

.e404 .lede { max-width: 46ch; }
.e404__art svg { width: 100%; height: auto; display: block; }

/* A short list of the places people actually meant to go. */
.e404__links { margin-top: 36px; padding-top: 26px; border-top: 1px solid var(--on-dark-br); }
.e404__links p {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .13em;
  color: var(--on-dark-3); margin-bottom: 14px;
}
.e404__links ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.e404__links a {
  display: inline-block; padding: 7px 14px;
  border: 1px solid var(--on-dark-br); border-radius: var(--r-pill);
  background: var(--on-dark-fill);
  font-size: 13px; font-weight: 600; color: #fff; text-decoration: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.e404__links a:hover { border-color: var(--a-2); background: rgba(255, 255, 255, .12); }

@media (max-width: 900px) {
  /* Illustration first would push the message below the fold on a phone. */
  .e404 { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .e404__art { order: 2; max-width: 380px; }
}


/* ==========================================================================
   18. DEVICE ADAPTATION
   --------------------------------------------------------------------------
   Everything here keys off what the device can DO, not how wide it is. A
   1024px-wide tablet and a 1024px-wide laptop want different hit areas, and a
   viewport query cannot tell them apart.
   ========================================================================== */

/* --- touch targets --------------------------------------------------------
   A coarse pointer needs 44x44px. These controls are all comfortable at 33-40px
   under a mouse, which is why they were sized that way; raising them globally
   would coarsen the desktop layout for no reason, so the increase is scoped to
   devices that actually need it. */
@media (pointer: coarse) {
  .chips__item span { padding: 12px 18px; }
  .e404__links a { padding: 11px 18px; }
  .slider__nav button { width: 46px; height: 46px; }
  .modal__x { width: 44px; height: 44px; }
  .drawer__close { width: 46px; height: 46px; }
  .mw-btn { padding: 15px 18px; }
  /* Footer link lists are the densest tap area on the site: 14.5px text on a
     10px rhythm gives roughly a 25px target. Padding widens the row without
     changing where the text sits. */
  .ftr li { margin-bottom: 2px; }
  .ftr li a { display: block; padding-block: 10px; }
  .ftr__legal a { padding-block: 8px; }
  .crumb a { padding-block: 6px; }
  .onpage__link { padding-block: 12px; }
  /* Inline text links that act as primary routes. Measured on a 390px iframe
     these were 18-27px tall, which is a miss on a phone even though they read
     fine under a mouse. */
  .app-demo, .app-card2__more, .svc-explore, .bgrid__go { padding-block: 10px; }
  .app-cta__links { gap: 0 20px; }
  /* The logo is the "go home" control and measured 27px. It is the one target
     on the page that every visitor is most likely to reach for by reflex. */
  .hdr__logo { padding-block: 9px; }
  /* Reply is a real control, not inline prose, so it needs a real target. */
  .comment__reply { padding-block: 11px; }
  .ftr__mark { padding-block: 8px; }
}

/* The carousel dots are a 9px circle. Growing the dot would make the indicator
   heavy, so the HIT AREA is expanded with a pseudo-element instead: the target
   is 44px square, the dot still looks like a dot. Applied at every pointer type
   because a 9px target is difficult with a mouse too. */
.slider__dot { position: relative; }
.slider__dot::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 24px; height: 24px; transform: translate(-50%, -50%);
}

/* --- safe areas -----------------------------------------------------------
   Notched phones in landscape put the display cutout over the leading edge of
   the page. `max()` keeps the normal gutter everywhere else, so this costs
   nothing on a device without insets. */
.wrap {
  padding-inline:
    max(var(--gutter), env(safe-area-inset-left))
    max(var(--gutter), env(safe-area-inset-right));
}
.hdr__inner { padding-inline: max(0px, env(safe-area-inset-left)) max(0px, env(safe-area-inset-right)); }
.drawer { padding-bottom: max(40px, env(safe-area-inset-bottom)); }
.ftr__copy { padding-bottom: max(20px, env(safe-area-inset-bottom)); }
.modal { padding-bottom: max(var(--gutter), env(safe-area-inset-bottom)); }

/* --- landscape phones -----------------------------------------------------
   The hero reserves clamp(140px, 18vh, 190px) of top padding. On a phone turned
   sideways the viewport is about 390px tall, 18vh is 70px, and the clamp floor
   pushes it back to 140px: over a third of the screen is empty before the
   headline starts. Short viewports get the floor lowered. */
@media (max-height: 560px) and (orientation: landscape) {
  .hero { padding-block: clamp(96px, 22vh, 140px) clamp(40px, 8vh, 64px); }
  .hero--svc { padding-block: clamp(92px, 20vh, 120px) clamp(36px, 7vh, 56px); }
  .hero .stats { margin-top: 32px; }
  .pstack { min-height: 0; }
  .modal__panel { padding: 22px; }
}

/* --- very large screens ---------------------------------------------------
   The container stops at 1440px, so past roughly 1600px the page is a fixed
   column in a widening field. Let the type and the field breathe rather than
   pinning the whole composition to a laptop's proportions. */
@media (min-width: 1600px) {
  .hero .stats { margin-top: 72px; }
  .bgrid__cell { min-height: 330px; padding: 34px 36px 38px; }
  .split { gap: 56px; }
}

/* --- print ----------------------------------------------------------------
   Service pages are the ones people forward internally to justify a budget.
   Drop the chrome, unfurl the accordions, and print the URL behind each link. */
@media print {
  .hdr, .drawer, .scrim, .modal, .ftr, .hero__particles,
  .marquee, .onpage, .e404__links { display: none !important; }
  .hero, .section--navy, .section--grad, .bgrid--dark {
    background: none !important;
    color: #000 !important;
  }
  .hero h1, .hero__sub, .hero .lede, .cta-band h2, .bgrid--dark .bgrid__cell h3 { color: #000 !important; }
  .acc__panel { display: block !important; height: auto !important; }
  .acc__panel > div { overflow: visible !important; }
  .pstack { display: block; }
  .pstack__item { break-inside: avoid; background: none !important; color: #000 !important; }
  .pstack__body { display: block !important; }
  .pstack__spine { display: none; }
  a[href^="http"]::after, a[href^="/"]::after {
    content: " (" attr(href) ")";
    font-size: 11px; color: #555;
  }
  .card, .practice, .bgrid__cell { break-inside: avoid; }
}


/* ==========================================================================
   19. SMALL-SCREEN REFINEMENTS
   ========================================================================== */

/* Two hero buttons side by side leave each about 150px on a phone, so both
   labels wrap to two lines inside a squeezed pill. One per line, full width,
   reads as a stack of choices instead of a broken row. */
@media (max-width: 620px) {
  .hero__cta,
  .cta-band__row,
  .e404 .hero__cta { flex-direction: column; align-items: stretch; gap: 10px; }
  .hero__cta .btn,
  .cta-band__row .btn { justify-content: center; width: 100%; }
  .hero .lede, .hero__sub, .e404 .lede { max-width: none; }
  .hero__badge { font-size: 11px; padding: 5px 12px; }
  .stats { margin-top: 36px; gap: 18px; }
  .drawer a { font-size: 17px; padding: 12px 0; }
  .drawer__group > button { font-size: 17px; }
  .lede { line-height: 1.55; }
}

/* The header CTA and the burger both sit on the right of a pill that is already
   holding a logo. Below the mega-menu breakpoint the CTA moves into the drawer,
   where it gets a full-width tap target instead of a squeezed one. */
@media (max-width: 1023px) {
  .hdr__inner > .btn { display: none; }
}
.drawer__cta { display: none; }
@media (max-width: 1023px) {
  .drawer__cta {
    display: flex; justify-content: center;
    text-align:center;
    width: 100%; margin-top: 26px;
    border-bottom: 0;      /* .drawer a adds a rule under every link */
  }
}

/* --- footer navigation: accordion on phones -------------------------------
   Five stacked columns of up to fourteen links is roughly 45 taps of scrolling
   past the end of the page. Native <details> handles the state and the aria for
   free; the Collapse component only decides, per breakpoint, whether they start
   open. Markup ships `open`, so with JS disabled every column stays expanded
   rather than becoming unreachable. */
.ftr__col > summary { list-style: none; cursor: pointer; }
.ftr__col > summary::-webkit-details-marker { display: none; }
.ftr__col > summary::marker { content: ''; }
.ftr__col > summary .ftr__h { margin: 0; }
.ftr__chev { display: none; width: 18px; height: 18px; flex: none; color: var(--on-dark-3); transition: transform var(--dur) var(--ease); }

@media (min-width: 701px) {
  /* Desktop: the summary is a heading, not a control. */
  .ftr__col > summary { cursor: default; }
  .ftr__col > summary .ftr__h { margin-bottom: 16px; }
}

@media (max-width: 700px) {
  .ftr__cols { display: block; }
  .ftr__col { border-bottom: 1px solid var(--on-dark-br); }
  .ftr__col > summary {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; padding-block: 16px;
  }
  .ftr__col > summary .ftr__h { margin-bottom: 0; }
  .ftr__chev { display: block; }
  .ftr__col[open] > summary .ftr__chev { transform: rotate(180deg); }
  .ftr__col > summary + * { margin-top: 2px; }
  .ftr__col > :last-child { margin-bottom: 18px; }
  .ftr .ftr__h + ul { margin-bottom: 18px; }
  .ftr__bottom { margin-top: 32px; }
}

/* ==========================================================================
   20. APPS INDEX (/apps/)
   --------------------------------------------------------------------------
   Alternating media/text rows. Reuses .split rather than inventing a second
   two-column primitive; only the feature list and the CTA cluster are new.
   ========================================================================== */

.app-row { padding-block: clamp(44px, 5vw, 72px); }
.app-row + .app-row { border-top: 1px solid var(--br); }
/* Alternating ground rather than alternating nothing: thirteen identical rows
   on one background reads as a list, not as thirteen products. */
.app-row:nth-child(odd) { background: var(--bga); }
.app-row:nth-child(odd) + .app-row { border-top: 0; }
.app-row .split { gap: clamp(32px, 4vw, 56px); align-items: center; }
.app-row h2 { margin-block: 10px 12px; }
.app-row .split__body > p { color: var(--m); margin-bottom: 20px; }

/* --- feature list ---------------------------------------------------------
   Not a card grid and not a card: four short capability lines under the
   description, marked with a check rather than a bullet so they read as
   "this app does this" instead of as prose fragments. */
.app-feats { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 10px; }
.app-feats li {
  position: relative; padding-inline-start: 28px;
  font-size: var(--fs-card); line-height: 1.55; color: var(--m);
}
.app-feats li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: .28em;
  width: 17px; height: 17px; border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .12);
}
.app-feats li::after {
  content: ''; position: absolute; inset-inline-start: 5px; top: .58em;
  width: 7px; height: 4px;
  border-inline-start: 2px solid var(--a-ink);
  border-block-end: 2px solid var(--a-ink);
  transform: rotate(-45deg);
}

/* --- CTA cluster ----------------------------------------------------------
   Two buttons side by side, and the demo link on its own row beneath the FIRST
   one. Explicit grid placement, because that alignment is the point: the demo
   store is a secondary route to the same decision as Install, so it belongs
   under Install rather than floating between the two buttons. */
/* Flex, not grid. `grid-template-columns: max-content max-content` cannot wrap:
   two buttons that need more than the column gets will simply overflow it, which
   is what pushed /apps/ 17px wider than the viewport at 768px, where the split
   is still two columns but each is only ~344px wide.

   flex-wrap lets the second button drop to its own line when the space is not
   there, and `flex-basis: 100%` on the links row keeps it starting on a fresh
   line at the leading edge — which is still directly under Install App, the
   alignment the grid was there to guarantee. */
.app-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* The secondary links live in their own row under the buttons. They were
   previously each pinned to `grid-row: 2` directly, which was fine while there
   was one of them and put two on top of each other the moment a second was
   added. A wrapper cannot collide with itself. */
.app-cta__links {
  flex-basis: 100%;
  display: flex; flex-wrap: wrap;
  align-items: center; gap: 6px 20px;
}
.app-demo {
  justify-self: start;
  font-size: 14px; font-weight: 600;
  color: var(--a-ink);          /* 14px accent on --bg / --bga -> must be --a-ink */
  text-decoration: underline;
  text-underline-offset: .28em;
  text-decoration-thickness: 1.5px;
}
.app-demo:hover { color: var(--p); }

/* --- status ---------------------------------------------------------------
   An app awaiting App Store review has nothing to install yet. Saying so is
   better than a live-looking button that goes nowhere. */
.app-status {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 10px 16px;
  border: 1px dashed var(--br);
  border-radius: var(--r-btn-lg);
  font-size: var(--fs-btn); font-weight: 600; color: var(--m);
}
.app-status::before {
  content: ''; width: 7px; height: 7px; border-radius: var(--r-pill);
  background: var(--a); flex: none;
}

@media (max-width: 620px) {
  .app-cta { flex-direction: column; align-items: stretch; }
  .app-cta .btn { justify-content: center; }
  .app-cta__links { flex-direction: column; align-items: center; gap: 10px; }
  .app-status { justify-content: center; }
}

/* ==========================================================================
   21. APP DETAIL (/apps/<slug>/)
   ========================================================================== */

/* The demo-store link also appears in the navy hero, where --a-ink (a
   light-ground colour) would be unreadable. --a-2 is 5.79:1 against the
   gradient's light end. */
.hero .app-demo { color: var(--a-2); }
.hero .app-demo:hover { color: #fff; }
.hero .app-cta { margin-top: 28px; }

/* --- meta strip -----------------------------------------------------------
   The facts a merchant checks before reading any marketing: who built it, what
   it needs, what it touches. Sits in the hero under the CTA, as a definition
   list because that is what it is. */
.app-meta {
  display: grid; gap: 22px 40px;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  margin-top: 44px; padding-top: 26px;
  border-top: 1px solid var(--on-dark-br);
}
.app-meta dt {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .13em;
  color: var(--on-dark-3); margin-bottom: 6px;
}
.app-meta dd { margin: 0; font-size: 15px; font-weight: 500; color: #fff; }

/* --- requirements ---------------------------------------------------------
   A two-column definition list rather than a table: there is no comparison
   happening, just labelled facts, and a table would imply one. */
.app-req { display: grid; gap: 0; border: 1px solid var(--br-2); border-radius: var(--r-lg); overflow: hidden; background: #fff; }
.app-req__row { display: grid; grid-template-columns: minmax(160px, 0.8fr) minmax(0, 2fr); gap: 20px; padding: 15px 22px; }
.app-req__row + .app-req__row { border-top: 1px solid var(--br-2); }
.app-req__row dt { font-weight: 600; color: var(--p); font-size: var(--fs-card); }
.app-req__row dd { margin: 0; color: var(--m); font-size: var(--fs-card); line-height: 1.55; }
@media (max-width: 620px) {
  .app-req__row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}


/* ==========================================================================
   22. HERO MEDIA (app detail pages)
   --------------------------------------------------------------------------
   Text left, media right. Only the app detail hero uses this; every other hero
   on the site stays single-column, so the rule is scoped to the modifier.
   ========================================================================== */

.hero--split .wrap {
  display: grid;
  column-gap: clamp(32px, 4vw, 56px);
  row-gap: 0;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* `start`, not `center`. Centring floats the media against the middle of a
     taller text column, which reads as misalignment: the video begins somewhere
     below the headline it belongs to. Starting both columns at the same line
     puts the top of the media level with the top of the copy. */
  align-items: start;
}
/* The crumb and the meta strip both span the full width: the crumb because it
   belongs to the page rather than to either column, the meta because it is a
   row of facts and squeezing it into half the width wraps four short values
   into a narrow stack for no reason. */
.hero--split .crumb { grid-column: 1 / -1; margin-bottom: 4px; }
.hero--split .app-meta { grid-column: 1 / -1; }
.hero--split .hero__body { min-width: 0; }
.hero--split h1 { max-width: none; }
.hero--split .hero__sub { max-width: 22ch; }
.hero--split .lede { max-width: 46ch; }

/* The scrim under the particles is a left-to-right gradient sized for a
   single-column hero, where the copy occupies the left half. That is exactly
   this layout, so it needs no change — but the media sits in the clear right
   half, which is why it carries its own solid surface rather than relying on
   the scrim for legibility. */
.hero__media {
  position: relative;
  min-width: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--on-dark-br);
  box-shadow: var(--shadow-xl);
}
.hero__media--empty .vf-play { opacity: .55; }
.hero__media img,
.hero__media video,
.hero__media svg,
.hero__media iframe { display: block; width: 100%; height: 100%; border: 0; }

/* 16/9 for video, 4/3 for a screenshot: a product screenshot cropped to video
   proportions loses the top and bottom of the interface it is meant to show. */
.hero__media--video { aspect-ratio: 16 / 9; }
.hero__media--image { aspect-ratio: 4 / 3; }

/* --- click-to-play facade -------------------------------------------------
   A YouTube iframe costs roughly a megabyte of script and sets cookies before
   anyone has asked to watch anything. The facade is a poster plus a button;
   the iframe is created on click. See assets/js/components/video-facade.js. */
.hero__media--video .vf-btn {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  width: 100%; height: 100%;
  padding: 0; border: 0; background: none;
  cursor: pointer;
}
.vf-play {
  display: grid; place-items: center;
  width: 68px; height: 68px;
  border-radius: var(--r-pill);
  background: var(--grad-a);
  box-shadow: 0 10px 30px rgba(10, 22, 50, .45);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.vf-play svg { width: 26px; height: 26px; color: #fff; margin-inline-start: 3px; }
@media (hover: hover) {
  .hero__media--video .vf-btn:hover .vf-play { transform: scale(1.06); box-shadow: 0 14px 38px rgba(10, 22, 50, .55); }
}
.hero__media--video .vf-btn:focus-visible { outline: 2px solid var(--a-2); outline-offset: -4px; }
/* The label sits on the poster, so it needs its own ground rather than trusting
   whatever the artwork happens to be behind it. */
.vf-label {
  position: absolute; inset-inline-start: 16px; inset-block-end: 16px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: rgba(10, 22, 50, .78);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: #fff; font-size: 12.5px; font-weight: 600;
}

/* Placeholder surface, used until real media exists. It carries the play glyph
   so the hero composition can be judged now — a plain grey box would not show
   whether the balance between copy and media is right. The dashed border and
   the "to be added" wording keep it obviously unfinished. */
.hero__media--empty {
  display: grid; place-items: center; gap: 16px;
  border-style: dashed;
  background:
    linear-gradient(135deg, rgba(240, 97, 74, .10), rgba(255, 255, 255, .02));
  color: var(--on-dark-3);
  font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  text-align: center; padding: 20px;
}
.hero__media--empty .vf-play { opacity: .55; }

@media (max-width: 900px) {
  /* Media above the copy would push the headline and the install button below
     the fold on a phone. Copy first, media after, facts last. */
  .hero--split .wrap { grid-template-columns: minmax(0, 1fr); row-gap: 32px; }
  .hero--split .crumb { order: 0; }
  .hero--split .hero__body { order: 1; }
  .hero--split .hero__media { order: 2; }
  .hero--split .app-meta { order: 3; margin-top: 4px; }
  .vf-play { width: 56px; height: 56px; }
  .vf-play svg { width: 21px; height: 21px; }
}

/* ==========================================================================
   23. PRICING
   --------------------------------------------------------------------------
   One component, two densities: --cols-4 on app pages, --cols-3 on service
   pages. Everything is left-aligned, including the price and the CTA, because
   a centred column of left-read feature lines fights itself.
   ========================================================================== */

/* --- billing toggle -------------------------------------------------------
   Two real radio inputs in a group, not buttons: the choice is one-of-two and
   persists, which is what radios are for, and it gets arrow-key navigation and
   the right screen-reader announcement without any JS. */
.bill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 5px; margin-bottom: 32px;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  background: #fff;
}
.bill__opt { position: relative; }
.bill__opt input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.bill__opt span {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 20px; border-radius: var(--r-pill);
  font-size: 14.5px; font-weight: 600; color: var(--m);
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.bill__opt input:checked + span { background: var(--p); color: #fff; }
/* Focus lands on the visually-hidden input, so the ring is drawn on the label
   beside it — otherwise a keyboard user gets no visible focus at all. */
.bill__opt input:focus-visible + span { outline: 2px solid var(--a); outline-offset: 2px; }
.bill__save {
  padding: 2px 9px; border-radius: var(--r-pill);
  background: rgba(20, 54, 94, .08); color: var(--p-2);
  font-size: 11.5px; font-weight: 700;
}
.bill__opt input:checked + span .bill__save { background: rgba(255, 255, 255, .18); color: #fff; }

/* --- the grid -------------------------------------------------------------
   Column count is a custom property rather than two separate rules, so a page
   picks its density with one class and the responsive steps below stay shared. */
.pricing {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(var(--pricing-cols, 3), minmax(0, 1fr));
  align-items: stretch;
}
.pricing--4 { --pricing-cols: 4; gap: 16px; }
.pricing--3 { --pricing-cols: 3; }

/* --- the card -------------------------------------------------------------
   Not `.card`: this needs a fixed internal rhythm (label, price, note, rule,
   features, CTA pinned to the foot) that the generic card does not have. */
.tier {
  display: flex; flex-direction: column;
  padding: 28px 26px;
  background: #fff;
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  text-align: start;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
@media (hover: hover) {
  .tier:hover { border-color: rgba(240, 97, 74, .3); box-shadow: var(--shadow-lg); transform: translateY(-2px); }
}

/* 12px uppercase accent — --a measures 3.22:1 on white and fails; --a-ink is
   5.34:1. This is the exact trap the house rule warns about. */
.tier__label {
  font-size: 12px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--a-ink);
  margin-bottom: 18px;
}
.tier__price {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  margin-bottom: 4px;
}
.tier__price b {
  font-size: clamp(24px, 2.2vw, 30px); font-weight: 700; color: var(--p);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.tier__price span { font-size: 15px; font-weight: 500; color: var(--m); }
.tier__note { font-size: 13.5px; color: var(--mm); margin: 0 0 22px; min-height: 1.4em; }

.tier__feats {
  list-style: none; margin: 0 0 26px; padding: 22px 0 0;
  border-top: 1px solid var(--br-2);
  display: grid; gap: 12px;
}
.tier__feats li {
  position: relative; padding-inline-start: 26px;
  font-size: var(--fs-card); line-height: 1.5; color: var(--m);
}
/* Same check mark as .app-feats, drawn in CSS rather than shipped as an icon
   thirteen times per page. */
.tier__feats li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: .25em;
  width: 16px; height: 16px; border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .12);
}
.tier__feats li::after {
  content: ''; position: absolute; inset-inline-start: 4.5px; top: .54em;
  width: 6.5px; height: 3.5px;
  border-inline-start: 2px solid var(--a-ink);
  border-block-end: 2px solid var(--a-ink);
  transform: rotate(-45deg);
}
.tier__feats li strong { color: var(--p); font-weight: 600; }

/* margin-top:auto pins the CTA to the foot so buttons line up across cards of
   different feature counts. */
.tier .btn { margin-top: auto; justify-content: center; width: 100%; }

/* --- featured -------------------------------------------------------------
   The tint is rgba(240,97,74,.03) over #fff, which measures rgb(255,250,250):
   body copy holds 5.29:1 and the tier label 5.16:1 on it, so nothing inside
   needs a different colour from the plain cards. */
.tier--featured {
  position: relative;
  border-color: var(--a);
  background: rgba(240, 97, 74, .03);
  box-shadow: 0 10px 34px rgba(240, 97, 74, .13);
}
.tier__badge {
  position: absolute; top: 0; inset-inline-start: 26px;
  transform: translateY(-50%);
  padding: 5px 13px; border-radius: var(--r-pill);
  /* White on --a is 3.22:1 and fails at 11px. --a-ink is 5.34:1. */
  background: var(--a-ink); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  white-space: nowrap;
}

/* --- footnote -------------------------------------------------------------
   Usage caveats belong under the grid, not squeezed into every card. */
.pricing-note {
  margin-top: 22px; font-size: 13.5px; color: var(--m); max-width: 70ch;
}

@media (max-width: 1100px) {
  .pricing--4 { --pricing-cols: 2; }
}
@media (max-width: 900px) {
  .pricing--3 { --pricing-cols: 2; }
}
@media (max-width: 620px) {
  .pricing--4, .pricing--3 { --pricing-cols: 1; }
  .tier { padding: 24px 22px; }
  /* Stacked, the badge overlapping the top edge collides with the card above. */
  .tier--featured { margin-top: 12px; }
}

/* --- linked bento cell -----------------------------------------------------
   A cell that navigates somewhere. The whole cell is the anchor rather than a
   link inside it: a 300px-tall card with a 90px "Explore" link at the bottom
   wastes the target, and nesting the link would leave most of the cell dead.

   The global `a { color: var(--a-ink) }` rule would put a light-ground accent on
   a navy panel, so the colour is reset here rather than inherited. */
a.bgrid__cell { text-decoration: none; color: inherit; }
a.bgrid__cell:focus-visible { outline: 2px solid var(--a); outline-offset: -3px; z-index: 2; }
.bgrid--dark a.bgrid__cell:focus-visible { outline-color: var(--a-2); }

.bgrid__go {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 18px;
  font-size: 14px; font-weight: 600;
  color: var(--a-ink);
}
.bgrid--dark .bgrid__go { color: var(--a-2); }   /* --a-ink is unreadable on navy */
.bgrid__go svg { width: 17px; height: 17px; transition: transform var(--dur) var(--ease); }
@media (hover: hover) {
  a.bgrid__cell:hover .bgrid__go svg { transform: translateX(4px); }
}

/* ==========================================================================
   24. PROSE — the default content page
   --------------------------------------------------------------------------
   Long-form flow content: privacy policies, terms, editorial. Everything else
   on this site is componentised, so these are the only rules that style raw
   markup rather than a named block. Scoped to .prose so they cannot leak into a
   component that happens to contain a <ul>.
   ========================================================================== */

/* Full container width, not a reading measure. The 68ch cap this replaced kept
   the text in a narrow column while the heading above it ran the full width,
   which read as a mistake rather than as typesetting.

   NOTE: at 1440px this makes a line roughly 150 characters, well past the 65-75
   comfortable range. That is a deliberate trade the client asked for — the page
   matches the rest of the site's full-width blocks. If long-form readability
   matters more on a specific page, put `style="max-width:68ch"` on that page's
   .prose element rather than changing this rule for all of them. */
.prose { max-width: none; }
.prose > * + * { margin-top: 1.1em; }
.prose p,
.prose ul,
.prose ol,
.prose blockquote { max-width: none; }
.prose p { color: var(--m); }

/* Headings need more space above than below: the gap belongs to the heading's
   relationship with the section it opens, not with the text it precedes. */
.prose h2 { margin-top: 2.2em; margin-bottom: .6em; }
.prose h3 { margin-top: 1.8em; margin-bottom: .5em; }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose > h2 + *, .prose > h3 + * { margin-top: 0; }

.prose ul, .prose ol { margin: 0 0 0 0; padding-inline-start: 22px; color: var(--m); }
.prose li + li { margin-top: .5em; }
.prose li::marker { color: var(--a-ink); }   /* 15px accent — --a-ink, never --a */
.prose ol { list-style: decimal; }
.prose ol li::marker { font-variant-numeric: tabular-nums; font-weight: 600; }

.prose a { color: var(--a-ink); text-underline-offset: .18em; }
.prose a:hover { color: var(--p); }

.prose strong { color: var(--p); font-weight: 600; }

/* Not a side-stripe: a full border and a tinted ground. A 4px left bar is the
   default that never looks deliberate. */
.prose blockquote {
  margin: 1.8em 0;
  padding: 22px 26px;
  border: 1px solid var(--br);
  border-radius: var(--r);
  background: var(--bga);
}
.prose blockquote p { color: var(--p); font-size: 17px; line-height: 1.6; }
.prose blockquote p:last-child { margin-bottom: 0; }

.prose hr { margin: 2.4em 0; border: 0; border-top: 1px solid var(--br); }

.prose code {
  font-family: inherit; font-weight: 600; font-size: .94em;
  color: var(--a-ink);
  background: rgba(240, 97, 74, .09);
  border-radius: 5px; padding: 1px 6px;
}

/* Wide content scrolls inside its own box; the page body never scrolls
   sideways. Same rule as the comparison table. */
.prose__table { overflow-x: auto; margin: 1.8em 0; border: 1px solid var(--br-2); border-radius: var(--r); background: #fff; }
.prose table { width: 100%; min-width: 460px; border-collapse: collapse; font-size: var(--fs-card); }
.prose th, .prose td { padding: 13px 18px; text-align: start; border-bottom: 1px solid var(--br-2); }
.prose thead th { background: var(--bga); color: var(--p); font-weight: 700; white-space: nowrap; }
.prose td { color: var(--m); }
.prose tbody tr:last-child th, .prose tbody tr:last-child td { border-bottom: 0; }

/* Small print: a last-updated line or a legal note under the body. */
.prose__meta {
  margin-top: 2.6em; padding-top: 20px;
  border-top: 1px solid var(--br);
  font-size: 13.5px; color: var(--mm);
}

/* ==========================================================================
   25. TYPE SPECIMEN (/page/)
   --------------------------------------------------------------------------
   A living reference for the type system. The readouts are written by the
   TypeScale component from the browser's own computed values, so this page
   cannot fall out of step with the tokens the way a hand-written spec sheet
   does. Sizes shown are whatever the current viewport resolves each clamp() to.
   ========================================================================== */

.ts-viewport {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: var(--r-pill);
  background: var(--bga); border: 1px solid var(--br);
  font-size: 12.5px; font-weight: 600; color: var(--m);
  font-variant-numeric: tabular-nums;
}
.ts-viewport::before {
  content: ''; width: 7px; height: 7px; border-radius: var(--r-pill);
  background: var(--a);
}

.ts-group { margin-top: 44px; }
.ts-group__label {
  font-size: 12px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--a-ink);            /* 12px accent -> --a-ink, never --a */
  padding-bottom: 12px; margin-bottom: 4px;
  border-bottom: 1px solid var(--br);
}

/* Sample left, readout right. The readout column is fixed so the numbers form a
   scannable column instead of ragging against variable sample widths. */
.ts-row {
  display: grid; gap: 6px 32px;
  grid-template-columns: minmax(0, 1fr) 260px;
  align-items: baseline;
  padding: 18px 0;
  border-bottom: 1px solid var(--br-2);
}
.ts-row > :first-child { min-width: 0; }
.ts-row p, .ts-row h1, .ts-row h2, .ts-row h3, .ts-row h4 { margin: 0; max-width: none; }

.ts-readout {
  font-size: 12.5px; font-weight: 500; color: var(--mm);
  font-variant-numeric: tabular-nums;
  text-align: end;
}
.ts-token {
  display: block; margin-bottom: 3px;
  font-size: 12px; font-weight: 700; color: var(--p);
  text-align: end;
}

/* Weight row: the same word at each available weight, so the steps are
   comparable rather than described. */
.ts-weights { display: grid; gap: 0; }
.ts-weights .ts-row { grid-template-columns: minmax(0, 1fr) 260px; }
.ts-w { font-size: clamp(22px, 2vw, 30px); letter-spacing: -.02em; color: var(--p); }

/* Colour swatches for type, on both grounds the site actually uses. */
.ts-colors { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); margin-top: 18px; }
.ts-swatch { padding: 20px 22px; border-radius: var(--r); border: 1px solid var(--br-2); }
.ts-swatch--light { background: #fff; }
.ts-swatch--alt { background: var(--bga); }
.ts-swatch--navy { background: var(--grad); border-color: var(--on-dark-br); }
.ts-swatch p { margin: 0 0 6px; font-size: var(--fs-card); max-width: none; }
.ts-swatch p:last-child { margin-bottom: 0; }
.ts-swatch code {
  font-family: inherit; font-size: 11.5px; font-weight: 700;
  opacity: .75; letter-spacing: .04em;
}

/* The measure demonstration: three columns of the same paragraph at the widths
   the site actually uses, so the difference is visible rather than asserted. */
.ts-measure { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); margin-top: 18px; }
.ts-measure > div { padding: 20px; border: 1px solid var(--br-2); border-radius: var(--r); background: #fff; }
.ts-measure p { font-size: var(--fs-card); color: var(--m); margin: 0; }
.ts-measure__cap { display: block; margin-bottom: 10px; font-size: 11.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--mm); }

@media (max-width: 760px) {
  .ts-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .ts-readout, .ts-token { text-align: start; }
}

/* ==========================================================================
   26. BLOG
   --------------------------------------------------------------------------
   Listing and article. Reuses .prose for the article body rather than defining
   a second set of flow-content rules.
   ========================================================================== */

/* --- listing --------------------------------------------------------------
   Three across, explicitly. auto-fit with a 320px floor produced FOUR columns
   at a 1400px container, because four 320px tracks fit. When the column count
   is a design decision rather than "as many as fit", state it. */
.post-grid {
  display: grid; gap: clamp(20px, 2.2vw, 28px);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: stretch;
}
@media (max-width: 1040px) { .post-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .post-grid { grid-template-columns: minmax(0, 1fr); } }

/* The whole card is the link. A 380px card with a title-sized link in the
   middle of it wastes the target and leaves most of the card dead. */
.post-card {
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid var(--br-2);
  border-radius: var(--r-lg);
  overflow: hidden;
  text-decoration: none;
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .post-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: rgba(240, 97, 74, .25); }
  .post-card:hover h2 { color: var(--a-ink); }
}
.post-card:focus-visible { outline: 2px solid var(--a); outline-offset: 3px; }

.post-card__media {
  aspect-ratio: 16 / 10;
  background: var(--bga);
  border-bottom: 1px dashed var(--br);
  display: grid; place-items: center;
  color: var(--mm); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; text-align: center;
}
.post-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.post-card__body { padding: 22px 24px 26px; display: flex; flex-direction: column; flex: 1; }
/* Wider than the default 12px. On a card the meta line is a separate band of
   information from the title, and at 12px the pill sat close enough to read as
   part of the heading. Scoped to the card so the article hero, where the meta
   line introduces an h1 directly, keeps the tighter spacing. */
.post-card .post-meta { margin-bottom: 20px; }
/* `text-wrap: balance` is set globally on h1-h4 and it is wrong here. Balance
   evens the line lengths, which on a card title produces "Shopify localization:
   keeping / a store translated after launch" — a short first line and a long
   second one. A card title should fill its line and then wrap. `pretty` keeps
   the orphan control without the balancing. */
.post-card h2 {
  font-size: 18px; line-height: 1.35; color: var(--p);
  margin-bottom: 12px;
  text-wrap: pretty;
  transition: color var(--dur) var(--ease);
}
.post-card p { font-size: 14.5px; line-height: 1.6; color: var(--m); margin: 0; max-width: none; }

/* Metadata line. 12.5px, so any accent here must be --a-ink. */
.post-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin-bottom: 12px;
  font-size: 12.5px; font-weight: 600; color: var(--mm);
}
.post-meta__cat {
  padding: 3px 10px; border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .1); color: var(--a-ink);
  font-size: 11.5px; letter-spacing: .04em;
}
.post-meta__sep { width: 3px; height: 3px; border-radius: 50%; background: var(--br); flex: none; }

/* --- category filter ------------------------------------------------------
   Real <button> elements, not links: this filters in place rather than
   navigating, so a link would lie about what happens on click. Pills left,
   result count right.

   The bar is its own band sitting flush under the hero, on --bga with a bottom
   rule, so it reads as part of the header block rather than as the first item
   in the grid. It is sticky too: with nine cards the pills scroll away
   immediately, and a filter you have to scroll back up to reach is a filter
   most people use once. */
.post-filter-bar {
  position: sticky; top: 88px; z-index: 20;   /* 88px clears the stuck header pill */
  background: var(--bga);
  border-bottom: 1px solid var(--br);
  padding-block: 16px;
  /* Cancel the section's top padding: this band belongs to the hero above it. */
  margin-bottom: clamp(28px, 3vw, 40px);
}
.post-filter {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 14px 20px;
  margin: 0;
}
/* The band is full-bleed, so the section it opens must not add padding above
   it or a stripe of white appears between the hero and the bar. */
.section--flush { padding-top: 0; }
.post-filter__pills { display: flex; flex-wrap: wrap; gap: 8px; }
.post-filter__btn {
  padding: 9px 18px;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  background: #fff; color: var(--m);
  font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), color var(--dur) var(--ease);
}
@media (hover: hover) {
  .post-filter__btn:hover { border-color: var(--a); color: var(--p); }
}
/* Active pill uses the same brand orange and white label as .btn-p, so the
   site has one "this is the active/primary thing" treatment rather than two.
   White on --a measures 3.22:1 — the same trade already accepted on the
   primary button. If that is ever revisited, both should move together. */
.post-filter__btn[aria-pressed="true"],
.post-filter-bar .post-filter__btn[aria-current="page"] {
  background: var(--grad-a-btn); border-color: transparent; color: #fff;
  box-shadow: var(--shadow-sm);
}
.widget__more {
    margin: 16px 0 0 !important;
}
/* On --bga the resting pill needs a slightly stronger edge than it did on white. */
.post-filter-bar .post-filter__btn { border-color: var(--br);text-decoration:none; }
.post-filter__btn:focus-visible { outline: 2px solid var(--a); outline-offset: 2px; }

.post-filter__count { font-size: 14px; color: var(--m); white-space: nowrap; }
.post-filter__query { margin: 0 0 26px; }
.post-filter__count b { color: var(--p); font-weight: 700; font-variant-numeric: tabular-nums; }

/* Filtering removes cards from the flow entirely rather than hiding them, so
   the grid reflows and no empty tracks are left behind. */
.post-card[hidden] { display: none; }

.post-empty { padding: 40px 0; color: var(--m); }

@media (max-width: 620px) {
  .post-filter { gap: 12px; }
  .post-filter__pills { gap: 7px; }
  .post-filter__btn { padding: 10px 15px; font-size: 13.5px; }
  /* Six pills plus a count is two or three rows on a phone. Sticky would then
     eat a third of the viewport, so it releases and scrolls with the page. */
  .post-filter-bar { position: static; }
}

/* --- pagination ----------------------------------------------------------- */
.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 44px; }
.pager a, .pager .pager__current {
    min-width: 42px;
    height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: 14px;
    border: 1px solid var(--br);
    border-radius: var(--r-btn-lg);
    font-size: 14.5px;
    font-weight: 600;
    color: var(--p);
    text-decoration: none;
    transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.pager [aria-current="page"] { background: var(--p); border-color: var(--p); color: #fff; }
.pager [aria-current="page"] [aria-hidden="true"]{color: #fff;}
.pager__gap { border: 0; color: var(--mm); min-width: 0; padding-inline: 4px; }
@media (hover: hover) {
  .pager a:hover { border-color: var(--a); color: var(--a-ink); }
}

/* --- article --------------------------------------------------------------
   Full container width, matching /page/ and the rest of the site's blocks.

   NOTE: at 1440px this puts an article line at roughly 175 characters, well past
   the 65-75 range where sustained reading is comfortable. That is the same trade
   already taken on /page/ and it is the client's call. If a specific long read
   should be narrower, put `style="max-width:74ch"` on that article's .article
   element rather than changing this for all of them. */
.article { max-width: none; }
.article .prose { max-width: none; }

.article__media {
  aspect-ratio: 16 / 9;
  border-radius: var(--r-lg);
  overflow: hidden; margin-bottom: 14px;
  background: var(--bga); border: 1px dashed var(--br);
  display: grid; place-items: center;
  color: var(--mm); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
}
.article__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.article__caption { font-size: 13px; color: var(--mm); margin-bottom: 40px; }

/* Author line, used in the hero and again in the bio block. */
.byline { display: flex; align-items: center; gap: 12px; }
.byline__avatar {
  width: 44px; height: 44px; flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--on-dark-fill); border: 1px solid var(--on-dark-br);
  color: #fff; font-size: 14px; font-weight: 700;
}
.byline__name { font-size: 14.5px; font-weight: 600; color: #fff; }
.byline__role { font-size: 12.5px; color: var(--on-dark-3); }

/* Light-ground variant for the bio block under the article. */
.author-card {
  display: flex; gap: 18px; align-items: flex-start;
  margin-top: 48px; padding: 26px;
  border: 1px solid var(--br-2); border-radius: var(--r-lg); background: var(--bga);
}
.author-card .byline__avatar { background: var(--p); border-color: var(--p); }
.author-card h3 { font-size: 16px; margin-bottom: 4px; }
.author-card p { font-size: var(--fs-card); color: var(--m); margin: 0; max-width: 56ch; }

/* --- share ---------------------------------------------------------------- */
.share { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--br); }
.share__label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--mm); margin-inline-end: 4px; }
.share a {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  color: var(--m);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.share a svg { width: 17px; height: 17px; }
@media (hover: hover) {
  .share a:hover { border-color: var(--a); color: var(--a-ink); }
}

@media (max-width: 760px) {
  .author-card { flex-direction: column; gap: 14px; }
}


/* --- article layout with sidebar ------------------------------------------
   Body and sidebar. The sidebar is sticky on desktop and moves BELOW the
   article on narrow screens, not above it: a reader who opened an article wants
   the article, and a column of promotional cards before the first paragraph is
   the pattern that makes people leave. */
.article-layout {
  display: grid;
  gap: clamp(32px, 4vw, 56px);
  grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
  align-items: start;
}
.aside { position: sticky; top: 104px; display: grid; gap: 20px; }   /* 104px clears the stuck header */

.widget { padding: 22px; border: 1px solid var(--br-2); border-radius: var(--r-lg); background: #fff; }
.widget__title {
  font-size: 12px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--a-ink);            /* 12px accent -> --a-ink, never --a */
  margin-bottom: 16px;
}

/* Search. A real GET form so it works with JS off: it lands on /blogs/?q=…,
   which the index reads. There is no search backend, and pretending otherwise
   with a dead box would be worse than a form that actually filters. */
.widget__search { display: flex; gap: 8px; }
.widget__search input {
  flex: 1; min-width: 0;
  padding: 11px 14px;
  border: 1px solid var(--br); border-radius: var(--r-btn);
  background: var(--bg); color: var(--p);
  font-size: 14.5px;
}
.widget__search input::placeholder { color: var(--mm); }   /* --mm is 4.4:1 on --bg; see note */
.widget__search input:focus-visible { outline: 2px solid var(--a); outline-offset: 1px; border-color: transparent; }
.widget__search button {
  flex: none; width: 42px; height: 42px;
  display: grid; place-items: center;
  border: 0; border-radius: var(--r-btn);
  background: var(--p); color: #fff; cursor: pointer;
}
.widget__search button svg { width: 17px; height: 17px; }

/* Category list */
.widget__cats { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.widget__cats a {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; margin-inline: -12px;
  border-radius: var(--r-btn);
  font-size: 14.5px; font-weight: 500; color: var(--m); text-decoration: none;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.widget__cats b { font-size: 12.5px; font-weight: 600; color: var(--mm); font-variant-numeric: tabular-nums; }
@media (hover: hover) {
  .widget__cats a:hover { background: var(--bga); color: var(--p); }
}

/* Promo. Navy, because it is an advert inside editorial and should read as one
   rather than pretending to be another article. */
.widget--promo {
  background: var(--grad); border-color: transparent; color: var(--on-dark-2);
}
.widget--promo .widget__title { color: var(--a-2); }   /* --a-ink is unreadable on navy */
.widget--promo h3 { color: #fff; font-size: 17px; margin-bottom: 8px; }
.widget--promo p { font-size: 14px; line-height: 1.55; color: var(--on-dark-3); margin: 0 0 16px; max-width: none; }
.widget--promo .btn { width: 100%; justify-content: center; }

.widget__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.widget__item { display: flex; gap: 12px; align-items: flex-start; text-decoration: none; }
.widget__item i {
  width: 34px; height: 34px; flex: none;
  border-radius: var(--r-btn);
  background: rgba(255, 255, 255, .1);
  display: grid; place-items: center;
  color: #fff; font-size: 12px; font-weight: 700; font-style: normal;
}
.widget__item strong { display: block; font-size: 14.5px; color: #fff; font-weight: 600; }
.widget__item span { font-size: 12.5px; color: var(--on-dark-3); }
@media (hover: hover) {
  .widget__item:hover strong { color: var(--a-2); }
}

@media (max-width: 1040px) {
  /* minmax(0, 1fr), NOT a bare 1fr. `1fr` is shorthand for minmax(auto, 1fr),
     and the `auto` minimum refuses to shrink below the content's min-content
     width. The article contains a table with `min-width: 460px`, so on a 320px
     phone the track sized itself to 462px and pushed the page 158px wide. The
     table's own `overflow-x: auto` wrapper does not help: a scroll container
     still reports its content's min-content to the grid unless the track is
     explicitly allowed to go to zero. */
  .article-layout { grid-template-columns: minmax(0, 1fr); }
  .aside { position: static; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
}

/* --- comments -------------------------------------------------------------
   List then form. The form goes AFTER the thread: someone who has just read an
   article wants to see whether their point has already been made before they
   make it, and a form above the discussion invites duplicates. */
.comments { margin-top: 56px; padding-top: 40px; border-top: 1px solid var(--br); }
.comments__head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 14px;
  margin-bottom: 28px;
}
.comments__head h2 { font-size: clamp(20px, 1.9vw, 26px); }
.comments__count {
  padding: 3px 11px; border-radius: var(--r-pill);
  background: rgba(20, 54, 94, .08); color: var(--p-2);
  font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}

.comment-list { list-style: none; margin: 0 0 40px; padding: 0; display: grid; gap: 4px; }
.comment { padding: 22px 0; border-bottom: 1px solid var(--br-2); }
.comment:last-child { border-bottom: 0; }
.comment__head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.comment__avatar {
  width: 40px; height: 40px; flex: none;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--p); color: #fff;
  font-size: 13px; font-weight: 700;
}
.comment__who { min-width: 0; }
.comment__name { display: block; font-size: 14.5px; font-weight: 600; color: var(--p); }
.comment__date { display: block; font-size: 12.5px; color: var(--mm); }
.comment__body { font-size: var(--fs-card); line-height: 1.65; color: var(--m); margin: 0; max-width: 68ch; }
.comment__body + .comment__actions { margin-top: 12px; }
.comment__actions { display: flex; gap: 16px; }
.comment__reply {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--a-ink);            /* 13.5px accent -> --a-ink, never --a */
}
.comment__reply:hover { color: var(--p); }
.comment__reply:focus-visible { outline: 2px solid var(--a); outline-offset: 3px; border-radius: 4px; }

/* One level of nesting only. Deeper threads on a marketing blog turn into a
   horizontal-space problem long before they turn into a conversation. */
.comment__replies { list-style: none; margin: 20px 0 0; padding: 0 0 0 26px; border-inline-start: 1px solid var(--br); display: grid; gap: 4px; }
.comment__replies .comment { padding-block: 18px; }
.comment__replies .comment__avatar { width: 34px; height: 34px; font-size: 12px; }

/* Author badge, so a reply from the writer is distinguishable from a reply by
   anyone else. */
.comment__badge {
  margin-inline-start: 8px; padding: 2px 8px;
  border-radius: var(--r-pill);
  background: rgba(240, 97, 74, .1); color: var(--a-ink);
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}

/* Form. Reuses .sh-form-card so it validates and traps bots exactly like the
   contact and booking forms rather than being a second implementation. */
.comment-form { padding: 28px; border: 1px solid var(--br-2); border-radius: var(--r-lg); background: var(--bga); }
.comment-form h3 { font-size: 18px; margin-bottom: 6px; }
.comment-form > p { font-size: var(--fs-card); color: var(--m); margin-bottom: 22px; max-width: 60ch; }
.comment-form .sh-form-card { background: none; border: 0; box-shadow: none; padding: 0; }
.contact-form{text-align:var(--sh-lab-align);}
@media (max-width: 620px) {
  .comment__replies { padding-inline-start: 16px; }
  .comment-form { padding: 22px 20px; }
}

/* ==========================================================================
   14. SHOPIFY SECTION RHYTHM
   --------------------------------------------------------------------------
   The only addition made during the move to Shopify. Nothing above this line
   was touched.

   On the static site the interior page body was one <section class="section">
   containing several sibling .svc-block elements, and this rule supplied the
   gap between them:

       .svc-block + .svc-block { margin-top: 72px; }   /* 56px below 1024px */

   In a theme each block is its own section, and Shopify wraps every section in
   its own <div class="shopify-section">. The blocks are therefore no longer
   siblings and that rule can never match again.

   Half the gap on each side of every block reproduces the same 72/56px rhythm,
   and — unlike the sibling rule — it keeps working whatever order a merchant
   drags the sections into, which is the point of being on OS 2.0. The first and
   last block in <main> take the full section padding instead, so the body still
   clears the hero above it and the footer below it.
   ========================================================================== */
.svc-section { padding-block: 36px; }
.svc-section > .wrap > .svc-layout > .svc-block { margin-top: 0; }

@media (max-width: 1023px) {
  .svc-section { padding-block: 28px; }
}

/* The first body block on a page takes the full section padding above it, and
   the last takes it below — so the body clears the hero above and the closing
   band below by exactly the distance the single .section wrapper used to give.

   :has() is doing the work, and it has to: a section has no other way to know
   whether its neighbour is a body block. Position selectors cannot answer it
   either — the first .shopify-section inside <main> is the HERO, not the first
   body block, and the last is the CTA band. An earlier version of this rule
   used :first-child/:last-child and therefore matched nothing at all, leaving
   the body 50px short of the hero and 50px short of the closing band.

   Specificity here comfortably beats the plain .svc-section rules above, so the
   mobile override cannot reset these back to 28px. */
main > .shopify-section:has(.svc-section):first-child .svc-section,
main > .shopify-section:not(:has(.svc-section)) + .shopify-section:has(.svc-section) .svc-section {
  padding-block-start: var(--section-y);
}

main > .shopify-section:has(.svc-section):not(:has(+ .shopify-section .svc-section)) .svc-section {
  padding-block-end: var(--section-y);
}

/* --- pagination -----------------------------------------------------------
   New in the theme: the static blog index listed every article on one page, so
   there was nothing to page through. Styled from the existing tokens rather
   than invented — same pill radius, border and accent as .post-filter__btn. */
.pagination { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: start; }
.pagination a,
.pagination > span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; min-height: 40px; padding: 0 14px;
  border: 1px solid var(--br); border-radius: var(--r-pill);
  font-size: 14px; font-weight: 600; color: var(--m); text-decoration: none;
  transition: border-color .15s cubic-bezier(.4,0,.2,1), color .15s cubic-bezier(.4,0,.2,1);
}
.p_top_0{padding-top:0;}
.pagination a:hover { border-color: var(--a); color: var(--p); }
.pagination [aria-current="page"] { background:var(--p);border-color: var(--p); color: #fff; }
.pagination__gap { border: 0; min-width: 0; padding: 0 4px; }
