/* Theme */

/* =============================================================
   Color System v2
   Hex-based palette. Four scales (Purple, Blue, Green, Yellow)
   each with dark / medium / regular / light stops, plus flat
   brand tokens and the Fusion gradient.
   ============================================================= */

:root {

  /* ── Grey scale ─────────────────────────────────────────── */
  --c-grey-00: #000000;
  --c-grey-01: #0D0D18;
  --c-grey-02: #161722;
  --c-grey-03: #252736;
  --c-grey-04: #36384A;
  --c-grey-05: #6A6B83;
  --c-grey-06: #A3A4BF;
  --c-grey-07: #D5D6EA;
  --c-grey-08: #E8E9F3;
  --c-grey-09: #F5F5F8;
  --c-grey-10: #FDFDFD;

  /* Page/body canvas + text — the single source of truth for the page.
     `body` background/color and the bg-glow edge fade reference these, so a
     fade dissolves into whatever the page is and text stays legible on it.
     Override both at page/template scope to flip a page light (see the
     body.bg-* rules in _typography.css). */
  --body-bg: var(--c-grey-01);
  --body-fg: var(--c-grey-09);

  /* ── Brand ─────────────────────────────────────────────── */
  --c-periwinkle:        #4864FF;
  --c-periwinkle-light:  #7A8FFF;
  --c-aqua:              #1ED4AA;
  --c-coral:             #FF815C;
  --c-black:             #000000;
  --c-white:             #FFFFFF;

  /* Fusion gradient (use --c-fusion with background-image) */
  --c-fusion-from:  #4864FF;
  --c-fusion-to:    #1ED4AA;
  --c-fusion:       linear-gradient(to right, var(--c-fusion-from), var(--c-fusion-to));

  /* ── Purple ─────────────────────────────────────────────── */
  --c-purple-dark:    #330069;
  --c-purple-medium:  #7F39C9;
  --c-purple-regular: #BE81FF;
  --c-purple-light:   #DEBFFF;

  /* ── Blue ───────────────────────────────────────────────── */
  --c-blue-dark:    #004148;
  --c-blue-medium:  #00A1B4;
  --c-blue-regular: #00E5FF;
  --c-blue-light:   #AAF5FF;

  /* ── Green ──────────────────────────────────────────────── */
  --c-green-dark:    #075000;
  --c-green-medium:  #12B902;
  --c-green-regular: #4FFF40;
  --c-green-light:   #BAFFB4;

  /* ── Yellow ─────────────────────────────────────────────── */
  --c-yellow-dark:    #524400;
  --c-yellow-medium:  #C1A000;
  --c-yellow-regular: #FFEE1E;
  --c-yellow-light:   #FFFAB9;

}


/* =============================================================
   TEXT COLOR CLASSES
   ============================================================= */

/* Grey */
.c-grey-00 { color: var(--c-grey-00); }
.c-grey-01 { color: var(--c-grey-01); }
.c-grey-02 { color: var(--c-grey-02); }
.c-grey-03 { color: var(--c-grey-03); }
.c-grey-04 { color: var(--c-grey-04); }
.c-grey-05 { color: var(--c-grey-05); }
.c-grey-06 { color: var(--c-grey-06); }
.c-grey-07 { color: var(--c-grey-07); }
.c-grey-08 { color: var(--c-grey-08); }
.c-grey-09 { color: var(--c-grey-09); }
.c-grey-10 { color: var(--c-grey-10); }

/* Brand */
.c-periwinkle       { color: var(--c-periwinkle); }
.c-periwinkle-light { color: var(--c-periwinkle-light); }
.c-aqua             { color: var(--c-aqua); }
.c-coral            { color: var(--c-coral); }
.c-black            { color: var(--c-black); }
.c-white            { color: var(--c-white); }

/* Purple */
.c-purple-dark    { color: var(--c-purple-dark); }
.c-purple-medium  { color: var(--c-purple-medium); }
.c-purple-regular { color: var(--c-purple-regular); }
.c-purple-light   { color: var(--c-purple-light); }
.c-purple         { color: var(--c-purple-regular); }

/* Blue */
.c-blue-dark    { color: var(--c-blue-dark); }
.c-blue-medium  { color: var(--c-blue-medium); }
.c-blue-regular { color: var(--c-blue-regular); }
.c-blue-light   { color: var(--c-blue-light); }
.c-blue         { color: var(--c-blue-regular); }

/* Green */
.c-green-dark    { color: var(--c-green-dark); }
.c-green-medium  { color: var(--c-green-medium); }
.c-green-regular { color: var(--c-green-regular); }
.c-green-light   { color: var(--c-green-light); }
.c-green         { color: var(--c-green-regular); }

/* Yellow */
.c-yellow-dark    { color: var(--c-yellow-dark); }
.c-yellow-medium  { color: var(--c-yellow-medium); }
.c-yellow-regular { color: var(--c-yellow-regular); }
.c-yellow-light   { color: var(--c-yellow-light); }
.c-yellow         { color: var(--c-yellow-regular); }


/* =============================================================
   BACKGROUND COLOR CLASSES
   ============================================================= */

/* Grey */
.bg-grey-00 { background-color: var(--c-grey-00); }
.bg-grey-01 { background-color: var(--c-grey-01); }
.bg-grey-02 { background-color: var(--c-grey-02); }
.bg-grey-03 { background-color: var(--c-grey-03); }
.bg-grey-04 { background-color: var(--c-grey-04); }
.bg-grey-05 { background-color: var(--c-grey-05); }
.bg-grey-06 { background-color: var(--c-grey-06); }
.bg-grey-07 { background-color: var(--c-grey-07); }
.bg-grey-08 { background-color: var(--c-grey-08); }
.bg-grey-09 { background-color: var(--c-grey-09); }
.bg-grey-10 { background-color: var(--c-grey-10); }

/* Brand */
.bg-periwinkle       { background-color: var(--c-periwinkle); }
.bg-periwinkle-light { background-color: var(--c-periwinkle-light); }
.bg-aqua             { background-color: var(--c-aqua); }
.bg-coral            { background-color: var(--c-coral); }
.bg-black            { background-color: var(--c-black); }
.bg-white            { background-color: var(--c-white); }

/* Fusion gradient */
.bg-fusion { background-image: var(--c-fusion); }

/* Purple */
.bg-purple-dark    { background-color: var(--c-purple-dark); }
.bg-purple-medium  { background-color: var(--c-purple-medium); }
.bg-purple-regular { background-color: var(--c-purple-regular); }
.bg-purple-light   { background-color: var(--c-purple-light); }
.bg-purple         { background-color: var(--c-purple-regular); }

/* Blue */
.bg-blue-dark    { background-color: var(--c-blue-dark); }
.bg-blue-medium  { background-color: var(--c-blue-medium); }
.bg-blue-regular { background-color: var(--c-blue-regular); }
.bg-blue-light   { background-color: var(--c-blue-light); }
.bg-blue         { background-color: var(--c-blue-regular); }

/* Green */
.bg-green-dark    { background-color: var(--c-green-dark); }
.bg-green-medium  { background-color: var(--c-green-medium); }
.bg-green-regular { background-color: var(--c-green-regular); }
.bg-green-light   { background-color: var(--c-green-light); }
.bg-green         { background-color: var(--c-green-regular); }

/* Yellow */
.bg-yellow-dark    { background-color: var(--c-yellow-dark); }
.bg-yellow-medium  { background-color: var(--c-yellow-medium); }
.bg-yellow-regular { background-color: var(--c-yellow-regular); }
.bg-yellow-light   { background-color: var(--c-yellow-light); }
.bg-yellow         { background-color: var(--c-yellow-regular); }


/* =============================================================
   BORDER COLOR CLASSES
   ============================================================= */

/* Grey */
.b-grey-00 { border: 1px solid var(--c-grey-00); }
.b-grey-01 { border: 1px solid var(--c-grey-01); }
.b-grey-02 { border: 1px solid var(--c-grey-02); }
.b-grey-03 { border: 1px solid var(--c-grey-03); }
.b-grey-04 { border: 1px solid var(--c-grey-04); }
.b-grey-05 { border: 1px solid var(--c-grey-05); }
.b-grey-06 { border: 1px solid var(--c-grey-06); }
.b-grey-07 { border: 1px solid var(--c-grey-07); }
.b-grey-08 { border: 1px solid var(--c-grey-08); }
.b-grey-09 { border: 1px solid var(--c-grey-09); }
.b-grey-10 { border: 1px solid var(--c-grey-10); }

/* Brand */
.b-periwinkle       { border: 1px solid var(--c-periwinkle); }
.b-periwinkle-light { border: 1px solid var(--c-periwinkle-light); }
.b-aqua             { border: 1px solid var(--c-aqua); }
.b-coral            { border: 1px solid var(--c-coral); }
.b-black            { border: 1px solid var(--c-black); }
.b-white            { border: 1px solid var(--c-white); }

/* Purple */
.b-purple-dark    { border: 1px solid var(--c-purple-dark); }
.b-purple-medium  { border: 1px solid var(--c-purple-medium); }
.b-purple-regular { border: 1px solid var(--c-purple-regular); }
.b-purple-light   { border: 1px solid var(--c-purple-light); }
.b-purple         { border: 1px solid var(--c-purple-regular); }

/* Blue */
.b-blue-dark    { border: 1px solid var(--c-blue-dark); }
.b-blue-medium  { border: 1px solid var(--c-blue-medium); }
.b-blue-regular { border: 1px solid var(--c-blue-regular); }
.b-blue-light   { border: 1px solid var(--c-blue-light); }
.b-blue         { border: 1px solid var(--c-blue-regular); }

/* Green */
.b-green-dark    { border: 1px solid var(--c-green-dark); }
.b-green-medium  { border: 1px solid var(--c-green-medium); }
.b-green-regular { border: 1px solid var(--c-green-regular); }
.b-green-light   { border: 1px solid var(--c-green-light); }
.b-green         { border: 1px solid var(--c-green-regular); }

/* Yellow */
.b-yellow-dark    { border: 1px solid var(--c-yellow-dark); }
.b-yellow-medium  { border: 1px solid var(--c-yellow-medium); }
.b-yellow-regular { border: 1px solid var(--c-yellow-regular); }
.b-yellow-light   { border: 1px solid var(--c-yellow-light); }
.b-yellow         { border: 1px solid var(--c-yellow-regular); }


/* =============================================================
   BORDER-TOP / BORDER-BOTTOM CLASSES
   For use as dividers — same color palette as the full-border
   variants above, but applied to one edge only.
   ============================================================= */

/* Grey */
.bt-grey-00 { border-top: 1px solid var(--c-grey-00); }
.bt-grey-01 { border-top: 1px solid var(--c-grey-01); }
.bt-grey-02 { border-top: 1px solid var(--c-grey-02); }
.bt-grey-03 { border-top: 1px solid var(--c-grey-03); }
.bt-grey-04 { border-top: 1px solid var(--c-grey-04); }
.bt-grey-05 { border-top: 1px solid var(--c-grey-05); }
.bt-grey-06 { border-top: 1px solid var(--c-grey-06); }
.bt-grey-07 { border-top: 1px solid var(--c-grey-07); }
.bt-grey-08 { border-top: 1px solid var(--c-grey-08); }
.bt-grey-09 { border-top: 1px solid var(--c-grey-09); }
.bt-grey-10 { border-top: 1px solid var(--c-grey-10); }

.bb-grey-00 { border-bottom: 1px solid var(--c-grey-00); }
.bb-grey-01 { border-bottom: 1px solid var(--c-grey-01); }
.bb-grey-02 { border-bottom: 1px solid var(--c-grey-02); }
.bb-grey-03 { border-bottom: 1px solid var(--c-grey-03); }
.bb-grey-04 { border-bottom: 1px solid var(--c-grey-04); }
.bb-grey-05 { border-bottom: 1px solid var(--c-grey-05); }
.bb-grey-06 { border-bottom: 1px solid var(--c-grey-06); }
.bb-grey-07 { border-bottom: 1px solid var(--c-grey-07); }
.bb-grey-08 { border-bottom: 1px solid var(--c-grey-08); }
.bb-grey-09 { border-bottom: 1px solid var(--c-grey-09); }
.bb-grey-10 { border-bottom: 1px solid var(--c-grey-10); }

/* Brand */
.bt-periwinkle       { border-top: 1px solid var(--c-periwinkle); }
.bt-periwinkle-light { border-top: 1px solid var(--c-periwinkle-light); }
.bt-aqua             { border-top: 1px solid var(--c-aqua); }
.bt-coral            { border-top: 1px solid var(--c-coral); }
.bt-black            { border-top: 1px solid var(--c-black); }
.bt-white            { border-top: 1px solid var(--c-white); }

.bb-periwinkle       { border-bottom: 1px solid var(--c-periwinkle); }
.bb-periwinkle-light { border-bottom: 1px solid var(--c-periwinkle-light); }
.bb-aqua             { border-bottom: 1px solid var(--c-aqua); }
.bb-coral            { border-bottom: 1px solid var(--c-coral); }
.bb-black            { border-bottom: 1px solid var(--c-black); }
.bb-white            { border-bottom: 1px solid var(--c-white); }

/* Purple */
.bt-purple-dark    { border-top: 1px solid var(--c-purple-dark); }
.bt-purple-medium  { border-top: 1px solid var(--c-purple-medium); }
.bt-purple-regular { border-top: 1px solid var(--c-purple-regular); }
.bt-purple-light   { border-top: 1px solid var(--c-purple-light); }
.bt-purple         { border-top: 1px solid var(--c-purple-regular); }

.bb-purple-dark    { border-bottom: 1px solid var(--c-purple-dark); }
.bb-purple-medium  { border-bottom: 1px solid var(--c-purple-medium); }
.bb-purple-regular { border-bottom: 1px solid var(--c-purple-regular); }
.bb-purple-light   { border-bottom: 1px solid var(--c-purple-light); }
.bb-purple         { border-bottom: 1px solid var(--c-purple-regular); }

/* Blue */
.bt-blue-dark    { border-top: 1px solid var(--c-blue-dark); }
.bt-blue-medium  { border-top: 1px solid var(--c-blue-medium); }
.bt-blue-regular { border-top: 1px solid var(--c-blue-regular); }
.bt-blue-light   { border-top: 1px solid var(--c-blue-light); }
.bt-blue         { border-top: 1px solid var(--c-blue-regular); }

.bb-blue-dark    { border-bottom: 1px solid var(--c-blue-dark); }
.bb-blue-medium  { border-bottom: 1px solid var(--c-blue-medium); }
.bb-blue-regular { border-bottom: 1px solid var(--c-blue-regular); }
.bb-blue-light   { border-bottom: 1px solid var(--c-blue-light); }
.bb-blue         { border-bottom: 1px solid var(--c-blue-regular); }

/* Green */
.bt-green-dark    { border-top: 1px solid var(--c-green-dark); }
.bt-green-medium  { border-top: 1px solid var(--c-green-medium); }
.bt-green-regular { border-top: 1px solid var(--c-green-regular); }
.bt-green-light   { border-top: 1px solid var(--c-green-light); }
.bt-green         { border-top: 1px solid var(--c-green-regular); }

.bb-green-dark    { border-bottom: 1px solid var(--c-green-dark); }
.bb-green-medium  { border-bottom: 1px solid var(--c-green-medium); }
.bb-green-regular { border-bottom: 1px solid var(--c-green-regular); }
.bb-green-light   { border-bottom: 1px solid var(--c-green-light); }
.bb-green         { border-bottom: 1px solid var(--c-green-regular); }

/* Yellow */
.bt-yellow-dark    { border-top: 1px solid var(--c-yellow-dark); }
.bt-yellow-medium  { border-top: 1px solid var(--c-yellow-medium); }
.bt-yellow-regular { border-top: 1px solid var(--c-yellow-regular); }
.bt-yellow-light   { border-top: 1px solid var(--c-yellow-light); }
.bt-yellow         { border-top: 1px solid var(--c-yellow-regular); }

.bb-yellow-dark    { border-bottom: 1px solid var(--c-yellow-dark); }
.bb-yellow-medium  { border-bottom: 1px solid var(--c-yellow-medium); }
.bb-yellow-regular { border-bottom: 1px solid var(--c-yellow-regular); }
.bb-yellow-light   { border-bottom: 1px solid var(--c-yellow-light); }
.bb-yellow         { border-bottom: 1px solid var(--c-yellow-regular); }

:root {
  --spacing-4xs: clamp(0.25rem, 0.227vw + 0.193rem, 0.375rem);
  --spacing-3xs: clamp(0.375rem, 0.227vw + 0.318rem, 0.5rem);
  --spacing-2xs: clamp(0.5rem, 0.227vw + 0.443rem, 0.625rem);
  --spacing-xs: clamp(0.625rem, 0.227vw + 0.568rem, 0.75rem);
  --spacing-s: clamp(0.75rem, 0.227vw + 0.693rem, 0.875rem);
  --spacing-m: clamp(0.875rem, 0.227vw + 0.818rem, 1rem);
  --spacing-l: clamp(1rem, 0.751vw + 0.824rem, 1.5rem);
  --spacing-xl: clamp(1.5rem, 0.909vw + 1.273rem, 2rem);
  --spacing-2xl: clamp(2rem, 1.818vw + 1.545rem, 3rem);
  --spacing-3xl: clamp(3rem, 1.818vw + 2.545rem, 4rem);
  --spacing-4xl: clamp(4rem, 1.818vw + 3.545rem, 5rem);
  --spacing-5xl: clamp(5rem, 1.818vw + 4.545rem, 6rem);
  --spacing-6xl: clamp(6rem, 1.818vw + 5.545rem, 7rem);
  --spacing-7xl: clamp(7rem, 1.818vw + 6.545rem, 8rem);
  --spacing-8xl: clamp(8rem, 1.818vw + 7.545rem, 9rem);
}

/* ========== Padding ========== */

.p-4xs {
  padding: var(--spacing-4xs);
}
.p-3xs {
  padding: var(--spacing-3xs);
}
.p-2xs {
  padding: var(--spacing-2xs);
}
.p-xs {
  padding: var(--spacing-xs);
}
.p-s {
  padding: var(--spacing-s);
}
.p-m {
  padding: var(--spacing-m);
}
.p-l {
  padding: var(--spacing-l);
}
.p-xl {
  padding: var(--spacing-xl);
}
.p-2xl {
  padding: var(--spacing-2xl);
}
.p-3xl {
  padding: var(--spacing-3xl);
}
.p-4xl {
  padding: var(--spacing-4xl);
}
.p-5xl {
  padding: var(--spacing-5xl);
}
.p-6xl {
  padding: var(--spacing-6xl);
}
.p-7xl {
  padding: var(--spacing-7xl);
}
.p-8xl {
  padding: var(--spacing-8xl);
}

/* ========== Padding Bottom ========== */

