/*
 * omnalingo.modifiers.css
 * ─────────────────────────────────────────────────────────────────────────────
 * Effect CSS that backs "marker" modifier classes which CANNOT be expressed as
 * Bricks global classes — registered @property custom properties, @keyframes, and
 * multi-pseudo effects. The classes themselves are added through component
 * switchers (e.g. the OM Button "Glow" property); this file does the rendering.
 *
 * Enqueued on the front end AND the builder canvas (functions.php). Unlayered, so
 * it beats Bricks' @layer base exactly like the rest of the design system.
 *
 * ⚠ The @property + @keyframes below animate REGISTERED custom properties on
 * purpose — the idiomatic rotating conic-gradient glow (see the matching note in
 * omnalingo.css). Do NOT "fix" by animating standard props or moving to JS.
 */

/* ── svg min-size floor ────────────────────────────────────────────────────────
 * Bricks cores in `svg:not([width]){min-width:1em}` / `svg:not([height]){min-height:1em}`,
 * so an inline icon with no width/height attr can't render below 1em of its font-size —
 * forcing small icons (stat stars, browser lock) up to 1em. Replace that floor with a tiny
 * 6px one (still guards against 0-size collapse) so icons size freely; per-element
 * `min-width:0` resets are then unnecessary — don't add them on new classes. */
svg {
  flex-shrink: 0;
}

svg:not([width]) {
  min-width: 6px;
}

svg:not([height]) {
  min-height: 6px;
}

html .om-on-dark,
html .om-on-dark * {
  color: #fff;
}

/*******************************************************************************
							FANCY Framework && Kriesi
*******************************************************************************/
html,
body {
  scroll-behavior: smooth;
  min-height: calc(100vh - var(--wp-admin--admin-bar--height, 0));
}

[id] {
  scroll-margin-top: var(--om-sticky-top, 0px);
}

/*Accessibility*/

body.bricks-is-frontend :focus {
  outline: none;
}

body.bricks-is-frontend :focus-visible {
  outline: solid 1px var(--om-color-primary);
  outline-offset: 5px;
  transition: all .3s;
}

/*Containers*/
:where(.brxe-container) {
  width: 1600px;
  gap: var(--om-gap-content);
}

:where(section:not(section section)) {
  padding: var(--om-section-padding-y) var(--om-section-padding-x);
  gap: var(--om-gap-content);
}

:is(h1, h2, h3, h4, h5, h6)+:is(p, ul, ol, h1, h2, h3, h4, h5, h6) {
  margin-top: 2rem;
}

:is(p, ul, ol)+:is(h1, h2, h3, h4, h5, h6, .__heading) {
  margin-top: 4rem;
}

:is(p) {
  margin-block: 0 1em;
}

/* section:where(:not(.bricks-shape-divider)) {
  gap: var(--om-section-gap);
}

:where(.brxe-container)>.brxe-block,
:where(.brxe-container) {
  gap: var(--om-content-gap);
} */

/*fix overflow*/

body.bricks-is-frontend {
  overflow-x: clip;
}

body.bricks-is-frontend.no-scroll,
html:has(body.bricks-is-frontend.no-scroll) {
  overflow: clip !important;
}

.om-pd-0 {
  padding: 0;
}

.om-m-0 {
  margin: 0;
}

@property --omna-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

@property --omna-c1 {
  syntax: '<color>';
  initial-value: #2271b1;
  inherits: true;
}

/* --om-info    */
@property --omna-c2 {
  syntax: '<color>';
  initial-value: #673AB7;
  inherits: true;
}

/* --om-brand   */
@property --omna-c3 {
  syntax: '<color>';
  initial-value: #d63638;
  inherits: true;
}

/* --om-error   */
@property --omna-c4 {
  syntax: '<color>';
  initial-value: #dba617;
  inherits: true;
}

/* --om-warning */

@keyframes omna-rotate-gradient {
  to {
    --omna-angle: 360deg;
  }
}

/* om-hover-card cursor position — om-hover-card.js sets --mx/--my on the hovered card;
   registered so the radial-gradient ring has a definite initial centre (50%) and a type. */
@property --mx {
  syntax: '<length-percentage>';
  initial-value: 50%;
  inherits: true;
}

@property --my {
  syntax: '<length-percentage>';
  initial-value: 50%;
  inherits: true;
}

/* hero animated-gradient pan — backs the .om-gradient--animate class (the hero's
   default / silk-canvas-fallback background). @keyframes can't live in a Bricks
   global class, so it's enqueued here. */
@keyframes om-gradient-shift {
  0% {
    background-position: 0% 50%;
  }

  50% {
    background-position: 100% 50%;
  }

  100% {
    background-position: 0% 50%;
  }
}

/* ── om-button--glow: subtle AI glow on hover ─────────────────────────────────
 * A BEHAVIOUR modifier (separate axis from the colour modifiers — composes with
 * --primary/--ghost/--on-dark/--cta). Purely additive (adds two pseudos + a local
 * stacking context; overrides no base property), so it needs no specificity nudge.
 * Hidden at rest; on hover a thin rotating conic ring + a soft blurred halo fade in.
 * Intensity locked to "subtle". */
.om-button--glow {
  position: relative;
  isolation: isolate;
  transition: all 0.8s ease !important;
}

.om-button--glow::before,
.om-button--glow::after {
  content: "";
  position: absolute;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.8s ease;
  background: conic-gradient(from var(--omna-angle),
      var(--omna-c1), var(--omna-c2), var(--omna-c3), var(--omna-c4), var(--omna-c1));
  /* BOTH layers are masked to a RING (content box excluded), so neither ever
     paints inside the button — the interior stays clean on ANY background
     (no wrapper, no opaque-fill requirement). The ring width = each layer's
     own `padding`; `inset` = -padding so the content box == the button box. */
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

/* crisp ring over the button edge. inset = -(button border width) so the ring
   covers the button's OWN border (which goes transparent on hover) instead of
   sitting inside it — otherwise that 1px reads as a non-glowing seam. --om-btn-bw
   is the single source: the base .om-button border reads the same token. Fallback
   0px ⇒ a genuinely borderless host behaves exactly as before (inset 0). */
.om-button--glow::before {
  inset: calc(-1 * var(--om-btn-bw, 0px));
  padding: 1px;
  z-index: 1;
}

/* soft halo — masked (above) so it never bleeds inward. The trick for a SOFT
   outer edge: a big box (room for the blur, so the mask doesn't clip the falloff)
   + a small conic source hugging the edge (background-size) + heavy blur. The
   glow fades to nothing well inside the box, so nothing gets chopped. */
.om-button--glow::after {
  inset: -34px;
  padding: 34px;
  /* content box == button box → interior excluded */
  z-index: -1;
  background-size: calc(100% - 58px) calc(100% - 58px);
  /* conic source ≈ button + 10px */
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(14px);
}

.om-button--glow:hover::before {
  opacity: 1;
  animation: omna-rotate-gradient 4s linear infinite;
}

.om-button--glow:hover::after {
  opacity: 0.6;
  animation: omna-rotate-gradient 4s linear infinite;
}

/* On hover the button flips to a clean white surface — dark text, no border — so
   the glowing ring frames a solid control (the design system's original AI-glow
   --hover behaviour). `!important` so it beats the colour variants' own hover
   rules (`html .om-button--primary:hover` etc.); the base button already
   transitions bg/color/border, so the flip animates. */
.om-button--glow:hover {
  background-color: var(--om-color-bg-page) !important;
  color: var(--om-color-text-body) !important;
  border-color: transparent !important;
}

@media (prefers-reduced-motion: reduce) {

  .om-button--glow:hover::before,
  .om-button--glow:hover::after {
    animation: none;
  }
}

/* ── om-ham — animated hamburger (ported from Kapitan, om- scheme) ────────────
 * Lives on a toggle's inline <svg> (raw classes, so styled here, not a Bricks
 * class). Morphs hamburger → X when the offcanvas it controls is open — detected
 * via :has() on the panel's .brx-open state (the class Bricks adds on open). */
.om-ham {
  transition: transform 400ms;
  transform-origin: center;
  transform-box: fill-box;
  /* rotate around the svg's own centre, not the viewBox origin */
}

.om-ham__line {
  fill: none;
  stroke: var(--om-color-text);
  stroke-width: 3;
  stroke-linecap: round;
  transition: stroke-dasharray 400ms, stroke-dashoffset 400ms;
}

.om-ham__line--top,
.om-ham__line--bottom {
  stroke-dasharray: 40 121;
}

body:has(.brxe-offcanvas.brx-open) .om-ham {
  transform: rotate(45deg);
}

body:has(.brxe-offcanvas.brx-open) .om-ham__line--top,
body:has(.brxe-offcanvas.brx-open) .om-ham__line--bottom {
  stroke-dashoffset: -68px;
}

/*animated a links. .om-links for underline and .om-links--inv for underline on hover */
/* base link style */
:is(.brxe-post-content, [class*="brxe-text"]) a:not([class], :has(*)),
[class*="om-links"] a,
.woocommerce-MyAccount-content a:not(.button),
:where(.bricks-widget-wrapper) a {
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) left bottom / 100% 1px no-repeat;
  transition: background-size .55s var(--om-ease-line);
  display: inline;
}

