/* ═══════════════════════════════════════════════════════════════════════════
   READ THIS FIRST — what is in this file and what is NOT

   The responsive layout intent also lives on the elements themselves as
   Elementor properties at mobile / tablet / laptop (tools/convert-responsive-
   to-properties.php, ~1,600 values across 29 templates).

   THE PROPERTY PIPELINE WORKS. Verified 2026-09-19: v4 atomic styles compile
   to uploads/elementor/css/local-<post>-frontend-<breakpoint>.css and are
   enqueued with the right media attributes (tablet max-width:1027, mobile
   max-width:767). An earlier note claiming non-desktop properties "never
   generate CSS" was WRONG — that was a stale cache plus a measuring harness
   that silently blocked the https stylesheets. Do not re-investigate it.

   WHAT ACTUALLY BLOCKS AN EDITOR CHANGE FROM APPLYING — two things, not one:
     1. !important (most rules here), and
     2. plain specificity. The page-gutter rule was 0,3,0 with no !important
        and still beat Elementor's own 0,2,0 padding rule.

   ALREADY MOVED OUT OF THIS FILE (do not re-add):
     - header bar padding + logo size  -> header template post 107, tablet and
       mobile properties. Set by tools/sg-set-props.php (idempotent, re-run
       after any fresh pull from WP Engine).
     - the page side gutter -> the per-section padding properties already
       carried it; verified no text sits within 8px of the edge on 78 sections
       across 7 pages at 375 and 805.

   IF YOU TRIM THIS FILE FURTHER: remove ONE block, then run
       node tools/sg-verify.mjs <label>
   from the theme directory. It drives headless Chrome over the DevTools
   protocol with no npm dependencies, measures each page twice 1.5s apart and
   refuses to report unless both agree. Expect: VERDICT: CLEAN, 28 frames,
   overflow/gutter/rails/is404/errors all 0. (The "squish" list is ADVISORY
   ONLY — it fires identically at 1440 as at 375, so it is catching
   legitimately narrow children, not a responsive fault.)

   WHAT :has() ACTUALLY MEANS HERE (corrected 2026-09-20)
     :has() is only needed so the CSS SELECTOR can find a row at render time.
     The property it applies (flex-wrap, flex, min-width) is ordinary and
     per-element. A script can evaluate the condition against the STORED data
     and write the property onto each element — which is what tools/sg-cards.php
     does for 96 cards + 31 rows across 14 templates. An earlier note here said
     :has() rules "cannot move to properties". That was WRONG.
     The real trade-off is maintenance, not capability: a per-element property
     does not auto-apply to a NEW row added later — whoever adds it sets it in
     the editor, which is normal Elementor work.

   WHAT GENUINELY CANNOT MOVE:
     - flex-basis floors like `max(280px, calc(50% - 16px))`. Elementor size
       properties are {size, unit} and no stored value on this site uses a
       custom unit, so a CSS function cannot be expressed. These two rules are
       why :has() still appears 15 times.
     - overflow-wrap (the long-word fixes)
     - the rails' physical margin-left (Elementor writes LOGICAL margins, which
       on a writing-mode:vertical-rl element move it vertically instead)
     - Gravity Forms styling (third-party markup, not Elementor elements)
     - the search overlay, its toggle and close button (custom markup + JS)
     - pseudo-element button arrows, the [hidden] guard, hello-elementor reset
       overrides (its pink :focus states)

   EDITING THIS FILE: CSS COMMENTS DO NOT NEST. Inserting a new comment
   inside an existing comment block silently terminates it early and turns the
   remaining text into garbage that kills the NEXT rule. That happened on
   2026-09-20 and cost a 39px overflow on /industries/law-enforcement/ @1100.
   After any edit, check that comment-open and comment-close counts match and
   that no comment-open appears inside an unterminated comment.

   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════
   SAEGIC — UI layer added after the comp build.
   Kept OUT of style.css on purpose: style.css is the pixel-for-pixel comp
   translation and should stay diffable against it. This file holds the
   things that came later — form styling, the search overlay, the
   404/search templates, and the responsive repairs.

   Palette (from the Elementor kit, post 8):
     green  #1DB57C   navy #12303E   body #444444   paper #FCFCFC
   Type: Unbounded (display, uppercase) / Figtree (body)
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --sg-slate:#5E7078;      /* 5.07:1 on paper — AA for small text */
  --sg-line:#C6D0D5;
  --sg-err:#C0392B;
}

/* ───────────────────────────────────────────────────────────────────────────
   1. GRAVITY FORMS
   GF 3.1.2 ships the "Orbital" theme, whose entire type scale descends from
   --gf-font-family-base (default: `initial`, i.e. the OS stack — which is why
   the form read as a different website). Setting the handful of root vars
   below re-skins fonts, controls and focus states without fighting the
   framework; only the submit button needs real rules, because the site's
   button is a pill with a masked arrow that has no variable equivalent.
   ─────────────────────────────────────────────────────────────────────────── */