.pb-4xs {
  padding-bottom: var(--spacing-4xs);
}
.pb-3xs {
  padding-bottom: var(--spacing-3xs);
}
.pb-2xs {
  padding-bottom: var(--spacing-2xs);
}
.pb-xs {
  padding-bottom: var(--spacing-xs);
}
.pb-s {
  padding-bottom: var(--spacing-s);
}
.pb-m {
  padding-bottom: var(--spacing-m);
}
.pb-l {
  padding-bottom: var(--spacing-l);
}
.pb-xl {
  padding-bottom: var(--spacing-xl);
}
.pb-2xl {
  padding-bottom: var(--spacing-2xl);
}
.pb-3xl {
  padding-bottom: var(--spacing-3xl);
}
.pb-4xl {
  padding-bottom: var(--spacing-4xl);
}
.pb-5xl {
  padding-bottom: var(--spacing-5xl);
}
.pb-6xl {
  padding-bottom: var(--spacing-6xl);
}
.pb-7xl {
  padding-bottom: var(--spacing-7xl);
}
.pb-8xl {
  padding-bottom: var(--spacing-8xl);
}

/* ========== Padding Bottom ========== */

.pt-4xs {
  padding-top: var(--spacing-4xs);
}
.pt-3xs {
  padding-top: var(--spacing-3xs);
}
.pt-2xs {
  padding-top: var(--spacing-2xs);
}
.pt-xs {
  padding-top: var(--spacing-xs);
}
.pt-s {
  padding-top: var(--spacing-s);
}
.pt-m {
  padding-top: var(--spacing-m);
}
.pt-l {
  padding-top: var(--spacing-l);
}
.pt-xl {
  padding-top: var(--spacing-xl);
}
.pt-2xl {
  padding-top: var(--spacing-2xl);
}
.pt-3xl {
  padding-top: var(--spacing-3xl);
}
.pt-4xl {
  padding-top: var(--spacing-4xl);
}
.pt-5xl {
  padding-top: var(--spacing-5xl);
}
.pt-6xl {
  padding-top: var(--spacing-6xl);
}
.pt-7xl {
  padding-top: var(--spacing-7xl);
}
.pt-8xl {
  padding-top: var(--spacing-8xl);
}

/* ========== Padding Right ========== */

.pr-4xs {
  padding-right: var(--spacing-4xs);
}
.pr-3xs {
  padding-right: var(--spacing-3xs);
}
.pr-2xs {
  padding-right: var(--spacing-2xs);
}
.pr-xs {
  padding-right: var(--spacing-xs);
}
.pr-s {
  padding-right: var(--spacing-s);
}
.pr-m {
  padding-right: var(--spacing-m);
}
.pr-l {
  padding-right: var(--spacing-l);
}
.pr-xl {
  padding-right: var(--spacing-xl);
}
.pr-2xl {
  padding-right: var(--spacing-2xl);
}
.pr-3xl {
  padding-right: var(--spacing-3xl);
}
.pr-4xl {
  padding-right: var(--spacing-4xl);
}
.pr-5xl {
  padding-right: var(--spacing-5xl);
}
.pr-6xl {
  padding-right: var(--spacing-6xl);
}
.pr-7xl {
  padding-right: var(--spacing-7xl);
}
.pr-8xl {
  padding-right: var(--spacing-8xl);
}

/* ========== Padding Left ========== */

.pl-4xs {
  padding-left: var(--spacing-4xs);
}
.pl-3xs {
  padding-left: var(--spacing-3xs);
}
.pl-2xs {
  padding-left: var(--spacing-2xs);
}
.pl-xs {
  padding-left: var(--spacing-xs);
}
.pl-s {
  padding-left: var(--spacing-s);
}
.pl-m {
  padding-left: var(--spacing-m);
}
.pl-l {
  padding-left: var(--spacing-l);
}
.pl-xl {
  padding-left: var(--spacing-xl);
}
.pl-2xl {
  padding-left: var(--spacing-2xl);
}
.pl-3xl {
  padding-left: var(--spacing-3xl);
}
.pl-4xl {
  padding-left: var(--spacing-4xl);
}
.pl-5xl {
  padding-left: var(--spacing-5xl);
}
.pl-6xl {
  padding-left: var(--spacing-6xl);
}
.pl-7xl {
  padding-left: var(--spacing-7xl);
}
.pl-8xl {
  padding-left: var(--spacing-8xl);
}

/* ========== Padding Cancel ========== */

.p-t-0 {
  padding-top: 0;
}
.p-r-0 {
  padding-right: 0;
}
.p-b-0 {
  padding-bottom: 0;
}
.p-l-0 {
  padding-left: 0;
}

/* ========== Margin ========== */

.m-s {
  margin: var(--spacing-s);
}
.m-m {
  margin: var(--spacing-m);
}
.m-l {
  margin: var(--spacing-l);
}
.m-xl {
  margin: var(--spacing-xl);
}
.m-2xl {
  margin: var(--spacing-2xl);
}
.m-3xl {
  margin: var(--spacing-3xl);
}
.m-4xl {
  margin: var(--spacing-4xl);
}

/* ========== Margin Bottom ========== */

.mb-s {
  margin-bottom: var(--spacing-s);
}
.mb-m {
  margin-bottom: var(--spacing-m);
}
.mb-l {
  margin-bottom: var(--spacing-l);
}
.mb-xl {
  margin-bottom: var(--spacing-xl);
}
.mb-2xl {
  margin-bottom: var(--spacing-2xl);
}
.mb-3xl {
  margin-bottom: var(--spacing-3xl);
}
.mb-4xl {
  margin-bottom: var(--spacing-4xl);
}

/* ========== Margin Top ========== */

.mt-s {
  margin-top: var(--spacing-s);
}
.mt-m {
  margin-top: var(--spacing-m);
}
.mt-l {
  margin-top: var(--spacing-l);
}
.mt-xl {
  margin-top: var(--spacing-xl);
}
.mt-2xl {
  margin-top: var(--spacing-2xl);
}
.mt-3xl {
  margin-top: var(--spacing-3xl);
}
.mt-4xl {
  margin-top: var(--spacing-4xl);
}

/* ========== Margin Right ========== */

.mr-s {
  margin-right: var(--spacing-s);
}
.mr-m {
  margin-right: var(--spacing-m);
}
.mr-l {
  margin-right: var(--spacing-l);
}
.mr-xl {
  margin-right: var(--spacing-xl);
}
.mr-2xl {
  margin-right: var(--spacing-2xl);
}
.mr-3xl {
  margin-right: var(--spacing-3xl);
}
.mr-4xl {
  margin-right: var(--spacing-4xl);
}

/* ========== Margin Left ========== */

.ml-s {
  margin-left: var(--spacing-s);
}
.ml-m {
  margin-left: var(--spacing-m);
}
.ml-l {
  margin-left: var(--spacing-l);
}
.ml-xl {
  margin-left: var(--spacing-xl);
}
.ml-2xl {
  margin-left: var(--spacing-2xl);
}
.ml-3xl {
  margin-left: var(--spacing-3xl);
}
.ml-4xl {
  margin-left: var(--spacing-4xl);
}

/* Gap */

.gap-s {
  gap: var(--spacing-s);
}
.gap-m {
  gap: var(--spacing-m);
}
.gap-l {
  gap: var(--spacing-l);
}
.gap-xl {
  gap: var(--spacing-xl);
}
.gap-2xl {
  gap: var(--spacing-2xl);
}
.gap-3xl {
  gap: var(--spacing-3xl);
}
.gap-4xl {
  gap: var(--spacing-4xl);
}

@font-face {
  font-display: swap;
  font-family: GT-Flexa Text;
  src: url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Black.woff2) format("woff2"), url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Black.woff) format("woff");
  font-weight: 900;
}

@font-face {
  font-display: swap;
  font-family: GT-Flexa Text;
  src: url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Bold.woff2) format("woff2"), url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Bold.woff) format("woff");
  font-weight: 700;
}

@font-face {
  font-display: swap;
  font-family: GT-Flexa Text;
  src: url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Medium.woff2) format("woff2"), url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Medium.woff) format("woff");
  font-weight: 500;
}

@font-face {
  font-display: swap;
  font-family: GT-Flexa Text;
  src: url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Regular.woff2) format("woff2"), url(https://go.shipfusion.com/hubfs/sf-theme/fonts/gt-flexa/GT-Flexa-Standard-Regular.woff) format("woff");
  font-weight: 400;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: Inter, Helvetica, Helvetica Neue, Arial, sans-serif;
  text-wrap: balance;
  overflow-wrap: break-word;
  background-color: var(--body-bg);
  color: var(--body-fg);
}

/* Light page templates set the body canvas via a bg-* utility (e.g.
   blank-light.html → body class="bg-grey-10"). Mirror that onto --body-bg
   AND flip --body-fg to a dark text color, scoped to <body> so neither
   leaks into nested bg-grey-10 cards. This keeps the bg-glow edge fade
   dissolving into the page (fade-follows-body) and body/heading text
   legible (headings inherit body color). Add a sibling line for any other
   utility used as a page canvas. */
body.bg-grey-10 { --body-bg: var(--c-grey-10); --body-fg: var(--c-grey-01); }
body.bg-grey-09 { --body-bg: var(--c-grey-09); --body-fg: var(--c-grey-01); }
body.bg-white   { --body-bg: var(--c-white);   --body-fg: var(--c-grey-01); }

.t-pretty {
  text-wrap: pretty;
}

/* Icons — sizing/alignment for Font Awesome.

   Covers both kit modes:
     - `<i class="fa-solid fa-…">`           (webfont, when kit serves CSS)
     - `<svg class="svg-inline--fa fa-…">`   (default — kit replaces <i> with SVG)
   Each FA style class (.fa-solid / .fa-regular / .fa-brands / .fa-light /
   .fa-thin / .fa-sharp) is matched explicitly. `.svg-inline--fa` catches the
   SVG injected at runtime. */

.fa-solid,
.fa-regular,
.fa-brands,
.fa-light,
.fa-thin,
.fa-sharp,
.svg-inline--fa {
  font-size: 1em;
  line-height: 1;
  vertical-align: middle;
}

.icon-text {
  display: inline-flex;
  align-items: center;
}

/* Hero/display headings only: pin the inline FA icon's box so the deferred
   FA-kit swap can't shift the line vertically. Before injection the empty
   <i> inherits the heading's large line-height (a tall flex item); the
   injected .svg-inline--fa is line-height:1 — that collapse nudges the line.
   Forcing line-height:1 + a 1em box keeps it identical before/after. Scoped
   to .h-display, so icon rendering in buttons/links/body is unchanged.
   Descendant (not child) selectors: inside an anim-text-chars heading the char
   splitter wraps the icon in a .anim-char-icon span, so it isn't a direct child
   of .icon-text — the wrapper is pinned alongside it. */
.h-display .icon-text i[class*="fa-"],
.h-display .icon-text .svg-inline--fa,
.h-display .icon-text .anim-char-icon {
  line-height: 1;
  height: 1em;
}

/* Paragraphs */

p,
.p {
  font-size: clamp(0.875rem, 0.455vw + 0.761rem, 1.125rem);
  line-height: clamp(1.488rem, 0.568vw + 1.345rem, 1.8rem);
  margin: 0;
}

.p-small {
  font-size: clamp(0.75rem, 0.227vw + 0.693rem, 0.875rem);
  line-height: clamp(1.275rem, 0.386vw + 1.178rem, 1.488rem);
  margin: 0;
  font-weight: 400;
}

/* Headings */

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  font-family: "GT-Flexa Text", Helvetica, Helvetica Neue, Arial, sans-serif;
}

.h1,
.h2,
.h3,
.h4,
.h5,
.h6,
.h-display {
  margin: 0;
  font-family: "GT-Flexa Text", Helvetica, Helvetica Neue, Arial, sans-serif;
}

h1,
.h-display {
  font-size: clamp(3rem, 2.727vw + 2.318rem, 4.5rem);
  line-height: clamp(3.3rem, 3vw + 2.55rem, 4.95rem);
  font-weight: 500;
  margin: 0;
}

.h-display-l {
  font-size: clamp(4.5rem, 4.545vw + 3.364rem, 7rem);
  line-height: clamp(4.95rem, 5vw + 3.7rem, 7.7rem);
  font-weight: 500;
  font-family: "GT-Flexa Text", Helvetica, Helvetica Neue, Arial, sans-serif;
  margin: 0;
}

h1,
.h1 {
  font-size: clamp(2.5rem, 1.818vw + 2.045rem, 3.5rem);
  line-height: clamp(3rem, 1.545vw + 2.614rem, 3.85rem);
  font-weight: 400;
}

h2,
.h2 {
  font-size: clamp(2rem, 1.818vw + 1.545rem, 3rem);
  line-height: clamp(2.4rem, 1.636vw + 1.991rem, 3.3rem);
  font-weight: 400;
}

h3,
.h3 {
  font-size: clamp(1.75rem, 1.364vw + 1.409rem, 2.5rem);
  line-height: clamp(2.275rem, 1.318vw + 1.945rem, 3rem);
  font-weight: 400;
}

h4,
.h4 {
  font-size: clamp(1.5rem, 0.909vw + 1.273rem, 2rem);
  line-height: clamp(1.95rem, 0.818vw + 1.745rem, 2.4rem);
  font-weight: 400;
}

h5,
.h5 {
  font-size: clamp(1.125rem, 0.682vw + 0.955rem, 1.5rem);
  line-height: clamp(1.688rem, 1.023vw + 1.432rem, 2.25rem);
  font-weight: 400;
}

h6,
.h6 {
  font-size: clamp(0.875rem, 0.455vw + 0.761rem, 1.125rem);
  line-height: clamp(1.4rem, 0.727vw + 1.218rem, 1.8rem);
  font-weight: 400;
  text-transform: uppercase;
}

/* Lists */

ul {
  padding-left: 1.5em;
}

li {
  margin: 0;
  line-height: clamp(1.488rem, 0.568vw + 1.345rem, 1.8rem);
}

li + li {
  margin-top: var(--spacing-2xs);
}

ul.li-check,
.li-check ul,
ul.li-check-dark,
.li-check-dark ul,
ul.li-xmark,
.li-xmark ul {
  list-style: none;
  padding: 0;
}

.li-check li,
.li-check-dark li,
.li-xmark li {
  position: relative;
  padding-left: var(--spacing-xl);
}

.li-check li::before,
.li-check-dark li::before,
.li-xmark li::before {
  content: "";

  position: absolute;
  left: 0;
  top: 0.2rem;

  width: var(--spacing-l);
  height: var(--spacing-l);
  border-radius: var(--spacing-4xs);

  /* Icon renders as an inline SVG via background-image. Self-contained — no
     webfont dependency, so it works regardless of how Font Awesome is loaded
     (kit, CDN, or not at all). Box (border + size + radius) stays on the
     pseudo-element; the SVG fills the inner area centered at ~55%. */
  background-position: center;
  background-repeat: no-repeat;
  background-size: 55%;
}

