/* Modernist — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
/* @import removed — Archivo is self-hosted via assets/css/fonts.css */
:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-divider: color-mix(in srgb, #201e1d 40%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff2ef;
  --color-accent-200: #ffe0d9;
  --color-accent-300: #ffc4b8;
  --color-accent-400: #ff9783;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;
  --color-accent-800: #7c1405;
  --color-accent-900: #4d170e;

  --color-accent-2-100: #fff2ef;
  --color-accent-2-200: #ffe0da;
  --color-accent-2-300: #ffc4b9;
  --color-accent-2-400: #ff9784;
  --color-accent-2-500: #ef6853;
  --color-accent-2-600: #c94b39;
  --color-accent-2-700: #9e3526;
  --color-accent-2-800: #71261b;
  --color-accent-2-900: #471d16;

  --font-heading: "Archivo", system-ui, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Archivo", system-ui, sans-serif;

  --space-1: 4.0px;
  --space-2: 8.0px;
  --space-3: 12.0px;
  --space-4: 16.0px;
  --space-6: 24.0px;
  --space-8: 32.0px;

  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 0px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

.grayscale{filter:grayscale(1) contrast(1.08)}

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
.hr {
  height: 2px; border: 0; margin: var(--space-4) 0;
  background: var(--color-divider);
}

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover { background: var(--color-accent-600); }
.btn-primary:active { background: var(--color-accent-700); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); justify-content: flex-start; text-align: left; }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 2px solid var(--color-divider);
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 2px solid var(--color-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-divider);
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* ══════════════════════════════════════════════════════════════════════════
   PAGE LAYOUT — .wrap / .sec / .eyebrow / .util / .foot-col
   ─────────────────────────────────────────────────────────────────────────
   Added 26 Aug 2026, after finding these were defined NOWHERE in the
   WordPress build.

   They were only ever declared inside each frame's own <style> block, and
   build_wp_theme.py's strip_shared() removes them from the per-page CSS on the
   assumption this file already owned them. It didn't. On top of that, the
   per-page CSS is only enqueued for pages using a TRi page template — so an
   Elementor page never loaded it at all.

   Net effect on the live site: no content gutters, no section rhythm or
   dividing rules, and eyebrow labels rendering as plain grey 14px text. It
   looked like an Elementor conversion problem; it wasn't.

   Verified in the browser against v2.triplc.com/company/ before shipping.
   ══════════════════════════════════════════════════════════════════════ */
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 40px; }

/* 64px is the middle of the three values the frames use (56/64/76); a page's
   own CSS still overrides it where that file is loaded. */
.sec { padding: 64px 0; border-top: 2px solid var(--color-divider); }

/* The small red section labels. The second selector reaches inside Elementor's
   heading widget, which wraps the text in its own element. */
.eyebrow,
.eyebrow .elementor-heading-title {
  color: var(--color-accent);
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  margin: 0 0 var(--space-3);
}

.util {
  display: flex; align-items: center; gap: var(--space-6);
  font-size: 12px; padding: 8px 0;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
.util a { color: inherit; text-decoration: none; }
.util a:hover { color: var(--color-accent); }

.foot-col a {
  display: block; color: inherit; text-decoration: none;
  font-size: 13px; padding: 5px 0; opacity: 0.8;
}
.foot-col a:hover { opacity: 1; color: var(--color-accent); }


/* ══════════════════════════════════════════════════════════════════════════
   ELEMENTOR RECONCILIATION
   ─────────────────────────────────────────────────────────────────────────
   Elementor wraps everything in its own section/container/column markup, and
   applies custom CSS classes to WIDGETS but not to sections or columns — so
   `.wrap` and `.sec` from the imported templates never reach the elements that
   need them. These rules put the design system's gutters and vertical rhythm
   onto Elementor's own wrappers instead.

   Scoped by `data-elementor-type` so page content, header and footer each get
   the right treatment: only page content gets section padding and dividing
   rules, or the header would be pushed down the screen by 64px.

   Harmless when Elementor isn't installed — none of these selectors match.
   ══════════════════════════════════════════════════════════════════════ */
.elementor-section > .elementor-container {
  max-width: 1180px; margin: 0 auto; padding: 0 40px;
}

/* FALLBACK ONLY — deliberately low specificity (0,2,0).
   Elementor discards _css_classes on sections during import, so `.sec` never
   arrives and section rhythm can't come from the stylesheet. build_elementor.py
   now emits each section's real padding, border and background as NATIVE
   Elementor settings, which Elementor writes as
   `.elementor-NN .elementor-element.elementor-element-XX {...}` — specificity
   (0,3,0), so a re-imported page overrides everything here.

   This rule exists for pages imported BEFORE that change: without it they have
   no section padding at all and the page collapses into one dense block.
   Remove it only once all 13 pages have been re-imported. */
[data-elementor-type="wp-page"] .elementor-top-section {
  padding: 64px 0; border-top: 2px solid var(--color-divider);
}
[data-elementor-type="wp-page"] .elementor-top-section:first-child { border-top: 0; }

/* Inner sections are the converted two- and three-up grids. They sit inside a
   parent that already has the gutters, so they must not add their own. */
.elementor .elementor-inner-section { padding: 0; border-top: 0; }
.elementor .elementor-inner-section > .elementor-container { padding: 0; max-width: none; }

[data-elementor-type="header"] .elementor-top-section,
[data-elementor-type="footer"] .elementor-top-section { padding: 0; border-top: 0; }

.elementor-widget-heading .elementor-heading-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em;
}