/* inverted links */
.om-links--inv a,
:where(.bricks-widget-wrapper) a {
  background-size: 0% 1px;
  /* expand underline */
  background-position: right bottom;
}

@media (hover: hover) and (pointer: fine) {
  /* apply hover effects only on devices that can hover precisely */

  /* hover animation */
  :is(.brxe-post-content, [class*="brxe-text"]) a:not([class], :has(*)):hover,
  [class*="om-links"] a:hover,
  .woocommerce-MyAccount-content a:not(.button):hover {
    background-size: 0% 1px;
    /* expand underline */
    background-position: right bottom;
  }

  /* inverted hover */
  .om-links--inv a:hover,
  :where(.bricks-widget-wrapper) a:hover {
    background-size: 100% 1px;
    /* expand underline */
    background-position: left bottom;
  }
}


/* ══════════════════════════════════════════════════════════════════════════
 * om-mock — animated skeleton / browser-mockup illustrations.
 * External (enqueued) on purpose: these are decorative, never edited in the
 * builder, and import as single raw code blocks (the om-mock → om-raw rule).
 * Includes the --mock-* theme knobs, the om-mock__* primitives, and the
 * om-anim-* motion library. Ported verbatim from omnalingo.css @layer components.
 * ════════════════════════════════════════════════════════════════════════ */
:root {
  --mock-skeleton: #e4e4e9;
  --mock-skeleton-hi: #f5f5f8;
  --mock-skeleton-soft: #eef0f2;
  --mock-surface: var(--om-color-bg-page);
  --mock-tile: #f1f1f4;
  --mock-glyph: var(--om-color-text-muted);
  --mock-line: var(--om-color-border);
}

.om-mock {
  /* Local --mock-* theme tokens registered at :root (see section 14).
       This component just consumes them. */
  position: relative;
  font-family: var(--om-font-text);
  color: var(--om-color-text);
}

[data-mock-theme="dark"] {
  --mock-skeleton: #2a2a30;
  --mock-skeleton-hi: #3b3b44;
  --mock-skeleton-soft: #1b1b1f;
  --mock-surface: var(--om-color-dark-alt);
  --mock-tile: #1e1e23;
  --mock-glyph: var(--om-white-40);
  --mock-line: var(--om-white-10);
  color: var(--om-white);
}

.om-mock>div:first-child {
  width: 100%;
}

/* ── surfaces ─────────────────────────────────────────────────────────── */
.om-mock__panel {
  background: var(--mock-surface);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-md);
  box-shadow: var(--om-shadow-sm);
}

[data-mock-theme="dark"] .om-mock__panel {
  border-color: var(--om-white-10);
  box-shadow: none;
}

/* mini browser / page frame */
.om-mock__frame {
  background: var(--mock-surface);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-md);
  overflow: hidden;
  box-shadow: var(--om-shadow-sm);
}

[data-mock-theme="dark"] .om-mock__frame {
  border-color: var(--om-white-10);
  box-shadow: none;
}

.om-mock__frame-bar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 11px;
  background: var(--mock-skeleton-soft);
  border-bottom: 1px solid var(--om-color-border);
}

[data-mock-theme="dark"] .om-mock__frame-bar {
  border-bottom-color: var(--om-white-10);
}

.om-mock__frame-bar i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--mock-skeleton);
}

.om-mock__frame-body {
  padding: 13px;
  display: grid;
  gap: 9px;
}

/* ── skeleton bar ─────────────────────────────────────────────────────── */
.om-mock__bar {
  height: 8px;
  border-radius: var(--om-radius-pill);
  background: var(--mock-skeleton);
}

.om-mock__bar--soft {
  background: var(--mock-skeleton-soft);
}

/* ── glyph tile ───────────────────────────────────────────────────────── */
.om-mock__tile {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--om-radius-sm);
  background: var(--mock-tile);
  color: var(--mock-glyph);
  flex: 0 0 auto;
}

.om-mock__tile--accent {
  background: var(--om-gradient-icon);
  color: #fff;
}

.om-mock__tile svg {
  display: block;
}

/* ── list row ─────────────────────────────────────────────────────────── */
.om-mock__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  background: var(--mock-surface);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-md);
}

[data-mock-theme="dark"] .om-mock__row {
  border-color: var(--om-white-10);
}

.om-mock__row--active {
  border-color: var(--om-error);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--om-error) 12%, transparent);
}

/* ── status dot ───────────────────────────────────────────────────────── */
.om-mock__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}

/* ── status / text chip ───────────────────────────────────────────────── */
.om-mock__chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 10px;
  border-radius: var(--om-radius-pill);
  background: var(--mock-surface);
  border: 1px solid var(--om-color-border);
  font-size: 11px;
  color: var(--om-color-text-body);
  white-space: nowrap;
}

[data-mock-theme="dark"] .om-mock__chip {
  border-color: var(--om-white-10);
}

/* ── highlighted inline variable token ────────────────────────────────── */
.om-mock__token {
  display: inline-block;
  height: 12px;
  border-radius: 3px;
  vertical-align: middle;
  background: color-mix(in srgb, var(--om-warning) 22%, var(--mock-surface));
  border: 1px solid color-mix(in srgb, var(--om-warning) 55%, transparent);
}

/* ── grid of cells ────────────────────────────────────────────────────── */
.om-mock__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

.om-mock__cell {
  width: 28px;
  height: 28px;
  border-radius: var(--om-radius-sm);
  background: var(--mock-skeleton-soft);
  border: 1px solid transparent;
}

[data-mock-theme="dark"] .om-mock__cell {
  background: #18181c;
}

.om-mock__cell--c1 {
  border-color: var(--om-error);
  background: color-mix(in srgb, var(--om-error) 12%, var(--mock-surface));
}

.om-mock__cell--c2 {
  border-color: var(--om-warning);
  background: color-mix(in srgb, var(--om-warning) 16%, var(--mock-surface));
}

.om-mock__cell--c3 {
  border-color: var(--om-brand);
  background: color-mix(in srgb, var(--om-brand) 12%, var(--mock-surface));
}

/* ── progress bar ─────────────────────────────────────────────────────── */
.om-mock__progress {
  height: 8px;
  border-radius: var(--om-radius-pill);
  background: var(--mock-skeleton);
  overflow: hidden;
}

.om-mock__progress>i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--om-info);
}

/* ── stepper ──────────────────────────────────────────────────────────── */
.om-mock__steps {
  display: flex;
  align-items: center;
}

.om-mock__step {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  background: var(--mock-tile);
  color: var(--mock-glyph);
  font-size: 10px;
  font-weight: 700;
}

.om-mock__step--done {
  background: var(--om-info);
  color: #fff;
}

.om-mock__step--active {
  background: var(--mock-surface);
  border: 2px solid var(--om-info);
  color: var(--om-info);
}

.om-mock__step-line {
  height: 2px;
  flex: 1;
  min-width: 16px;
  background: var(--mock-skeleton);
}

.om-mock__step-line--done {
  background: var(--om-info);
}