/* Stroke color is baked into each SVG to match the box border. */
.li-check li::before {
  background-color: transparent;
  border: 1px solid var(--c-aqua);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231ED4AA' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}

.li-check-dark li::before {
  background-color: var(--c-grey-02);
  border: 1px solid var(--c-grey-05);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23D5D6EA' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}

.li-xmark li::before {
  background-color: transparent;
  border: 1px solid var(--c-coral);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FF815C' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>");
}

.li-none li,
li.li-none {
  list-style: none;
  padding-left: 0;
}

.li-none li::before,
li.li-none::before {
  content: none;
  display: none;
}

ul,
ol {
  margin: 0;
}

ul ul,
ol ul,
ul ol,
ol ol {
  margin: 0;
}

/* No list */
ul.no-list,
ol.no-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul.no-list > li,
ol.no-list > li {
  position: static;
  padding-left: 0;
  margin: 0;
  line-height: inherit;
}

ul.no-list > li::before,
ol.no-list > li::before {
  content: none; /* hides the checkmark */
  display: none;
}

/* Code blocks */

pre {
  overflow: auto;
}

code {
  vertical-align: bottom;
}

/* Blockquotes */

blockquote {
  border-left: 2px solid var(--c-grey-05);
  margin: 0;
  padding-left: var(--spacing-xs);
}

/* Text Align */
.t-align-center {
  text-align: center;
}

.t-align-left {
  text-align: left;
}

.t-align-right {
  text-align: right;
}

/* Text Transform */

.t-uppercase {
  text-transform: uppercase;
}

/* Text Decoration */

.t-line-through {
  text-decoration: line-through;
  text-decoration-thickness: 0.4px;
}

.div-dots {
  width: 100%;
  height: 2px;
  background-image: radial-gradient(circle, oklch(var(--c-l-3) var(--c-c) var(--c-h-0) / 32%) 1px, transparent 1px);
  background-size: var(--spacing-s);
  background-repeat: repeat-x;
  margin-top: var(--spacing-3xl);
  margin-bottom: var(--spacing-3xl);
}

.div-line {
  width: 100%;
  height: 1px;
  margin-top: var(--spacing-xl);
  margin-bottom: var(--spacing-xl);
}

.div-bar {
  width: 1px;
  min-height: 24px;
}

.media-fg {
  position: relative;
}

.media-fg img {
  display: block;
  max-width: 100%;
  height: auto;
}

.p-t-0 .media-fg {
  border-radius: 0 0 var(--spacing-xs) var(--spacing-xs);
  top: -1px;
}

.p-r-0 .media-fg {
  border-radius: var(--spacing-xs) 0 0 var(--spacing-xs);
  right: -1px;
}

.p-b-0 .media-fg {
  border-radius: var(--spacing-xs) var(--spacing-xs) 0 0;
  bottom: -4px;
}

.p-l-0 .media-fg {
  border-radius: 0 var(--spacing-xs) var(--spacing-xs) 0;
  left: -1px;
}

.media-bg {
  position: relative;
}

/* ── iframe-wrap ──────────────────────────────────────────────────────
 * Wrapper for embedded iframes (animations, embeds, demos).
 *
 * Paste into a rich text / media_src field:
 *
 *   <div class="iframe-wrap iframe-w-160 iframe-aspect-16-9">
 *     <iframe src="..."></iframe>
 *   </div>
 *
 * For non-standard ratios, override the variable inline:
 *
 *   <div class="iframe-wrap iframe-w-160" style="--iframe-aspect: 1920/1380">
 *     <iframe src="..."></iframe>
 *   </div>
 *
 * Width variants overscale the wrapper for visual bleed past its column.
 * Mobile (< 991px) clamps width back to 100%.
 * ─────────────────────────────────────────────────────────────────── */

.iframe-wrap {
  --iframe-w: 100%;
  --iframe-aspect: 16 / 9;

  position: relative;
  width: var(--iframe-w);
  aspect-ratio: var(--iframe-aspect);
  overflow: visible;
}

.iframe-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Width scale */
.iframe-w-100 { --iframe-w: 100%; }
.iframe-w-110 { --iframe-w: 110%; }
.iframe-w-120 { --iframe-w: 120%; }
.iframe-w-130 { --iframe-w: 130%; }
.iframe-w-140 { --iframe-w: 140%; }
.iframe-w-150 { --iframe-w: 150%; }
.iframe-w-160 { --iframe-w: 160%; }
.iframe-w-180 { --iframe-w: 180%; }
.iframe-w-200 { --iframe-w: 200%; }

/* Aspect ratio variants */
.iframe-aspect-16-9 { --iframe-aspect: 16 / 9; }
.iframe-aspect-4-3  { --iframe-aspect: 4 / 3; }
.iframe-aspect-3-2  { --iframe-aspect: 3 / 2; }
.iframe-aspect-1-1  { --iframe-aspect: 1 / 1; }
.iframe-aspect-9-16 { --iframe-aspect: 9 / 16; }

@media (max-width: 991px) {
  .iframe-wrap { --iframe-w: 100%; }
}

/* ── bg-glow — section background: CSS radial blobs + wavy rotating SVG
   rings + tint + grain. Markup is injected by the bg-glow runtime in
   js/animations.js (auto-finds .bg-glow hosts: sections, cards, containers).
   Replaced the heavier 6-layer SVG-gradient system. Variants bg-glow-1/2/3
   + bg-glow-fade-top / bg-glow-fade-bottom modifiers. ──────────────────── */
.bg-glow {
  position: relative;
  background-color: var(--bg-canvas, #000000);
  overflow: hidden;
  isolation: isolate;
  contain: paint;

  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 24%;
  --blob1-cy: 110%;
  --blob1-size-x: 24%;
  --blob1-size-y: 37%;
  --blob1-mobile-cx: -4%;
  --blob1-mobile-cy: 93%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 200%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #1ed4aa;
  --blob1-overlay-c2: #1ed4aa;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 217deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #4864ff;
  --blob2-mid: #4864ff;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 91%;
  --blob2-cy: -32%;
  --blob2-size-x: 30%;
  --blob2-size-y: 55%;
  --blob2-mobile-cx: 86%;
  --blob2-mobile-cy: 10%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 200%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #4864ff;
  --blob2-overlay-c3: #be81ff;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 101deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #be81ff;
  --ring1-end: #4864ff;
  --opacity-ring1: 0.5;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 91%;
  --ring1-cy: -14%;
  --ring1-base-r: 52%;
  --ring1-mobile-cx: 72%;
  --ring1-mobile-cy: 1%;
  --ring1-mobile-base-r: 28%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 134deg;
  --ring1-gradient-stop-start: 51%;
  --ring1-gradient-stop-end: 100%;
  --ring1-rotate: 66s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #1ed4aa;
  --ring2-end: #4864ff;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 30%;
  --ring2-cy: 99%;
  --ring2-base-r: 38%;
  --ring2-mobile-cx: 36%;
  --ring2-mobile-cy: 99%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 40%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;

  /* ── Fade-bottom modifier defaults ── */
  --bg-glow-fade-color:  var(--body-bg, #0D0D18);
  --bg-glow-fade-height: 40%;
}


/* ── Variant 1 · bg-glow-1 ── */
.bg-glow-1 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 0%;
  --blob1-cy: 72%;
  --blob1-size-x: 31%;
  --blob1-size-y: 50%;
  --blob1-mobile-cx: 0%;
  --blob1-mobile-cy: 69%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 60%;
  --blob1-stop-end: 100%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #4864ff;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 191deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 100%;
  --blob2-cy: 20%;
  --blob2-size-x: 29%;
  --blob2-size-y: 46%;
  --blob2-mobile-cx: 100%;
  --blob2-mobile-cy: 24%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 50%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #1ed4aa;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 217deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #1ed4aa;
  --opacity-ring1: 0.55;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 104%;
  --ring1-cy: 20%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 4deg;
  --ring1-gradient-stop-start: 47%;
  --ring1-gradient-stop-end: 66%;
  --ring1-rotate: 80s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #ff815c;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 1%;
  --ring2-cy: 72%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 27%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 2 · bg-glow-2 ── */
.bg-glow-2 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 24%;
  --blob1-cy: -20%;
  --blob1-size-x: 24%;
  --blob1-size-y: 37%;
  --blob1-mobile-cx: -4%;
  --blob1-mobile-cy: -5%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 200%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #1ed4aa;
  --blob1-overlay-c2: #1ed4aa;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 217deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #4864ff;
  --blob2-mid: #4864ff;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 91%;
  --blob2-cy: 136%;
  --blob2-size-x: 30%;
  --blob2-size-y: 55%;
  --blob2-mobile-cx: 100%;
  --blob2-mobile-cy: 90%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 200%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #be81ff;
  --blob2-overlay-c3: #be81ff;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 101deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #be81ff;
  --ring1-end: #4864ff;
  --opacity-ring1: 0.5;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 91%;
  --ring1-cy: 110%;
  --ring1-base-r: 52%;
  --ring1-mobile-cx: 72%;
  --ring1-mobile-cy: 89%;
  --ring1-mobile-base-r: 28%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 134deg;
  --ring1-gradient-stop-start: 51%;
  --ring1-gradient-stop-end: 100%;
  --ring1-rotate: 66s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #1ed4aa;
  --ring2-end: #4864ff;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 30%;
  --ring2-cy: 4%;
  --ring2-base-r: 38%;
  --ring2-mobile-cx: 36%;
  --ring2-mobile-cy: 4%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 40%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 3 · bg-glow-3 ── */
.bg-glow-3 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 85%;
  --blob1-cy: 100%;
  --blob1-size-x: 37%;
  --blob1-size-y: 50%;
  --blob1-mobile-cx: 97%;
  --blob1-mobile-cy: 97%;
  --blob1-mobile-size-x: 71%;
  --blob1-mobile-size-y: 37%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 100%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #ff815c;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 25deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 8%;
  --blob2-cy: 0%;
  --blob2-size-x: 46%;
  --blob2-size-y: 49%;
  --blob2-mobile-cx: -5%;
  --blob2-mobile-cy: 8%;
  --blob2-mobile-size-x: 78%;
  --blob2-mobile-size-y: 36%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #1ed4aa;
  --blob2-overlay-c2: #7f39c9;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 91deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #1ed4aa;
  --opacity-ring1: 0;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 108%;
  --ring1-cy: 33%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 165deg;
  --ring1-gradient-stop-start: 47%;
  --ring1-gradient-stop-end: 66%;
  --ring1-rotate: 78s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #ff815c;
  --opacity-ring2: 0;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 1%;
  --ring2-cy: 60%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 27%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 4 · bg-glow-4 ── */
.bg-glow-4 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 85%;
  --blob1-cy: 10%;
  --blob1-size-x: 37%;
  --blob1-size-y: 50%;
  --blob1-mobile-cx: 120%;
  --blob1-mobile-cy: 23%;
  --blob1-mobile-size-x: 75%;
  --blob1-mobile-size-y: 40%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 100%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #ff815c;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 25deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 8%;
  --blob2-cy: 90%;
  --blob2-size-x: 46%;
  --blob2-size-y: 49%;
  --blob2-mobile-cx: 0%;
  --blob2-mobile-cy: 84%;
  --blob2-mobile-size-x: 47%;
  --blob2-mobile-size-y: 34%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #1ed4aa;
  --blob2-overlay-c2: #7f39c9;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 91deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #1ed4aa;
  --opacity-ring1: 0;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 108%;
  --ring1-cy: 33%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 165deg;
  --ring1-gradient-stop-start: 47%;
  --ring1-gradient-stop-end: 66%;
  --ring1-rotate: 78s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #ff815c;
  --opacity-ring2: 0;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 1%;
  --ring2-cy: 60%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 27%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 5 · bg-glow-5 ── */
.bg-glow-5 {
  /* canvas + atmosphere */
  --bg-canvas: #ffffff;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(255, 255, 255, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 24%;
  --blob1-cy: 110%;
  --blob1-size-x: 24%;
  --blob1-size-y: 37%;
  --blob1-mobile-cx: -4%;
  --blob1-mobile-cy: 93%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 200%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #1ed4aa;
  --blob1-overlay-c2: #1ed4aa;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 0deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #4864ff;
  --blob2-mid: #4864ff;
  --blob2-end: rgba(255, 255, 255, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 91%;
  --blob2-cy: -32%;
  --blob2-size-x: 30%;
  --blob2-size-y: 55%;
  --blob2-mobile-cx: 86%;
  --blob2-mobile-cy: 10%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 200%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #4864ff;
  --blob2-overlay-c3: #be81ff;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 101deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #be81ff;
  --ring1-end: #4864ff;
  --opacity-ring1: 0.5;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 91%;
  --ring1-cy: -14%;
  --ring1-base-r: 52%;
  --ring1-mobile-cx: 72%;
  --ring1-mobile-cy: 1%;
  --ring1-mobile-base-r: 28%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 134deg;
  --ring1-gradient-stop-start: 51%;
  --ring1-gradient-stop-end: 100%;
  --ring1-rotate: 66s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #1ed4aa;
  --ring2-end: #4864ff;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 12%;
  --ring2-cy: 99%;
  --ring2-base-r: 38%;
  --ring2-mobile-cx: 36%;
  --ring2-mobile-cy: 99%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 40%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 6 · bg-glow-6 ── */
.bg-glow-6 {
  /* canvas + atmosphere */
  --bg-canvas: #ffffff;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(255, 255, 255, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 0%;
  --blob1-cy: 72%;
  --blob1-size-x: 31%;
  --blob1-size-y: 50%;
  --blob1-mobile-cx: 0%;
  --blob1-mobile-cy: 69%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 60%;
  --blob1-stop-end: 100%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #4864ff;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 191deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(255, 255, 255, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 100%;
  --blob2-cy: 20%;
  --blob2-size-x: 29%;
  --blob2-size-y: 46%;
  --blob2-mobile-cx: 100%;
  --blob2-mobile-cy: 24%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 50%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #1ed4aa;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 217deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #1ed4aa;
  --opacity-ring1: 0;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 104%;
  --ring1-cy: 20%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 4deg;
  --ring1-gradient-stop-start: 47%;
  --ring1-gradient-stop-end: 66%;
  --ring1-rotate: 80s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #ff815c;
  --opacity-ring2: 0;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 1%;
  --ring2-cy: 72%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 27%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 7 · bg-glow-7 ── */
.bg-glow-7 {
  /* canvas + atmosphere */
  --bg-canvas: #3352ff;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 10%;
  --blob1-cy: 78%;
  --blob1-size-x: 50%;
  --blob1-size-y: 62%;
  --blob1-mobile-cx: 0%;
  --blob1-mobile-cy: 69%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 100%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #4864ff;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #1ed4aa;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 281deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 93%;
  --blob2-cy: 35%;
  --blob2-size-x: 29%;
  --blob2-size-y: 46%;
  --blob2-mobile-cx: 100%;
  --blob2-mobile-cy: 24%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #1ed4aa;
  --blob2-overlay-c2: #7f39c9;
  --blob2-overlay-c3: #4864ff;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 217deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #1ed4aa;
  --opacity-ring1: 0;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 108%;
  --ring1-cy: 33%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 165deg;
  --ring1-gradient-stop-start: 47%;
  --ring1-gradient-stop-end: 66%;
  --ring1-rotate: 78s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #ff815c;
  --opacity-ring2: 0;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 1%;
  --ring2-cy: 60%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 27%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 8 · bg-glow-8 ── */
.bg-glow-8 {
  /* canvas + atmosphere */
  --bg-canvas: #3352ff;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #1ed4aa;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 16%;
  --blob1-cy: 100%;
  --blob1-size-x: 31%;
  --blob1-size-y: 50%;
  --blob1-mobile-cx: 0%;
  --blob1-mobile-cy: 69%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 128%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #4864ff;
  --blob1-overlay-c2: #4864ff;
  --blob1-overlay-c3: #1ed4aa;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 191deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #1ed4aa;
  --blob2-mid: #1ed4aa;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 92%;
  --blob2-cy: 0%;
  --blob2-size-x: 29%;
  --blob2-size-y: 46%;
  --blob2-mobile-cx: 100%;
  --blob2-mobile-cy: 24%;
  --blob2-mobile-size-x: 29%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 116%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #1ed4aa;
  --blob2-overlay-c2: #4864ff;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 217deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #4864ff;
  --ring1-end: #ff815c;
  --opacity-ring1: 0.55;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 104%;
  --ring1-cy: 12%;
  --ring1-base-r: 44%;
  --ring1-mobile-cx: 96%;
  --ring1-mobile-cy: 16%;
  --ring1-mobile-base-r: 52%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 322deg;
  --ring1-gradient-stop-start: 32%;
  --ring1-gradient-stop-end: 75%;
  --ring1-rotate: 78s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #4864ff;
  --ring2-end: #1ed4aa;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 16%;
  --ring2-cy: 92%;
  --ring2-base-r: 30%;
  --ring2-mobile-cx: 30%;
  --ring2-mobile-cy: 71%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 153deg;
  --ring2-gradient-stop-start: 44%;
  --ring2-gradient-stop-end: 60%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 9 · bg-glow-9 ── */
.bg-glow-9 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 67%;
  --blob1-cy: 126%;
  --blob1-size-x: 24%;
  --blob1-size-y: 37%;
  --blob1-mobile-cx: 93%;
  --blob1-mobile-cy: 92%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 200%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #1ed4aa;
  --blob1-overlay-c2: #1ed4aa;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 217deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #4864ff;
  --blob2-mid: #4864ff;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 38%;
  --blob2-cy: -50%;
  --blob2-size-x: 30%;
  --blob2-size-y: 55%;
  --blob2-mobile-cx: 8%;
  --blob2-mobile-cy: 9%;
  --blob2-mobile-size-x: 45%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 200%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #4864ff;
  --blob2-overlay-c3: #be81ff;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 101deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #be81ff;
  --ring1-end: #4864ff;
  --opacity-ring1: 0.5;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 43%;
  --ring1-cy: -15%;
  --ring1-base-r: 52%;
  --ring1-mobile-cx: 35%;
  --ring1-mobile-cy: 10%;
  --ring1-mobile-base-r: 28%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 134deg;
  --ring1-gradient-stop-start: 51%;
  --ring1-gradient-stop-end: 100%;
  --ring1-rotate: 66s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #1ed4aa;
  --ring2-end: #4864ff;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 63%;
  --ring2-cy: 108%;
  --ring2-base-r: 38%;
  --ring2-mobile-cx: 61%;
  --ring2-mobile-cy: 91%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 40%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Variant 10 · bg-glow-10 ── */
.bg-glow-10 {
  /* canvas + atmosphere */
  --bg-canvas: #000000;
  --bg-speed: 10s;
  --bg-darkness: 0;
  --bg-grain: 1;

  /* Blob 1 (radial) */
  --blob1-start: #4864ff;
  --blob1-mid: #4864ff;
  --blob1-end: rgba(0, 0, 0, 0);
  --opacity-blob1: 0.5;
  --blob1-cx: 35%;
  --blob1-cy: 126%;
  --blob1-size-x: 24%;
  --blob1-size-y: 37%;
  --blob1-mobile-cx: -9%;
  --blob1-mobile-cy: 92%;
  --blob1-mobile-size-x: 50%;
  --blob1-mobile-size-y: 22%;
  --blob1-stop-mid: 0%;
  --blob1-stop-end: 200%;
  --blob1-drift: 0.9;
  --blob1-overlay-c1: #be81ff;
  --blob1-overlay-c2: #be81ff;
  --blob1-overlay-c3: #4864ff;
  --blob1-overlay-stop-mid: 50%;
  --blob1-overlay-angle: 225deg;
  --blob1-overlay-blend: normal;
  --blob1-overlay-opacity: 1;

  /* Blob 2 (radial) */
  --blob2-start: #4864ff;
  --blob2-mid: #4864ff;
  --blob2-end: rgba(0, 0, 0, 0);
  --opacity-blob2: 0.42;
  --blob2-cx: 82%;
  --blob2-cy: -50%;
  --blob2-size-x: 30%;
  --blob2-size-y: 55%;
  --blob2-mobile-cx: 105%;
  --blob2-mobile-cy: 9%;
  --blob2-mobile-size-x: 45%;
  --blob2-mobile-size-y: 22%;
  --blob2-stop-mid: 0%;
  --blob2-stop-end: 200%;
  --blob2-drift: 1.4;
  --blob2-overlay-c1: #4864ff;
  --blob2-overlay-c2: #4864ff;
  --blob2-overlay-c3: #1ed4aa;
  --blob2-overlay-stop-mid: 50%;
  --blob2-overlay-angle: 360deg;
  --blob2-overlay-blend: normal;
  --blob2-overlay-opacity: 1;

  /* Ring 1 (wavy) */
  --ring1-start: #1ed4aa;
  --ring1-end: #4864ff;
  --opacity-ring1: 0.5;
  /* path geometry (consumed by runtime JS) */
  --ring1-cx: 79%;
  --ring1-cy: -15%;
  --ring1-base-r: 52%;
  --ring1-mobile-cx: 69%;
  --ring1-mobile-cy: 10%;
  --ring1-mobile-base-r: 28%;
  --ring1-waviness: 4%;
  --ring1-waves: 4;
  --ring1-gradient-angle: 134deg;
  --ring1-gradient-stop-start: 51%;
  --ring1-gradient-stop-end: 100%;
  --ring1-rotate: 66s;
  --ring1-rotate-dir: normal;
  --blur-ring1: 12px;
  --stroke-ring1: 60;

  /* Ring 2 (wavy) */
  --ring2-start: #be81ff;
  --ring2-end: #4864ff;
  --opacity-ring2: 0.46;
  /* path geometry (consumed by runtime JS) */
  --ring2-cx: 39%;
  --ring2-cy: 104%;
  --ring2-base-r: 38%;
  --ring2-mobile-cx: 34%;
  --ring2-mobile-cy: 91%;
  --ring2-mobile-base-r: 25%;
  --ring2-waviness: 9%;
  --ring2-waves: 3;
  --ring2-gradient-angle: 169deg;
  --ring2-gradient-stop-start: 40%;
  --ring2-gradient-stop-end: 100%;
  --ring2-rotate: 94s;
  --ring2-rotate-dir: reverse;
  --blur-ring2: 20px;
  --stroke-ring2: 80;
}


/* ── Mobile breakpoint swap ─────────────────────────────────────────
   Below 991px (sf-theme mobile boundary), each shape's active
   position/size var switches to its mobile-* counterpart. */
@media (max-width: 991px) {
  .bg-glow {
    --blob1-cx:     var(--blob1-mobile-cx);
    --blob1-cy:     var(--blob1-mobile-cy);
    --blob1-size-x: var(--blob1-mobile-size-x);
    --blob1-size-y: var(--blob1-mobile-size-y);
    --blob2-cx:     var(--blob2-mobile-cx);
    --blob2-cy:     var(--blob2-mobile-cy);
    --blob2-size-x: var(--blob2-mobile-size-x);
    --blob2-size-y: var(--blob2-mobile-size-y);
    --ring1-cx:     var(--ring1-mobile-cx);
    --ring1-cy:     var(--ring1-mobile-cy);
    --ring1-base-r: var(--ring1-mobile-base-r);
    --ring2-cx:     var(--ring2-mobile-cx);
    --ring2-cy:     var(--ring2-mobile-cy);
    --ring2-base-r: var(--ring2-mobile-base-r);
  }
}


/* ── Layer scaffolding ──────────────────────────────────────────── */

.bg-glow .bg-layer {
  position: absolute;
  inset: -10%;
  width: 120%;
  height: 120%;
  pointer-events: none;
}
.bg-glow .bg-layer svg { width: 100%; height: 100%; display: block; overflow: visible; }

.bg-glow .bg-layer--blob1 { z-index: 0; opacity: var(--opacity-blob1); }
.bg-glow .bg-layer--blob2 { z-index: 1; opacity: var(--opacity-blob2); }
.bg-glow .bg-layer--ring1 { z-index: 2; opacity: var(--opacity-ring1); filter: blur(var(--blur-ring1)) saturate(1.15); }
.bg-glow .bg-layer--ring2 { z-index: 3; opacity: var(--opacity-ring2); filter: blur(var(--blur-ring2)) saturate(1.15); }


/* ── Blob shapes ────────────────────────────────────────────────── */

.bg-glow .bg-shape--blob1 {
  position: absolute; inset: 0;
  isolation: isolate;
  background: radial-gradient(
    ellipse var(--blob1-size-x) var(--blob1-size-y)
    at var(--blob1-cx) var(--blob1-cy)
    in oklab,
    var(--blob1-start),
    var(--blob1-mid) var(--blob1-stop-mid),
    var(--blob1-end) var(--blob1-stop-end)
  );
  animation: glowBlobDriftA calc(var(--bg-speed) * var(--blob1-drift)) ease-in-out infinite;
  will-change: transform;
}

/* Linear overlay clipped by a copy of the radial used as alpha mask, so
   it only renders within the blob's shape. mix-blend-mode + parent
   isolation confine the blend to the radial below it.  The composed
   gradient string is set inline by the runtime onto
   --blob1-overlay-gradient. */
.bg-glow .bg-shape--blob1::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--blob1-overlay-gradient, none);
  -webkit-mask-image: radial-gradient(
    ellipse var(--blob1-size-x) var(--blob1-size-y)
    at var(--blob1-cx) var(--blob1-cy),
    var(--blob1-start),
    var(--blob1-mid) var(--blob1-stop-mid),
    var(--blob1-end) var(--blob1-stop-end)
  );
  mask-image: radial-gradient(
    ellipse var(--blob1-size-x) var(--blob1-size-y)
    at var(--blob1-cx) var(--blob1-cy),
    var(--blob1-start),
    var(--blob1-mid) var(--blob1-stop-mid),
    var(--blob1-end) var(--blob1-stop-end)
  );
  mix-blend-mode: var(--blob1-overlay-blend, normal);
  pointer-events: none;
}

.bg-glow .bg-shape--blob2 {
  position: absolute; inset: 0;
  isolation: isolate;
  background: radial-gradient(
    ellipse var(--blob2-size-x) var(--blob2-size-y)
    at var(--blob2-cx) var(--blob2-cy)
    in oklab,
    var(--blob2-start),
    var(--blob2-mid) var(--blob2-stop-mid),
    var(--blob2-end) var(--blob2-stop-end)
  );
  animation: glowBlobDriftB calc(var(--bg-speed) * var(--blob2-drift)) ease-in-out infinite;
  will-change: transform;
}
.bg-glow .bg-shape--blob2::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--blob2-overlay-gradient, none);
  -webkit-mask-image: radial-gradient(
    ellipse var(--blob2-size-x) var(--blob2-size-y)
    at var(--blob2-cx) var(--blob2-cy),
    var(--blob2-start),
    var(--blob2-mid) var(--blob2-stop-mid),
    var(--blob2-end) var(--blob2-stop-end)
  );
  mask-image: radial-gradient(
    ellipse var(--blob2-size-x) var(--blob2-size-y)
    at var(--blob2-cx) var(--blob2-cy),
    var(--blob2-start),
    var(--blob2-mid) var(--blob2-stop-mid),
    var(--blob2-end) var(--blob2-stop-end)
  );
  mix-blend-mode: var(--blob2-overlay-blend, normal);
  pointer-events: none;
}


/* Subtle drift — ±5% translate, ±10% scale. */
@keyframes glowBlobDriftA {
  0%, 100% { transform: translate(-3%, -2%) scale(1); }
  33%      { transform: translate(2%, 3%)   scale(1.08); }
  66%      { transform: translate(4%, -3%)  scale(0.95); }
}
@keyframes glowBlobDriftB {
  0%, 100% { transform: translate(2%, 1%)   scale(1); }
  35%      { transform: translate(-3%, 4%)  scale(0.92); }
  70%      { transform: translate(-5%, -2%) scale(1.1); }
}


/* ── Ring shapes ────────────────────────────────────────────────── */

.bg-glow .bg-shape--ring1,
.bg-glow .bg-shape--ring2 {
  transform-box: fill-box;
  transform-origin: center;
  will-change: transform;
}
.bg-glow .bg-layer--ring1 path { stroke-width: var(--stroke-ring1); fill: none; }
.bg-glow .bg-layer--ring2 path { stroke-width: var(--stroke-ring2); fill: none; }

.bg-glow .bg-shape--ring1 {
  animation: glowRingRotate var(--ring1-rotate) linear infinite;
  animation-direction: var(--ring1-rotate-dir);
}
.bg-glow .bg-shape--ring2 {
  animation: glowRingRotate var(--ring2-rotate) linear infinite;
  animation-direction: var(--ring2-rotate-dir);
}
@keyframes glowRingRotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}


/* ── Tint + grain ───────────────────────────────────────────────── */

.bg-glow > .bg-glow-tint {
  position: absolute; inset: 0;
  z-index: 7;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 50%, transparent 0%, rgba(0, 0, 0, var(--bg-darkness)) 100%),
    linear-gradient(180deg,
      rgba(0, 0, 0, calc(var(--bg-darkness) * 0.4)) 0%,
      rgba(0, 0, 0, calc(var(--bg-darkness) * 0.7)) 100%);
}
.bg-glow > .bg-glow-grain {
  position: absolute; inset: 0;
  /* z-index 7 (same level as tint, rendered after tint via DOM order so
     it still overlays it). Critically, this keeps the grain BELOW both
     fade modifiers (::before / ::after at z 8), so the fade colors
     aren't distorted by the overlay blend mode. */
  z-index: 7;
  pointer-events: none;
  opacity: var(--bg-grain);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}


/* ── Fade-bottom modifier — dissolves section bottom into the body
      color so the section reads as continuous with what follows. */
.bg-glow.bg-glow-fade-bottom::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: var(--bg-glow-fade-height, 40%);
  z-index: 8;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--bg-glow-fade-color, #0D0D18));
}

/* ── Fade-top modifier — symmetric to fade-bottom on the top edge.
      Shares --bg-glow-fade-color and --bg-glow-fade-height with the
      bottom variant. Use both classes together to fade both edges. */
.bg-glow.bg-glow-fade-top::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: var(--bg-glow-fade-height, 40%);
  z-index: 8;
  pointer-events: none;
  background: linear-gradient(to top, transparent, var(--bg-glow-fade-color, #0D0D18));
}


/* ── Content always above bg layers ─────────────────────────────── */
.bg-glow > *:not(.bg-layer):not(.bg-layer--blob1):not(.bg-layer--blob2):not(.bg-layer--ring1):not(.bg-layer--ring2):not(.bg-glow-tint):not(.bg-glow-grain) {
  position: relative;
  z-index: 9;
}


/* ── Reduced motion — kill all animations ──────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .bg-glow .bg-shape--blob1,
  .bg-glow .bg-shape--blob2,
  .bg-glow .bg-shape--ring1,
  .bg-glow .bg-shape--ring2 { animation: none; }
}


/* ── .bg-frosted: cohesive frosted-glass surface family.

   Recipe (shared across all variants):
     - solid color canvas
     - two off-frame radial blobs (top-right + bottom-left) with multi-stop
       Gaussian-ish falloff
     - feTurbulence grain layer via mix-blend-mode: overlay
     - barely-visible top-edge highlight ("glass bevel")

   Self-contained (no SVG / filter:blur), so it can sit inside
   3D-transformed elements like a flip-card face where filter on a
   child would break backface-visibility.

   Three CSS variables drive the palette:
     --bg-frosted-base   : the canvas color
     --bg-frosted-blob-a : the top-right blob
     --bg-frosted-blob-b : the bottom-left blob

   Variants below override those three vars and inherit everything else,
   matching the .bg-glow-1/2/3 pattern (base class + modifier).

   Usage:
     class="bg-frosted"                — default (periwinkle / aqua / coral)
     class="bg-frosted bg-frosted-aqua"
     class="bg-frosted bg-frosted-coral"
     class="bg-frosted bg-frosted-purple" */
.bg-frosted {
  /* Palette tokens — override in variants below. */
  --bg-frosted-base:   var(--c-periwinkle);
  --bg-frosted-blob-a: var(--c-aqua);
  --bg-frosted-blob-b: var(--c-coral);

  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--c-grey-10);

  background-color: var(--bg-frosted-base);
  background-image:
    radial-gradient(circle at 82% 12%,
      color-mix(in srgb, var(--bg-frosted-blob-a) 85%, transparent) 0%,
      color-mix(in srgb, var(--bg-frosted-blob-a) 55%, transparent) 18%,
      color-mix(in srgb, var(--bg-frosted-blob-a) 22%, transparent) 40%,
      color-mix(in srgb, var(--bg-frosted-blob-a) 6%,  transparent) 60%,
      transparent 78%
    ),
    radial-gradient(circle at -8% 108%,
      color-mix(in srgb, var(--bg-frosted-blob-b) 85%, transparent) 0%,
      color-mix(in srgb, var(--bg-frosted-blob-b) 55%, transparent) 20%,
      color-mix(in srgb, var(--bg-frosted-blob-b) 25%, transparent) 42%,
      color-mix(in srgb, var(--bg-frosted-blob-b) 8%,  transparent) 65%,
      transparent 85%
    );
}

.bg-frosted::before {
  /* grain — identical feTurbulence SVG to .bg-glow-grain */
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.22;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

.bg-frosted::after {
  /* top-edge highlight — barely-visible frosted-glass bevel */
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 12%);
}

.bg-frosted > * {
  position: relative;
  z-index: 1;
}

/* ── Variants — only the palette swaps. Composition, grain, highlight,
   and falloff stops all inherit from .bg-frosted. */

/* Aqua canvas, periwinkle + purple blobs. Fresh, jewel-toned.
   Mood: tech / interactive / data surfaces. */
.bg-frosted-aqua {
  --bg-frosted-base:   var(--c-aqua);
  --bg-frosted-blob-a: var(--c-periwinkle);
  --bg-frosted-blob-b: var(--c-purple-regular);
}

/* Coral canvas, aqua + periwinkle blobs. Warm sunset, energetic.
   Mood: CTAs / momentum / promotional surfaces. */
.bg-frosted-coral {
  --bg-frosted-base:   var(--c-coral);
  --bg-frosted-blob-a: var(--c-aqua);
  --bg-frosted-blob-b: var(--c-periwinkle);
}

/* Purple canvas, periwinkle + aqua blobs. Soft, dreamy.
   Mood: editorial / storytelling / case-study surfaces. */
.bg-frosted-purple {
  --bg-frosted-base:   var(--c-purple-regular);
  --bg-frosted-blob-a: var(--c-periwinkle);
  --bg-frosted-blob-b: var(--c-aqua);
}

/* ── Dark variants — built for WHITE text on top.
   Same recipe (grain, highlight, falloff) and the family's inherited
   near-white text color (--c-grey-10); only the canvas goes dark and the
   blobs use the brighter brand hues so they read as glows, not washes.
   The dark base is what gives white text its contrast. */

/* Charcoal-navy canvas, periwinkle + aqua glow. Versatile default dark. */
.bg-frosted-night {
  --bg-frosted-base:   var(--c-grey-02);
  --bg-frosted-blob-a: var(--c-periwinkle);
  --bg-frosted-blob-b: var(--c-aqua);
}

/* Deep purple canvas, purple + periwinkle glow. Editorial / premium. */
.bg-frosted-violet {
  --bg-frosted-base:   var(--c-purple-dark);
  --bg-frosted-blob-a: var(--c-purple-regular);
  --bg-frosted-blob-b: var(--c-periwinkle);
}

/* Deep teal canvas, aqua + periwinkle glow. Tech / data surfaces. */
.bg-frosted-ocean {
  --bg-frosted-base:   var(--c-blue-dark);
  --bg-frosted-blob-a: var(--c-aqua);
  --bg-frosted-blob-b: var(--c-periwinkle);
}

/* ── .bg-glass: true frosted-glass surface — backdrop blur + translucent
   tint + gradient sheen + feTurbulence grain + inner glow + hairline edge.

   Unlike .bg-frosted (opaque colored canvas), this blurs the content BEHIND
   it, so it needs real content/background behind the element to read.

   Composability (this class loads after _colors.css, so it would otherwise
   win every shorthand): the edge/glow/bevel are box-shadow layers and it sets
   no border or color — so b-*, bt-*, rounded-*, p-* and c-* all compose:
     class="bg-glass rounded-l p-xl b-aqua c-grey-01"

   Tinting: the tint IS the sheen color (a low-alpha sheen layered on top of
   the translucent --glass-fill body). Use the bg-glass-* variants below, or
   set inline: style="--glass-tint: var(--c-aqua)". Dial the sheen with
   --glass-sheen (default 8%) and the body with --glass-fill. Don't combine
   with the opaque bg-* classes — they'd cover the fill.
   Usage: class="bg-glass rounded-l p-xl"  /  class="bg-glass bg-glass-aqua" */
.bg-glass {
  position: relative;
  isolation: isolate;
  overflow: hidden;

  /* Tint = the sheen color; --glass-sheen = its strength. Only the gradient
     sheen is tinted (low alpha), so the panel stays glassy. Variants below
     just swap --glass-tint. */
  --glass-tint: var(--c-white);
  --glass-sheen: 8%;
  /* Translucent body — lets a moving/glow background show through (dimmed)
     instead of a backdrop-filter blur, which is a no-op over flat backgrounds
     and a per-frame repaint cost over an animated bg-glow. Tune per instance
     via --glass-fill: raise alpha to protect text, lower to reveal more glow. */
  --glass-fill: rgba(13, 13, 24, 0.64);
  background-color: var(--glass-fill);
  background-image: linear-gradient(135deg,
    transparent 0%,
    color-mix(in srgb, var(--glass-tint) var(--glass-sheen), transparent) 100%);

  /* Edge, inner glow and bevel are box-shadow layers, NOT the border
     property — so b-*, bt-*, rounded-* utilities compose cleanly on top.
     No color set here, so c-* utilities win for text. Held in a variable so
     hover utilities (.h-glow) can ADD a halo instead of replacing the stack —
     see the .bg-glass.h-glow rules in _interactions.css. */
  --glass-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.16),
    inset 0 0 28px 1px rgba(255, 255, 255, 0.1),
    inset 0 1px 0 0 rgba(255, 255, 255, 0.28),
    0 22px 48px rgba(0, 0, 0, 0.12);
  box-shadow: var(--glass-shadow);
}

.bg-glass::before {
  /* grain — feTurbulence noise, same recipe family as .bg-glow-grain */
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.18;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

.bg-glass > * { position: relative; z-index: 1; }

/* ── Tint variants — pair: class="bg-glass bg-glass-aqua". Each just swaps
   the sheen color; strength is the shared --glass-sheen (8%). */
.bg-glass-periwinkle { --glass-tint: var(--c-periwinkle); }
.bg-glass-aqua       { --glass-tint: var(--c-aqua); }
.bg-glass-coral      { --glass-tint: var(--c-coral); }
.bg-glass-purple     { --glass-tint: var(--c-purple-regular); }
.bg-glass-dark       { --glass-tint: var(--c-grey-01); }
.bg-glass-light      { --glass-tint: var(--c-white); }

/* ── Frost — the LIGHT panel variant. The base .bg-glass body is a dark
   translucent fill (--glass-fill: rgba(13,13,24,.64)) tuned for the dark
   theme / bg-glow; frost flips it to a bright translucent body so the card
   reads light — over the dark glow (colored light bleeds through the low
   opacity) or on a light bg-grey-10 body. The inset highlight stack is
   flipped too: white bevels vanish on a light panel, so the edge becomes a
   dark hairline (defines the shape on light) plus one bright top bevel, and
   the drop shadow is deepened to separate it from a light background.
   Sheen is off (white-on-white is invisible); pair a bg-glass-* tint after
   it to reintroduce a colored sheen. Like .bg-glass it sets no text color —
   add c-grey-01 for the (now required) dark text.
   Usage: class="bg-glass bg-glass-frost rounded-l p-xl c-grey-01" */
.bg-glass-frost {
  --glass-fill: rgba(255, 255, 255, 0.68);
  --glass-tint: var(--c-white);
  --glass-sheen: 0%;
  --glass-shadow:
    inset 0 0 0 1px rgba(13, 13, 24, 0.06),
    inset 0 1px 0 0 rgba(255, 255, 255, 0.9),
    0 12px 32px rgba(0, 0, 0, 0.1);
}

/* ── .icon-glow: soft radial bloom behind an icon or any element that
   needs an ambient color halo. Color is parameterized via
   --icon-glow-color (defaults to aqua); set it inline or via a
   wrapping class to recolor.

   Pairs naturally with .icon-slot (which provides position: relative
   + isolation: isolate). On any other host, the rule re-establishes
   those itself so the z-index: -1 pseudo stays scoped.
   Usage: class="icon-slot icon-glow"
       or class="icon-slot icon-glow" style="--icon-glow-color: var(--c-coral);" */
.icon-glow {
  position: relative;
  isolation: isolate;
}

.icon-glow::before {
  content: "";
  position: absolute;
  inset: -60%;
  z-index: -1;
  pointer-events: none;
  --_g: var(--icon-glow-color, var(--c-aqua));
  background: radial-gradient(circle at center,
    color-mix(in srgb, var(--_g) 28%, transparent) 0%,
    color-mix(in srgb, var(--_g) 14%, transparent) 25%,
    color-mix(in srgb, var(--_g) 5%, transparent)  48%,
    transparent 72%);
}

:root {
  --btn-font-size: clamp(0.75rem, 0.227vw + 0.693rem, 0.875rem);
  --btn-font-weight: 400;

  --btn-radius: 999px;
  --btn-padding-y: var(--spacing-2xs);
  --btn-padding-x: var(--spacing-l);
  --btn-shadow: 0 0 0 var(--c-periwinkle) / 0%;
  --btn-shadow-hover: 0 16px 32px rgba(72, 100, 255, 0.12);
  --btn-transition: 200ms ease;
}

/* ── Anchors ──────────────────────────────────────────────────── */

/* Anchors inherit the size of the text they sit in. An inline link inside body
   copy (FAQ answers, rich text, .prose, table cells) has to match its
   surrounding paragraph — pinning every <a> to the small button size shrank
   those links to ~78% of the copy around them. Anchors that ARE controls
   (.btn, .chip, .link, .nav-link, pagination) set their own font-size below. */
a {
  cursor: pointer;
  color: inherit;
  margin: 0;
  font-size: inherit;
}

.link {
  font-size: var(--btn-font-size);
  text-decoration: none;
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  transition: all 200ms ease;
}

.link-text {
  transition: all 200ms ease;
}

.link-icon-1 {
  margin-left: var(--spacing-xs);
  transition: transform 200ms ease;
}

.link:hover .link-icon-1 {
  transform: translateX(var(--spacing-4xs));
}

.link-text-2 {
  transform: translateX(0);
  transition: transform 200ms ease;
}

.link:hover .link-text-2 {
  transform: translateX(24px);
}

.link-icon-2 {
  margin: 0;
  opacity: 0;
  width: 0;
  transition: all 400ms ease;
}

.link:hover .link-icon-2 {
  opacity: 1;
  transform: translateX(0);
}

.link-secondary {
  color: inherit;
}

.link-secondary:hover {
  color: var(--c-periwinkle-light);
}

/* Underline-on-hover link.
 *
 * For a bare `.link` that carries no `.link-icon-2` / `.link-text-2` children:
 * those supply the slide-and-arrow hover, so without them a `.link` has no
 * hover response at all and reads as static text. That's the case for a link
 * doing double duty as a section label — the Locations mega-menu's USA / Canada
 * headings sit above their city lists.
 *
 * The underline is kept off at rest and revealed on hover/focus, so the label
 * stays visually a heading until you reach for it.
 *
 * Declared as `underline` with a transparent colour rather than toggling
 * `text-decoration-line`, because `line` is not animatable and would pop in;
 * `text-decoration-color` transitions cleanly. `currentColor` keeps it usable
 * on any accent, and `text-underline-offset` clears the descenders.
 *
 * `:focus-visible` is included so keyboard users get the same affordance a
 * mouse user gets on hover.
 *
 * Note `.link` blockifies to `flex` when it's a flex item, so the underline
 * still hugs the text rather than spanning the full box — verified in-browser.
 */
.link-underline-hover {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
  transition: text-decoration-color 200ms ease;
}

.link-underline-hover:hover,
.link-underline-hover:focus-visible {
  text-decoration-color: currentColor;
}

/* ── Buttons ──────────────────────────────────────────────────────
 *
 * Composition: btn + type + (optional) color + (optional) btn-arrow
 *
 *   <a class="btn">…</a>                                 default primary
 *   <a class="btn btn-primary">…</a>                     primary (explicit)
 *   <a class="btn btn-secondary">…</a>                   transparent + border
 *   <a class="btn btn-primary btn-coral">…</a>           coral filled
 *   <a class="btn btn-secondary btn-aqua">…</a>          aqua-bordered, fills on hover
 *   <a class="btn btn-primary btn-arrow">…</a>           with right-side arrow circle
 *
 * The system is token-based: type classes consume CSS custom properties
 * (--btn-bg, --btn-text, --btn-border, and their *-hover variants); color
 * modifier classes override those tokens. Each color has a special-case
 * rule for .btn-secondary because secondary fills with the color on hover
 * (rather than swapping to white like primary does).
 *
 * Per-instance overrides still work — drop a style="--btn-bg: red" on any
 * element for a one-off color.
 * ──────────────────────────────────────────────────────────────────── */

.button,
.hs-button,
.btn {
  /* Defaults — periwinkle pill that swaps to aqua on hover. These tokens
     are what the color modifier classes below override. */
  --btn-bg:           var(--c-periwinkle);
  --btn-bg-hover:     var(--c-aqua);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-black);
  --btn-border:       transparent;
  --btn-border-hover: transparent;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.04em;

  padding: var(--btn-padding-y) var(--btn-padding-x);
  border-radius: var(--btn-radius);
  border: 1px solid var(--btn-border);
  outline: none;

  background-color: var(--btn-bg);
  color: var(--btn-text);
  font-size: var(--btn-font-size);
  font-weight: var(--btn-font-weight);

  cursor: pointer;
  box-shadow: var(--btn-shadow);
  transform: translateY(0);

  transition:
    background-color var(--btn-transition),
    color var(--btn-transition),
    border-color var(--btn-transition),
    box-shadow var(--btn-transition),
    transform var(--btn-transition);
}

.button:hover,
.hs-button:hover,
.btn:hover {
  background-color: var(--btn-bg-hover);
  color: var(--btn-text-hover);
  border-color: var(--btn-border-hover);
  box-shadow: var(--btn-shadow-hover);
  transform: translateY(-2px);
}

.button:active,
.hs-button:active,
.btn:active {
  transform: translateY(0);
}

.button:focus-visible,
.hs-button:focus-visible,
.btn:focus-visible {
  outline: 2px solid var(--c-grey-07);
  outline-offset: 2px;
}

.button[disabled],
.hs-button[disabled],
.btn[disabled],
.btn.is-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

/* FA icons sit slightly below the cap-height center of uppercase button
   text. Nudge them up to optically center. Matches both <i class="fa-…">
   (webfont mode) and the .svg-inline--fa SVG injected by the kit. */
.button .fa-solid,        .button .fa-regular,        .button .fa-brands,        .button .fa-light,        .button .fa-thin,        .button .fa-sharp,        .button .svg-inline--fa,
.hs-button .fa-solid,     .hs-button .fa-regular,     .hs-button .fa-brands,     .hs-button .fa-light,     .hs-button .fa-thin,     .hs-button .fa-sharp,     .hs-button .svg-inline--fa,
.btn .fa-solid,           .btn .fa-regular,           .btn .fa-brands,           .btn .fa-light,           .btn .fa-thin,           .btn .fa-sharp,           .btn .svg-inline--fa,
.link .fa-solid,          .link .fa-regular,          .link .fa-brands,          .link .fa-light,          .link .fa-thin,          .link .fa-sharp,          .link .svg-inline--fa {
  transform: translateY(-1px);
}

/* ── Type variants ──
   btn-primary is the implicit default; the explicit class is provided so
   markup reads consistently. btn-secondary inverts to a bordered transparent
   pill — its color tokens differ because secondary's "color" is its border,
   not its background. */

.btn-primary {
  /* Inherits defaults from the base button rule. Listed here for clarity
     and to give markup an explicit class to opt back into primary if it's
     also receiving btn-secondary from another source. */
}

.btn-secondary {
  --btn-bg:           transparent;
  --btn-bg-hover:     transparent;
  --btn-text:         var(--c-grey-09);
  --btn-text-hover:   var(--c-grey-09);
  --btn-border:       var(--c-grey-07);
  --btn-border-hover: var(--c-aqua);
}

/* ── Color modifiers ──
   Each color sets the same set of tokens. The .btn-secondary.btn-{color}
   override flips the hover pattern so secondary fills with the color on
   hover instead of swapping to white. */

/* periwinkle — same hue as the default, but explicit. Useful on secondary
   to get a periwinkle-bordered button that fills with periwinkle on hover. */
.btn-periwinkle {
  --btn-bg:           var(--c-periwinkle);
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-periwinkle);
  --btn-border:       var(--c-periwinkle);
  --btn-border-hover: var(--c-periwinkle);
}
.btn-secondary.btn-periwinkle {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-periwinkle);
  --btn-text:         var(--c-periwinkle);
  --btn-text-hover:   var(--c-white);
}