/* Elementor image widgets have no intrinsic size cap, so the logo renders at
   its natural 150x126 instead of the 34px the design calls for. */
.tri-hf-logo img { height: 34px; width: auto; }
[data-elementor-type="footer"] .elementor-widget-image img { height: 28px; width: auto; }


/* ── Ask A.I. launcher (BotPress webchat) ─────────────────────────────────
   Replaced the TRibot demo widget in August 2026. The artwork is a speech
   bubble, so the button is just a transparent frame around the image — the
   shadow goes on the image silhouette via drop-shadow() rather than on a box,
   or you'd see a rectangle behind the bubble's rounded corners and tail.

   Lives here rather than in each page's <style> block, which is where the old
   .fab rules were duplicated 23 times.

   BotPress binds the click itself (Webchat > Deploy settings > Chat launcher =
   Custom element, Element selector = chatbotButton). Nothing here should add a
   handler — see the comment in the frames.
   ───────────────────────────────────────────────────────────────────────── */
#chatbotButton {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  width: 140px;                    /* image is 1784x1586, so height follows */
  padding: 0; border: 0; background: none; cursor: pointer;
  line-height: 0;                  /* kills the inline-image descender gap */
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 6px 16px color-mix(in srgb, var(--color-neutral-900) 30%, transparent));
  transition: transform 0.16s ease, filter 0.16s ease;
}
#chatbotButton img { width: 100%; height: auto; display: block; }
#chatbotButton:hover {
  transform: translateY(-3px);
  filter: drop-shadow(0 10px 22px color-mix(in srgb, var(--color-neutral-900) 38%, transparent));
}
#chatbotButton:active { transform: translateY(-1px); }
#chatbotButton:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }

/* Hide BotPress's own floating bubble — the Ask A.I. artwork is the launcher.
   Setting the dashboard's Chat launcher to "Custom element" also suppresses it,
   but this makes the result the same either way, so the page can never end up
   with two chat buttons in the corner. bpFabContainer / bpFabWrapper are
   BotPress's documented class names. */
.bpFabContainer, .bpFabWrapper { display: none !important; }

/* ══════════════════════════════════════════════════════════════════════════
   RESPONSIVE LAYER
   ─────────────────────────────────────────────────────────────────────────
   Added July 2026. The Modernist mockups were authored desktop-only; mobile is
   ~50% of triplc.com traffic and Google indexes mobile-first, so this is a
   ranking concern as much as a usability one.

   Breakpoints:
     ≤1180px  gutters tighten (content column stops floating)
     ≤1024px  tablet — 4/5-col grids fold to 2, sidebars unstack
     ≤880px   nav collapses to the hamburger (see responsive.js)
     ≤760px   mobile — everything single-column, type scale steps down
     ≤420px   small phones — final trim

   ── Why !important appears below ────────────────────────────────────────
   The 23 frames carry a lot of layout in `style="…"` attributes and in a
   page-level <style> block that loads AFTER this file. Neither can be beaten
   by specificity alone, and rewriting all of it into classes would mean a
   large refactor of a design the client has already signed off on.
   So the overrides are !important, but ONLY inside these media queries —
   desktop rendering is untouched.

   When this becomes the WordPress theme, the inline styles become template
   classes and every !important here can be dropped. See
   docs/RESPONSIVE-NOTES.md.
   ══════════════════════════════════════════════════════════════════════ */