/* GF injects per-form theme vars inline via `.gform_wrapper[data-form-index="0"]`
 * (specificity 0,3,0), which beats any sane class selector here. !important on
 * the custom properties is the documented way to reclaim them; the values they
 * derive still cascade normally. */
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--framework{
  /* type */
  --gf-font-family-base:"Figtree","Figtree Fallback",sans-serif !important;
  --gf-font-family-primary:var(--gf-font-family-base) !important;
  --gf-font-family-secondary:var(--gf-font-family-base) !important;
  --gf-font-family-tertiary:var(--gf-font-family-base) !important;

  /* brand */
  --gf-color-primary:#1DB57C !important;
  --gf-color-primary-rgb:29,181,124 !important;
  --gf-color-primary-contrast:#FFFFFF !important;
  --gf-color-danger:var(--sg-err) !important;

  /* controls */
  --gf-ctrl-size-md:52px !important;
  --gf-ctrl-radius:8px !important;
  --gf-ctrl-padding-x:16px !important;
  --gf-ctrl-font-size:16px !important;          /* 16px stops iOS zooming the page on focus */
  --gf-ctrl-color:#12303E !important;
  --gf-ctrl-border-color:var(--sg-line) !important;
  --gf-ctrl-border-color-focus:#1DB57C !important;
  --gf-ctrl-bg-color:#FFFFFF !important;

  /* labels */
  --gf-ctrl-label-color-primary:#12303E !important;
  --gf-ctrl-label-font-size-primary:15px !important;
  --gf-ctrl-label-font-weight-primary:600 !important;
  --gf-ctrl-label-color-secondary:var(--sg-slate) !important;
  --gf-ctrl-label-color-tertiary:var(--sg-slate) !important;
}

/* Form title picks up the site's display face. */
.gform_wrapper .gform_title{
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-weight:400;
  text-transform:uppercase;
  color:#12303E;
  letter-spacing:-.01em;
}

/* "(Required)" shipped as loud red next to every label, which made a blank
   form look like it was already erroring. Demote it to slate and keep true
   red for actual validation failures. */
.gform_wrapper .gfield_required{
  color:var(--sg-slate);
  font-weight:500;
  font-size:13px;
}