/* coral */
.btn-coral {
  --btn-bg:           var(--c-coral);
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-coral);
  --btn-border:       var(--c-coral);
  --btn-border-hover: var(--c-coral);
}
.btn-secondary.btn-coral {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-coral);
  --btn-text:         var(--c-coral);
  --btn-text-hover:   var(--c-white);
}

/* aqua */
.btn-aqua {
  --btn-bg:           var(--c-aqua);
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-black);
  --btn-text-hover:   var(--c-aqua);
  --btn-border:       var(--c-aqua);
  --btn-border-hover: var(--c-aqua);
}
.btn-secondary.btn-aqua {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-aqua);
  --btn-text:         var(--c-aqua);
  --btn-text-hover:   var(--c-black);
}

/* purple */
.btn-purple {
  --btn-bg:           var(--c-purple-regular);
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-purple-regular);
  --btn-border:       var(--c-purple-regular);
  --btn-border-hover: var(--c-purple-regular);
}
.btn-secondary.btn-purple {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-purple-regular);
  --btn-text:         var(--c-purple-regular);
  --btn-text-hover:   var(--c-white);
}

/* white — for use on dark surfaces */
.btn-white {
  --btn-bg:           var(--c-white);
  --btn-bg-hover:     var(--c-black);
  --btn-text:         var(--c-black);
  --btn-text-hover:   var(--c-white);
  --btn-border:       var(--c-white);
  --btn-border-hover: var(--c-white);
}
.btn-secondary.btn-white {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-black);
}