/* Safety net against sideways scroll.
   NOTE: `clip`, not `hidden`. `overflow-x:hidden` turns the element into a
   scroll container, which silently breaks `position:sticky` descendants —
   and the accessories catalog relies on a sticky `.jump` nav. `clip` does
   not create a scroll container, so sticky keeps working.
   This is a net, not a fix: real overflow sources are handled below. */
html, body { overflow-x: clip; }
img, video, iframe, svg, table { max-width: 100%; }

/* Wide tables get a scroll container instead of blowing out the page.
   responsive.js wraps every table, then measures and tags only the ones that
   genuinely don't fit — so a narrow 2-column table is never forced to scroll. */
.tbl-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl-scroll.is-wide > table { min-width: 520px; }
.tbl-scroll.is-wide { border-right: 2px solid var(--color-divider); }

/* Mobile nav — hidden until responsive.js marks the nav as collapsible. */
.nav-toggle { display: none; }

/* The links wrapper must be invisible to layout on desktop. Both the static
   build (responsive.js) and the React build (SiteNav) put the nav items inside
   a .nav-links div so the mobile menu has something to collapse; without this
   the div is a block box and the anchors stop being flex children of .nav —
   they lose the row gap and the CTA buttons wrap wrongly.
   The ≤880px block below overrides this to none / flex. */
.nav-links { display: contents; }
.nav.has-toggle .nav-toggle {
  order: 99; margin-left: auto; width: 42px; height: 42px; flex: none;
  align-items: center; justify-content: center;
  background: transparent; border: 2px solid var(--color-text);
  color: var(--color-text); cursor: pointer; padding: 0;
}
.nav.has-toggle .nav-toggle:hover { background: var(--color-text); color: var(--color-bg); }

/* ── ≤1180px — tighten the gutters ─────────────────────────────────────── */
/* Sections that set their own 40px side gutters inline must track .wrap.
   These are enumerated exactly rather than matched loosely on "40px" —
   a looser selector also catches `padding:64px 0 40px` (the footer, which
   has NO side padding by design) and knocks it out of alignment. */
@media (max-width: 1180px) {
  .wrap,
  [style*="padding:8px 40px"], [style*="padding:28px 40px"],
  [style*="padding:48px 40px"], [style*="padding:52px 40px"],
  [style*="padding:56px 40px"], [style*="padding:64px 40px"],
  [style*="padding:72px 40px"] {
    padding-left: 24px !important; padding-right: 24px !important;
  }
}