.gform_wrapper .ginput_container input,
.gform_wrapper .ginput_container select,
.gform_wrapper .ginput_container textarea{
  font-family:"Figtree","Figtree Fallback",sans-serif;
}
.gform_wrapper .ginput_container textarea{
  padding:14px 16px;
  min-height:170px;
  line-height:1.5;
}
.gform_wrapper ::placeholder{ color:#8A9AA2; opacity:1; }

/* Focus ring — the framework's own focus colour is set above, this adds the
   halo so the active field is obvious against the pale paper background. */
.gform_wrapper .ginput_container input:focus,
.gform_wrapper .ginput_container select:focus,
.gform_wrapper .ginput_container textarea:focus{
  outline:none;
  box-shadow:0 0 0 3px rgba(29,181,124,.18);
}

/* ── submit: the site's pill button, including the masked arrow ─────────── */
.gform_wrapper.gform-theme .gform_footer button[type="submit"],
.gform_wrapper.gform-theme .gform_footer input[type="submit"],
.gform_wrapper.gform-theme .gform_page_footer button[type="submit"]{
  display:inline-flex !important;
  align-items:center !important;
  justify-content:center !important;
  gap:20px !important;
  height:50px !important;
  padding:0 30px !important;
  border:3px solid #1DB57C !important;
  border-radius:50px !important;
  background:#1DB57C !important;
  color:#FFFFFF !important;
  font-family:"Figtree","Figtree Fallback",sans-serif !important;
  font-size:16px !important;
  font-weight:700 !important;
  line-height:1 !important;
  text-transform:uppercase !important;
  cursor:pointer !important;
  transition:background-color .18s ease,color .18s ease !important;
}
.gform_wrapper.gform-theme .gform_footer button[type="submit"]::after,
.gform_wrapper.gform-theme .gform_page_footer button[type="submit"]::after{
  content:'' !important;
  display:inline-block !important;
  width:36px !important;
  height:12px !important;
  flex:0 0 auto !important;
  /* GF's framework sets an explicit `color: var(--gf-local-color)` on this
     ::after, so currentColor here does NOT follow the button's own colour —
     the arrow stayed white while the label went navy on hover. Set the
     arrow's colour per state and let currentColor read from that. */
  color:#FFFFFF !important;
  background:currentColor !important;
  -webkit-mask:no-repeat center/contain !important;
          mask:no-repeat center/contain !important;
  -webkit-mask-image:var(--sg-arrow) !important;
          mask-image:var(--sg-arrow) !important;
}
.gform_wrapper.gform-theme .gform_footer button[type="submit"]:hover,
.gform_wrapper.gform-theme .gform_page_footer button[type="submit"]:hover{
  background:transparent !important;
  color:#12303E !important;
}
.gform_wrapper.gform-theme .gform_footer button[type="submit"]:hover::after,
.gform_wrapper.gform-theme .gform_page_footer button[type="submit"]:hover::after{
  color:#12303E !important;
}
.gform_wrapper.gform-theme .gform_footer button[type="submit"]:focus-visible{
  outline:3px solid #12303E !important;
  outline-offset:3px !important;
}

/* The arrow mask, shared with the theme's own buttons. */
:root{
  --sg-arrow:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 12'><path d='M0 6h41M35.5 1 41 6l-5.5 5' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* ───────────────────────────────────────────────────────────────────────────
   2. RESPONSIVE
   The comp was translated at fixed desktop pixel widths. The Elementor-side
   pins are fixed in the page data (tools/fix-responsive-widths.php); these are
   the ones that live in style.css and so have to be relaxed here.

   Elementor's tablet breakpoint on this site is 1027px (kit post 8,
   viewport_tablet), so that is the number used throughout — keeping CSS and
   Elementor's own responsive variants switching at the same place.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Solutions: built as a rigid 588 list + 455 panel row (1163px total).
      Below tablet, stack the two halves and let both go fluid. ───────────── */
@media (max-width:1027px){
  .sg-solutions .e-n-tabs{
    flex-direction:column !important;
    gap:32px !important;
  }
  .sg-solutions .e-n-tabs-heading{
    flex:0 0 auto !important;
    width:100% !important;
  }
  .sg-solutions .e-n-tab-title{
    width:100% !important;
  }
  .sg-solutions .e-n-tabs-content{
    flex:1 1 auto !important;
    width:100% !important;
  }
  /* 455px CTA on a 375px phone */
  button.sg-btn-green{
    width:100% !important;
    max-width:455px;
  }
}

/* ── Header ──────────────────────────────────────────────────────────────
   Three separate faults, all visible at 768px:
     1. padding stayed at the desktop 38/60, making the bar 178px tall;
     2. the logo held max-width:250px, so it ate a third of the screen;
     3. .sg-nav kept its full desktop width (271px) once the menu collapsed,
        and the toggle centres itself in that box — which is why the burger
        floated ~112px short of the right edge instead of sitting flush.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:1027px){
  /* Header bar padding and logo size now live on the Elementor header
     template (post 107) as tablet/mobile properties — edit them in the
     editor, not here. See tools/sg-set-props.php. */
  /* Collapse the nav box to its contents so the toggle can sit hard right.
     .sg-nav is a COLUMN flex container, so its children stretch to the cross
     axis by default — that is what blew the 47px burger up to full width once
     the auto margins that had been centring it were removed. Pin both. */
  .sg-header .sg-nav{
    flex:0 0 auto !important;
    width:auto !important;
    margin-left:auto !important;
    align-items:flex-end !important;
  }
  .sg-header .sg-nav .elementor-menu-toggle{
    flex:0 0 auto !important;
    align-self:flex-end !important;
    width:47px !important;
    height:47px !important;
    margin:0 !important;
  }

  /* Dropdown panel was 232px wide and anchored so it ran off the right edge.
     It is position:absolute inside the (now flush-right) .sg-nav, so pinning
     inset-inline-end:0 puts it back on screen. A vw-based width is wrong here
     — vw includes the scrollbar — so cap with max-width instead. */
  .sg-nav .elementor-nav-menu--dropdown{
    position:absolute !important;   /* else it sizes .sg-nav and re-widens the bar */
    min-width:0 !important;
    width:280px !important;
    inset-inline-end:0 !important;
    inset-inline-start:auto !important;
  }
}

@media (max-width:600px){
  .sg-nav .elementor-nav-menu--dropdown{
    width:260px !important;
  }
}

/* ── The 1028–1080px dead zone ────────────────────────────────────────────
   The hamburger switches in at 1027, but the real nav needs ~1081px
   (logo 250 + nav 711 + the desktop 60px side padding twice). Between those
   two numbers the menu was too wide for the bar and too wide to collapse.
   Trimming the side padding in that band buys the 56px needed, without
   moving Elementor's global tablet breakpoint (which would drag every other
   tablet variant on the site with it).
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:1028px) and (max-width:1200px){
  .sg-header{
    padding-inline:32px !important;
  }
  /* Measured at a 1025px viewport: the nav needs 831px in 699px of space.
     Trimming the side padding alone recovered 56px, still ~44px short — hence
     the small type step as well. 15px/8px measures 767px and clears it with
     room to spare; 14px was not needed. */
  .sg-nav .elementor-nav-menu--main .elementor-item{
    font-size:15px !important;
    padding-inline:8px !important;
  }
}