/* black */
.btn-black {
  --btn-bg:           var(--c-black);
  --btn-bg-hover:     var(--c-white);
  --btn-text:         var(--c-white);
  --btn-text-hover:   var(--c-black);
  --btn-border:       var(--c-black);
  --btn-border-hover: var(--c-black);
}
.btn-secondary.btn-black {
  --btn-bg:           transparent;
  --btn-bg-hover:     var(--c-black);
  --btn-text:         var(--c-black);
  --btn-text-hover:   var(--c-white);
}

/* ── btn-arrow ──
   Self-contained right-side accent: black circle with a coral arrow that
   rotates 45° → 0° on hover. Implemented as a ::after pseudo-element with
   an inline SVG data URI so it works on any button without per-module
   markup. No HubL conditional required.
   ────────────────────────────────────────────────────────────── */

.btn-arrow {
  position: relative;
  padding-right: 2.75em;
}

.btn-arrow::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  aspect-ratio: 1;
  box-sizing: border-box;
  border-radius: 999px;
  border: 2px solid var(--btn-bg);
  background-color: var(--c-black);
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23FF815C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>');
  background-repeat: no-repeat;
  background-position: center;
  background-size: 45%;
  transform: rotate(45deg);
  transition: transform var(--btn-transition), border-color var(--btn-transition);
}

.btn-arrow:hover::after {
  transform: rotate(0deg);
  border-color: var(--btn-bg-hover);
}

/* btn-arrow is primary-only — secondary buttons drop the circle and the
   reserved right-side padding. */
.btn-secondary.btn-arrow {
  padding-right: var(--btn-padding-x);
}

.btn-secondary.btn-arrow::after {
  display: none;
}

/* ── Button Group ── */

.btn-group {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--spacing-s);
}

/* ── Chips ──────────────────────────────────────────────────────
 *
 * Composition: chip + (optional) color
 *
 *   <span class="chip">…</span>                 default — grey border, grey-07 text
 *   <span class="chip chip-coral">…</span>      coral border + coral text
 *   <span class="chip chip-aqua">…</span>       aqua border + aqua text
 *
 * Token-based like buttons. Color modifier classes override --chip-bg,
 * --chip-text, --chip-border (+ -hover variants). Per-instance overrides
 * still work — drop style="--chip-border: red" on any element for a one-off.
 * Chips are bordered-only by default (no filled variant); for a filled chip
 * set --chip-bg via inline style or a project-local class.
 * ──────────────────────────────────────────────────────────────────── */

.chip {
  --chip-bg:           transparent;
  --chip-bg-hover:     transparent;
  --chip-text:         var(--c-grey-07);
  /* Hover text follows the chip's own text color (resolved lazily at use, so
     color modifiers below that only set --chip-text carry through to hover).
     Override per-instance/variant if a distinct hover text is ever needed. */
  --chip-text-hover:   var(--chip-text);
  --chip-border:       var(--c-grey-04);
  --chip-border-hover: var(--c-aqua);

  text-decoration: none;
  display: inline-flex;
  flex-direction: row;
  padding: var(--spacing-4xs) var(--spacing-m);
  border-radius: var(--btn-radius);

  background-color: var(--chip-bg);
  color: var(--chip-text);
  border: 1px solid var(--chip-border);

  font-size: var(--btn-font-size);
  text-transform: uppercase;
  letter-spacing: 0.04em;

  transition:
    background-color var(--btn-transition),
    color var(--btn-transition),
    border-color var(--btn-transition);
}

.chip:hover {
  background-color: var(--chip-bg-hover);
  color: var(--chip-text-hover);
  border-color: var(--chip-border-hover);
}

/* ── Color modifiers ──
   Tint the border and text. Setting --chip-text also drives the hover text
   (see --chip-text-hover above), and --chip-border-hover keeps the same color
   on hover (no swap to aqua like the default chip does) — so colored chips
   stay fully on-brand on hover. */

.chip-periwinkle {
  --chip-text:         var(--c-periwinkle);
  --chip-border:       var(--c-periwinkle);
  --chip-border-hover: var(--c-periwinkle);
}

.chip-coral {
  --chip-text:         var(--c-coral);
  --chip-border:       var(--c-coral);
  --chip-border-hover: var(--c-coral);
}

.chip-aqua {
  --chip-text:         var(--c-aqua);
  --chip-border:       var(--c-aqua);
  --chip-border-hover: var(--c-aqua);
}

.chip-purple {
  --chip-text:         var(--c-purple-regular);
  --chip-border:       var(--c-purple-regular);
  --chip-border-hover: var(--c-purple-regular);
}

.chip-white {
  --chip-text:         var(--c-white);
  --chip-border:       var(--c-white);
  --chip-border-hover: var(--c-white);
}

.chip-black {
  --chip-text:         var(--c-black);
  --chip-border:       var(--c-black);
  --chip-border-hover: var(--c-black);
}

/* Sections */

.section {
  padding-left: var(--spacing-l);
  padding-right: var(--spacing-l);
  scroll-margin-top: 100px;
}

/* Containers */

.container-s {
  margin: auto;
  max-width: 48rem;
}
.container-m {
  margin: auto;
  max-width: 64rem;
}
.container-l {
  margin: auto;
  max-width: 80rem;
}

.container-full {
  margin: auto;
  max-width: 100%;
}

/* Wrapper */

.wrapper {
  width: 100%;
}

.logo-wrapper {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: var(--spacing-xl);
  height: var(--spacing-xl);
}

.logo-wrapper img{
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.logo {
  width: auto;
  height: var(--spacing-xl);
}

/* Logo cell — fixed-frame slot for normalizing logo display in
   carousels, sliders, or grids. Inner <img> / <svg> sizes to fit
   without distortion. Override --logo-cell-w / --logo-cell-h
   inline or via a modifier class to resize per-context. */

.logo-cell {
  --logo-cell-w: var(--spacing-8xl);
  --logo-cell-h: var(--spacing-3xl);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--logo-cell-w);
  height: var(--logo-cell-h);
  padding: var(--spacing-2xs) var(--spacing-s);
  box-sizing: border-box;
  flex-shrink: 0;
}

.logo-cell-s {
  --logo-cell-w: var(--spacing-6xl);
  --logo-cell-h: var(--spacing-2xl);
}

.logo-cell-l {
  --logo-cell-w: calc(var(--spacing-8xl) + var(--spacing-3xl));
  --logo-cell-h: var(--spacing-4xl);
}

.logo-cell img,
.logo-cell svg {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* Card width utilities — fixed slide/card widths. Global (NOT module-scoped)
   so they apply on every page regardless of which modules are present. Used by
   slider-horizontal cards (.slider-card) and slider-carousel slides
   (.marquee-slide), set per-slide via the Slide Style field. Each module's
   mobile override (cards → near-full-width) stays in that module's own CSS. */

.card-w-xs  { width: 14rem; }
.card-w-s   { width: 18rem; }
.card-w-m   { width: 22rem; }
.card-w-l   { width: 28rem; }
.card-w-xl  { width: 34rem; }
.card-w-2xl { width: 40rem; }
.card-w-3xl { width: 48rem; }
.card-w-4xl { width: 56rem; }

/* Content-hugging slide — width follows the slide's own content instead of a
   fixed card size. For marquees of small, mixed-width items (logos, badges)
   where a fixed card-w-* leaves large empty gaps; spacing is then controlled
   entirely by the carousel gap. The card-w- prefix also opts out of the
   slider-carousel fallback min-width. */
.card-w-auto { width: max-content; }

/* Badge — fixed-width image slot. Width is set by the size variant; height
   auto-derives from the image's intrinsic aspect ratio so badges never
   distort. flex-shrink: 0 keeps them sized correctly in tight flex rows. */

.badge {
  --badge-w: var(--spacing-6xl);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--badge-w);
  flex-shrink: 0;
}

.badge-xs { --badge-w: var(--spacing-3xl); }
.badge-s  { --badge-w: var(--spacing-4xl); }
.badge-m  { --badge-w: var(--spacing-6xl); }
.badge-l  { --badge-w: var(--spacing-8xl); }

@media (max-width: 991px) {
  .badge-xs { --badge-w: var(--spacing-2xl); }
  .badge-s  { --badge-w: var(--spacing-3xl); }
  .badge-m  { --badge-w: var(--spacing-4xl); }
  .badge-l  { --badge-w: var(--spacing-6xl); }
}

.badge img,
.badge svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Optional fixed-height slot. Pair with a badge size (width); the image
   scales to fit inside the box, centered, preserving its aspect ratio — so
   cards whose source images have different aspect ratios align vertically.
   Opt-in: the object-fit override is scoped to badge-h-* so plain badges
   (logo rows, tight flex) keep their intrinsic auto-height behaviour. */

.badge-h-xs { height: var(--spacing-4xl); }
.badge-h-s  { height: var(--spacing-5xl); }
.badge-h-m  { height: var(--spacing-6xl); }
.badge-h-l  { height: var(--spacing-8xl); }

.badge[class*="badge-h-"] img,
.badge[class*="badge-h-"] svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Height-driven badge — locks the slot HEIGHT and lets WIDTH follow the image's
   aspect ratio (the inverse of plain .badge, which locks width). For badge rows
   that mix square and wide logos sharing a common source height, so they align
   on one baseline instead of a common width. The height reuses the badge-size
   scale (--badge-w set by badge-xs/s/m/l), so `badge badge-s badge-fluid`
   locks to the small size and stays in step with the square badges beside it. */