/* ── segmented toggle ─────────────────────────────────────────────────── */
.om-mock__toggle {
  position: relative;
  display: inline-flex;
  padding: 3px;
  border-radius: var(--om-radius-pill);
  background: var(--mock-skeleton-soft);
  border: 1px solid var(--om-color-border);
}

[data-mock-theme="dark"] .om-mock__toggle {
  border-color: var(--om-white-10);
}

.om-mock__toggle-seg {
  position: relative;
  z-index: 1;
  width: 60px;
  text-align: center;
  padding: 5px 0;
  font-size: 11px;
  color: var(--om-color-text-muted);
}

.om-mock__toggle-knob {
  position: absolute;
  z-index: 0;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: 60px;
  border-radius: var(--om-radius-pill);
  background: var(--mock-surface);
  box-shadow: var(--om-shadow-sm);
}

/* ── checkbox ─────────────────────────────────────────────────────────── */
.om-mock__check {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  border-radius: var(--om-radius-sm);
  border: 1.5px solid var(--om-color-border);
  background: var(--mock-surface);
  display: grid;
  place-items: center;
}

.om-mock__check--on {
  border-color: var(--om-success);
}

/* % (not px) so the tick scales with each instance's check size (authored 14–18px); min:0 neutralises any inherited svg min */
.om-mock__check svg {
  width: 80%;
  height: 80%;
  min-width: 0;
  min-height: 0;
}

.om-mock__check svg path {
  fill: none;
  stroke: var(--om-success);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── slider ───────────────────────────────────────────────────────────── */
.om-mock__slider {
  position: relative;
  height: 16px;
}

.om-mock__slider-track {
  position: absolute;
  top: 7px;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--mock-skeleton);
}

.om-mock__slider-ticks {
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(90deg, var(--mock-skeleton) 0 1px, transparent 1px 28px);
}

.om-mock__slider-knob {
  position: absolute;
  top: 1px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--mock-surface);
  border: 2px solid var(--om-error);
  box-shadow: var(--om-shadow-sm);
}

/* ── misc helpers ─────────────────────────────────────────────────────── */
.om-mock__btn {
  font-family: var(--om-font-mono);
  font-size: 11px;
  color: var(--om-color-text-muted);
  background: var(--mock-tile);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-sm);
  padding: 6px 10px;
  white-space: nowrap;
}

[data-mock-theme="dark"] .om-mock__btn {
  border-color: var(--om-white-10);
}

.om-mock__price {
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}

.om-mock__dash {
  border: 0;
  border-top: 1px dashed var(--om-color-border);
  margin: 0;
}

[data-mock-theme="dark"] .om-mock__dash {
  border-top-color: var(--om-white-20);
}

/* ── connectors (SVG overlay) ─────────────────────────────────────────── */
.om-mock__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.om-mock__svg path {
  fill: none;
  stroke: var(--mock-line);
  stroke-width: 1.5;
}

.om-mock__spark {
  fill: var(--om-error);
}

/* traveling dot      */
.om-mock__spark--info {
  fill: var(--om-info);
}

.om-mock__spark--brand {
  fill: var(--om-brand);
}

/* ── compat stack (.om-mock.om-compat-stack) ──────────────────────────────
   6 cards rotate front → back on a pure-CSS 12s loop. Each card's surface
   comes from .om-mock__panel; these rules add the layout, the cycle, and the
   11px green check. (Was only in omnalingo.css, which isn't enqueued — so the
   mock rendered unstyled with enormous unsized svgs until ported here.) */