/* ── Phone: two things still overflowed after the width pins were released ──
   1. The footer link columns sat in a nowrap row. Releasing their min-width
      stopped them forcing the page wide, but then they just crushed instead —
      a 96px link inside a 5px box. They need to wrap, not shrink.
   2. Unbounded is a wide display face; a single long word ("TRANSPORTATION")
      has a min-content width of ~426px, which no amount of container fixing
      can absorb. Let long words break.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:767px){
  .elementor-location-footer .e-con{
    flex-wrap:wrap !important;
  }
  .elementor-location-footer .e-con > .e-con{
    flex:1 1 140px !important;
    min-width:140px !important;
  }

  /* Unbounded is a very wide display face and the comp's heading sizes were
     never stepped down for phones, so a single word ("TRANSPORTATION",
     "MANAGEMENT") has a min-content width of 426-583px — wider than the
     screen. Two things are needed:
       - `anywhere`, NOT `break-word`: only `anywhere` reduces the intrinsic
         min-content width, which is what actually lets the box narrow;
       - a smaller mobile size, so `anywhere` rarely has to break anything. */
  .sg-h2,
  .sg-hero-title,
  .elementor h1, .elementor h2, .elementor h3{
    overflow-wrap:anywhere;
  }
  .elementor .sg-hero-title{
    font-size:clamp(26px, 7.5vw, 40px) !important;
    line-height:1.1 !important;
  }
  .elementor .sg-h2{
    font-size:clamp(24px, 7vw, 34px) !important;
    line-height:1.15 !important;
  }
}

/* Images were sized from the comp and are not capped to their container.
   NOTE: deliberately no `height:auto` here — several marks (the footer lockup
   among them) are sized by an explicit height, and releasing it let them snap
   back to their natural 924px width, which was worse than the original bug. */
.elementor img,
.elementor .e-image-base{
  max-width:100%;
}

/* Elementor wraps linked images in <a class="e-image-link-base"> with
   max-width:none. The wrapper therefore keeps the comp's pixel width, and the
   image's own max-width:100% resolves against THAT rather than the column —
   which is why the footer lockup still measured 924px inside a 212px column.
   Cap the wrapper, then let the image take its natural ratio on phones. */
.elementor .e-image-link-base{
  max-width:100%;
}
@media (max-width:767px){
  .elementor-location-footer img.e-image-base{
    height:auto !important;
  }
}

/* Button pairs ("Request a demo" / "Explore industries") sit in a nowrap row.
   Two 280px pills do not fit side by side on a phone. Scoped with :has() so
   only rows that actually contain buttons start wrapping — blanket-wrapping
   every flex row would disturb the tabs and the wedge stacks. */
/* Scoped to the TABLET breakpoint, not 767: the 331px "View industry
 * solutions" pill overflows an 805px viewport by ~12px, and because the page
 * can then scroll horizontally the section backgrounds stop at the viewport
 * edge — which is the white strip down the right-hand side on tablet. */
@media (max-width:1027px){
  /* the variants are named button, button-2, button-3 ... hence the substring */
  .elementor .e-con:has(> a[class*="button"]){
    flex-wrap:wrap !important;
  }
  .elementor a[class*="button"]{
    max-width:100% !important;
    flex-shrink:1 !important;
  }
}

/* ───────────────────────────────────────────────────────────────────────────
   3. SEARCH
   The trigger replaces the old decorative `.sg-header::after`; that rule stays
   in style.css (it is part of the comp translation) and is switched off here
   once the script has added the real button.
   ─────────────────────────────────────────────────────────────────────────── */
.sg-header.sg-has-search::after{
  display:none !important;
}

.sg-search-toggle{
  flex:0 0 auto;
  width:22px;
  height:22px;
  margin-left:34px;
  padding:0;
  border:0;
  background:#1DB57C;
  cursor:pointer;
  -webkit-mask:no-repeat center/contain;
          mask:no-repeat center/contain;
  -webkit-mask-image:var(--sg-search);
          mask-image:var(--sg-search);
}
.sg-search-toggle:focus-visible{
  outline:2px solid #1DB57C;
  outline-offset:6px;
}

/* hello-elementor's reset.css claims bare buttons for its own accent:
 *   [type="button"]       { color:#CC3366 }
 *   [type="button"]:focus { background:#CC3366; color:#fff }
 * The toggle is a masked shape *painted with background*, so that focus rule
 * repainted the magnifier pink the moment it was clicked; on the close button
 * it put a pink box behind the X. Both selectors are (0,2,0), so pinning every
 * state at equal specificity from a later stylesheet is enough — no
 * !important needed, but the states must stay explicit. */
.sg-search-toggle,
.sg-search-toggle:focus,
.sg-search-toggle:focus-visible,
.sg-search-toggle:active{
  background:#1DB57C;
}
.sg-search-toggle:hover{
  background:#FCFCFC;
}