.badge-fluid { width: auto; height: var(--badge-w); }
.badge-fluid img,
.badge-fluid svg { width: auto; height: 100%; }

/* Icon slot — fixed-HEIGHT frame for inline icons (SVG or image). Sibling
   to .logo-cell / .badge. Sized by --icon-slot-w / --icon-slot-h so it
   can be re-themed in place; position: relative + isolation: isolate so
   companion utilities like .icon-glow can use ::before z-index: -1
   without falling behind ancestor backgrounds. Inherits currentColor,
   so any `c-*` color class on the slot tints stroke='currentColor'
   SVGs to brand.

   Height is the LOCKED axis and width follows the icon's aspect ratio —
   the same reasoning as .badge-fluid. Font Awesome draws every icon on a
   common height (viewBox 512 tall) with a varying width, so height-locking
   is what makes a mixed row read at one optical size; fitting each glyph
   inside a square instead renders wide icons visibly smaller than square
   ones and drifts the content below them. The SLOT keeps its fixed
   --icon-slot-w box so horizontal rhythm never moves (icon-before-title
   rows like section-dropdown's keep a shared text left edge); a wide icon
   simply overflows that invisible box, centered, by a few px. Give an
   icon-slot a visible background/border only at icon-slot-w >= its widest
   icon's aspect, or the glyph will poke past the tile. */

.icon-slot {
  --icon-slot-w: var(--spacing-2xl);
  --icon-slot-h: var(--spacing-2xl);
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-slot-w);
  height: var(--icon-slot-h);
  flex-shrink: 0;
}

.icon-slot-s { --icon-slot-w: var(--spacing-xl);  --icon-slot-h: var(--spacing-xl);  }
.icon-slot-m { --icon-slot-w: var(--spacing-2xl); --icon-slot-h: var(--spacing-2xl); }
.icon-slot-l { --icon-slot-w: var(--spacing-4xl); --icon-slot-h: var(--spacing-4xl); }

/* Pass the slot's height down through a wrapper element: section-builder and
   the slider modules nest media_src inside .media-fg, so the icon is not
   always a direct child of the slot. A percentage height only resolves
   against a definite parent height — without this the icon ignores the slot
   entirely and falls back to its intrinsic viewBox aspect, so every icon in
   a row renders at a different height. flex-shrink keeps a wider-than-square
   icon at full size (and centered) instead of being squeezed to the slot. */
.icon-slot > * {
  height: 100%;
  flex-shrink: 0;
}

/* object-fit is inert on an inline <svg> (not a replaced element) and a no-op
   while one axis is auto — it's kept so an <img> icon still fits instead of
   distorting if a consumer pins both axes. */
.icon-slot svg,
.icon-slot img {
  width: auto;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Dividers */

.v-line {
  width: 1px;
  height: var(--spacing-xl);
  background-color: var(--c-purple-medium);
}

.h-line {
  width: var(--spacing-xl);
  height: 1px;
  background-color: var(--c-purple-medium);
}

/* Grid */

.g-cols-12 {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
/* 10-track variant, for rows whose cell count doesn't divide 12 — a 5-up row is
   5 x .g-col-span-2. The span utilities are shared, so span-2 is 1/5 here and
   1/6 on .g-cols-12; pair it with .g-col-span-10 for a full-width child. */
.g-cols-10 {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
.g-rows-12 {
  display: grid;
  grid-template-rows: repeat(1, minmax(0, 1fr));
}

@media (min-width: 991px) {
  .g-cols-12 {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }
  .g-cols-10 {
    grid-template-columns: repeat(10, minmax(0, 1fr));
  }
  .g-rows-12 {
    grid-template-rows: repeat(12, minmax(0, 1fr));
  }
}

/* Sibling alignment for grid rows of equal-shape cards (numbered steps, feature
   columns). Reserves N lines for the heading so every card's body copy starts on
   the same baseline even when one heading wraps an extra line — without it a
   single long title drops its own paragraph a line below its neighbours.
   Pick N from the LONGEST title at the real render width; it is a measured value,
   not a guess (scripts/_titlefit.mjs prints the line count per title). If `lh` is
   unsupported the rule is simply dropped and the row falls back to ragged. */
.title-lines-1 { min-height: 1lh; }
.title-lines-2 { min-height: 2lh; }
.title-lines-3 { min-height: 3lh; }
.title-lines-4 { min-height: 4lh; }

/* Grid Column Span */

.g-col-span-1,
.g-col-span-2,
.g-col-span-3,
.g-col-span-4,
.g-col-span-5,
.g-col-span-6,
.g-col-span-7,
.g-col-span-8,
.g-col-span-9,
.g-col-span-10,
.g-col-span-11,
.g-col-span-12 {
  grid-column: span 1 / span 1;
}

@media (min-width: 991px) {
  .g-col-span-1 {
    grid-column: span 1 / span 1;
  }
  .g-col-span-2 {
    grid-column: span 2 / span 2;
  }
  .g-col-span-3 {
    grid-column: span 3 / span 3;
  }
  .g-col-span-4 {
    grid-column: span 4 / span 4;
  }
  .g-col-span-5 {
    grid-column: span 5 / span 5;
  }
  .g-col-span-6 {
    grid-column: span 6 / span 6;
  }
  .g-col-span-7 {
    grid-column: span 7 / span 7;
  }
  .g-col-span-8 {
    grid-column: span 8 / span 8;
  }
  .g-col-span-9 {
    grid-column: span 9 / span 9;
  }
  .g-col-span-10 {
    grid-column: span 10 / span 10;
  }
  .g-col-span-11 {
    grid-column: span 11 / span 11;
  }
  .g-col-span-12 {
    grid-column: span 12 / span 12;
  }
}

/* Grid Row Span */

.g-row-span-1,
.g-row-span-2,
.g-row-span-3,
.g-row-span-4,
.g-row-span-5,
.g-row-span-6,
.g-row-span-7,
.g-row-span-8,
.g-row-span-9,
.g-row-span-10,
.g-row-span-11,
.g-row-span-12 {
  grid-row: span 1 / span 1;
}

@media (min-width: 640px) {
  .g-row-span-1 {
    grid-row: span 1 / span 1;
  }
  .g-row-span-2 {
    grid-row: span 2 / span 2;
  }
  .g-row-span-3 {
    grid-row: span 3 / span 3;
  }
  .g-row-span-4 {
    grid-row: span 4 / span 4;
  }
  .g-row-span-5 {
    grid-row: span 5 / span 5;
  }
  .g-row-span-6 {
    grid-row: span 6 / span 6;
  }
  .g-row-span-7 {
    grid-row: span 7 / span 7;
  }
  .g-row-span-8 {
    grid-row: span 8 / span 8;
  }
  .g-row-span-9 {
    grid-row: span 9 / span 9;
  }
  .g-row-span-10 {
    grid-row: span 10 / span 10;
  }
  .g-row-span-11 {
    grid-row: span 11 / span 11;
  }
  .g-row-span-12 {
    grid-row: span 12 / span 12;
  }
}

.grid-strech {
  justify-self: stretch;
}

/* Order */

.g-order-2 {
  order: 2;
}

@media (min-width: 991px) {
  .g-order-2 {
    order: 0;
  }
}

/* Step card & badge — sequential process flow ("How it works" pattern).
   Apply .step-card to each card; a dashed connector draws in the gap
   to the LEFT of every step-card except the first, visually linking
   adjacent steps. .step-badge styles a numbered pill (01, 02, …)
   sitting at the top of each card. */

.step-card {
  position: relative;
}

.step-card + .step-card::before {
  content: '';
  position: absolute;
  top: calc(var(--spacing-l) + 28px); /* card padding + half badge height */
  left: calc(-1 * var(--spacing-l));   /* extend left into the gap */
  width: var(--spacing-l);              /* span the full gap */
  border-top: 2px dashed var(--c-grey-04);
  z-index: 0;
  pointer-events: none;
}

@media (max-width: 991px) {
  .step-card + .step-card::before { display: none; }
}

.step-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background-color: var(--c-periwinkle);
  color: var(--c-white);
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  position: relative;
  z-index: 1; /* sit on top of the dashed line */
}

/* Minimal text variant of .step-badge — no filled circle, no bold,
   absolutely positioned to the top-left of a `position: relative` host
   (e.g. a card face). Pair with a typography class (h6, etc.) on the
   element to control text size/weight. */
.step-badge-minimal {
  position: absolute;
  top: var(--spacing-l);
  left: var(--spacing-l);
  z-index: 1;
  pointer-events: none;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

/* Icon Boxes */

.box-xs {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--spacing-4xs);
  width: var(--spacing-xl);
  height: var(--spacing-xl);
  aspect-ratio: 1 /1;
}

.box-s {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--spacing-4xs);
  width: var(--spacing-2xl);
  height: var(--spacing-2xl);
  aspect-ratio: 1 /1;
}

.box-m {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--spacing-4xs);
  width: var(--spacing-3xl);
  height: var(--spacing-3xl);
  aspect-ratio: 1 /1;
}

/* Border radius */

.rounded-s {
  border-radius: var(--spacing-4xs);
}

.rounded-m {
  border-radius: var(--spacing-3xs);
}

.rounded-l {
  border-radius: var(--spacing-2xs);
}


/* Divided grid — hairline rules BETWEEN cells, one rounded frame around the whole
   grid. Goes on the grid CONTAINER; children need no border class of their own.
   Override the line colour per instance with `--grid-line`.

   Why box-shadow on the children rather than a border: a border on every cell
   doubles up on every shared edge, and at the container's rounded corners it gets
   clipped into a square notch that no radius can fix (the straight border can't
   follow the arc). Instead each child paints a 1px rule to its right and below;
   the trailing column and last row paint theirs exactly under the container's own
   border, where `overflow: hidden` clips them away. The container's border draws
   the curve, so corners stay clean.

   Outer box-shadows are clipped to outside the border box, so a 1px offset with
   no blur/spread reads as a hairline even on transparent cells.

   The payoff is that this stays independent of column count, row count and cell
   spans — no :nth-child() arithmetic to keep in sync with the grid. */

.grid-lines {
  --grid-line: var(--c-grey-04);
  gap: 0; /* the rules ARE the separation; any gap breaks them into segments */
  border: 1px solid var(--grid-line);
  border-radius: var(--spacing-2xs);
  overflow: hidden; /* clips the trailing rules + the cells' square corners */
}

.grid-lines > * {
  box-shadow:
    1px 0 0 var(--grid-line), /* rule to the right */
    0 1px 0 var(--grid-line); /* rule below */
}


/* Flex */

.flex-column {
  display: flex;
  flex-direction: column;
}

.flex-row {
  display: flex;
  flex-direction: row;
}

.justify-between {
  justify-content: space-between;
}

.justify-center {
  justify-content: center;
}

.justify-end {
  justify-content: end;
}

/* Desktop-only end-alignment — flips to start on mobile (≤991px).
   Useful for right-aligned button groups that should hug the left edge
   when the layout collapses to one column. */
.justify-end-desktop {
  justify-content: start;
}

@media (min-width: 991px) {
  .justify-end-desktop {
    justify-content: end;
  }
}

.align-end {
  align-items: end;
}

.align-center {
  align-items: center;
}

.align-start {
  align-items: start;
}

.align-stretch {
  align-items: stretch;
}

.flex-wrap {
  flex-wrap: wrap;
}

.flex-nowrap {
  flex-wrap: nowrap;
}

.flex-grow {
  flex-grow: 1;
}

/* Sizing — numeric = percentage, matching the iframe-w-* convention. */

.w-100 {
  width: 100%;
}

.h-100 {
  height: 100%;
}

/* =================================================================
   Sticky — pins a grid/flex child to the top while a taller sibling
   in the same row scrolls past (e.g. a section-builder title column
   beside a long description column).

   Self-sufficient: also sets align-self: start so the item shrinks to
   its content instead of stretching to the row height — a stretched
   item has zero scroll travel and would never appear to "stick". Drop
   `sticky` on the short column; no container change needed.

   top offset defaults to 100px to clear the fixed 72px header (matches
   .section's scroll-margin-top). Override per-instance:
     style="--sticky-top: 140px"

   Desktop-only (≥991px): below that, .g-cols-12 collapses to one column
   and items stack — a sticky title would pin over its own body text and
   read as a bug. No-op on mobile, mirroring .card-align.
   ================================================================= */

@media (min-width: 991px) {
  .sticky {
    position: sticky;
    top: var(--sticky-top, 100px);
    align-self: start;
  }
}

/* =================================================================
   Card alignment (opt-in, per card).

   Add .card-align to each card in a row that should share vertical
   rhythm. Each card:
     - becomes a flex column
     - reserves space for up to 2 lines of title (so 1-line titles
       still take the height of a 2-line title)
     - reserves space for up to 2 lines of description
     - bottom-anchors the links / button group

   Result: sibling cards with .card-align line up at title row,
   description row, and link row, without touching the parent grid
   or affecting any sibling that omits the class. Adding the class
   to a card has zero impact on its neighbors — safe to drop into
   any section-builder / slider / custom layout.

   Tune via CSS variables on the card:
     style="--card-title-lines: 3"   (e.g. for a row with longer titles)
     style="--card-desc-lines: 4"

   Scoped to ≥992px because on mobile cards stack full-width and
   the reserved empty lines read as layout bugs. On mobile the
   class is a no-op and cards flow naturally.
   ================================================================= */

@media (min-width: 992px) {
  .card-align {
    --card-title-lines: 2;
    --card-desc-lines: 2;
    display: flex;
    flex-direction: column;
  }
  .card-align > .title-section {
    min-height: calc(var(--card-title-lines) * 1lh);
  }
  .card-align > .description-section {
    min-height: calc(var(--card-desc-lines) * 1lh);
  }
  .card-align > .links-section,
  .card-align > .btn-group {
    margin-top: auto;
  }
}

:root {
    --hsf-global__font-family: inherit;
    --hsf-global__font-size: clamp(0.75rem, 0.227vw + 0.693rem, 0.875rem);
    --hsf-global__color: var(--c-grey-09);
    --hsf-global-error__color: var(--c-coral);

    --hsf-button__font-size: clamp(0.875rem, 0.227vw + 0.818rem, 1rem);
    --hsf-button__background-color: var(--c-periwinkle);
    --hsf-button__border-radius: 999px;
    --hsf-button__padding: var(--spacing-2xs) var(--spacing-l);

    --hsf-field-label__color: var(--c-grey-07);
    --hsf-field-input__color: var(--c-grey-09);
    --hsf-field-input__background-color: var(--c-grey-02);
    --hsf-field-input__placeholder-color: var(--c-grey-05);
    --hsf-field-input__border-color: var(--c-grey-04);
    --hsf-field-input__border-color-focus: var(--c-periwinkle);
    --hsf-field-input__border-width: 1px;
    --hsf-field-input__border-radius: 10px;
    --hsf-field-input__padding: var(--spacing-s) var(--spacing-m);
    --hsf-field-input__focus-ring: 0 0 0 3px rgba(72, 100, 255, 0.22);
}

/* Form root */

form {
  color: var(--hsf-global__color);
  font-family: var(--hsf-global__font-family);
  font-size: var(--hsf-global__font-size);
}

form fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  max-width: 100% !important;
}

/* Full-width fields must reach the container's right edge. HubSpot's default form
   CSS renders `.form-columns-1` inputs at ~95% and leaves the 2-column gutter margin
   on their `.input` wrapper, so they stop ~34px short (the 2-column fields are fine). */
form .form-columns-1 .hs-input { width: 100% !important; }
form .form-columns-1 .input { margin-right: 0 !important; }

/* Fields */

.hs-form-field {
  margin-bottom: var(--spacing-l);
}

/* Labels */

form label {
  display: block;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--hsf-field-label__color);
  margin-bottom: var(--spacing-2xs);
}

/* Form Title */
.form-title {
  margin-bottom: var(--spacing-m);
}

/* Help text & legends */

form legend,
.hs-field-desc {
  font-size: 0.75rem;
  color: var(--c-grey-06);
  margin-bottom: var(--spacing-2xs);
}

/* Inputs */

form input[type=text],
form input[type=search],
form input[type=email],
form input[type=password],
form input[type=tel],
form input[type=number],
form input[type=url],
form input[type=date],
form input[type=time],
form input[type=file],
form select,
form textarea,
.hs-input {
  display: block;
  width: 100%;
  font-family: inherit;
  font-size: var(--hsf-global__font-size);
  color: var(--hsf-field-input__color);
  background-color: var(--hsf-field-input__background-color);
  border: var(--hsf-field-input__border-width) solid var(--hsf-field-input__border-color);
  border-radius: var(--hsf-field-input__border-radius);
  padding: var(--hsf-field-input__padding);
  transition: border-color 200ms ease, box-shadow 200ms ease, background-color 200ms ease;
  appearance: none;
  -webkit-appearance: none;
}

form input::placeholder,
form textarea::placeholder,
.hs-input::placeholder {
  color: var(--hsf-field-input__placeholder-color);
  opacity: 1;
}

form input:hover,
form select:hover,
form textarea:hover,
.hs-input:hover {
  border-color: var(--c-grey-05);
}

form input:focus,
form select:focus,
form textarea:focus,
.hs-input:focus,
.hs-input:focus-visible {
  outline: none;
  border-color: var(--hsf-field-input__border-color-focus);
  box-shadow: var(--hsf-field-input__focus-ring);
}

form textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.5;
}

/* Select chevron */

form select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%23A3A4BF' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right var(--spacing-m) center;
  padding-right: calc(var(--spacing-m) * 2 + 12px);
}

/* Inputs - checkbox & radio */

form .inputs-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2xs);
}

form .inputs-list > li {
  display: block;
  margin: 0;
}

form .inputs-list label {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-2xs);
  margin: 0;
  cursor: pointer;
  color: var(--c-grey-08);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

form input[type=checkbox],
form input[type=radio] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  background-color: var(--c-grey-02);
  border: 1px solid var(--c-grey-04);
  cursor: pointer;
  position: relative;
  transition: border-color 150ms ease, background-color 150ms ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

form input[type=checkbox] {
  border-radius: 4px;
}

form input[type=radio] {
  border-radius: 999px;
}

form input[type=checkbox]:hover,
form input[type=radio]:hover {
  border-color: var(--c-grey-06);
}

form input[type=checkbox]:checked,
form input[type=radio]:checked {
  background-color: var(--c-periwinkle);
  border-color: var(--c-periwinkle);
}

form input[type=checkbox]:checked::after {
  content: "";
  width: 4px;
  height: 8px;
  border: solid var(--c-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}

form input[type=radio]:checked::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background-color: var(--c-white);
}

form input[type=checkbox]:focus-visible,
form input[type=radio]:focus-visible {
  outline: none;
  box-shadow: var(--hsf-field-input__focus-ring);
}

