/* Pepper UI — @pepperui/tokens (--pui-*) and @pepperui/css (.pui-*) are loaded by layout-new.blade.php as two <link>s
   just before this file (after layout.min.css), so the cascade is: bootstrap → layout.min → tokens → pepper-ui → this file.
   The :root block below aliases the site's own names to the tokens; a design-system part in the markup carries the pui- classes ONLY (step 12).
   The two files live in public/css/pepper-ui/, written by `npm run pepper-ui` — never edit them there. */
/* =========================================================================
   GLOBAL 2026 — shared design tokens, nav, footer, responsive rules.
   Loaded by layout-new.blade.php for every page using the new design.
   Extracted from html_prototypes/css/styles.css (lines covering shared
   tokens, .nav-bar-wrap, .footer-wrap, and their responsive rules).
   ========================================================================= */

/* =========================================================================
   DESIGN TOKENS — synced from Figma file rP1q5erxNQKyUuxqPmPZBU.
   Variable names mirror Figma's local-variable names so the same vocabulary
   works in design and code. Edit Figma → re-sync here; do not invent new
   token names ad-hoc. Categories below mirror Figma's collections:
     1. Primitives  → color/* + Spacing + Border radius
     2. Color Tokens (semantic) → card_body_surface, primary_surface
     3. Typography  → Font Family/*, Font Size/* (Desktop default, Mobile @media)
     4. Legacy aliases (kept so existing page CSS keeps resolving)
   ========================================================================= */
:root {
  /* 2.4.2 — every primitive below is an alias of its @pepperui/tokens value (artifacts/migration-map.csv, S5);
     the values are unchanged except the four marked STATED (D50). */
  /* Neutrals */
  --color-neutral-1000: var(--pui-color-neutral-1000);
  /* Light blue */
  --color-light-blue-100: var(--pui-color-light-blue-100);

  /* ---- 1. PRIMITIVES — spacing (Figma `Spacing` collection, step values in px) ---- */
  --space-8: var(--pui-space-8);
  --space-12: var(--pui-space-12);
  --space-24: var(--pui-space-24);

  /* ---- 1. PRIMITIVES — border radius (Figma `Border radius` collection) ---- */
  --radius-sm: var(--pui-radius-8);
  --radius-md: var(--pui-radius-16);


  /* Primary (black) button — Figma `general/primary`, `unofficial/primary hover`,
     `general/primary foreground`. Apply on EVERY black button in the site:
     default, :hover, :disabled. */
  --color-btn-primary-bg: var(--pui-action-primary-bg);   /* 2.4.2 STATED — was #171717, now #0b0202 — action/primary/bg is neutral/900, the black (D50; Paggy's gate ran, Fedor confirmed) */
  --color-btn-primary-bg-hover: var(--pui-action-primary-bg-hover);   /* 2.4.2 STATED — was #404040, now #3b3333 — action/primary/bg-hover is neutral/700; hover only */
  --color-btn-primary-fg: var(--pui-action-primary-fg);   /* 2.4.2 STATED — was #fafafa, now #ffffff — action/primary/fg */


  /* ---- 3. TYPOGRAPHY — font sizes (Desktop mode; Mobile overrides below) ---- */
  --fs-body-large: var(--pui-type-body-large-font-size);
  --fs-body-medium: var(--pui-type-body-medium-font-size);
  --fs-body-extra-small: var(--pui-type-body-x-small-font-size);
  --fs-h1-web-page:      22px;   /* 2.4.2: no token holds this — the site's own */

  /* ---- PAGE TOP — the eyebrow's line. Every page that opens with the page eyebrow (the page's name, the
       first child of its first .container) starts it here: 132 desktop · 116 tablet · 96 phone. A page's main
       writes `padding-top: var(--page-top)` once and no per-breakpoint line — so every page reads ONE value and
       none can drift (the case studies had their own 115 / 96 / 80 and no eyebrow; Contact Us 110 / 100). ---- */
  --page-top: 132px;

  /* ---- 4. LEGACY ALIASES — kept so existing page CSS keeps resolving.
       Do NOT introduce new aliases; use the canonical names above instead. ---- */
  /* STEP 12 — the names above are kept for one reader: the shared layout stylesheet (layout.css, the cookie window), which the legacy pages
     read too and which this step does not touch. The 2026 stylesheets read the design system's names. */
}
/* 2.4.2 — literal sweep: a literal whose value is a token became the token (the nav's shadow → elevation/modal, the pill's
   1/2 → elevation/flat, the frost → surface/glass + blur/*, #fff / #000 / #b5b3b3 → the ramp). Only exact values; the rest is counted in the report. */