.sg-visually-hidden{
  position:absolute !important;
  width:1px; height:1px;
  margin:-1px; padding:0;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* ── overlay ─────────────────────────────────────────────────────────────── */
/* CRITICAL: `display:flex` on a class beats the UA's `[hidden]{display:none}`
 * (attribute selector, lower specificity), so without the rule below the
 * overlay stays in the layout at opacity:0, fixed across the whole viewport at
 * z-index 9999 — silently eating every click on the site. Keep these together. */
.sg-search-overlay[hidden]{
  display:none !important;
}

.sg-search-overlay{
  position:fixed;
  inset:0;
  z-index:9999;
  display:flex;
  align-items:flex-start;
  justify-content:center;
  padding:18vh 24px 24px;
  background:rgba(18,48,62,.97);
  opacity:0;
  transition:opacity .18s ease;
}
.sg-search-overlay:not(.is-open){ pointer-events:none; }
.sg-search-overlay.is-open{ opacity:1; pointer-events:auto; }
@media (prefers-reduced-motion:reduce){
  .sg-search-overlay{ transition:none; }
}

.sg-search-panel{
  position:relative;
  width:100%;
  max-width:760px;
}
.sg-search-panel form{
  display:flex;
  align-items:center;
  gap:16px;
  border-bottom:3px solid #1DB57C;
}

.sg-search-field{
  flex:1 1 auto;
  min-width:0;
  padding:12px 0;
  /* the theme skins input[type=search] with a white field + radius; strip the
     whole native/theme treatment rather than fighting it property by property */
  -webkit-appearance:none;
          appearance:none;
  border:0 !important;
  border-radius:0 !important;
  background:transparent !important;
  box-shadow:none !important;
  color:#FCFCFC !important;
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-size:clamp(20px, 4vw, 34px);
  font-weight:400;
  line-height:1.2;
}
.sg-search-field::placeholder{ color:rgba(252,252,252,.45); }
.sg-search-field::-webkit-search-cancel-button{ -webkit-appearance:none; }
.sg-search-field:focus{ outline:none; }

.sg-search-submit{
  flex:0 0 auto;
  height:50px;
  padding:0 30px;
  border:3px solid #1DB57C;
  border-radius:50px;
  background:#1DB57C;
  color:#FFFFFF;
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-size:16px;
  font-weight:700;
  text-transform:uppercase;
  cursor:pointer;
  transition:background-color .18s ease,color .18s ease;
}
.sg-search-submit:hover,
.sg-search-submit:focus,
.sg-search-submit:focus-visible{
  background:transparent;
  color:#FCFCFC;
}
.sg-search-submit:focus-visible{ outline:2px solid #1DB57C; outline-offset:3px; }

.sg-search-close{
  position:absolute;
  top:-56px;
  inset-inline-end:0;
  width:32px;
  height:32px;
  border:0;
  background:transparent;
  cursor:pointer;
}
.sg-search-close::before,
.sg-search-close::after{
  content:'';
  position:absolute;
  top:50%; left:0;
  width:100%; height:2px;
  background:#FCFCFC;
}
.sg-search-close::before{ transform:rotate(45deg); }
.sg-search-close::after{ transform:rotate(-45deg); }
.sg-search-close,
.sg-search-close:hover,
.sg-search-close:focus,
.sg-search-close:focus-visible,
.sg-search-close:active{
  background:transparent;
}
.sg-search-close:hover::before,
.sg-search-close:hover::after{
  background:#1DB57C;
}
.sg-search-close:focus-visible{ outline:2px solid #1DB57C; outline-offset:4px; }

@media (max-width:600px){
  .sg-search-overlay{ padding:14vh 16px 16px; }
  .sg-search-panel form{ flex-wrap:wrap; gap:12px; }
  .sg-search-submit{ width:100%; }
}

/* ───────────────────────────────────────────────────────────────────────────
   4. 404 + SEARCH RESULTS
   Both templates sit under an absolutely-positioned header with no hero to
   carry it, so they need their own top offset — that is why the old fallback
   pages had their first line tucked behind the logo.
   ─────────────────────────────────────────────────────────────────────────── */
.elementor-element-sg404wrap,
.elementor-element-sgsrwrap{
  padding-block-start:220px;
  padding-block-end:120px;
  padding-inline:24px;
  background:#12303E;
  color:#FCFCFC;
}

/* ── 404 ─────────────────────────────────────────────────────────────────── */
.elementor-element-sg404wrap{ text-align:center; }

.elementor-element-sg404wrap .sg-404-code .elementor-heading-title{
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-size:clamp(80px, 18vw, 180px);
  font-weight:700;
  line-height:1;
  color:#1DB57C;
  letter-spacing:-.03em;
}
.elementor-element-sg404wrap .sg-404-head .elementor-heading-title{
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-size:clamp(26px, 4vw, 44px);
  font-weight:400;
  text-transform:uppercase;
  line-height:1.15;
  color:#FCFCFC;
  margin-block-start:12px;
}
.elementor-element-sg404wrap .sg-404-body{
  max-width:560px;
  margin-inline:auto;
  margin-block-start:20px;
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-size:18px;
  line-height:1.7;
  color:rgba(252,252,252,.72);
}
.elementor-element-sg404acts{
  display:flex;
  flex-wrap:wrap;
  gap:16px;
  justify-content:center;
  margin-block-start:36px;
}
.elementor-element-sg404wrap .sg-404-btn .elementor-button{
  display:inline-flex;
  align-items:center;
  gap:16px;
  height:50px;
  padding:0 30px;
  border:3px solid #1DB57C;
  border-radius:50px;
  background:#1DB57C;
  color:#FFFFFF;
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-size:16px;
  font-weight:700;
  text-transform:uppercase;
  transition:background-color .18s ease,color .18s ease;
}
.elementor-element-sg404wrap .sg-404-btn-ghost .elementor-button{
  background:transparent;
}
.elementor-element-sg404wrap .sg-404-btn .elementor-button:hover{
  background:transparent;
  color:#FCFCFC;
}

/* ── search results ──────────────────────────────────────────────────────── */
.elementor-element-sgsrwrap{ text-align:left; }

.elementor-element-sgsrwrap .sg-results-title .elementor-heading-title{
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-size:clamp(26px, 4.5vw, 48px);
  font-weight:400;
  text-transform:uppercase;
  line-height:1.15;
  color:#FCFCFC;
  padding-block-end:24px;
  border-block-end:3px solid #1DB57C;
}

.elementor-element-sgsrwrap .sg-results-list{ margin-block-start:48px; }

.elementor-element-sgsrwrap .elementor-post{
  padding-block:28px;
  border-block-end:1px solid rgba(252,252,252,.14);
}
.elementor-element-sgsrwrap .elementor-post__title,
.elementor-element-sgsrwrap .elementor-post__title a{
  font-family:"Unbounded","Unbounded Fallback",sans-serif;
  font-size:clamp(18px, 2.4vw, 24px);
  font-weight:400;
  line-height:1.3;
  color:#FCFCFC;
  text-decoration:none;
}
.elementor-element-sgsrwrap .elementor-post__title a:hover{ color:#1DB57C; }
.elementor-element-sgsrwrap .elementor-post__excerpt p{
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-size:16px;
  line-height:1.7;
  color:rgba(252,252,252,.7);
}
.elementor-element-sgsrwrap .elementor-post__read-more{
  color:#1DB57C;
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-weight:700;
  text-transform:uppercase;
  font-size:14px;
  text-decoration:none;
}
.elementor-element-sgsrwrap .elementor-posts-nothing-found{
  font-family:"Figtree","Figtree Fallback",sans-serif;
  font-size:18px;
  color:rgba(252,252,252,.72);
}

@media (max-width:767px){
  .elementor-element-sg404wrap,
  .elementor-element-sgsrwrap{
    padding-block-start:150px;
    padding-block-end:80px;
    padding-inline:16px;
  }
}

/* ── Phones below ~400px ──────────────────────────────────────────────────
   Two structural defaults were still forcing the page wide:

   1. A flex item's `min-width` is `auto`, meaning it refuses to shrink below
      its own min-content width. A 426px heading or a 289px card body simply
      would not narrow, whatever their container did. min-width:0 releases it.
      (Note `overflow-wrap:break-word` alone does NOT help here — unlike
      `anywhere`, it has no effect on intrinsic min-content sizing.)
   2. Card rows were still nowrap, so a three-up row stayed three-up.
      Excluded: the tabs widget, which has its own stacking rule above, and
      the diagonal wedges, which are decorative overlays.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:767px){
  .elementor .e-con,
  .elementor .e-con > *{
    min-width:0 !important;
  }
  /* NOTE: a blanket `flex-wrap:wrap` on every container was tried here and
   * reverted — it reduced overflow on some pages but made /about/ markedly
   * worse (74px -> 436px), because wrapping re-flowed rows whose children
   * still carry comp-era fixed widths. Wrapping has to be decided per row. */
}

/* Card rows (Law Enforcement, Public Transit, School Transportation, Trucking,
   DEM) are four-up rows of `flex:1 1 0` columns. On a phone each column is
   squeezed to ~78px while its body copy stays ~289px, so the text — not the
   container — is what punched through the viewport. Stack the cards instead.

   Deliberately scoped with :has() to rows that actually hold a card, rather
   than wrapping every container: the blanket version of this made /about/
   much worse (see the note above). */

/* ── Phones: stack multi-column rows ──────────────────────────────────────
   The remaining horizontal overflow was not containers punching out — it was
   text inside them. Three- and four-up rows stayed side-by-side on a phone,
   crushing each column to 53-75px, and a word like "Vancouver" (89px) or a
   link like ">> Explore Digital Evidence Management" simply cannot fit that,
   so it spilled past the viewport.

   Stacking (flex-direction:column) rather than wrapping: with `wrap` the
   children keep their flex-basis and re-flow two-up at odd sizes, which is
   what made /about/ worse when that was tried earlier.

   Two selectors because the rows are built differently — industry cards are
   containers (`> .e-con`), the About office list is three bare `<p>`s.
   `:nth-child(3)` is the "three or more children" test, so two-up rows and
   icon+label pairs are left alone.

   padding-inline gives the now-full-width cards a gutter; these rows are
   full-bleed (x:0, width:100vw) today, so this adds edge spacing rather than
   replacing any.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:767px){
  .elementor .e-con:has(> .e-con:nth-child(3)),
  .elementor .e-con:has(> p:nth-child(3)){
    flex-direction:column !important;
    flex-wrap:nowrap !important;
  }
  .elementor .e-con:has(> .e-con:nth-child(3)) > .e-con,
  .elementor .e-con:has(> p:nth-child(3)) > *{
    width:100% !important;
    max-width:100% !important;
    flex:0 0 auto !important;
  }
}


/* ── Page gutter below the container width ────────────────────────────────
   The comp's side gutter is not padding — it is a side effect of the content
   containers being max-width 1190-1272 and centred: at 1385px that leaves
   57-98px of auto margin either side. Below ~1272 the max-width stops binding,
   the auto margins collapse to zero, and because the top-level sections carry
   NO padding of their own, every section runs flush to the screen edge. That
   is why tablet has no gutter at all.

   Give the top-level sections a real gutter instead of relying on the
   centring. Scoped to the section level so nested containers are untouched,
   and to <=1027 so desktop keeps the comp's measurements exactly.
   The header is excluded — it sets its own padding above. */

/* ── Tablet: card rows go two-up, not three ───────────────────────────────
   Between 768 and 1027 the card rows kept their desktop 3-up (and on the
   Solutions page 5-up), which at 790px leaves each card ~236px with the body
   copy wrapping every three or four words. Two-up gives ~360px per card.

   Scoped via the card classes rather than a child count: several containers
   on this site are flex-direction:column, and forcing flex-wrap on one of
   those makes children wrap into a second COLUMN, i.e. sideways off-screen —
   which is what happened to /about/ when a broader selector was tried.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:768px) and (max-width:1027px){
  .elementor .e-con:has(> .e-con > .sg-card-body) > .e-con,
  .elementor .e-con:has(> .e-con > .sg-card-title) > .e-con{
    /* grow:0 so a lone third card stays half-width instead of stretching
       across the row on its own line.
       max(280px, ...) is a floor: this selector can match a card row nested
       inside an already-narrow column, and a bare 50% then squeezed a card to
       108px while its text needed 191px. With the floor the card drops to one
       per line instead of overflowing. */
    flex:0 1 max(280px, calc(50% - 16px)) !important;
    min-width:0 !important;
  }
  .elementor .elementor-icon-list-item{ flex-wrap:wrap !important; }
  .elementor .elementor-icon-list-text{ min-width:0 !important; overflow-wrap:break-word; }
}

/* ── Long words at tablet ─────────────────────────────────────────────────
   The residual tablet overflow was not a box sticking out — every element's
   getBoundingClientRect sat inside the viewport, yet scrollWidth did not.
   The cause is text overflowing its own box: getBoundingClientRect measures
   the box, scrollWidth follows the ink. Unbounded is wide enough that a
   single long word in an h2 renders past a 726px box.

   The wrap rules were previously scoped to <=767, so tablet never got them.
   Applied here up to the tablet breakpoint; the phone font-size steps stay at
   <=767 because those are a deliberate phone treatment, not an overflow fix.
   ───────────────────────────────────────────────────────────────────────── */
/* 1240, not 1027: the desktop widths come back at 1028 but do not actually
   fit until ~1240, so the long-word overflow persists through that band too. */
@media (max-width:1240px){
  .sg-h2,
  .sg-hero-title,
  .elementor h1, .elementor h2, .elementor h3, .elementor h4,
  /* Blog posts render through the THEME's single template, outside .elementor,
     so the .elementor-scoped rules never reached them — the em-dash title
     "Celebrating Jim Haigh — 43 Years of..." spilled 41px at 375px. */
  .site-main h1, .site-main h2, .site-main h3, .site-main h4, .entry-title{
    overflow-wrap:anywhere;
  }
  /* body copy only needs break-word: it breaks a word that would overflow the
     line, without `anywhere`'s habit of breaking mid-word in ordinary prose */
  .elementor p,
  .elementor li,
  .elementor a,
  .elementor strong,
  .elementor em,
  .elementor .elementor-icon-list-text,
  .site-main p, .site-main li, .site-main a{
    overflow-wrap:break-word;
  }
}


/* ── The 1028-1240px dead zone ────────────────────────────────────────────
   Elementor's tablet breakpoint is 1027, so from 1028 up the DESKTOP widths
   apply again — the About row (552 + 626 ~= 1190) and the Solutions tabs
   module (588 + 455 + gutter = 1163). Those only fit once the viewport passes
   ~1240, so every width in between overflowed: 165px at 1040, 105px at 1100,
   55px at 1150. Scrolling that overflow is what shows the white bar down the
   right-hand side, because the section backgrounds stop at the viewport edge.

   Above 1240 the container max-width binds and its auto margins provide the
   gutter, so this block stops there. flex-shrink:1 keeps the comp's
   proportions while letting the row fit, which is the same approach
   tools/fix-responsive-widths.php takes at tablet.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:1028px) and (max-width:1240px){
  /* The laptop side gutter that used to be declared here is gone: each
     section's @laptop padding property already produces the identical
     inline-start:67px / inline-end:32px across this whole band. */
  .elementor .e-con > .e-con{
    flex-shrink:1 !important;
    min-width:0 !important;
  }
  .sg-solutions .e-n-tabs-heading,
  .sg-solutions .e-n-tabs-content{
    flex-shrink:1 !important;
    min-width:0 !important;
  }
  .sg-solutions .e-n-tab-title{
    width:100% !important;
  }

  /* Card rows go three-up here rather than the tablet two-up — there is room
     for three at 1028-1240, and the 280px floor drops them to fewer per line
     if a row is nested somewhere narrow. Without this the card body copy still
     overflowed on Law Enforcement (50px at 1040, 22px at 1150). */
  .elementor .e-con:has(> .e-con > .sg-card-body) > .e-con,
  .elementor .e-con:has(> .e-con > .sg-card-title) > .e-con{
    flex:0 1 max(280px, calc(33.333% - 16px)) !important;
    min-width:0 !important;
  }
}