.om-mock.om-compat-stack {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* selector carries .om-compat-stack so the 220px width beats the broader
   `.om-mock > div { width:100% }` (which would otherwise stretch the stage to
   100% of the flex parent — and since the cards are position:absolute the whole
   compat-stack then collapses to 0). flex-shrink:0 keeps the fixed stage intact. */
.om-compat-stack>.om-compat-stack__scene {
  position: relative;
  min-width: 220px;
  height: 170px;
  flex-shrink: 0;
}

.om-compat-stack__card {
  position: absolute;
  left: 0;
  top: 30px;
  width: 186px;
  padding: 12px;
  opacity: 0;
  animation: om-compat-cycle 12s cubic-bezier(.4, 0, .2, 1) infinite;
}

.om-compat-stack__card:nth-child(1) {
  animation-delay: 0s;
}

.om-compat-stack__card:nth-child(2) {
  animation-delay: -2s;
}

.om-compat-stack__card:nth-child(3) {
  animation-delay: -4s;
}

.om-compat-stack__card:nth-child(4) {
  animation-delay: -6s;
}

.om-compat-stack__card:nth-child(5) {
  animation-delay: -8s;
}

.om-compat-stack__card:nth-child(6) {
  animation-delay: -10s;
}

@keyframes om-compat-cycle {

  0%,
  12.5% {
    left: 0;
    top: 30px;
    transform: scale(1);
    opacity: 1;
    filter: none;
    z-index: 3;
  }

  16.67%,
  29.17% {
    left: 15px;
    top: 15px;
    transform: scale(.97);
    opacity: 1;
    filter: brightness(1.05);
    z-index: 2;
  }

  33.33%,
  45.83% {
    left: 30px;
    top: 0;
    transform: scale(.94);
    opacity: 1;
    filter: brightness(1.1);
    z-index: 1;
  }

  50%,
  95.83% {
    left: 38px;
    top: -14px;
    transform: scale(.91);
    opacity: 0;
    filter: brightness(1.15);
    z-index: 0;
  }

  95.84% {
    left: -10px;
    top: 44px;
    transform: scale(1.04);
    opacity: 0;
    filter: none;
    z-index: 4;
  }

  100% {
    left: 0;
    top: 30px;
    transform: scale(1);
    opacity: 1;
    filter: none;
    z-index: 4;
  }
}

.om-compat-stack__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.om-compat-stack__name {
  font-size: 13px;
  font-weight: var(--om-weight-bold);
  color: var(--om-color-text);
  letter-spacing: -.01em;
  line-height: 1;
}

.om-compat-stack__row {
  display: flex;
  gap: 8px;
}

.om-compat-stack__col {
  flex: 1;
}

.om-compat-stack__meta {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 7px;
}

.om-compat-stack__check {
  width: 11px;
  height: 11px;
  min-width: 0;
  min-height: 0;
  color: var(--om-success);
  flex-shrink: 0;
}

/* mk-txt — tiny mono label used inside om-mock illustrations (was only in omnalingo.css). */
.mk-txt {
  font-family: var(--om-font-mono);
  font-weight: var(--om-weight-bold);
  font-size: var(--om-text-xs);
  line-height: 1;
  color: var(--om-color-text-muted);
  letter-spacing: .02em;
}

/* Speed keyframes — the "Translation Speed" mock drives these via inline animation:… (ported from omnalingo.css). */
@keyframes om-speed-bar1 {
  0% {
    transform: scaleX(0);
    opacity: 1
  }

  25% {
    transform: scaleX(1);
    opacity: 1
  }

  88% {
    transform: scaleX(1);
    opacity: 1
  }

  96% {
    transform: scaleX(1);
    opacity: 0
  }

  96.01% {
    transform: scaleX(0);
    opacity: 0
  }

  100% {
    transform: scaleX(0);
    opacity: 0
  }
}

@keyframes om-speed-bar2 {

  0%,
  25% {
    transform: scaleX(0);
    opacity: 0
  }

  25.01% {
    opacity: 1
  }

  50% {
    transform: scaleX(1);
    opacity: 1
  }

  88% {
    transform: scaleX(1);
    opacity: 1
  }

  96% {
    transform: scaleX(1);
    opacity: 0
  }

  96.01% {
    transform: scaleX(0);
    opacity: 0
  }

  100% {
    transform: scaleX(0);
    opacity: 0
  }
}

@keyframes om-speed-bar3 {

  0%,
  50% {
    transform: scaleX(0);
    opacity: 0
  }

  50.01% {
    opacity: 1
  }

  75% {
    transform: scaleX(1);
    opacity: 1
  }

  88% {
    transform: scaleX(1);
    opacity: 1
  }

  96% {
    transform: scaleX(1);
    opacity: 0
  }

  96.01% {
    transform: scaleX(0);
    opacity: 0
  }

  100% {
    transform: scaleX(0);
    opacity: 0
  }
}

@keyframes om-speed-page1 {

  0%,
  23% {
    opacity: 1
  }

  27% {
    opacity: 0
  }

  96% {
    opacity: 0
  }

  96.01%,
  100% {
    opacity: 1
  }
}

@keyframes om-speed-page2 {

  0%,
  48% {
    opacity: 1
  }

  52% {
    opacity: 0
  }

  96% {
    opacity: 0
  }

  96.01%,
  100% {
    opacity: 1
  }
}

@keyframes om-speed-page3 {

  0%,
  73% {
    opacity: 1
  }

  77% {
    opacity: 0
  }

  96% {
    opacity: 0
  }

  96.01%,
  100% {
    opacity: 1
  }
}

@keyframes om-speed-check1 {

  0%,
  23% {
    opacity: 0
  }

  27%,
  88% {
    opacity: 1
  }

  96%,
  100% {
    opacity: 0
  }
}

@keyframes om-speed-check2 {

  0%,
  48% {
    opacity: 0
  }

  52%,
  88% {
    opacity: 1
  }

  96%,
  100% {
    opacity: 0
  }
}

@keyframes om-speed-check3 {

  0%,
  73% {
    opacity: 0
  }

  77%,
  88% {
    opacity: 1
  }

  96%,
  100% {
    opacity: 0
  }
}

/* ============================================================================
     MOTION  —  small, continuous, looping. Apply a .om-anim-* alongside any
     primitive. Kept gentle on purpose; honours prefers-reduced-motion.
     ============================================================================ */

/* skeleton shimmer sweep (loading feel) */
@keyframes om-shimmer {
  0% {
    background-position: 180% 0;
  }

  100% {
    background-position: -80% 0;
  }
}

.om-anim-shimmer {
  background: linear-gradient(100deg,
      var(--mock-skeleton) 35%, var(--mock-skeleton-hi) 50%, var(--mock-skeleton) 65%);
  background-size: 220% 100%;
  animation: om-shimmer 1.8s linear infinite;
}

/* expanding ring on a status dot */
@keyframes om-dotpulse {
  0% {
    box-shadow: 0 0 0 0 currentColor;
  }

  70% {
    box-shadow: 0 0 0 7px transparent;
  }

  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}

.om-anim-dotpulse {
  animation: om-dotpulse 2s ease-out infinite;
}

/* soft opacity breathe */
@keyframes om-pulse {

  0%,
  100% {
    opacity: .5;
  }

  50% {
    opacity: 1;
  }
}

.om-anim-pulse {
  animation: om-pulse 2s ease-in-out infinite;
}

/* accent-tile glow breathe */
@keyframes om-glow {

  0%,
  100% {
    filter: brightness(1);
  }

  50% {
    filter: brightness(1.14);
  }
}

.om-anim-glow {
  animation: om-glow 2.4s ease-in-out infinite;
}

/* progress fill loop (scaleX = no reflow) */
@keyframes om-fill {
  0% {
    transform: scaleX(0);
  }

  55% {
    transform: scaleX(1);
  }

  88% {
    transform: scaleX(1);
  }

  100% {
    transform: scaleX(0);
  }
}

.om-anim-fill {
  transform-origin: left center;
  animation: om-fill 3.2s cubic-bezier(.4, 0, .2, 1) infinite;
}

/* staggered reveal-rise loop (give children animation-delay) */
@keyframes om-rise {
  0% {
    opacity: 0;
    transform: translateY(9px);
  }

  16%,
  80% {
    opacity: 1;
    transform: none;
  }

  100% {
    opacity: 0;
    transform: translateY(-9px);
  }
}

.om-anim-rise {
  animation: om-rise 4s ease-in-out infinite;
}

/* blink (tokens) */
@keyframes om-blink {

  0%,
  100% {
    opacity: .4;
  }

  50% {
    opacity: 1;
  }
}

.om-anim-blink {
  animation: om-blink 1.4s ease-in-out infinite;
}

/* sequential cell flash — set animation-delay per cell */
@keyframes om-cellflash {

  0%,
  68%,
  100% {
    border-color: transparent;
    background: var(--mock-skeleton-soft);
  }

  18%,
  50% {
    border-color: var(--om-error);
    background: color-mix(in srgb, var(--om-error) 14%, var(--mock-surface));
  }
}

.om-anim-cell {
  animation: om-cellflash 3s ease-in-out infinite;
}

/* checkmark draw loop (path needs pathLength="1") */
@keyframes om-checkdraw {
  0% {
    stroke-dashoffset: 1;
  }

  28% {
    stroke-dashoffset: 0;
  }

  82% {
    stroke-dashoffset: 0;
  }

  100% {
    stroke-dashoffset: 1;
  }
}

.om-anim-check path {
  stroke-dasharray: 1;
  animation: om-checkdraw 3s ease infinite;
}

/* connector draw loop (path needs pathLength="1") */
@keyframes om-drawloop {
  0% {
    stroke-dashoffset: 1;
  }

  45% {
    stroke-dashoffset: 0;
  }

  80% {
    stroke-dashoffset: 0;
  }

  100% {
    stroke-dashoffset: 1;
    opacity: 0;
  }
}

.om-anim-draw {
  stroke-dasharray: 1;
  animation: om-drawloop 3s ease-in-out infinite;
}

/* toggle knob travelling across 3 segments (60px each + 3px pad) */
@keyframes om-toggle {

  0%,
  14% {
    left: 3px;
  }

  33%,
  47% {
    left: 63px;
  }

  66%,
  80% {
    left: 123px;
  }

  100% {
    left: 3px;
  }
}

.om-anim-toggle {
  animation: om-toggle 5s cubic-bezier(.5, 0, .2, 1) infinite;
}

/* slider knob travelling */
@keyframes om-slide {

  0%,
  100% {
    left: 8%;
  }

  50% {
    left: 72%;
  }
}

.om-anim-slide {
  animation: om-slide 4s ease-in-out infinite;
}

/* step ring pulse for the active step */
@keyframes om-steppulse {

  0%,
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--om-info) 45%, transparent);
  }

  60% {
    box-shadow: 0 0 0 6px transparent;
  }
}

.om-anim-steppulse {
  animation: om-steppulse 2s ease-out infinite;
}

/* ============================================================================
     FLUID FLOW HELPERS — responsive connector illustrations (no fixed widths)
     ============================================================================ */

/* vertical connector segment with a traveling dot — for stacked flows */
.om-mock__conn {
  position: relative;
  width: 2px;
  height: 24px;
  justify-self: center;
  background: var(--mock-line);
}

.om-mock__conn-dot {
  position: absolute;
  left: 50%;
  top: -3px;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--om-error);
  animation: om-travel-y 2s linear infinite;
}

.om-mock__conn-dot--info {
  background: var(--om-info);
}

.om-mock__conn-dot--brand {
  background: var(--om-brand);
}

@keyframes om-travel-y {
  0% {
    top: -3px;
    opacity: 0;
  }

  15% {
    opacity: 1;
  }

  85% {
    opacity: 1;
  }

  100% {
    top: calc(100% - 3px);
    opacity: 0;
  }
}

/* relay variant: dot travels top→bottom in first half, invisible second half.
     Offset dot 2 by half the period so it departs when dot 1 arrives. */
@keyframes om-travel-relay {
  0% {
    top: -3px;
    opacity: 0;
  }

  8% {
    opacity: 1;
  }

  42% {
    opacity: 1;
  }

  50% {
    top: calc(100% - 3px);
    opacity: 0;
  }

  50.01% {
    top: -3px;
    opacity: 0;
  }

  100% {
    top: -3px;
    opacity: 0;
  }
}

/* progress fill that fades out on reset instead of reversing */
@keyframes om-fill-fade {
  0% {
    transform: scaleX(0);
    opacity: 1;
  }

  55% {
    transform: scaleX(1);
    opacity: 1;
  }

  80% {
    transform: scaleX(1);
    opacity: 1;
  }

  95% {
    transform: scaleX(1);
    opacity: 0;
  }

  95.01% {
    transform: scaleX(0);
    opacity: 0;
  }

  100% {
    transform: scaleX(0);
    opacity: 0;
  }
}