/* ── ≤1024px — tablet ──────────────────────────────────────────────────── */
@media (max-width: 1024px) {
  /* 4- and 5-across grids fold to 2 */
  .grid4, .grid5, .logo-row, .acc-cat-grid, .price-grid,
  [style*="grid-template-columns:repeat(4,1fr)"],
  [style*="grid-template-columns:repeat(5,1fr)"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  /* 3-across grids fold to 2 */
  .pgrid, .acc-grid, .feat-grid, .peri-grid,
  [style*="grid-template-columns:repeat(3,1fr)"],
  [style*="grid-template-columns:1fr 1fr 1fr"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  /* the footer's 1.6fr + 4 columns → brand full width, links 2-up */
  [style*="grid-template-columns:1.6fr 1fr 1fr 1fr 1fr"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  /* Product-selector sidebar: filters above results, not beside */
  .layout { grid-template-columns: 1fr !important; gap: var(--space-6) !important; }

  /* Section vertical rhythm eases off */
  .sec { padding-top: 52px !important; padding-bottom: 52px !important; }

  /* Big display type steps down */
  [style*="font-size:52px"] { font-size: 40px !important; }
  [style*="font-size:44px"] { font-size: 36px !important; }
  h1 { font-size: 36px; }
}

/* ── ≤880px — nav collapses ────────────────────────────────────────────── */
@media (max-width: 880px) {
  .nav.has-toggle { flex-wrap: wrap; gap: var(--space-3); position: relative; }
  .nav.has-toggle .nav-toggle { display: inline-flex; }
  .nav.has-toggle .nav-links {
    display: none; order: 100; width: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    border-top: 2px solid var(--color-divider); margin-top: var(--space-3);
  }
  .nav.has-toggle .nav-links.open { display: flex; }
  .nav.has-toggle .nav-links > a {
    padding: 14px 2px; font-size: 16px;
    border-bottom: 1px solid var(--color-divider);
  }
  /* the two CTA buttons keep their button look, full width */
  .nav.has-toggle .nav-links > a.btn {
    margin: var(--space-3) 0 0 !important;
    justify-content: center; padding: 14px; border-bottom: 0;
  }
  .nav.has-toggle .nav-links > a.btn + a.btn { margin-top: var(--space-2) !important; }

  /* Utility bar: drop the tagline, keep the useful links, allow wrapping */
  .util { flex-wrap: wrap; gap: var(--space-3) var(--space-4) !important; }
  .util > span:first-child { display: none; }
  .util > span[style*="margin-left:auto"] { margin-left: 0 !important; }
}

/* ── ≤760px — mobile ───────────────────────────────────────────────────── */
@media (max-width: 760px) {
  body { font-size: 16px; }             /* 15px is small on a phone */

  .wrap,
  [style*="padding:8px 40px"], [style*="padding:28px 40px"],
  [style*="padding:48px 40px"], [style*="padding:52px 40px"],
  [style*="padding:56px 40px"], [style*="padding:64px 40px"],
  [style*="padding:72px 40px"] {
    padding-left: 18px !important; padding-right: 18px !important;
  }

  /* EVERY multi-column grid becomes one column. This single attribute
     selector catches all 15 inline grid patterns in the frames. */
  [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
  .grid2, .grid4, .grid5, .logo-row, .family, .media-grid, .tgrid, .dgrid,
  .doc-grid, .oem-wrap, .phero, .feat-grid, .peri-grid, .pgrid, .acc-grid,
  .acc-cat-grid, .price-grid, .layout {
    grid-template-columns: 1fr !important;
    gap: var(--space-5) !important;
  }
  /* .family.rev alternates image/text on desktop; on mobile always image first */
  .family.rev .media { order: 0 !important; }

  /* Section headers with a trailing "view all" link stack instead of squeezing */
  [style*="justify-content:space-between"] {
    flex-wrap: wrap !important; gap: var(--space-3) !important;
  }
  [style*="align-items:flex-end"][style*="space-between"] {
    align-items: flex-start !important;
  }

  /* Type scale */
  h1 { font-size: 30px; }
  h2 { font-size: 25px; }
  h3 { font-size: 21px; }
  h4 { font-size: 18px; }
  [style*="font-size:52px"] { font-size: 30px !important; line-height: 1.12 !important; }
  [style*="font-size:44px"] { font-size: 30px !important; }
  [style*="font-size:40px"] { font-size: 28px !important; }
  [style*="font-size:38px"] { font-size: 27px !important; }
  [style*="font-size:36px"] { font-size: 26px !important; }
  [style*="font-size:34px"] { font-size: 25px !important; }
  [style*="font-size:32px"] { font-size: 24px !important; }
  [style*="font-size:30px"] { font-size: 23px !important; }
  [style*="font-size:28px"] { font-size: 22px !important; }
  [style*="font-size:26px"] { font-size: 21px !important; }
  /* reading-column caps are already narrower than the viewport — leave them */

  /* Images sized for a 1180px canvas are too tall on a phone */
  [style*="height:420px"], [style*="height:360px"], [style*="height:340px"],
  [style*="height:320px"], [style*="height:300px"], [style*="height:280px"] {
    height: 240px !important;
  }
  [style*="height:260px"], [style*="height:240px"], [style*="height:220px"] {
    height: 200px !important;
  }
  .phero .shot { min-height: 0 !important; padding: var(--space-4) !important; }
  .phero .shot img { max-height: 260px !important; }
  [style*="min-height:360px"] { min-height: 0 !important; }

  /* Vertical rhythm */
  .sec { padding-top: 40px !important; padding-bottom: 40px !important; }

  /* Tables: spec tables carry the detail engineers come for — keep them
     readable rather than shrinking them to nothing. */
  .table, table.spec { font-size: 14px; }
  table.spec td.k { width: 40% !important; }
  .table th, .table td, table.spec th, table.spec td { padding: 8px 10px !important; }

  /* Tap targets — 44px is the accessibility floor.
     min-height is the reliable lever here: many buttons carry an inline
     `padding:` that we can't (and shouldn't) beat, but none of them set a
     min-height, so this applies cleanly on top. */
  .btn { min-height: 44px; padding: 11px 18px; }
  .nav a, .util a { padding-top: 8px; padding-bottom: 8px; }
  .foot-col a { padding-top: 9px !important; padding-bottom: 9px !important; }
  .model-chip, .chip-sugg { min-height: 44px; }

  /* Buttons that sit in a row are usually two CTAs — stack them full width */
  .ctarow, .pcard .cta, .price-card .cta, .acc-btnrow { flex-direction: column; }
  .ctarow > .btn, .pcard .cta > a, .price-card .cta > a { width: 100%; }

  /* Footer */
  footer { padding-top: 40px !important; }
  .foot-col a { font-size: 15px !important; }
  footer [style*="justify-content:space-between"] {
    flex-direction: column !important; gap: var(--space-2) !important;
  }

  /* Accessories sticky jump-nav becomes a horizontal scroller so it
     doesn't eat half the screen */
  .jump .wrap {
    flex-wrap: nowrap !important; overflow-x: auto;
    -webkit-overflow-scrolling: touch; gap: var(--space-4) !important;
  }
  .jump a { white-space: nowrap; }

  /* Ask A.I. launcher: smaller and tighter into the corner on a phone.
     No !important needed — unlike the old .fab, this button is styled only
     here, not re-declared in every page's <style> block. */
  #chatbotButton { width: 104px; right: 14px; bottom: 14px; }

  /* Forms: 16px prevents iOS zoom-on-focus.
     bpComposerInput is BotPress's own message box — the chat is a real input
     users will type into on a phone, so it needs the same treatment. */
  .input, .field input, .field select, .field textarea,
  .bpComposerInput { font-size: 16px !important; }

  /* Dialogs already use width:min(440px,100%) — fine as-is */
}

/* ── ≤420px — small phones ─────────────────────────────────────────────── */
@media (max-width: 420px) {
  .wrap,
  [style*="padding:8px 40px"], [style*="padding:28px 40px"],
  [style*="padding:48px 40px"], [style*="padding:52px 40px"],
  [style*="padding:56px 40px"], [style*="padding:64px 40px"],
  [style*="padding:72px 40px"] {
    padding-left: 14px !important; padding-right: 14px !important;
  }
  h1, [style*="font-size:52px"] { font-size: 27px !important; }
  .sec { padding-top: 32px !important; padding-bottom: 32px !important; }
  /* Spec tables: label above value reads better than a 40/60 squeeze */
  table.spec td.k { width: 45% !important; }
  .model-row { gap: var(--space-2) !important; }
}

/* ── Respect reduced-motion and print ──────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}
@media print {
  /* bpFabContainer / bpWebchat are BotPress's own elements — hidden here in
     case the dashboard is ever switched back to its default chat bubble. */
  #chatbotButton, .nav-toggle, .jump,
  .bpFabContainer, .bpFabWrapper, .bpWebchat { display: none !important; }
  .wrap { max-width: none !important; }
}


/* ── Image classes for Elementor ────────────────────────────────────────────
   The frames style their images inline. Elementor's image widget can't carry
   an inline style through the editor, so build_elementor.py swaps each known
   inline signature for one of these classes and emits a real image widget —
   which is what makes "click the image, upload a new one" work in WordPress
   instead of hand-editing an <img> tag.

   IMPORTANT: Elementor applies _css_classes to the WIDGET WRAPPER, not to the
   <img> inside it. Sizing only the element carrying the class therefore left
   the wrapper 150px tall with a 276px image spilling out of it on /products/.
   Every rule below is written to match the image whether the class landed on
   the <img> itself (standalone frames, the review file) or on a wrapper around
   it (Elementor). Keep both selectors on any new class.

   If you add a new image to a frame, give it one of these classes rather than
   an inline style, or the converter will fall back to frozen HTML. */
img.img-editorial,     .img-editorial img     { width:100%; height:320px; object-fit:cover; filter:grayscale(1) contrast(1.05); }
img.img-thumb,         .img-thumb img         { width:100%; height:140px; object-fit:cover; filter:grayscale(1); }
img.img-card,          .img-card img          { width:100%; height:150px; object-fit:contain; background:var(--color-surface); }
img.img-card-bleed,    .img-card-bleed img    { width:100%; height:150px; object-fit:contain; background:var(--color-surface); }
img.img-portrait,      .img-portrait img      { width:100%; height:240px; object-fit:cover; object-position:top;
                                                border:2px solid var(--color-text); display:block; }
img.img-framed,        .img-framed img        { width:100%; height:auto; display:block; border:2px solid var(--color-text); }
img.img-showcase,      .img-showcase img      { width:100%; height:360px; object-fit:contain; background:var(--color-surface); }
img.img-showcase-tall, .img-showcase-tall img { width:100%; height:420px; object-fit:contain; background:var(--color-surface); }
img.img-showcase-wide, .img-showcase-wide img { width:100%; height:300px; object-fit:contain; background:var(--color-surface); }
img.img-acc-tile,      .img-acc-tile img      { width:100%; height:150px; object-fit:contain;
                                                background:var(--color-surface); display:block; padding:var(--space-3); }
img.img-media-tile,    .img-media-tile img    { width:100%; height:170px; object-fit:contain; background:var(--color-surface); }

/* Spacing belongs to the block, not the picture — applied to whichever element
   carries the class so it works in both placements. */
.img-card       { margin-bottom: var(--space-4); }
.img-card-bleed { margin:calc(-1*var(--space-3)) calc(-1*var(--space-3)) 0; }

/* Elementor wraps every image in .elementor-widget-image > figure > img and
   applies its own width rules, so the class has to win on the <img> itself.
   The wrapper must not impose a height of its own — the image inside is what
   gets sized. */
.elementor-widget-image img { max-width:none; }
.elementor-widget-image .elementor-widget-container,
.elementor-widget-image figure { margin:0; }
.elementor-widget-image[class*="img-"] { height:auto; }

/* ── FAQ category filter ────────────────────────────────────────────────────
   11 category buttons above an accordion; clicking one swaps which
   .faq-group is shown. See design-system/faq.js. The buttons reuse the
   .faq-cat pill look the page already had, with an active state added. */
.faq-cat { display: flex; flex-wrap: wrap; gap: 10px; margin-top: var(--space-4); }
.faq-cat-btn {
  font: inherit; font-size: 13px; line-height: 1.2;
  color: var(--color-accent); background: none;
  border: 1px solid var(--color-divider); padding: 7px 12px;
  cursor: pointer; text-decoration: none;
}
.faq-cat-btn:hover { border-color: var(--color-accent); }
.faq-cat-btn.is-active {
  background: var(--color-accent); border-color: var(--color-accent);
  color: var(--color-bg);
}
.faq-cat-btn:focus-visible { outline: 2px solid var(--color-text); outline-offset: 2px; }

/* Answer bodies carry real markup from the legacy FAQ — lists, tables and
   blockquotes — so they need more than the single-paragraph rule the page
   originally had. */
.faq-a { margin: var(--space-3) 0 0; font-size: 15px; line-height: 1.55;
         color: color-mix(in srgb, var(--color-text) 82%, transparent); }
.faq-a > :first-child { margin-top: 0; }
.faq-a > :last-child { margin-bottom: 0; }
.faq-a p { margin: 0 0 var(--space-3); }
.faq-a ul, .faq-a ol { margin: 0 0 var(--space-3); padding-left: 1.25em; }
.faq-a li { margin: 0 0 6px; }
.faq-a a { color: var(--color-accent); }
.faq-a blockquote {
  margin: 0 0 var(--space-3); padding: var(--space-3) var(--space-4);
  border-left: 2px solid var(--color-accent); background: var(--color-surface);
}
.faq-a table { width: 100%; border-collapse: collapse; margin: 0 0 var(--space-3);
               font-size: 14px; }
.faq-a th, .faq-a td {
  border: 1px solid var(--color-divider); padding: 8px 10px;
  text-align: left; vertical-align: top;
}
.faq-a th { font-weight: 600; background: var(--color-surface); }
/* Legacy spec tables are wide; let them scroll rather than blow out the page. */
.faq-a { overflow-x: auto; }

@media (max-width: 620px) {
  .faq-cat { gap: 8px; }
  .faq-cat-btn { font-size: 12px; padding: 6px 10px; }
}


/* The `hidden` attribute must beat component display rules.
   Browsers apply [hidden]{display:none} from the UA stylesheet, which any
   author rule outranks — so `.pcard{display:flex}` kept the product-selector
   cards visible even with hidden set, and the filter silently did nothing
   while the result count updated correctly. One line, applied globally,
   because every future component with a display rule has the same trap. */
[hidden] { display: none !important; }