/* ── Vertical side rails vs. the page gutter ──────────────────────────────
   The rails (.sg-rail) are 51px wide, absolutely positioned at left:0, and
   visible from 981px up. Two separate problems once the gutter existed:

   1. ANCHORING. An absolutely positioned element resolves its offsets against
      its containing block's PADDING box, whose left edge sits at the border —
      so the gutter does not move a rail whose containing block is the section
      itself ("Why Saegic", "Industries We Serve", "Featured Applications",
      all still at x:0). But two rails ("What is Saegic", "By the Numbers" —
      the Solution section and the one below it) hang off an INNER container,
      and that container is itself pushed in by the section's padding, so those
      rails came in with it. They are pulled back out by exactly that amount.

   2. OVERLAP. The rail occupies 0-51px, and the gutter starts text at 32px, so
      the rail sat under the first ~19px of copy. Rail-bearing sections get a
      67px leading inset instead (51px rail + 16px breathing room).
      Capped at 1320px: beyond that the container's own centring already leaves
      more than 67px, so the comp's desktop measurements stay untouched.
   ───────────────────────────────────────────────────────────────────────── */
/* The 1241-1320 rail-inset band is gone: the laptop breakpoint is now 1320,
   so each section's @laptop padding property carries the inset across the
   whole 1028-1320 range and the card rules apply there too. */