@media (max-width: 1023px) {
  :root { --page-top: 116px; }
}

/* THE TEXT INK (Fedor's decision, 2026-10-05): the 2026 pages read in the design system's text/default. layout.min.css paints the
   body color/neutral/1000 — pure black, which the system keeps for masks and print (D4), not for text (R4). One rule on the site's own
   element; the page stylesheets no longer need to say `color: text/default` on a title or a paragraph. */
body { color: var(--pui-text-default); }

/* Mobile typography mode — mirrors Figma Typography collection's "Mobile" mode.
   Display sizes are intentionally unset in Figma for mobile (value 0); they
   inherit Desktop values here. */
@media (max-width: 767px) {
  :root {
    /* 2.4.2 — the --fs-* roles now alias --pui-type-*-font-size, which carry this mobile mode themselves
       (tokens.css @media (max-width: 767px), the same eleven values); only the site's own size stays. */
    --fs-h1-web-page:      16px;
    --page-top:            96px;
  }
}

/* ===========================================================
   FIXED MAIN NAV (2026 design)
   =========================================================== */
.nav-bar-wrap {
  position: fixed;
  top: 30px;
  left: 0;
  width: 100%;
  z-index: 100;
  display: flex;
  justify-content: center;
  pointer-events: none;
}
/* THE BAR IS THE KIT'S — .pui-navigation-menu (navigation-menu.css): its width, paint and padding, the logo, the links row,
   the links, the caret and its turn. Nothing here restates a kit class (Fedor, 2026-10-05: a kit class is never copied into
   this file and edited; what the site adds stands on a class of the site's own BESIDE the kit's — DS request 47).
   .main-nav is the site's: the bar takes the pointer inside the band, and its place at the two smaller widths (request 48). */
.main-nav { pointer-events: auto; }

[id="navProductsMenu"] {
  position: fixed;
  /* R — request 13 shipped: the kit's mount animation ends without an opacity; the site's animation: none went */
  top: 0;
  left: 0;
  transform: translateY(-4px) scale(0.97);
  transform-origin: top center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease-out, transform 0.22s var(--pui-motion-easing-enter);
  z-index: 101;
  /* 2.4.2 — the panel's paint, padding, column and gap are .pui-navigation-panel; position, the open/closed transform and opacity stay — global-2026.js positions it and toggles .is-open */
}
[id="navProductsMenu"].is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
}
/* 2.4.2 — the panel link's type, padding, radius, ink and hover are .pui-navigation-panel__link */
/* THE BURGER IS THE KIT'S — .pui-navigation-menu__burger: the 32 bars, 4 tall, 4 apart, the ink. .main-nav__burger is the
   site's beside it: hidden on the one bar above the phone width, a space/4 inset that makes the 40 hit box at radius/8, and
   the open state the kit does not draw yet (its master is the closed bar): the bars turn into an X (request 48). */
.main-nav__burger { display: none; padding: var(--pui-space-4); border-radius: var(--pui-radius-8); }
.main-nav__burger > span { transition: transform var(--pui-motion-menu) var(--pui-motion-easing), opacity var(--pui-motion-move) var(--pui-motion-easing); }
.main-nav__burger.is-open > span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.main-nav__burger.is-open > span:nth-child(2) { opacity: 0; }
.main-nav__burger.is-open > span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