/* node tree (sitemap) — pure-CSS org-chart, fully responsive, border connectors */
.om-mock__tree,
.om-mock__tree ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
}

.om-mock__tree ul {
  position: relative;
  padding-top: 20px;
}

.om-mock__tree li {
  position: relative;
  padding: 20px 4px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.om-mock__tree>li {
  padding-top: 0;
}

.om-mock__tree li::before,
.om-mock__tree li::after {
  content: '';
  position: absolute;
  top: 0;
  right: 50%;
  width: 50%;
  height: 20px;
  border-top: 1.5px solid var(--mock-line);
}

.om-mock__tree li::after {
  right: auto;
  left: 50%;
  border-left: 1.5px solid var(--mock-line);
}

.om-mock__tree>li::before,
.om-mock__tree>li::after {
  display: none;
}

.om-mock__tree li:first-child::before,
.om-mock__tree li:last-child::after {
  border: 0;
}

.om-mock__tree li:last-child::before {
  border-right: 1.5px solid var(--mock-line);
}

.om-mock__tree ul::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 1.5px;
  height: 20px;
  background: var(--mock-line);
  transform: translateX(-50%);
}

.om-mock__node {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  background: var(--mock-surface);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-md);
  white-space: nowrap;
}

[data-mock-theme="dark"] .om-mock__node {
  border-color: var(--om-white-10);
}

@media (prefers-reduced-motion: reduce) {

  .om-mock *,
  .om-mock {
    animation: none !important;
  }

  .om-mock__svg [class*="anim"] {
    animation: none !important;
  }

  /* compat-stack cards default to opacity:0 (revealed by the cycle) — keep the
     front card visible when the animation is suppressed. */
  .om-compat-stack__card:first-child {
    opacity: 1;
  }
}

/* ── gradient text utilities (often live in raw heading text → enqueued, not Bricks classes) ── */
.om-text-gradient {
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

html .om-gradient {
  background-image: var(--om-gradient-brand);
  background-size: 250% 250%;
}

html .om-gradient-primary {
  background-image: var(--om-gradient-primary);
}

html .om-gradient-brand {
  background-image: var(--om-gradient-brand);
}

html .om-gradient-warm {
  background-image: var(--om-gradient-warm);
}

html .om-gradient-icon {
  background-image: var(--om-gradient-icon);
}

html .om-gradient--animate {
  animation: om-gradient-shift 20s ease infinite;
}

/* OM Media slice + aspect modifiers — enqueued so they apply on NESTED instances too
   (Bricks does not reliably emit a nested component's property-driven classes). */
html .om-media--grad-start {
  background-position: 0% 50%;
}

html .om-media--grad-mid {
  background-position: 50% 50%;
}

html .om-media--grad-end {
  background-position: 100% 50%;
}

html .om-media--4-5 {
  aspect-ratio: 4 / 5;
}

html .om-media--3-4 {
  aspect-ratio: 3 / 4;
}

html .om-media--1-1 {
  aspect-ratio: 1 / 1;
}

html .om-media--4-3 {
  aspect-ratio: 4 / 3;
}

html .om-media--3-2 {
  aspect-ratio: 3 / 2;
}

html .om-media--16-9 {
  aspect-ratio: 16 / 9;
}

/* ── om-features filter bar (injected by om-features-filter.js) + grid/filter modifiers ── */
/* OM Filter Bar STRUCTURAL styles — .om-features__filter / __filter-inner / __filter-tags /
   __filter-search — now live in the Bricks global classes (ported, editable in the builder).
   Kept external here: the om-hscroll scroller (below), the JS-built pills (__filter-btn),
   the raw search icon/input, and the empty state. */

/* The search icon + input come from a single raw code element (div.om-raw); collapse that
   wrapper so they become direct flex children of the search box and align/center properly. */
.om-features__filter-search>* {
  display: contents;
}

.om-features__filter-search-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}

.om-features__filter-search-input {
  appearance: none;
  background: transparent;
  border: 0;
  outline: 0;
  font: inherit;
  font-family: var(--om-font-text);
  font-size: var(--om-text-sm);
  color: var(--om-color-text);
  padding: 1rem 0;
  width: 14ch;
}

.om-features__filter-search-input::placeholder {
  color: var(--om-color-text-muted);
}

.om-features__filter-search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

.om-features__filter-search-input::-webkit-search-decoration {
  -webkit-appearance: none;
}

.om-features__filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--om-font-text);
  font-weight: var(--om-weight-bold);
  font-size: var(--om-text-sm);
  letter-spacing: .01em;
  color: var(--om-color-text-muted);
  background: transparent;
  border: 0;
  border-radius: var(--om-radius-pill);
  padding: 0 1.5rem;
  min-width: 70px;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--om-transition-base), background var(--om-transition-base), box-shadow var(--om-transition-base);
}

.om-features__filter-btn:hover {
  color: var(--om-color-text);
}

.om-features__filter-btn[aria-pressed="true"] {
  color: var(--om-color-text);
  background: var(--om-color-bg-page);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 2px 8px rgba(0, 0, 0, .04);
}

.om-features__empty {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--om-space-2);
  padding: var(--om-space-12) var(--om-space-6);
  background: var(--om-color-bg);
  color: var(--om-color-text-muted);
}

.om-features__empty[hidden] {
  display: none;
}

.om-features__empty-icon {
  width: 32px;
  height: 32px;
  color: var(--om-color-text-muted);
  margin-bottom: var(--om-space-2);
}

.om-features__empty-title {
  margin: 0;
  color: var(--om-color-text);
}

.om-features__empty-desc {
  margin: 0;
  font-size: var(--om-text-sm);
}

/* filter visibility (switcher modifier — enqueued for reliable emission when nested).
   Column counts come from the om-grid utilities in the @layer omna-static block below. */
html .om-features--no-filter .om-features__filter {
  display: none;
}

/* ============================================================================
   TOOLTIPS — a trimmed balloon.css (https://kazzkiq.github.io/balloon.css/), themed to
   our tokens. ONLY the `up` (centered) + `up-left` positions are kept — balloon's
   down/left/right positions and its length/break/blunt/visible/font-awesome variants
   were dropped. Author with `aria-label="…"` + `data-balloon-pos="up"|"up-left"`.
   Inverse colours: put `.om-tip-invert` on any ancestor (e.g. the dark Pro card).
   ============================================================================ */
:root {
  --balloon-color: var(--om-color-dark);
  --balloon-text-color: var(--om-white);
  --balloon-font-size: var(--om-text-sm);
  --balloon-border-radius: var(--om-radius-sm);
  --balloon-move: 4px;
}

.om-tip-invert {
  --balloon-color: var(--om-color-bg-page);
  --balloon-text-color: var(--om-color-text);
}

[aria-label][data-balloon-pos] {
  position: relative;
  cursor: pointer;
}

/* bubble */
[aria-label][data-balloon-pos]:after {
  content: attr(aria-label);
  position: absolute;
  bottom: 100%;
  margin-bottom: 10px;
  z-index: 10;
  padding: var(--om-space-2) var(--om-space-3);
  background: var(--balloon-color);
  color: var(--balloon-text-color);
  border-radius: var(--balloon-border-radius);
  font-family: var(--om-font-text);
  font-size: var(--balloon-font-size);
  font-weight: normal;
  font-style: normal;
  line-height: var(--om-leading-snug);
  text-indent: 0;
  text-shadow: none;
  white-space: normal;
  width: max-content;
  max-width: 26rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease-out .18s, transform .18s ease-out .18s;
}

/* arrow — points down at the element; sits 1px UP into the bubble to hide the
   sub-pixel seam (the bubble, painted after, covers the junction). */
[aria-label][data-balloon-pos]:before {
  content: "";
  position: absolute;
  bottom: calc(100% + 1px);
  z-index: 10;
  width: 0;
  height: 0;
  border: 5px solid transparent;
  border-top-color: var(--balloon-color);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease-out .18s, transform .18s ease-out .18s;
}

/* no empty bubble when there's no tooltip text */
[aria-label=""][data-balloon-pos]:after,
[aria-label=""][data-balloon-pos]:before {
  display: none;
}