/* Nested rails are re-anchored by an Elementor PROPERTY now, not here:
   margin block-end -67px at laptop (tools/sg-rails.php). On a
   writing-mode:vertical-rl element the block axis runs right-to-left, so
   margin-block-end IS physical margin-left. Session 1 tried
   margin-inline-start, which on this element is margin-TOP, and concluded
   logical margins could not do it. The rule that used to live here won on
   specificity (0,4,0) and pinned margin-left to 0, so it had to go. */

/* ── Two-column rows: stack up to tablet ──────────────────────────────────
   Sections built as "heading | copy + CTA" (Trusted By, The Challenge, and 70+
   more across the site) kept both columns side by side all the way down,
   leaving each one ~152px on a phone and ~280px on tablet.

   These were deliberately excluded from the 3+ column stacking rule earlier,
   on the theory that two-up rows were safe. They are not — at these widths a
   two-column row is one column too many.

   The :not() guards matter: Elementor builds buttons as .e-con too, and their
   internals are a two-child row (label + arrow). Stacking those would break
   every button on the site, so anything that is or sits inside a button is
   excluded, and the children are required to be .e-con (a button's label and
   arrow are not).
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:1027px){
  .elementor .e-con:not(a):not(button):not([class*="button"]):has(> .e-con:nth-child(2)):not(:has(> .e-con:nth-child(3))){
    flex-direction:column !important;
    flex-wrap:nowrap !important;
  }
  .elementor .e-con:not(a):not(button):not([class*="button"]):has(> .e-con:nth-child(2)):not(:has(> .e-con:nth-child(3))) > .e-con{
    width:100% !important;
    max-width:100% !important;
    flex:0 0 auto !important;
  }
}

/* ── Wedge heights: restore the variable formula ──────────────────────────
   style.css pins each wedge to desktop pixels with .e-con.sg-wedge-N
   (height:114px, margin-top:-90px, ...) and no media query, so those values
   beat the variable-driven calc() and the green diagonal kept its DESKTOP
   height on phones — even though :root drops --sg-rise1..5 below 980px and
   the clip-path had already shrunk to match.

   These rules restate the same formula at the same specificity. Because this
   file loads after style.css they win, and the wedges follow --sg-rise again
   at every width. Desktop output is unchanged: rise1 90 + stripe 24 = 114,
   rise2 85, rise3 114 + 25 = 139, rise4 114, rise5 105.
   ───────────────────────────────────────────────────────────────────────── */
.e-con.sg-wedge-1,
.e-con.sg-wedge-2,
.e-con.sg-wedge-3,
.e-con.sg-wedge-4,
.e-con.sg-wedge-5{
  height:calc(var(--sg-rise) + var(--sg-stripe,0px)) !important;
  margin-top:0 !important;
  margin-bottom:0 !important;
}
.e-con.sg-wedge-over{
  margin-top:calc(-1 * var(--sg-rise)) !important;
  margin-bottom:0 !important;
}
.e-con.sg-wedge-under{
  height:var(--sg-rise) !important;
  margin-top:0 !important;
  margin-bottom:calc(-1 * var(--sg-rise)) !important;
}