[id="mobileNav"] {
  position: fixed;
  width: auto;   /* A3 — the kit's panel hugs (fit-content) as a dropdown; the site's mobile menu spans the viewport between its 16 px insets */
  /* R — request 13 shipped: the kit's mount animation ends without an opacity; the site's animation: none went */
  top: 90px;
  left: 16px;
  right: 16px;
  z-index: 99;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px) scale(0.97);
  transform-origin: top center;
  transition: opacity 0.18s ease-out, transform 0.22s var(--pui-motion-easing-enter);
  /* A3 — the panel's paint (surface/glass-strong over blur/panel, radius 8, padding 20, elevation/floating — the site's 0 25 37.6 -12 at 21 %, stated) is .pui-navigation-panel; position, the open/closed transform and opacity stay — global-2026.js toggles .is-open */
}
[id="mobileNav"].is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
}
[id="mobileNav"] ul { display: flex; flex-direction: column; gap: var(--pui-space-4); list-style: none; padding: 0; margin: 0; }   /* A3 — the panel's gap (the site's 6 is off the scale) */
[id="mobileNav"] a,
[aria-controls="mobileProductsMenu"] {
  display: flex;
  align-items: center;
  gap: var(--pui-space-2);   /* A3 — the label-to-caret gap by name (the Nav link's), the site's 6 is off the scale */
  width: 100%;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
  /* A3 — the link (padding 4 — the site's 4 / 6; 16 Regular text/default on a 1.4 line — the site's 1.2, stated; radius 4; hover text/disabled) is .pui-navigation-panel__link; the button reset and the flex row for the caret stay the site's */
}
/* A3 — the hover (text/disabled — the site's neutral/300 is the same #b5b3b3) is .pui-navigation-panel__link */
[id="mobileNav"] a[aria-current="page"] { color: var(--pui-text-disabled); }   /* A3 — the site's current-page state, by role */
.mobile-nav__products { position: relative; }
.mobile-nav__caret { transition: transform var(--pui-motion-move) var(--pui-motion-easing); }   /* the site's caret in the site's nested products group */
.mobile-nav__products.is-open .mobile-nav__caret { transform: rotate(180deg); }
.mobile-nav__dropdown {
  display: flex;
  flex-direction: column;
  gap: var(--pui-space-4);            /* A3 — the site's nested products group, on the scale (was 6 / 14 / 6) */
  padding-left: var(--pui-space-16);
  margin-top: var(--pui-space-4);
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height var(--pui-motion-menu) var(--pui-motion-easing), opacity var(--pui-motion-move) var(--pui-motion-easing), margin-top var(--pui-motion-menu) var(--pui-motion-easing);
}
.mobile-nav__products.is-open .mobile-nav__dropdown {
  max-height: 240px;
  opacity: 1;
}
body.nav-locked { overflow: hidden; }


/* =========================================================================
   WHAT THE SITE ADDS TO A KIT PART (Fedor, 2026-10-05). Never a rule on a `.pui-*` class: the design system's classes have
   ONE definition, in the design system's own stylesheet. A part that needs something of the site's carries the kit's class
   AND a class of the site's own, and the site's class holds only the addition (`pui-heading-pair__eyebrow page-eyebrow`).
   What the site would rather the kit owned is a request (pepper-ui-adoption/gates/DS-REQUESTS.md); the strategy is the
   whole site on the kit's classes, so these additions stay few.
   ========================================================================= */
/* PAGE EYEBROW — the Heading pair's eyebrow standing alone as the page's "you are here" line, on the --page-top line.
   The space under it is the page's (the contract: the space below the pair before content is the layout's rule). */
.page-eyebrow { margin-bottom: var(--pui-space-24); }
@media (max-width: 767px) { .page-eyebrow { margin-bottom: var(--pui-space-12); } }
/* THE SITE'S WEIGHT HIERARCHY (Fedor, 2026-10-05 — his R17 exception, DS request 17): a person's name, a country, the HQ card's title read
   Bold at body size; a job's title, a sidebar's heading, a tile's title read Medium. The kit's roles stay as they are; the weight is the
   site's addition, on a class of the site's BESIDE the role class — `<strong class="pui-text--body-medium site-bold">`. */
.site-bold { font-weight: var(--pui-font-weight-700); }
.site-medium { font-weight: var(--pui-font-weight-500); }
.site-tight { letter-spacing: var(--pui-font-letter-spacing-tight); }   /* the blog feature's title, as it was */
/* PREVIEW CARD (blocks/preview-card-2026 — the kit's Card as a link: blog post, case study, team member). The site's two insets and
   the title clamp stand here ONCE, on the block's own classes beside the kit's, until the kit owns the link card (request 41):
   the default inset space/20 with space/12 under (the case and team cards), --compact space/12 all round (the blog's). */