/* reveal on hover / keyboard focus. position: up (centered) is the default. */
[aria-label][data-balloon-pos]:after,
[aria-label][data-balloon-pos]:before {
  left: 50%;
  transform: translate(-50%, var(--balloon-move));
}

[aria-label][data-balloon-pos]:hover:after,
[aria-label][data-balloon-pos]:hover:before,
[aria-label][data-balloon-pos]:focus:after,
[aria-label][data-balloon-pos]:focus:before {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* position: up-left — left-anchored (won't overflow a left column); the bubble is
   pulled a further -10px left so its corner clears the arrow. */
[aria-label][data-balloon-pos="up-left"]:after {
  left: -10px;
  transform: translate(0, var(--balloon-move));
}

[aria-label][data-balloon-pos="up-left"]:before {
  left: 5px;
  transform: translate(0, var(--balloon-move));
}

[aria-label][data-balloon-pos="up-left"]:hover:after,
[aria-label][data-balloon-pos="up-left"]:hover:before,
[aria-label][data-balloon-pos="up-left"]:focus:after,
[aria-label][data-balloon-pos="up-left"]:focus:before {
  transform: translate(0, 0);
}


/* FAQ accordion (om-faq) styling now lives in the Bricks `.om-faq` global class
   Custom CSS (builder-editable, on Pricing #1176), NOT here. Design-system source
   of truth stays in omnalingo-design-system/assets/css/omnalingo.css. */


/* ── Bricks form builder — design-system field & button defaults ──────────────
 * Generic styling for ANY form built with the Bricks Form element (`.brxe-form`):
 * roomier, slightly-rounded fields + a black, fully-rounded (pill) submit button
 * with white text. Scoped to `.brxe-form`, so it never touches the footer
 * newsletter (an om-raw form), the search box, or the features filter inputs.
 * html-boosted like the rest of this file → beats Bricks' own form CSS without
 * !important. Per-form tweaks can still override via that form's Bricks settings. */
html .brxe-form input:not([type="submit"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]),
html .brxe-form textarea,
html .brxe-form select {
  padding: var(--om-space-4) var(--om-space-5);
  border-radius: var(--om-radius-md);
  /* Bricks/theme set line-height:40px to fake field height; reset to normal so the
     height comes from our padding + text (these fields are border-box). */
  line-height: var(--om-leading-normal);
}

html .brxe-form button[type="submit"] {
  background-color: var(--om-color-dark);
  color: var(--om-white);
  border-radius: var(--om-radius-pill);
  padding: var(--om-space-4) var(--om-space-6);
  font-weight: var(--om-weight-bold);
  cursor: pointer;
  transition: background-color var(--om-transition-base);
}

html .brxe-form button[type="submit"]:hover {
  background-color: var(--om-color-dark-alt);
}


/*
 * BRICKS-OVERRIDABLE utility defaults.
 *
 * The grid utilities are wrapped in `@layer omna-static`. Bricks emits ALL of its
 * global-class, element (#brxe) and per-breakpoint CSS UNLAYERED — and unlayered
 * always beats a layer — so any edit made in the Bricks builder automatically wins
 * over these defaults, regardless of stylesheet load order. Set columns with a
 * class for the default; override per-element / per-breakpoint in Bricks when a
 * specific instance wants something different. NO `html` boost on purpose.
 *
 * The REST of this file is unlayered + `html`-boosted → it BEATS Bricks (for
 * marker/effect classes Bricks can't own). These grid utilities are the opposite —
 * layered so Bricks wins. Both intents intentionally coexist in one file.
 *
 * Breakpoints mirror Bricks' own (so a Bricks per-breakpoint override lands on the
 * exact same media query): tablet ≤991 · mobile-landscape ≤767 · mobile-portrait ≤478.
 * `wide` (≥1200) has no native Bricks breakpoint — it's an apply-by-hand class for
 * adding columns on large screens.
 *
 * Any grid using `om-grid` must NOT also declare grid-template-columns on its own
 * class, or that unlayered rule beats the utility. `om-grid` is the sole owner.
 */
@layer omna-static {

  /* ── Icon SVG colour, auto by mode ─────────────────────────────────────
     Every svg inherits `color` correctly without setting fill/stroke by hand:
     branch on the svg's OWN `fill` attribute — line icons declare `fill="none"`
     (→ colour the stroke, reset fill); everything else fills (→ colour the fill,
     reset stroke). In THIS layer on purpose, so it's a base default: anything
     set in the Bricks builder (id/class-scoped, unlayered) wins over it at any
     time, and any svg carrying its own unlayered fill/stroke CSS keeps it — only
     svgs relying on a bare presentation attribute fall through to currentColor.
     (Replaces the per-instance icon-control fill/stroke that Bricks leaks across
     shared component instances — leave those controls EMPTY.) */
  svg[fill="none"] {
    fill: none;
    stroke: currentColor;
  }

  svg:not([fill="none"]) {
    fill: currentColor;
    stroke: none;
  }

  .om-grid {
    display: grid;
  }

  /* base / desktop (≥992) */
  .om-grid--1 {
    grid-template-columns: var(--om-grid-1);
  }

  .om-grid--2 {
    grid-template-columns: var(--om-grid-2);
  }

  .om-grid--3 {
    grid-template-columns: var(--om-grid-3);
  }

  .om-grid--4 {
    grid-template-columns: var(--om-grid-4);
  }

  .om-grid--5 {
    grid-template-columns: var(--om-grid-5);
  }

  .om-grid--6 {
    grid-template-columns: var(--om-grid-6);
  }

  .om-grid--300px-1 {
    grid-template-columns: 300px minmax(0, 1fr);
  }


  /* ── Asymmetric ratio grids (2-up) ───────────────────────────────────
     1fr:Nfr (and Nfr:1fr) column pairs. Collapse to a single column at a
     breakpoint by adding om-grid-{tab,ml,mp}--1. */
  .om-grid--1-2 {
    grid-template-columns: var(--om-grid-1-2);
  }

  .om-grid--1-3 {
    grid-template-columns: var(--om-grid-1-3);
  }

  .om-grid--1-4 {
    grid-template-columns: var(--om-grid-1-4);
  }

  .om-grid--2-1 {
    grid-template-columns: var(--om-grid-2-1);
  }

  .om-grid--3-1 {
    grid-template-columns: var(--om-grid-3-1);
  }

  .om-grid--4-1 {
    grid-template-columns: var(--om-grid-4-1);
  }

  /* ── Span helpers ────────────────────────────────────────────────────
     first-wide → the FIRST item spans the whole row (featured), the rest flow
     below it. last-wide → a LONE last item (an odd count in a 2-column grid)
     spans the whole row instead of leaving a hole next to it. Both come in
     -tab/-ml/-mp variants (in the @media blocks below): add the one that matches
     the breakpoint where the grid is 2-up, so a 3-up that collapses to 2-up either
     fills its lone trailing card (last-wide) or leads with a full-width first card
     (first-wide). */
  .om-grid--first-wide> :first-child {
    grid-column: 1 / -1;
  }

  .om-grid--last-wide> :last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* wide ≥1200 — apply by hand for extra columns on large screens */
  @media (min-width: 1200px) {
    .om-grid-wide--1 {
      grid-template-columns: var(--om-grid-1);
    }

    .om-grid-wide--2 {
      grid-template-columns: var(--om-grid-2);
    }

    .om-grid-wide--3 {
      grid-template-columns: var(--om-grid-3);
    }

    .om-grid-wide--4 {
      grid-template-columns: var(--om-grid-4);
    }

    .om-grid-wide--5 {
      grid-template-columns: var(--om-grid-5);
    }

    .om-grid-wide--6 {
      grid-template-columns: var(--om-grid-6);
    }
  }

  /* tablet ≤991 */
  @media (max-width: 991px) {
    .om-grid-tab--1 {
      grid-template-columns: var(--om-grid-1);
    }

    .om-grid-tab--2 {
      grid-template-columns: var(--om-grid-2);
    }

    .om-grid-tab--3 {
      grid-template-columns: var(--om-grid-3);
    }

    .om-grid-tab--4 {
      grid-template-columns: var(--om-grid-4);
    }

    .om-grid-tab--5 {
      grid-template-columns: var(--om-grid-5);
    }

    .om-grid-tab--6 {
      grid-template-columns: var(--om-grid-6);
    }

    .om-grid-tab--first-wide> :first-child {
      grid-column: 1 / -1;
    }

    .om-grid-tab--last-wide> :last-child:nth-child(odd) {
      grid-column: 1 / -1;
    }
  }

  /* mobile landscape ≤767 */
  @media (max-width: 767px) {
    .om-grid-ml--1 {
      grid-template-columns: var(--om-grid-1);
    }

    .om-grid-ml--2 {
      grid-template-columns: var(--om-grid-2);
    }

    .om-grid-ml--3 {
      grid-template-columns: var(--om-grid-3);
    }

    .om-grid-ml--4 {
      grid-template-columns: var(--om-grid-4);
    }

    .om-grid-ml--5 {
      grid-template-columns: var(--om-grid-5);
    }

    .om-grid-ml--6 {
      grid-template-columns: var(--om-grid-6);
    }

    .om-grid-ml--first-wide> :first-child {
      grid-column: 1 / -1;
    }

    .om-grid-ml--last-wide> :last-child:nth-child(odd) {
      grid-column: 1 / -1;
    }
  }

  /* mobile portrait ≤478 */
  @media (max-width: 478px) {
    .om-grid-mp--1 {
      grid-template-columns: var(--om-grid-1);
    }

    .om-grid-mp--2 {
      grid-template-columns: var(--om-grid-2);
    }

    .om-grid-mp--3 {
      grid-template-columns: var(--om-grid-3);
    }

    .om-grid-mp--4 {
      grid-template-columns: var(--om-grid-4);
    }

    .om-grid-mp--5 {
      grid-template-columns: var(--om-grid-5);
    }

    .om-grid-mp--6 {
      grid-template-columns: var(--om-grid-6);
    }

    .om-grid-mp--first-wide> :first-child {
      grid-column: 1 / -1;
    }

    .om-grid-mp--last-wide> :last-child:nth-child(odd) {
      grid-column: 1 / -1;
    }
  }
}

/*
 * om-hscroll — horizontal scroller (opt-in, UNLAYERED structural utility).
 * Items size to content by default (flexible, never shrink → overflow → scroll).
 * For fixed-width slides, set --hscroll-item-width on the .om-hscroll element.
 * Add .om-hscroll--snap for scroll snapping. Thin scrollbar, hidden until hover.
 */
.om-hscroll {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: stretch;
  overflow-x: auto;
  overflow-y: clip;
  overscroll-behavior-x: contain;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
  transition: scrollbar-color .3s ease;
}

.om-hscroll>* {
  flex-shrink: 0;
  width: var(--hscroll-item-width, auto);
}

.om-hscroll--snap {
  scroll-snap-type: x mandatory;
}

.om-hscroll--snap>* {
  scroll-snap-align: start;
}

/*
 * om-hslider — JS-augmented slider on top of om-hscroll (om-hslider.js).
 * Wrapper holds the .om-hscroll track + .om-hs-prev / .om-hs-next navs; the JS
 * scrolls one item per click and toggles .disabled on a nav at the track's edge.
 * Add .om-hslider--center to centre the active item. Lay out / style the navs in
 * Bricks — these are just the hooks + the functional disabled state.
 */
.om-hslider {
  position: relative;
}

.om-hs-prev,
.om-hs-next {
  cursor: pointer;
  transition: opacity var(--om-transition-fast);
}

.om-hs-prev.disabled,
.om-hs-next.disabled {
  opacity: .35;
  pointer-events: none;
  cursor: default;
}



.om-hscroll:not(.om-hscroll--nobar):hover {
  scrollbar-color: var(--om-color-border) transparent;
}

.om-hscroll::-webkit-scrollbar {
  height: 6px;
}

.om-hscroll::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 6px;
}

/* ── OM Section Nav — sticky in-page section nav (TOC) + scrollspy ────────────
 * Links (left) / CTA (right). om-section-nav.js sets a[aria-current="page"] on the
 * link of the section in view and mirrors its text into the mobile __current label.
 * Mobile: the list collapses behind a checkbox-hack dropdown (:has(__toggle:checked)). */
.om-section-nav {
  display: flex;
  align-items: center;
  gap: var(--om-space-6);
  position: sticky;
  top: var(--om-sticky-top);
  z-index: 20;
  background: var(--om-color-bg-page);
  border-bottom: 1px solid var(--om-color-border);
  padding: var(--om-space-1) var(--om-section-padding-x);
}

/* the toggle + current-label come from one raw code element; collapse the wrapper so
   they sit as direct flex children of the nav */
.om-section-nav>.om-raw {
  display: contents;
}

.om-section-nav__list {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: var(--om-space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.om-section-nav__list li {
  list-style: none;
}

.om-section-nav__link {
  display: inline-flex;
  align-items: center;
  padding: var(--om-space-2) var(--om-space-4);
  font-family: var(--om-font-text);
  font-size: var(--om-text-sm);
  color: var(--om-color-text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--om-transition-base);
}

.om-section-nav__link:hover {
  color: var(--om-color-text);
}

/* active = dark + bold, no pill, no background (matches Kapitan) */
.om-section-nav__link[aria-current="page"] {
  color: var(--om-color-text);
  font-weight: var(--om-weight-bold);
}

.om-section-nav__cta {
  flex: 0 0 auto;
}

/* mobile toggle (visually hidden checkbox) + current-section trigger (hidden on desktop) */
.om-section-nav__toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.om-section-nav__current {
  display: none;
}

@media (max-width: 767px) {

  /* Active section (left) + CTA (right) on ONE line; the list is a flush overlay panel
     at the bottom of the bar. The bar stays pinned (base position:sticky — which also
     anchors the absolute dropdown, so no position:relative override here). */
  .om-section-nav {
    justify-content: space-between;
  }

  .om-section-nav__current {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    font-family: var(--om-font-text);
    font-weight: var(--om-weight-bold);
    font-size: var(--om-text-sm);
    color: var(--om-color-text);
    cursor: pointer;
    margin: 0;
  }

  /* border-chevron directly next to the active label — down, flips up when open */
  .om-section-nav__current::after {
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-left: var(--om-space-2);
    margin-top: -2px;
    border-right: 2px solid;
    border-bottom: 2px solid;
    transform: rotate(45deg);
    transition: transform var(--om-transition-base);
  }

  .om-section-nav:has(.om-section-nav__toggle:checked) .om-section-nav__current::after {
    transform: rotate(-135deg);
    margin-top: 6px;
  }

  .om-section-nav__list {
    position: absolute;
    top: 100%;
    left: var(--om-section-padding-x);
    z-index: 30;
    flex-direction: column;
    align-items: stretch;
    gap: var(--om-space-1);
    min-width: 240px;
    width: max-content;
    max-width: calc(100% - 2 * var(--om-section-padding-x));
    padding: var(--om-space-3);
    background: var(--om-color-bg-page);
    border: 1px solid var(--om-color-border);
    border-top: none;
    border-radius: 0;
    box-shadow: 0 8px 16px rgba(0, 0, 0, .06);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--om-transition-base), transform var(--om-transition-base), visibility var(--om-transition-base);
  }

  .om-section-nav:has(.om-section-nav__toggle:checked) .om-section-nav__list {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }

  .om-section-nav__link {
    width: 100%;
  }
}

/* ══ OM Bento — raw-HTML families kept enqueued ═══════════════════════════════
   Structural bento classes (om-bento__*, om-globe) now live in BRICKS GLOBAL
   CLASSES (moved out of this stylesheet). These two families render inside
   `om-raw` code blocks, whose classes Bricks' inline-CSS mode does NOT emit — so
   they must stay here to render. */

/* Ecommerce logos — white tiles in a row, in-flow at the bottom of the card
   (re-parented into .om-bento__foot, next to the description). margin-left:auto
   pushes them to the right of the copy; flex-wrap drops them onto their own line
   on narrow cards instead of overlaying the description. */
.om-ecomm-logos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--om-space-3);
  margin-left: auto;
  pointer-events: none;
}