/* Inputs - date picker */

.hs-dateinput {
  position: relative;
}

.hs-dateinput:before {
  content: '\01F4C5';
  position: absolute;
  right: var(--spacing-m);
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
}

.fn-date-picker .pika-table thead th {
  color: var(--c-grey-09);
}

.fn-date-picker td.is-selected .pika-button {
  background-color: var(--c-periwinkle);
  color: var(--c-white);
}

.fn-date-picker td .pika-button:hover,
.fn-date-picker td .pika-button:focus {
  background-color: var(--c-grey-03);
  color: var(--c-grey-09);
}

/* Inputs - file picker */

form input[type=file] {
  background-color: transparent;
  border: 1px dashed var(--c-grey-04);
  padding: var(--spacing-m);
  cursor: pointer;
}

form input[type=file]::file-selector-button {
  font-family: inherit;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background-color: var(--c-grey-03);
  color: var(--c-grey-09);
  border: 0;
  padding: var(--spacing-2xs) var(--spacing-m);
  border-radius: 999px;
  margin-right: var(--spacing-m);
  cursor: pointer;
  transition: background-color 200ms ease;
}

form input[type=file]::file-selector-button:hover {
  background-color: var(--c-grey-04);
}

/* Headings and richtext */

form .hs-richtext,
form .hs-richtext p {
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--c-grey-07);
  margin: 0 0 var(--spacing-m);
}

form .hs-richtext img {
  max-width: 100% !important;
}

/* GDPR */

.legal-consent-container {
  font-size: 0.75rem;
  color: var(--c-grey-06);
  line-height: 1.55;
}

.legal-consent-container .hs-form-booleancheckbox-display > span,
.legal-consent-container .hs-form-booleancheckbox-display > span p {
  margin-left: var(--spacing-s) !important;
  color: var(--c-grey-07);
}

/* Validation */

.hs-form-required {
  color: var(--c-coral);
  margin-left: 4px;
}

.hs-input.invalid.error,
.hs-input.invalid {
  border-color: var(--c-coral);
}

.hs-input.invalid.error:focus,
.hs-input.invalid:focus {
  box-shadow: 0 0 0 3px rgba(255, 129, 92, 0.22);
}

/* `.hs-error-msgs .hs-error-msg` (0,2,0) is needed to beat `form .inputs-list
   label` (0,1,2) above — HubSpot renders errors as a label inside a ul that also
   carries .inputs-list, so without this the error text inherits the grey list-
   label color instead of the error color (on both themes). */
.hs-error-msg,
.hs-error-msgs label,
.hs-error-msgs .hs-error-msg {
  color: var(--hsf-global-error__color);
  font-size: 0.75rem;
  margin-top: var(--spacing-2xs);
  display: block;
}

/* Submit button — base styling lives in _buttons.css via .hs-button */

form input[type=submit],
form .hs-button {
  cursor: pointer;
  display: inline-flex;
  text-align: center;
  white-space: normal;
}

.hs_submit {
  margin-top: var(--spacing-l);
}

/* Captcha */

.grecaptcha-badge {
  margin: 0 auto;
}

/* Search input — these rules only apply when HubSpot renders the v1 search field on the page. */

.body-container-wrapper .hs-search-field__button {
  padding: var(--spacing-s) var(--spacing-m);
}

.body-container-wrapper .hs-search-field__bar--button-inline .hs-search-field__button {
  margin-left: 6px;
  margin-bottom: 0;
}

.body-container-wrapper .hs-search-field__button svg {
  height: 15px;
  fill: var(--c-white);
}

.body-container-wrapper .hs-search-field__bar > form > .hs-search-field__input {
  padding: var(--hsf-field-input__padding);
}

.body-container-wrapper .hs-search-field__suggestions li a {
  color: var(--c-grey-08);
  padding: var(--spacing-2xs) var(--spacing-m);
  text-decoration: none;
  transition: background-color 200ms ease;
}

.body-container-wrapper .hs-search-field__suggestions li a:hover {
  background-color: var(--c-grey-03);
}

/* ── Light forms (body.bg-grey-10) ──────────────────────────────────────────
   Forms are fully driven by the --hsf-* vars declared in :root (dark defaults).
   On a light page canvas, flip those vars once so every form input, label and
   placeholder inverts to a light field with dark text — no per-form styling.
   Same token-flip mechanism as the body bg/fg in _typography.css. Accents
   (periwinkle button/focus, coral error) already read on both and stay. */
body.bg-grey-10 {
  --hsf-global__color:                  var(--c-grey-01);
  --hsf-field-label__color:             var(--c-grey-03);
  --hsf-field-input__color:             var(--c-grey-01);
  --hsf-field-input__background-color:  var(--c-grey-10);
  --hsf-field-input__placeholder-color: var(--c-grey-06);
  --hsf-field-input__border-color:      var(--c-grey-07);
  /* c-coral (#FF815C) pops on dark but is low-contrast as small text on white —
     darken it toward black for the error message (border/asterisk stay c-coral). */
  --hsf-global-error__color:            color-mix(in oklch, var(--c-coral), var(--c-grey-00) 35%);
}

/* Custom checkbox/radio controls are hardcoded (not --hsf vars) — flip here too.
   The :checked accent (periwinkle) already reads on both themes. */
body.bg-grey-10 form input[type=checkbox],
body.bg-grey-10 form input[type=radio] {
  background-color: var(--c-grey-10);
  border-color: var(--c-grey-07);
}

/* =============================================================
   Tables
   Minimal dark style: hairline row dividers, uppercase header,
   periwinkle accent on hover. Works for both content-editor
   inserted tables and HubSpot module-rendered tables.
   ============================================================= */

table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--spacing-l);
  overflow-wrap: break-word;
  font-size: clamp(0.8125rem, 0.227vw + 0.756rem, 0.9375rem);
  color: var(--c-grey-08);
}

caption {
  text-align: left;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-grey-06);
  padding: var(--spacing-s) var(--spacing-m);
  border-bottom: 1px solid var(--c-grey-04);
}

/* Cells */

td,
th {
  vertical-align: top;
  text-align: left;
  padding: var(--spacing-s) var(--spacing-m);
}

/* Header row */

thead th {
  vertical-align: bottom;
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--c-grey-06);
  border-bottom: 1px solid var(--c-grey-04);
  background-color: transparent;
}

/* Body rows */

tbody td {
  border-bottom: 1px solid var(--c-grey-03);
  color: var(--c-grey-08);
  transition: background-color 200ms ease;
}

tbody tr:last-child td {
  border-bottom: 0;
}

tbody tr:hover td {
  background-color: var(--c-grey-02);
}

/* Footer */

tfoot td,
tfoot th {
  border-top: 1px solid var(--c-grey-04);
  color: var(--c-grey-07);
  font-size: 0.8rem;
}

/* Numeric / right-aligned cells (apply class manually when authoring) */

.t-num,
td.t-num,
th.t-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Narrow viewports: fit the table to the screen instead of letting it widen
   the page. Editor-inserted tables (the location comparison + transit-zone
   tables) are raw HTML in richtext with no wrapper element to clip them, so
   left alone they push <body> wider than the viewport and the whole page
   scrolls sideways.

   Rather than scroll the table (which hides a column and reads as broken), we
   keep `display: table` with auto layout so columns are sized in proportion to
   their content, then buy back the space with a smaller type size and tighter
   cell padding.

   MUST STAY LAST IN THIS FILE. A media query adds no specificity, so when this
   block sat above the base `td, th` and `thead th` rules it lost the cascade on
   every property those rules also set — `padding` and the header `font-size`
   were silently dead for a year, and the cells kept their desktop
   `var(--spacing-m)` padding on phones. That cost the USA/Canada comparison
   table ~15px of text width per column at 390px (60px → 75px once fixed) and
   made rows 25% taller. Don't reorder this above them, and don't "fix" a future
   version of this with !important — keep it last instead. */

@media (max-width: 700px) {
  table {
    /* Auto layout on purpose: it sizes each column to its content, so a short
       label column doesn't get the same share as a column of full sentences.
       `fixed` was tried and is worse here — these tables lead with an EMPTY
       header cell, which starves the label column to ~57px and shreds the
       labels ("Oper / ating / stan / dard / s").
       Auto only stayed within the viewport once the two inline
       `white-space: nowrap` declarations were removed from the cell content
       (see scripts/fix-zone-table-wrap.mjs) — without that it overflowed. */
    table-layout: auto;
    width: 100%;
    max-width: 100%;
    font-size: 0.75rem;
    line-height: 1.4;
  }

  th,
  td {
    padding: var(--spacing-xs);
    /* `break-word`, NOT `anywhere`: `anywhere` also shrinks the column's
       min-content size, which lets the browser break mid-word on every line
       ("disconne / cted"). `break-word` keeps the longest word as the column
       minimum and only breaks a word that genuinely cannot fit.
       `hyphens: auto` stays ON: at ~75px these columns still cannot fit words
       like "disconnected", and a hyphenated break reads better than the bare
       mid-word break that `break-word` would fall back to. */
    overflow-wrap: break-word;
    hyphens: auto;
  }

  thead th {
    font-size: 0.625rem;
    letter-spacing: 0.06em;
  }
}

/* ── .prose — long-form rich-text rhythm ──────────────────────────────
   Restores vertical rhythm and media/quote/code/link styling for flowing
   HTML produced by HubSpot's render_body() / rich-text fields (blog posts,
   long-form copy). The global reset zeroes margins; this scope re-applies
   spacing only inside .prose, so it never leaks into utility-built layouts.
   Generic and reusable — anywhere long-form HTML renders, not blog-only. */

.prose {
  color: var(--c-grey-08);
}

.prose > :first-child { margin-top: 0; }
.prose > :last-child  { margin-bottom: 0; }

/* Block rhythm */
.prose p,
.prose ul,
.prose ol,
.prose blockquote,
.prose pre,
.prose figure,
.prose table {
  margin: 0 0 var(--spacing-l);
}

/* Headings sit closer to the text they introduce than to what precedes. */
.prose h2,
.prose h3,
.prose h4,
.prose h5,
.prose h6 {
  margin: var(--spacing-2xl) 0 var(--spacing-m);
  color: var(--c-grey-10);
}

/* Media */
.prose img,
.prose video,
.prose iframe {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--spacing-3xs);
}

.prose figure { margin-inline: 0; }

.prose figcaption {
  margin-top: var(--spacing-2xs);
  text-align: center;
  color: var(--c-grey-06);
  font-size: clamp(0.75rem, 0.227vw + 0.693rem, 0.875rem);
}

/* ── Inline links in editor-authored rich text ─────────────────────────────
   One recipe for every place an editor can drop a link into body copy: the
   blog body (.prose) plus the module rich-text wrappers (section-builder and
   FAQ descriptions, FAQ answers, warehouse cards, dropdown copy). Without
   this, links outside .prose inherited the surrounding text colour and read
   as plain underlined copy.

   Distinct from the utility .link / .btn / .chip controls — those are
   excluded so a CTA pasted into a rich-text field keeps its own styling.
   Sizing is NOT set here: anchors inherit the size of the copy they sit in
   (see the `a` rule in _buttons.css). */
:is(.prose,
    .description-section,
    .faq-answer-inner,
    .warehouse-description,
    .dropdown-description,
    .dropdown-card-description) a:not(.btn, .link, .chip) {
  color: var(--c-periwinkle-light);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color 200ms ease;
}

:is(.prose,
    .description-section,
    .faq-answer-inner,
    .warehouse-description,
    .dropdown-description,
    .dropdown-card-description) a:not(.btn, .link, .chip):hover {
  color: var(--c-aqua);
}

/* Light canvas — periwinkle-light is too pale on grey-10, drop to the full
   periwinkle. Same body-level scoping convention as LIGHT-THEME.md §5. */
body.bg-grey-10 :is(.prose,
    .description-section,
    .faq-answer-inner,
    .warehouse-description,
    .dropdown-description,
    .dropdown-card-description) a:not(.btn, .link, .chip) {
  color: var(--c-periwinkle);
}

/* Lists */
.prose ul,
.prose ol { padding-left: 1.5em; }

.prose li + li { margin-top: var(--spacing-2xs); }

/* Quotes — brand accent rule, slightly muted text. */
.prose blockquote {
  border-left: 2px solid var(--c-periwinkle);
  padding: var(--spacing-2xs) 0 var(--spacing-2xs) var(--spacing-l);
  color: var(--c-grey-07);
}

/* Code */
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875em;
  background: var(--c-grey-02);
  padding: 0.1em 0.4em;
  border-radius: var(--spacing-4xs);
}

.prose pre {
  background: var(--c-grey-02);
  padding: var(--spacing-l);
  border-radius: var(--spacing-3xs);
  overflow: auto;
}

.prose pre code {
  background: none;
  padding: 0;
}

/* Rule */
.prose hr {
  border: 0;
  border-top: 1px solid var(--c-grey-03);
  margin: var(--spacing-2xl) 0;
}

/* ============================================================================
   Blog components — global, component-level styles for the CMS blog (listing
   + post). Sits alongside _tables.css / _forms.css in the elements layer.
   Structure only (aspect ratios, sticky rail, pagination, meta rows); colour,
   spacing, glass/glow surfaces are composed from utilities in the markup.

   Flicker rule (see memory: glass_transform_glow_clash): blog cards sit on
   bg-glass over a bg-glow section, so reveal them with opacity-only
   anim-fade-in — never anim-fade-up/zoom (transform re-samples backdrop).
   ========================================================================== */

/* ── Topic pill bar ──────────────────────────────────────────────────────
   Horizontal, wraps on desktop, scrolls horizontally on mobile so a long
   topic set never stacks into a tall block. Pills are .chip (see _buttons). */
.blog-topics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-2xs);
}

@media (max-width: 640px) {
  .blog-topics {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .blog-topics::-webkit-scrollbar { display: none; }
  .blog-topics .chip { flex-shrink: 0; }
}

/* Topics + search row: the tags nav wraps its chips internally (it shrinks in
   the row) so the fixed-width search stays pinned top-right beside the first
   row of pills. Stacks to a column on mobile so the search isn't crushed next
   to the horizontally-scrolling pill bar. */
.blog-topics { min-width: 0; }

@media (max-width: 640px) {
  .blog-topics-row { flex-direction: column; align-items: stretch; }
  .blog-topics-row .blog-search { width: 100%; }
}

/* Active pill — generic chip state, reusable beyond the blog. */
.chip.is-active {
  --chip-bg: var(--c-periwinkle);
  --chip-bg-hover: var(--c-periwinkle);
  --chip-text: var(--c-white);
  --chip-text-hover: var(--c-white);
  --chip-border: var(--c-periwinkle);
  --chip-border-hover: var(--c-periwinkle);
}

/* ── Breadcrumb ───────────────────────────────────────────────────────────
   Home / Blog / topic / current, above the post title. Separators are a plain
   "/" via ::before (same char-based convention as .blog-dot) — no FA webfont
   dependency. Colour comes from the grey scale (theme-mirrored on light). */
.blog-breadcrumb__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Inline flow (not flex) so every item — links, "/" separators, and the
   current-page label — sits on one shared text baseline. Flexing each <li>
   introduced a per-item baseline offset that lifted the first crumb. */
.blog-breadcrumb__list li { display: inline; }
.blog-breadcrumb__list li + li::before {
  content: "/";
  margin: 0 var(--spacing-2xs);
  color: var(--c-grey-05);
}
.blog-breadcrumb a { color: var(--c-grey-05); }
.blog-breadcrumb a:hover { color: var(--c-periwinkle); }
.blog-breadcrumb [aria-current="page"] {
  display: inline-block;
  max-width: 32ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
  color: var(--c-grey-03);
}

/* ── Search field ─────────────────────────────────────────────────────── */
.blog-search { position: relative; flex-shrink: 0; width: min(18rem, 100%); }
.blog-search__form { position: relative; display: flex; align-items: center; }

.blog-search input[type="text"],
.blog-search input[type="search"] {
  width: 100%;
  padding: var(--spacing-2xs) var(--spacing-l) var(--spacing-2xs) var(--spacing-2xl);
  background: var(--c-grey-02);
  border: 1px solid var(--c-grey-04);
  border-radius: 999px;
  color: var(--c-grey-09);
  font-family: inherit;
  font-size: var(--btn-font-size);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

.blog-search input::placeholder { color: var(--c-grey-05); }

.blog-search input:focus {
  outline: none;
  border-color: var(--c-periwinkle);
  box-shadow: 0 0 0 3px rgba(72, 100, 255, 0.22);
}

.blog-search__icon {
  position: absolute;
  left: var(--spacing-m);
  top: 50%;
  transform: translateY(-50%);
  color: var(--c-grey-05);
  pointer-events: none;
}

/* ── Post card ────────────────────────────────────────────────────────────
   Card chrome (glass, radius, padding, glow) comes from utilities. This adds
   the media crop + a subtle zoom that fires from anywhere on the clickable
   card (.is-clickable is the overlay's ancestor — see _interactions.css). */
.blog-card { overflow: hidden; }

.blog-card__media {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--c-grey-02);
}

.blog-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 800ms ease;
}

.blog-card:hover .blog-card__media img { transform: scale(1.05); }

/* Title link — only the title is clickable (the stretched-link overlay can't
   work inside bg-glass). `font: inherit` keeps the anchor on the heading's full
   font stack, size and weight regardless of any anchor defaults.
   Inherits the heading's full font + colour; underlines on hover. */
.blog-card__link {
  color: inherit;
  font: inherit;
  text-decoration: none;
}

.blog-card__link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .blog-card__media img { transition: none; }
  .blog-card:hover .blog-card__media img { transform: none; }
}

/* Clamp the title/excerpt so cards in a row stay even without .card-align. */
.blog-card__title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-card__excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Featured (first) post — wide split on desktop, stacks on mobile. ───── */
@media (min-width: 991px) {
  .blog-featured { flex-direction: row; }
  .blog-featured .blog-card__media { width: 56%; aspect-ratio: auto; }
  .blog-featured .blog-card__body  { width: 44%; justify-content: center; }
  .blog-featured .blog-card__title { -webkit-line-clamp: 3; }
}

/* ── Meta row (author • date • read time) ──────────────────────────────── */
.blog-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-2xs);
  color: var(--c-grey-05);
}

.blog-dot {
  color: var(--c-grey-05);
  user-select: none;
}

/* ── Author avatar ─────────────────────────────────────────────────────── */
.blog-avatar {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.blog-avatar-l {
  width: 4.5rem;
  height: 4.5rem;
}

/* ── TLDR / summary box — sits under the post thumbnail. ────────────────── */
.blog-tldr {
  border: 1px solid var(--c-grey-03);
  border-left: 3px solid var(--c-periwinkle);
  border-radius: var(--spacing-3xs);
  background: var(--c-grey-02);
  padding: var(--spacing-l) var(--spacing-xl);
}

.blog-tldr__label {
  display: flex;
  align-items: center;
  gap: var(--spacing-2xs);
  margin-bottom: var(--spacing-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--c-periwinkle);
}

/* ── Pagination ────────────────────────────────────────────────────────── */
.blog-pagination {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--spacing-2xs);
}