.preview-card { padding: var(--pui-space-20) var(--pui-space-20) var(--pui-space-12); }
.preview-card--compact { padding: var(--pui-space-12); }
.preview-card__title.site-bold { font-weight: var(--pui-font-weight-700); }   /* a person's name on a link card: the kit sets the link card's title Regular at (0,2,0) — the site's Bold meets it at the same weight of selector, on the block's own class */
.preview-card--clamp .preview-card__title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 2.8em; }   /* two lines of the title's 1.4 */
@media (max-width: 1023px) { .preview-card { padding: var(--pui-space-12); } }   /* below the desktop width every preview card is compact (the hubs' and the team's tablet rule) */

/* ===========================================================
   FOOTER (2026 design)
   =========================================================== */
/* Match prototype's `html, body { overflow-x: clip }` + desktop min-width
   1320 so:
     - 1296-wide content (footer card) fits inside the 1320 page width
     - The blob anchor reaches past the card's right edge, like in the proto
     - Narrow viewports clip cleanly (no horizontal scrollbar)
   Min-width only applies at desktop (≥1024); below that the responsive
   tablet/mobile rules take over and need body = viewport width. */
html, body { overflow-x: clip; }
@media (min-width: 1024px) {
  body { min-width: 1320px; }
}

/* .footer-2026 spans the full body width so the blob anchor inside it
   reaches the viewport's right edge — matching the prototype where the
   anchor was a body-width sibling of the centered footer card. */
/* THE FOOTER'S PLACE — the same on every page (Fedor, 2026-09-28: "the footer must be 100 % the same on each page"): space/128 above the card
   (the primitive at every width — not the section step, which would lift the footer on a tablet and a phone), space/24 below. A page never sets the space around the footer; a page whose footer sits at the
   bottom of a short window does it with `margin-top: auto` on the band and nothing else. */
.footer-2026 {
  width: 100%;
  margin: 0 0 var(--pui-space-24);
  padding-top: var(--pui-space-128);
  position: relative;
  display: block;
}
:has(+ .footer-2026) { margin-bottom: 0 !important; }   /* what stands before the footer ends where its box ends — the 128 is the footer's */
.footer-2026 .footer-blob-anchor {
  position: relative;
  height: 0;
  overflow: visible;
}
.footer-2026 .footer-blob {
  position: absolute;
  right: 0;
  bottom: -30px; /* extends 30px below the dark footer card (matches prototype's .page-contact .footer-wrap { margin-bottom: 30px }) */
  width: 1000px;
  height: 511px;
  pointer-events: none;
  z-index: 0;
  max-width: none;
}
/* THE CARD IS THE KIT'S — .pui-footer (footer.css, Fedor's footer): the paint, padding 64, the columns and their 4 gap, the
   headings, the links, the field's 303 and the 8 above it. The site's classes beside the kit's: .footer-2026__card (the card's
   place in the band — 1296, centred, over the blob), .footer-2026__stack (the Terms + Subscription column's tablet width),
   .footer-2026__awards (the third column fills the rest and centres the marks — the site's awards at their own sizes),
   .footer-2026__field (the field on a phone). The two smaller widths are the site's form of the footer until the kit draws
   them (request 49). */
.footer-2026 .footer-2026__card { width: 1296px; margin: 0 auto; position: relative; z-index: 1; }
.footer-2026 .footer-2026__awards { flex: 1 0 0; align-self: stretch; align-items: center; justify-content: center; }
.footer-2026 .footer__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: var(--pui-space-24);
  column-gap: var(--pui-space-40);   /* D — space/24 and space/40 by name; the marks' boxes (67 × 114, 48 × 82, 44 × 75) are the award images' own — stated; the marks themselves belong with the brand package, request 6 */
}
.footer-2026 .footer__badges-gptw {
  display: flex;
  align-items: center;
  gap: var(--pui-space-12);   /* D — by name */
}
.footer-2026 .footer__badge { width: 67px; height: 114px; }
.footer-2026 .footer__mga   { width: 89px; height: 86px; }
.footer-2026 .footer__iab   { width: 109px; height: 89px; }
.footer-2026 .footer__reddit { width: 122px; height: 118px; }

/* Badge display order. Desktop: GPTW group → MGA → IAB → Reddit (last).
   Tablet/mobile flip Reddit to the front via the `order` override below. */
.footer-2026 .footer__badges-gptw { order: 1; }
.footer-2026 .footer__mga         { order: 2; }
.footer-2026 .footer__iab         { order: 3; }
.footer-2026 .footer__reddit      { order: 4; }