.om-ecomm-logo {
  width: 120px;
  height: 64px;
  background: var(--om-color-bg-page);
  border-radius: var(--om-radius-lg);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.10);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--om-space-3) var(--om-space-4);
}

.om-ecomm-logo img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}

/* SEO bento — Search Console-style traffic chart */
.om-gsc {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--om-space-3);
}

.om-gsc__head {
  display: flex;
  align-items: baseline;
  gap: var(--om-space-3);
}

.om-gsc__delta {
  font-family: var(--om-font-serif);
  font-size: clamp(3.2rem, 3.2vw, 4rem);
  line-height: var(--om-leading-none);
  letter-spacing: -0.02em;
  background: var(--om-gradient-primary);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.om-gsc__label {
  font-size: var(--om-text-xs);
  color: var(--om-color-text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.om-gsc__chart {
  position: relative;
  width: 100%;
  aspect-ratio: 5 / 2;
  background: var(--om-color-bg-page);
  border: 1px solid var(--om-color-border);
  border-radius: var(--om-radius-md);
  padding: var(--om-space-3);
}

.om-gsc__chart svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.om-gsc__grid {
  stroke: var(--om-color-border);
  stroke-width: 1;
}

.om-gsc__line {
  fill: none;
  stroke: var(--om-info);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.om-gsc__area {
  fill: var(--om-info);
  opacity: 0.08;
}

.om-gsc__dot {
  fill: var(--om-info);
}

.om-gsc__dot-ring {
  fill: none;
  stroke: var(--om-info);
  stroke-width: 2;
  opacity: 0.3;
}

/* ══ OM Footer — newsletter form (om-raw, kept enqueued) ══════════════════════
   The newsletter <form> is a single om-raw code block, so Bricks' inline-CSS mode
   won't emit these classes — they live here. Everything else in the footer lives in
   Bricks global classes. */
.om-footer__form {
  display: grid;
  gap: var(--om-space-4);
}

.om-footer__fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--om-space-4);
}

.om-footer__input {
  height: var(--om-space-14);
  width: 100%;
  background: transparent;
  border: 1px solid var(--om-white-20);
  border-radius: var(--om-radius-pill);
  color: var(--om-white);
  font-family: var(--om-font-text);
  font-size: var(--om-text-base);
  padding: 0 var(--om-space-5);
  transition: border-color 0.2s ease;
}

.om-footer__input::placeholder {
  color: var(--om-white-40);
}

.om-footer__input:focus {
  outline: none;
  border-color: var(--om-white-50);
}

.om-footer__subscribe {
  height: var(--om-space-14);
  width: 100%;
  text-align: center;
  border: 0;
  border-radius: var(--om-radius-pill);
  background: var(--om-white-10);
  color: var(--om-white);
  font-family: var(--om-font-text);
  font-weight: var(--om-weight-bold);
  font-size: var(--om-text-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.2s ease;
}

.om-footer__subscribe:hover {
  background: var(--om-white-20);
}

@media (max-width: 767px) {
  .om-footer__fields {
    grid-template-columns: 1fr;
  }
}

/* ── Fluid type scale (rem) ──────────────────────────────────────────────
   Root is 10px (62.5%), so a token value of 4.8 = 48px. Two ways to use it:
   1. Standalone: compose .om-text-min-* + .om-text-max-* on any element (linear 320→1600px).
   2. Modifier on a display heading: add ONE .om-text-min-* / .om-text-max-* to
      .om-h1/h2/h3 to override just that bound, keeping its vw curve + serif —
      e.g. `om-h2 om-text-max-5xl` caps at 4.8rem (48px), between h2 (60) and h3 (36).
   Ladder (rem = Tailwind px ÷10): xs 1.2 sm 1.4 base 1.6 lg 1.8 xl 2 2xl 2.4
     3xl 3 4xl 3.6 5xl 4.8 6xl 6 7xl 7.2 8xl 9.6 9xl 12.8                      */
:root {
  --om-fluid-min: 1.6;
  --om-fluid-max: 1.6;
  --om-fluid-screen-min: 320;
  --om-fluid-screen-max: 1600;
}

/* Display headings keep their vw curve; bounds = fluid vars (defaults = current). */
.om-h1 {
  --om-fluid-min: 4.8;
  --om-fluid-max: 7.2;
}

.om-h2 {
  --om-fluid-min: 3;
  --om-fluid-max: 6;
}

.om-h3 {
  --om-fluid-min: 2.4;
  --om-fluid-max: 3.6;
}

html .om-h1 {
  font-size: clamp(calc(var(--om-fluid-min) * 1rem), 4vw + 1.6rem, calc(var(--om-fluid-max) * 1rem));
}

html .om-h2 {
  font-size: clamp(calc(var(--om-fluid-min) * 1rem), 3vw + 1.6rem, calc(var(--om-fluid-max) * 1rem));
}

html .om-h3 {
  font-size: clamp(calc(var(--om-fluid-min) * 1rem), 2vw + 1.2rem, calc(var(--om-fluid-max) * 1rem));
}

/* Standalone fluid font-size (linear interpolation between the bounds) */
.om-text-min-xs,
.om-text-min-sm,
.om-text-min-base,
.om-text-min-lg,
.om-text-min-xl,
.om-text-min-2xl,
.om-text-min-3xl,
.om-text-min-4xl,
.om-text-min-5xl,
.om-text-min-6xl,
.om-text-min-7xl,
.om-text-min-8xl,
.om-text-min-9xl,
.om-text-max-xs,
.om-text-max-sm,
.om-text-max-base,
.om-text-max-lg,
.om-text-max-xl,
.om-text-max-2xl,
.om-text-max-3xl,
.om-text-max-4xl,
.om-text-max-5xl,
.om-text-max-6xl,
.om-text-max-7xl,
.om-text-max-8xl,
.om-text-max-9xl {
  font-size: clamp(calc(var(--om-fluid-min) * 1rem),
      calc(var(--om-fluid-min) * 1rem + (var(--om-fluid-max) - var(--om-fluid-min)) * 1rem * (100vw - var(--om-fluid-screen-min) * 1px) / ((var(--om-fluid-screen-max) - var(--om-fluid-screen-min)) * 1px)),
      calc(var(--om-fluid-max) * 1rem));
}

/* The ladder (rem, ÷10) — after the om-h* defaults so a modifier wins. */
.om-text-min-xs {
  --om-fluid-min: 1.2
}

.om-text-max-xs {
  --om-fluid-max: 1.2
}

.om-text-min-sm {
  --om-fluid-min: 1.4
}

.om-text-max-sm {
  --om-fluid-max: 1.4
}

.om-text-min-base {
  --om-fluid-min: 1.6
}

.om-text-max-base {
  --om-fluid-max: 1.6
}

.om-text-min-lg {
  --om-fluid-min: 1.8
}

.om-text-max-lg {
  --om-fluid-max: 1.8
}

.om-text-min-xl {
  --om-fluid-min: 2
}

.om-text-max-xl {
  --om-fluid-max: 2
}

.om-text-min-2xl {
  --om-fluid-min: 2.4
}

.om-text-max-2xl {
  --om-fluid-max: 2.4
}

.om-text-min-3xl {
  --om-fluid-min: 3
}

.om-text-max-3xl {
  --om-fluid-max: 3
}

.om-text-min-4xl {
  --om-fluid-min: 3.6
}

.om-text-max-4xl {
  --om-fluid-max: 3.6
}

.om-text-min-5xl {
  --om-fluid-min: 4.8
}

.om-text-max-5xl {
  --om-fluid-max: 4.8
}

.om-text-min-6xl {
  --om-fluid-min: 6
}

.om-text-max-6xl {
  --om-fluid-max: 6
}

.om-text-min-7xl {
  --om-fluid-min: 7.2
}

.om-text-max-7xl {
  --om-fluid-max: 7.2
}

.om-text-min-8xl {
  --om-fluid-min: 9.6
}

.om-text-max-8xl {
  --om-fluid-max: 9.6
}

.om-text-min-9xl {
  --om-fluid-min: 12.8
}

.om-text-max-9xl {
  --om-fluid-max: 12.8
}


.om-h-small :is(h1, h2, h3) {
  font-size: 2.2rem;
}

.om-h-small :is(h4, h5, h6) {
  font-size: 1.8rem;
}