.blog-pagination a,
.blog-pagination span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.5rem;
  height: 2.5rem;
  padding: 0 var(--spacing-2xs);
  border: 1px solid var(--c-grey-03);
  border-radius: var(--spacing-4xs);
  color: var(--c-grey-07);
  font-size: var(--btn-font-size);
  text-decoration: none;
  transition: border-color 200ms ease, color 200ms ease, background-color 200ms ease;
}

.blog-pagination a:hover {
  border-color: var(--c-periwinkle);
  color: var(--c-grey-10);
}

.blog-pagination .is-active {
  background: var(--c-periwinkle);
  border-color: var(--c-periwinkle);
  color: var(--c-white);
}

.blog-pagination .is-disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* ── Constrain media inside the readable post column. ──────────────────── */
.blog-post__hero-media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--spacing-3xs);
}

/* ── Light blog post (body.bg-grey-10) ──────────────────────────────────────
   The post template (templates/blog/blog-post.html) flips the body canvas to
   light. These override the blog surfaces + long-form prose colors that are
   hardcoded for the dark theme. Scoped to the light body so the dark defaults —
   and the still-dark blog listing — are untouched. Mid-grey text (c-grey-05/06)
   and accents (c-aqua, c-periwinkle) already read on both and are left alone. */
body.bg-grey-10 .prose { color: var(--body-fg); }
body.bg-grey-10 .prose :is(h1, h2, h3, h4, h5, h6) { color: var(--body-fg); }
/* .prose a — inline-link colour (both themes) lives in _prose.css. */
body.bg-grey-10 .prose blockquote { color: var(--c-grey-03); }
body.bg-grey-10 .prose :is(code, pre) { background: var(--c-grey-09); }
body.bg-grey-10 .prose hr { border-top-color: var(--c-grey-07); }
body.bg-grey-10 .blog-tldr {
  background: var(--c-grey-09);
  border-color: var(--c-grey-07);
  border-left-color: var(--c-periwinkle);
}

/* Light listing surfaces (search input, card-media placeholder, pagination).
   The .is-active pagination pill keeps its periwinkle fill (not targeted). */
body.bg-grey-10 .blog-search input[type="text"],
body.bg-grey-10 .blog-search input[type="search"] {
  background: var(--c-grey-10);
  border-color: var(--c-grey-07);
  color: var(--c-grey-01);
}
body.bg-grey-10 .blog-search input::placeholder { color: var(--c-grey-05); }
body.bg-grey-10 .blog-card__media { background: var(--c-grey-09); }
body.bg-grey-10 .blog-pagination a,
body.bg-grey-10 .blog-pagination .is-disabled {
  border-color: var(--c-grey-07);
  color: var(--c-grey-03);
}
body.bg-grey-10 .blog-pagination a:hover { color: var(--c-grey-00); }

/* ── Blog listing header glow band ──────────────────────────────────────────
   The hero + filter tags + featured post sit over one glow. Instead of the glow
   being the wrapper AROUND the content (which stretches its shapes to the full
   grid height), it's a fixed 100vh band behind the content, so the shapes keep
   their natural proportions. Blog-scoped — the shared .bg-glow is untouched. */
.blog-header { position: relative; }
.blog-header__glow {
  position: absolute;
  inset: 0 0 auto 0;   /* top-anchored, full width */
  height: 100vh;
  z-index: 0;
  pointer-events: none;
}
.blog-header__content { position: relative; z-index: 1; }

/* ── Blog search — inline results (HubSpot Content Search API) ────────────────
   The form is the pill input row; .blog-search__results is an absolutely
   positioned dropdown anchored to .blog-search. Shown only while searching or
   done (class-gated by js/blog-search.js). */
.blog-search__reset {
  position: absolute;
  right: var(--spacing-s);
  top: 50%;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--c-grey-05);
  padding: var(--spacing-2xs);
}
.blog-search--searching .blog-search__reset,
.blog-search--done .blog-search__reset { display: inline-flex; }

.blog-search__results {
  position: absolute;
  top: calc(100% + var(--spacing-2xs));
  left: 0;
  right: 0;
  z-index: 30;
  display: none;
  flex-direction: column;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--spacing-2xs);
  background: var(--c-grey-02);
  border: 1px solid var(--c-grey-04);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}
.blog-search--searching .blog-search__results,
.blog-search--done .blog-search__results { display: flex; }

/* "Searching…" hint while the request is in flight (results are cleared). */
.blog-search--searching .blog-search__results::before {
  content: "Searching\2026";
  padding: var(--spacing-s) var(--spacing-m);
  color: var(--c-grey-05);
  font-size: 0.85rem;
}

.blog-search__result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--spacing-s) var(--spacing-m);
  border-radius: 10px;
  text-decoration: none;
  color: var(--c-grey-09);
}
.blog-search__result:hover,
.blog-search__result:focus-visible {
  background: var(--c-grey-03);
  outline: none;
}
.blog-search__result-title { font-weight: 600; color: var(--c-grey-00); }
.blog-search__result-desc {
  font-size: 0.8rem;
  color: var(--c-grey-05);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.blog-search__result .hs-search-highlight { font-style: normal; color: var(--c-periwinkle); }
.blog-search__zero {
  padding: var(--spacing-s) var(--spacing-m);
  color: var(--c-grey-05);
  font-size: 0.85rem;
}

/* Light theme (blog runs on body.bg-grey-10) */
body.bg-grey-10 .blog-search__results {
  background: var(--c-grey-10);
  border-color: var(--c-grey-08);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
}
body.bg-grey-10 .blog-search__result { color: var(--c-grey-02); }
body.bg-grey-10 .blog-search__result:hover,
body.bg-grey-10 .blog-search__result:focus-visible { background: var(--c-grey-09); }
body.bg-grey-10 .blog-search__result-title { color: var(--c-grey-00); }
body.bg-grey-10 .blog-search__reset { color: var(--c-grey-06); }

/* ============================================================================
   Resources listing — minimal additions on top of the blog card system.
   The cards reuse .blog-card / .blog-card__media / __title / __link / __excerpt
   and the filter chips reuse .chip / .blog-topics / .blog-search. Only the type
   badge and the client-side hidden state are resources-specific.

   Flicker rule (see memory: glass_transform_glow_clash): cards sit on bg-glass
   over a bg-glow hero, so they reveal opacity-only (anim-fade-in) — never a
   transform reveal.
   ========================================================================== */

/* Sidebar filter group label ("Topic", "Content Type") — small uppercase
   heading above each chip group. */
.resources-filter__label {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--c-grey-07);
}

/* Type badge — small uppercase eyebrow above the title (Guide / Calculator…). */
.resource-card__label {
  align-self: flex-start;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--c-aqua);
}

/* Client-side filtering toggles the native `hidden` attribute. .blog-card adds
   .flex-column (display:flex), whose class specificity beats the UA
   `[hidden] { display:none }` rule — so filtered cards (and pruned chips / the
   empty message) wouldn't actually hide. Force it, scoped to the listing. */
.resources-listing [hidden] {
  display: none !important;
}

/* sf-theme Animation System
   Add classes in the HubSpot editor CSS class field to enable animations.

   TYPE (pick one):
     anim-fade-up | anim-fade-in | anim-zoom-in | anim-slide-left | anim-slide-right | anim-text-chars

   TRIGGER (optional, default is scroll):
     anim-load        triggers on page load instead of scroll (use on heroes)

   TIMING (optional):
     anim-delay-200   delay before animation starts, in ms (200, 400, 600...)
     anim-duration-900  animation duration, in ms (400, 600, 800, 1000...)

   STAGGER (add to a parent element):
     anim-stagger     staggers direct children that have a type class, 80ms apart
     anim-gap-100     custom stagger gap in ms (use alongside anim-stagger)

   TEXT CHARS - child delay (add to a child span inside anim-text-chars):
     anim-char-gap-500  pauses the char stagger by 500ms before animating that span's chars */


/* Initial states */

.js-anim .anim-fade-up {
  opacity: 0;
  transform: translateY(30px);
}

.js-anim .anim-fade-in {
  opacity: 0;
}

.js-anim .anim-zoom-in {
  opacity: 0;
  transform: scale(0.93);
}

.js-anim .anim-slide-left {
  opacity: 0;
  transform: translateX(-40px);
}

.js-anim .anim-slide-right {
  opacity: 0;
  transform: translateX(40px);
}

/* Parent held hidden until play so the full title can't paint before JS
   splits it into chars (otherwise: flash of the whole title, then it
   vanishes as the .anim-char rule below kicks in, then it animates in).
   The early-reveal bootstrap in base.html adds .anim-play at parse time so
   this hidden window — and the LCP deferral it causes on the hero — stays
   minimal. Reduced motion resets this below. */
.js-anim .anim-text-chars { opacity: 0; }
.js-anim .anim-text-chars.anim-play { opacity: 1; }

.js-anim .anim-text-chars .anim-char {
  opacity: 0;
}

/* Icon chars are wrapped, not tagged (see splitTextToChars in animations.js):
   the FA kit replaces the <i> with an <svg> mid-animation, and a freshly
   inserted node restarts its animation clock. The wrapper is the animated
   char; the icon inside it is left alone. */
.anim-char-icon {
  display: inline-flex;
  align-items: center;
}


/* Keyframes */

@keyframes sfFadeUp {
  to { opacity: 1; transform: translateY(0); }
}

@keyframes sfFadeIn {
  to { opacity: 1; }
}

@keyframes sfZoomIn {
  to { opacity: 1; transform: scale(1); }
}

@keyframes sfSlideLeft {
  to { opacity: 1; transform: translateX(0); }
}

@keyframes sfSlideRight {
  to { opacity: 1; transform: translateX(0); }
}

@keyframes sfChar {
  from { opacity: 0; }
  to { opacity: 1; }
}


/* Play states — .anim-play added by JS */

.anim-fade-up.anim-play {
  animation: sfFadeUp var(--anim-duration, 800ms) cubic-bezier(0.22, 1, 0.36, 1) var(--anim-delay, 0ms) both;
}

.anim-fade-in.anim-play {
  animation: sfFadeIn var(--anim-duration, 800ms) ease var(--anim-delay, 0ms) both;
}

.anim-zoom-in.anim-play {
  animation: sfZoomIn var(--anim-duration, 800ms) cubic-bezier(0.22, 1, 0.36, 1) var(--anim-delay, 0ms) both;
}

.anim-slide-left.anim-play {
  animation: sfSlideLeft var(--anim-duration, 800ms) cubic-bezier(0.22, 1, 0.36, 1) var(--anim-delay, 0ms) both;
}

.anim-slide-right.anim-play {
  animation: sfSlideRight var(--anim-duration, 800ms) cubic-bezier(0.22, 1, 0.36, 1) var(--anim-delay, 0ms) both;
}

.anim-text-chars.anim-play .anim-char {
  animation: sfChar var(--anim-duration, 400ms) ease var(--anim-char-delay, 0ms) both;
}


/* Done state — belt-and-suspenders after animation completes */

.anim-done {
  opacity: 1 !important;
  transform: none !important;
}

.anim-done .anim-char {
  opacity: 1 !important;
}


/* Reduced motion */

@media (prefers-reduced-motion: reduce) {
  .js-anim .anim-fade-up,
  .js-anim .anim-fade-in,
  .js-anim .anim-zoom-in,
  .js-anim .anim-slide-left,
  .js-anim .anim-slide-right,
  .js-anim .anim-text-chars,
  .js-anim .anim-text-chars .anim-char {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
}

/* h-* — hover-triggered interaction utilities.
 *
 * Distinct from anim-* (scroll-triggered animations in _animations.css).
 * Apply directly to any container. Add a color variant for a different hue.
 */


/* h-glow — soft color halo that fades in on hover.
 *
 *   <div class="card h-glow">                 default periwinkle
 *   <div class="card h-glow h-glow-aqua">
 *   <div class="card h-glow h-glow-coral">
 *
 * Per-instance overrides via --h-glow-color and --h-glow-blur.
 */

.h-glow {
  --h-glow-color: var(--c-periwinkle);
  --h-glow-blur: 40px;

  transition: box-shadow 800ms ease-out;
}

.h-glow:hover {
  box-shadow: 0 0 var(--h-glow-blur) 0 color-mix(in oklch, var(--h-glow-color), transparent 50%);
}

/* Compose with .bg-glass: h-glow would otherwise replace the whole box-shadow
   and wipe the glass edge/glow/bevel/drop. Re-include the glass stack (via its
   --glass-shadow var) and ADD the halo. A transparent halo layer in the resting
   state keeps the layer count equal so the hover transition fades smoothly. */
.bg-glass.h-glow {
  box-shadow:
    var(--glass-shadow),
    0 0 var(--h-glow-blur) 0 transparent;
}

.bg-glass.h-glow:hover {
  box-shadow:
    var(--glass-shadow),
    0 0 var(--h-glow-blur) 0 color-mix(in oklch, var(--h-glow-color), transparent 50%);
}

.h-glow-periwinkle       { --h-glow-color: var(--c-periwinkle); }
.h-glow-periwinkle-light { --h-glow-color: var(--c-periwinkle-light); }
.h-glow-aqua             { --h-glow-color: var(--c-aqua); }
.h-glow-coral            { --h-glow-color: var(--c-coral); }
.h-glow-purple           { --h-glow-color: var(--c-purple-regular); }
.h-glow-blue             { --h-glow-color: var(--c-blue-regular); }


/* h-fade — element dims to a lower opacity on hover. Generalized from the
 * integration-logo hover in the header. Tune the hover target with
 * --h-fade-opacity (default 0.7).
 *
 *   <a class="h-fade"><img …></a>      logo / icon link
 *   <div class="card is-clickable h-fade"> … </div>
 */

.h-fade {
  --h-fade-opacity: 0.7;
  transition: opacity 200ms ease;
}

.h-fade:hover {
  opacity: var(--h-fade-opacity);
}


/* h-scale — element scales up subtly and smoothly on hover. Tune the amount
 * with --h-scale (default 1.03). Keep it small; large values feel jumpy.
 *
 *   <div class="card h-scale"> … </div>
 *   <a class="h-scale" style="--h-scale: 1.05;"><img …></a>
 */

.h-scale {
  --h-scale: 1.03;
  transition: transform 250ms ease-out;
}

/* !important so the hover scale survives on elements that also carry a
   transform-based reveal (anim-fade-up/zoom/slide): once that reveal finishes,
   .anim-done pins `transform: none !important`, which would otherwise win and
   kill the hover. h-scale is meant to compose with anim-*, so it takes precedence
   on hover. */
.h-scale:hover {
  transform: scale(var(--h-scale)) !important;
}


@media (prefers-reduced-motion: reduce) {
  .h-glow,
  .h-fade,
  .h-scale { transition: none; }
  .h-scale:hover { transform: none !important; }
}


/* is-clickable / card-link — make a whole container a single clickable card
 * (the "stretched link" pattern). Put .is-clickable on the card to give it a
 * positioning context, then drop one <a class="card-link"> inside it; the
 * link's ::after expands to cover the entire card, so a click anywhere
 * follows it. Keeps the card a valid <div> (no <a> wrapping headings/images).
 *
 *   <div class="card is-clickable">
 *     …content…
 *     <a class="card-link" href="…" aria-label="…"></a>   (place last)
 *   </div>
 *
 * Hover: drive effects from .is-clickable:hover — it's an ancestor of the
 * overlay, so it fires from anywhere on the card (e.g.
 * .is-clickable:hover .title-section { … }).
 *
 * Inner interactive children (real links/buttons) sit BELOW the overlay and
 * won't receive clicks. To keep one live, lift it above the overlay with
 * position: relative; z-index: 1. */

.is-clickable {
  position: relative;
}

.card-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Hide on mobile */

.d-desktop {}

.d-mobile {}

@media (max-width: 991px) {
  .d-desktop {
    display: none;
  }
}

@media (min-width: 991px) {
  .d-mobile {
    display: none;
  }
}

/* Skip-to-content link — visually hidden until focused, then jumps to
   the top-right corner so keyboard users can bypass the header chrome. */

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--spacing-l);
  z-index: 9999;
  padding: var(--spacing-s) var(--spacing-l);
  background: var(--c-periwinkle);
  color: var(--c-white);
  text-decoration: none;
  border-radius: var(--spacing-2xs);
  font-size: 0.875rem;
  transition: top 150ms ease;
}

.skip-link:focus-visible {
  top: var(--spacing-l);
  outline: 2px solid var(--c-white);
  outline-offset: 2px;
}

/* TBD nav placeholders — links to pages that don't exist yet, marked
   data-tbd-url with href="#". Hidden until the page is built: give the link a
   real href and drop the data-tbd-url attribute to reveal it. Links marked
   data-tbd-url that already have a real href (e.g. All Partners → /partners)
   are intentionally NOT matched, so they stay visible. The full pending list is
   tracked in modules/global/nav-links.md. */
a[data-tbd-url][href="#"],
li:has(> a[data-tbd-url][href="#"]) {
  display: none !important;
}

/* Visually hidden, but present in the DOM for screen readers and crawlers.
   Used for crawlable fallback copy beside non-text content like iframes. */
.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;
}

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */

/* Document
   ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/* Sections
   ========================================================================== */

/**
 * Remove the margin in all browsers.
 */

body {
  margin: 0;
}

/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/* Grouping content
   ========================================================================== */

/**
 * Add the correct box sizing in Firefox.
 */

hr {
  box-sizing: content-box;
  height: 0;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/* Text-level semantics
   ========================================================================== */

/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.
 */

abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}

/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */

b,
strong {
  font-weight: bolder;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/**
 * Add the correct font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/* Forms
   ========================================================================== */

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
 * Remove the inheritance of text transform in Edge and Firefox.
 * 1. Remove the inheritance of text transform in Firefox.
 */

button,
select { /* 1 */
  text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */

button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */

fieldset {
  padding: 0.35em 0.75em 0.625em;
}

/**
 * Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers.
 */

legend {
  padding: 0;
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */

progress {
  vertical-align: baseline;
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */

[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/* Interactive
   ========================================================================== */

/*
 * Add the correct display in Edge and Firefox.
 */

details {
  display: block;
}

/*
 * Add the correct display in all browsers.
 */

summary {
  display: list-item;
}

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

/* Non-.btn <button> controls (slider arrows, FAQ triggers, etc.) reset to
   inherit their container's look. Element-level specificity, so any component
   or utility class (.btn, .nav-tab, .video-btn, bg-*) overrides it. Loaded
   after _normalize.css to undo its `-webkit-appearance: button`. */
button {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}