/* =========================================================================
   RESPONSIVE — tablet + mobile (covers nav + footer)
   ========================================================================= */
@media (max-width: 1023px) {
  .nav-bar-wrap { top: 20px; padding: 0 var(--pui-space-32); }
  .main-nav { width: 100%; max-width: 770px; }

  /* Tablet — below ~849px the .main-nav drops under its 770px cap and the full
     horizontal link row stops fitting, so the Contact-us CTA used to overflow /
     clip past the right edge near the bottom of the tablet range. Tighten ONLY
     the link spacing across the whole tablet range — inter-link gap 8→4px and
     per-item horizontal padding 8→4px — so the row always fits (no overflow, no
     wrapping) while justify-content:space-between still keeps a ≥16px gap between
     the logo and the links (≈22px at 768px, the tightest point). Logo untouched. */
  .main-nav__links { gap: var(--pui-space-4); }
  /* The tightening sits on the site's classes beside the kit's (the kit has no tablet form of the bar — request 48). */
  .main-nav__link { padding-left: var(--pui-space-4); padding-right: var(--pui-space-4); }
  .main-nav__products { padding-right: 0; }
  .main-nav__cta { margin-left: var(--pui-space-4); margin-right: var(--pui-space-4); padding-left: 6px; padding-right: 6px; }

  /* Keep .footer-2026 body-width with NO side padding so the blob anchor
     reaches the body's right edge (matches prototype). The 32px breathing
     room moves onto the inner .footer card as side margins. */
  .footer-2026 {
    width: 100%;
    max-width: 100%;
    padding-left: 0;
    padding-right: 0;
  }
  .footer-2026 .footer-2026__card { width: auto; margin: 0 var(--pui-space-32); padding: var(--pui-space-40); }   /* the tablet card — the site's form: padding space/40 (request 49) */
  .footer-2026 .footer-2026__stack { max-width: 320px; }
  .footer-2026 .footer-2026__awards { flex: 1 1 auto; }
  .footer-2026 .footer__badges {
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: center;
    row-gap: 28px;
    column-gap: 28px;   /* D — the tablet cluster's 28 is its own (between space/24 and space/32) — stated */
    max-width: 200px;
  }
  .footer-2026 .footer__badges-gptw { gap: var(--pui-space-8); }   /* D — by name */
  .footer-2026 .footer__badge { width: 48px; height: 82px; }
  .footer-2026 .footer__mga   { width: 58px; height: 56px; }
  .footer-2026 .footer__iab   { width: 73px; height: 60px; }
  /* Reddit badge — 75×73 on tablet AND mobile (this block matches both).
     order:0 floats it to the top of the badge stack; desktop keeps it last. */
  .footer-2026 .footer__reddit { width: 75px; height: 73px; order: 0; }
  .footer-2026 .footer-blob { width: 700px; height: 358px; }
}

@media (max-width: 767px) {
  .nav-bar-wrap { top: 12px; padding: 0 var(--pui-space-16); }
  .main-nav { width: 100%; max-width: 100%; }   /* the kit's padding (space/8 all round) stands — the site's 12 at the left went with the copied rule (2026-10-05) */
  .main-nav__logo { width: 100px; height: auto; }
  .main-nav__links { display: none; }
  .main-nav__burger { display: flex; }

  /* See tablet rule: .footer-2026 stays body-width so the blob anchor
     reaches body's right edge; spacing lives on the inner .footer card. */
  .footer-2026 {
    padding-left: 0;
    padding-right: 0;
  }
  .footer-2026 .footer-2026__card { margin: 0 var(--pui-space-16); flex-direction: column; padding: var(--pui-space-24); align-items: stretch; }   /* the phone card — the site's form: one column, padding space/24 (request 49) */
  .footer-2026 .footer-2026__card > * { flex: 1 1 100%; width: 100%; }
  .footer-2026 .footer-2026__stack { max-width: none; }
  .footer-2026 .footer-2026__awards { align-items: stretch; justify-content: flex-start; }
  .footer-2026 .footer-2026__field { width: 100%; }

  /* Mobile badges — left-aligned with a fixed 24px gap so wrapped rows pack
     to the left (space-between left an oversized gap on sparse rows). */
  .footer-2026 .footer__badges {
    width: 100%;
    max-width: 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: center;
    row-gap: var(--pui-space-24);
    column-gap: var(--pui-space-24);   /* D — by name */
  }
  .footer-2026 .footer__badges-gptw { gap: var(--pui-space-8); }   /* D — by name */
  .footer-2026 .footer__badge { width: 44px; height: 75px; }
  .footer-2026 .footer__mga   { width: 58px; height: 56px; }
  .footer-2026 .footer__iab   { width: 71px; height: 58px; }

  .footer-2026 .footer-blob {
    width: 460px;
    height: 235px;
  }
}

/* =========================================================================
   FORM CARD TITLE — site-wide STANDARD heading INSIDE a form card ("Get in
   touch with us to know more"). ONE class for every 2026 form so the heading
   reads the same everywhere; pages used to fork it per page
   (.irtb-contact__form-title / .mafo-contact__form-title / `.form-card h3`),
   which drifted apart (22px on MAFO+iRTB, 20px on Echo AI).

   Usage: first child inside the <form>, `<h3 class="ui-form__title">…</h3>`.
   Margin is 0 on purpose — the vertical rhythm comes from the form's own
   flex `gap` (the shared `.ui-form` block), never from this heading.
   ========================================================================= */
.ui-form__title {
  margin: 0;
  /* P2 — the form heading is .pui-card__title — card.css names `.ui-form__title` as its source (body/large at Medium, 22 web / 18 mobile). line-height 1.4 for the site's 1.3; the ink inherits the page's */
}

/* =========================================================================
   FORM — the one form of the 2026 site (blocks/form-2026.blade.php). Every
   page's form is that block: `.ui-form` › the title › the fields › the consent
   › the button › the result. These classes are the hooks forms-2026.js
   validates by; the paint is the design system's (.pui-field, .pui-input,
   .pui-checkbox, .pui-button, .pui-form-result). The rules below were copied
   into seven page stylesheets; they are stated once here (F — 2026-09-28).
   What stays a page's own: the width of the card in its row.
   ========================================================================= */
/* The card a form sits in — part of the form (the block writes it): the design system's Card, tinted, in one of
   three finishes — `.pui-card--lined` (the line around it), `.form-card--raised` (no line, lifted by its shadow),
   `.pui-card--plain` (white). One inset on every page: space/32, space/24 on a phone — the form card's own
   (the Card's is space/20; stated). The card's width is its row's, set by the page. */

/* =========================================================================
   SUBSCRIBE FIELD — the one newsletter field (blocks/subscribe-2026.blade.php):
   the design system's Input group in a Field, in the footer of every page and
   twice on a blog article. The box, the control and the Button in it are the
   kit's (.pui-input-group, .pui-button); a place gives the Field its width.
   handleSubscribe() (global-2026.js) raises `.is-invalid` on the box and
   forms-2026.js clears it — the state below is the kit's error state for that
   class (.pui-input-group--error: the line and the ring every field wears).
   ========================================================================= */
.subscribe-field.is-invalid { border-color: var(--pui-border-error); box-shadow: var(--pui-ring-error); }
.subscribe-field.is-invalid:focus-within { box-shadow: var(--pui-ring-error-focus); }

/* =========================================================================
   FIELD ERROR — site-wide STANDARD inline validation message for every 2026
   form. ONE look so validation reads the same on every page (mirrors the Echo
   AI form). Place a `.field__error` as the LAST child of a `.field` (right
   after the control, or after a wrapped `.checkbox`); it is hidden until the
   shared forms-2026.js adds `.is-visible` on an invalid submit, and is cleared
   the moment the user fixes the field. The red invalid border comes from the
   control's `.is-invalid` (shared form library); this is the message text.
   ========================================================================= */
.field__error {
  display: none;                 /* hidden until invalid */
  /* 2.4.2 — the error text's paint is .pui-field__error; `display: none` + `.is-visible` stay — forms-2026.js toggles them */
}
.field__error.is-visible { display: block; }

/* =========================================================================
   FORM SUCCESS MESSAGE — site-wide STANDARD component for every 2026 form.
   (Added for the 2026 redesign; mirror to other forms as they adopt it.)

   Usage: place a `.form-success-msg` as the LAST child INSIDE a <form>; it is
   hidden until submit. On a successful submit the form's JS adds `.is-success`
   to the <form> — the other form children fade out and this card reveals in
   their place, inside the same form card (`.form-card`, which the form block
   writes around every form).
   A legacy/standalone trigger `.form-success-msg.visible` is also supported
   for markup where the message sits OUTSIDE the form.

   Pick the colour variant by the FORM CARD background:
     • default                     → white slot — for a COLOURED/grey card
     • .form-success-msg--on-white → grey  slot — for a WHITE card

   Markup:
     <form ... >                     ← JS adds `.is-success` on success
       … fields … <button>…</button>
       <div class="form-success-msg" role="status" aria-live="polite">
         <div class="form-success-msg__head">
           <img class="form-success-msg__icon" src="/images-new/common/circle-check-green.svg" …>
           <p class="form-success-msg__title">Thank you</p>
         </div>
         <div class="form-success-msg__slot">
           <p class="form-success-msg__text">Our team will get back to you shortly.</p>
         </div>
       </div>
     </form>
   ========================================================================= */
.form-success-msg {
  display: none;                 /* hidden by default — the site's behaviour; R — request 7 shipped: the block's paint (column, gap, head, icon, title, slot, text, the on-white / on-dark / compact variants) is .pui-form-result */
}
form.is-success > :not(.form-success-msg) {
  pointer-events: none;
  animation: form-fields-out var(--pui-motion-menu) var(--pui-motion-easing) forwards;
}
@keyframes form-fields-out {
  to { opacity: 0; display: none; }
}
form.is-success .form-success-msg,
.form-success-msg.visible {
  display: flex;
  animation: form-success-in 0.3s ease 0.18s both;
}
@keyframes form-success-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  form.is-success > :not(.form-success-msg) { animation: none; display: none; }
  form.is-success .form-success-msg,
  .form-success-msg.visible { animation: none; }
}


/* Dark-section variant — white text for a subscribe form on the DARK footer.
   The green check icon is reused as-is (it reads fine on dark). */


/* Compact size — for the small inline subscribe pills (footer + blog share bar),
   where the full 22/18 sizing would overpower the tight column. */


   /* 18 */

     /* 16 */

/* =========================================================================
   VIDEO SOUND TOGGLE — site-wide STANDARD sound button for the muted autoplay
   hero videos (home, MAFO, MobuppsX, i/RTB). Browsers only autoplay MUTED
   video, so the voice-over is off until the visitor clicks the pill.
   Muted  → dark pill: speaker-off icon + "Turn on sound" (compact 32px on
            videos ≤480px wide).
   Sound  → the kit's --icon-only (set by global-2026.js): icon-only round button, the glyph volume-2.
   Hidden until wanted (YouTube-style), fading in smoothly: on mouse hover over
   the video, on keyboard focus, or — touch screens have no hover — for 3s
   after a tap on the video (`.is-controls-visible`, set by global-2026.js).
   While hidden it ignores clicks, so a tap can't toggle sound unseen.
   Selectors are scoped under `.video-sound-host` so they outrank each page's
   `.page-<slug> button { background: transparent; padding: 0 }` reset.

   Markup (Blade partial blocks/video-sound-2026.blade.php):
     <div class="… video-sound-host">          ← wraps ONLY the video box
       <video … autoplay muted loop playsinline>…</video>
       @include('blocks.video-sound-2026')
     </div>
   ========================================================================= */
/* Compact size is keyed to the VIDEO's width, not the viewport: the product
   hero video is only ~308px wide on tablet, where the full pill would cover
   half of it, while the home video there is 704px and keeps the full pill. */
/* R — request 22 shipped: the host is .pui-media-host, the pill .pui-media-control — the kit paints the pill (glass-dark over blur/control, the 40 and 32 sizes, the label, the hidden-until-wanted fade, the hover step, the on-media ring); the glyph's sprite name follows the state in global-2026.js — one slot, no hidden twin */

/* C — the ink of every glyph the kit does not paint itself, bound by name (the file's colour → its token; 2026-09-25). Glyphs inside a
   kit slot (.pui-card__icon, .pui-badge, .pui-icon-button, .pui-input-group__icon, .pui-select__chevron, .pui-nav-link__caret, .pui-form-result__icon) take the kit's ink. */
/* 2026-10-05 — the carets take the kit's ink (currentColor, the link's text/default); the site's text/subtle on them went with the rule on the kit's class */
/* STEP 12 · TOKENS — the site's alias names became the design system's; a typed value that equals a token is the token */
